Time-lapse tilt-shift photography

Time-lapse photography is a technique where each frame is captured at a much slower rate than it is played back.  When it is replayed everything appears to be moving faster.

Tilt-shift photography is a technique of distorting the plane of focus of an image by tilting the camera lens and distorting the perspective by shifting the lens.  This leads to images which appear to be of miniture worlds.

Combining these two techiniques creates some interesting videos, such as the one below by Keith loutit.


Beached from Keith Loutit on Vimeo.

I found this video here at Web Urbanist.  They have a couple more examples by Keith Loutit, along with several examples of tilt-shit photography.

7 Day Shop

7 Day Shop have always provided good value photographic products, computer & digital accessories (and more as well).

I have used them several times in the past and they have always been reliable and efficient. They have recently announced that they are no longer charging for postage in the UK.

This is great news!

Connect to a Windows remote desktop using Linux

Whilst browsing I found this article of 10 tips when making the switch to Ubuntu Linux.  One of the tips is Remote desktop to a Windows desktop/server.

There is a program called rdesktop that allows you to connect to a windows remote desktop sesson on an IP address (over RDP):
rdesktop [server]:[port]
The remote desktop I tried this on was using a VPN tunnel using this command:
rdesktop localhost:52893

The article also linked to the Wikipedia rDesktop article which linked to information for other RDP clients.

The only downside I found so far is that the screen resolution was restricted to 800*600 with 16 colours. Not a big problem for occasional use, but I may investigate some of the other solutions.

Does anyone else know of a better alternative?

MySQL slow query log

The MySQL slow query log enables you to log all queries that take longer than a specified number of seconds to execute.  This should help identify any queries that are not performing sufficiently.

All that is required is two additional lines in the MySQL configuration file “my.cnf” in the [mysqld] section.
[mysqld]
log-slow-queries = /var/log/mysql-slow.log
long_query_time = 4

The above configuration will log any queries taking longer than 4 seconds to execute in to the specified log file.

MySQL appears to require that the specified log file exists otherwise the logging is disabled and the error below appears in the MySQL log. (Or it may be that it didn’t have permissions to create the file. I haven’t investigated).
081013 14:55:37 [ERROR] Could not use /var/log/mysql-slow.log for logging (error 13). Turning logging off for the whole duration of the MySQL server process. To turn it on again: fix the cause, shutdown the MySQL server and restart it.

To create the log file I did the following:
touch /var/log/mysql-slow.log
chown mysql.mysql /var/log/mysql-slow.log
chmod o-r /var/log/mysql-slow.log

The third command is probably unnecessary, but it meant that the permissions matched the mysqld.log in the same directory.

Once this is done MySQL needs to be restarted to start the query logging:
service mysql restart

Visual Basic 6, ActiveX and Unicode

One of the older applications I support uses ActiveX controls embedded inside a web page.  These controls request data from a web server to update the information on the page without requesting the whole page again, much in the same way that AJAX is now commonly used.

This has worked fine for the Latin code pages (ISO8859-1, ISO8859-15), and for the double byte code page (cp950)  that have been tested.  However it did not work when I tried the UTF-8 Unicode code page.

The reason for this is fairly simple:

VB stores strings internally using Unicode, but assumes that the outside world is ANSI.

This means that Visual Basic will convert from ANSI to Unicode (UTF-16) when storing a string, and convert it back again when it is retrieved.

The ActiveX controls use the Microsoft Inet control to request data via HTTP.  This uses the GetChunck() method in the StateChanged event in order to read the data in to a string. This was the first cause of my problems as Visual Basic will automatically convert the data in the string to ANSI, which loses the Unicode characters.

The Inet control GetChunck() method takes two parameters; size and data type. The size parameter tells it how much data to read, and the data type parameter tells it what data type to read it in to. The data was being read in to a string (icString), but to avoid the conversion I had to change this to a byte array (icByteArray) to avoid the automatic conversion process.

So far so good. But now I had a UTF-8 byte array that I needed to convert in to a string without losing data in the conversion process. This was a bit of a sticking point as Visual Basics string conversion function StrConv() can’t cope with UTF-8 and none of the API calls I found to convert the string worked. You can assign a string equal to a byte array and no automatic conversion happens, but as strings are stored internally as UTF-16 this does not work.

I was nearly at the stage where I either needed to write my own conversion process, or re-develop the controls in another language with better UTF-8 support.

Then I found this solution:
Public Function ConvertUtf8BytesToString(ByRef data() As Byte) As String
    Dim objStream As ADODB.Stream
    Dim strTmp As String
    ' init stream
    Set objStream = New ADODB.Stream
    objStream.Charset = "utf-8"
    objStream.Mode = adModeReadWrite
    objStream.Type = adTypeBinary
    objStream.Open
    ' write bytes into stream
    objStream.Write data
    objStream.Flush
    ' rewind stream and read text
    objStream.Position = 0
    objStream.Type = adTypeText
    strTmp = objStream.ReadText
    ' close up and return
    objStream.Close
    ConvertUtf8BytesToString = strTmp
End Function

This does not use any APIs but requires the Microsoft ActiveX Data Objects 2.5 Library or later.

Using this solution I was able to assign the original internal string variable to the result of this function and the rest of the code in the controls worked.
strWSConnectReturnData = ConvertUtf8BytesToString(bytWSConnectReturnData)

The ActiveX controls also read data values from the webpage and POST them back to the webserver.  The values are read via the DOM. These also need to be converted in the opposite direction, before they can be URL encoded.

Public Function ConvertStringToUtf8Bytes(ByRef strText As String) As Byte()
Dim objStream As ADODB.Stream
Dim data() As Byte
' init stream
Set objStream = New ADODB.Stream
objStream.Charset = "utf-8"
objStream.Mode = adModeReadWrite
objStream.Type = adTypeText
objStream.Open
' write bytes into stream
objStream.WriteText strText
objStream.Flush
' rewind stream and read text
objStream.Position = 0
objStream.Type = adTypeBinary
objStream.Read 3 ' skip first 3 bytes as this is the utf-8 marker
data = objStream.Read()
' close up and return
objStream.Close
ConvertStringToUtf8Bytes = data
End Function

This returns a byte array, and I pass it directly in to a function that URL encodes the byte array, returning a sting.
String = URLEncodeUTF8ByteArray( ConvertStringToUtf8Bytes( DomValue) )

Many thanks to Tim Hastings for his solution, as this has saved me a lot of pain!

Internet Explorer 6 and HTTP compression

Recently I wrote about installing mod_gzip on CentOS 5. However since then I have discovered that Internet Explorer 6 has does not support this properly, and intermittently does not load items properly!

To resolve this I had to change the Apache configuration. This is the configuration that I am now using:
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.[0678] no-gzip
BrowserMatch \bMSIE\s7 !no-gzip !gzip-only-text/html
BrowserMatch \bOpera !no-gzip
Header append Vary User-Agent

This turns off the HTTP compression based on their user agent.

Here are some of the known issues:
http://support.microsoft.com/kb/321722/EN-US/ (IE5.5, IE6 and IE6SP1 always cache gzip encoded content)
http://support.microsoft.com/default.aspx?scid=kb;LN;Q312496 (IE6 http://support.microsoft.com/default.aspx?scid=kb;en-us;823386&Product=ie600 (IE6sp1, compressed HTML pages only partially appear)

And this is one of the sites I found to help with the resolution:
http://www.contentwithstyle.co.uk/Blog/147/

Ikea mobile phones

Ikea has launched its own mobile phone service called Family Mobile (which piggybacks on the T-Mobile network). This is “pay as you go” service offering very competitive rates when compared to other UK providers.

Basically it is a flat rate of 9p per minute whether you are calling a land line or another mobile phone, regardless of the network. Text messages are also reasonable at 6p each.

The service allows you to automatically top up your balance when a pre-set minimum is reached, so there is no need to worry about buying top up vouchers, and as it is aimed at family usage you can have multiple phones on the same account.

If you need to buy a handset then their prices do look more expensive than other service providers, so it will probably be cheaper to bring an existing handset or buy one elsewhere and take their SIM only option.

If you already have a phone that is compatible with the T-Mobile network then it should work, otherwise you may need to get your phone unlocked. Your existing provider may be able to do this for a fee, alternatively you can try and do it yourself. There are several sites on the internet that can give you the necessary information. One example is http://unlockme.co.uk/.

Installing PHP XCache on CentOS 5

XCache is a PHP opcode cacher, which basically means that it will cache the compiled code the first time a PHP page/script is executed thus avoiding the compilation step on subsequent executions.

I used the 1.2.2. release of XCache and followed the quick guide instructions to install from source.

The installation requires that the php-devel package is installed. This is required to compile PHP extensions (the comand phpize is required for this installation).

[root@testserver xcache-1.2.2]# yum install php-devel
Dependencies Resolved
=============================================================================
Package Arch Version Repository Size
=============================================================================
Installing:
php-devel i386 5.1.6-20.el5_2.1 updates 512 k
Updating for dependencies:
php i386 5.1.6-20.el5_2.1 updates 1.1 M
php-cli i386 5.1.6-20.el5_2.1 updates 2.1 M
php-common i386 5.1.6-20.el5_2.1 updates 154 k
php-gd i386 5.1.6-20.el5_2.1 updates 113 k
php-ldap i386 5.1.6-20.el5_2.1 updates 35 k
php-mbstring i386 5.1.6-20.el5_2.1 updates 969 k
php-mysql i386 5.1.6-20.el5_2.1 updates 84 k
php-pdo i386 5.1.6-20.el5_2.1 updates 62 k
php-xml i386 5.1.6-20.el5_2.1 updates 94 k
Transaction Summary
=============================================================================
Install 1 Package(s)
Update 9 Package(s)
Remove 0 Package(s)
Total download size: 5.2 M
Is this ok [y/N]:

It appears that this will also update the core PHP package and dependancies, so care should be taken. Try this on a test server and not your production server!

Here are the steps I took to install XCache:

[root@testserver ~]# tar -zxf xcache-1.2.2.tar.gz
[root@testserver ~]# cd xcache-1.2.2
[root@testserver xcache-1.2.2]# phpize
[root@testserver xcache-1.2.2]# ./configure –enable-xcache
[root@testserver xcache-1.2.2]# make
[root@testserver xcache-1.2.2]# make install
[root@testserver xcache-1.2.2]# cp /etc/php.ini /etc/php.ini.bk
[root@testserver xcache-1.2.2]# cat xcache.ini >> /etc/php.ini

In my configuration the xcache.ini and resulting php.ini had the wrong path to the module that has been installed. The module was installed in /usr/lib/php/modules/ but the configuration was looking in /usr/local/lib/php/extensions/non-debug-non-zts-xxx/.

All that was needed was a simple change to the configuration file to comment out the fully qualified path and tell it to use the extensions directory:

[xcache-common]
;; install as zend extension (recommended), normally “$extension_dir/xcache.so”
;; zend_extension = /usr/local/lib/php/extensions/non-debug-non-zts-xxx/xcache.so
; zend_extension_ts = /usr/local/lib/php/extensions/non-debug-zts-xxx/xcache.so
;; For windows users, replace xcache.so with php_xcache.dll
;; zend_extension_ts = c:/php/extensions/php_xcache.dll
;; or install as extension, make sure your extension_dir setting is correct
extension = xcache.so
;; or win32:
; extension = php_xcache.dll

Then just check it’s installed:

[root@testserver xcache-1.2.2]# php -v
PHP 5.1.6 (cli) (built: Jul 16 2008 19:53:00)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
with XCache v1.2.2, Copyright (c) 2005-2007, by mOo

Success! However Apache must be restarted in order for this to work with PHP web pages.
service httpd restart
Now if you access a page containing the phpinfo(); function you should be able to search for XCache and find it.

XCache is now installed and running.

I did not see the need to install the php-devel package on our live servers and I know that our live servers are identical to our test servers other than hard disk and memory sizes (we use VMWare extensively and they come from the same template).

This means that all the binaries compiled on the test server should be compatible with our live servers, so I just copied the xcache-1.2.2 folder from the test server and followed the above steps again starting with the “make install” step.

[root@testserver ~]# tar -cvzf xcache-install.tgz xcache-1.2.2/
copy this to the /root/ directory on the live server

[root@liveserver ~]# tar -xvzf xcache-install.tgz
[root@liveserver xcache-1.2.2]# make install
[root@liveserver xcache-1.2.2]# cp /etc/php.ini /etc/php.ini.bk
[root@liveserver xcache-1.2.2]# cat xcache.ini >> /etc/php.ini
[root@liveserver xcache-1.2.2]# vi /etc/php.ini
[root@liveserver xcache-1.2.2]# php -v
PHP 5.1.6 (cli) (built: Sep 20 2007 10:16:10)
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
with XCache v1.2.2, Copyright (c) 2005-2007, by mOo

Installing mod_gzip on CentOS 5

CentOS 5 is packaged with Apache 2 which is not compatible with mod_gzip. The module mod_deflate is the Apache 2 equivalent.

Installing mod_deflate on CentOS 5 is a fairly simple process. The module is included in CentOS 5 and just need to be configured.

The only changes required are to the Apache configuration file /etc/httpd/conf/httpd.conf. I recommend that you take a backup before you make any changes.

Here are the steps that I took:

1. Check that the deflate module is loaded.
In my configuration file this was already done with this line:
LoadModule deflate_module modules/mod_deflate.so
If this is not there then I suspect all that is required is to add this line. However if you need to do this I recommend that you check the module /etc/httpd/modules/mod_deflate.so is installed.

2. Configure the deflate module
All that was required was to add the following lines to the Apache configuration file.
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/x-javascript
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.[0678] no-gzip
BrowserMatch \bMSIE\s7 !no-gzip !gzip-only-text/html
BrowserMatch \bOpera !no-gzip
Header append Vary User-Agent
Update 26/08/2008: Originally I only had the first line of the above configuration. However it turns out that there are issues with Internet Explorer 6 and HTTP compression.

I added this after
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
but you should be able to add it anywhere in the main section.

3. Restart Apache
service httpd restart

4. Test it’s working
The easiest way to check that it is working is with the YSlow plugin for Firebug. Firebug is a Firefox plugin that will give you lots of useful information.

To test just load a page in your browser, go to the Firebug/YSlow plug and select the “Performance” option. This will give you a performance grade. You should hopefully see an “A” for “4. Gzip components”. If not do a Ctrl-F5 to ensure that you’re not viewing cached content.

If this still does not report an “A” for “4. Gzip components”. then it is possible that your page has other content types that need to be added for YSlow to be happy.

Summary
This is only a quick overview of the steps I took, and by no means comprehensive A more detailed tutorial is available here: http://www.howtoforge.com/apache2_mod_deflate

MySQL export to CSV

MySQL allows you to export a query directly in to a CSV file that can be opened by Microsoft Excel.

This is the basic syntax:

select fields from table into outfile '/path/to/file_name.csv' fields terminated by ',' optionally enclosed by '"' lines terminated by '\n';

The export file that is created “file_name.csv” must not already exist, the MySQL user must have write permissions to the directory the file will be created in, and the FILE permission within MySQL.

See the MySQL manual: SELECT Syntax