<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jamie Thompson</title>
	<atom:link href="http://jamiethompson.co.uk/feed/" rel="self" type="application/rss+xml" />
	<link>http://jamiethompson.co.uk</link>
	<description>Web Developer</description>
	<lastBuildDate>Tue, 08 May 2012 10:58:26 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Working From Home</title>
		<link>http://jamiethompson.co.uk/web/2012/05/08/working-from-home/</link>
		<comments>http://jamiethompson.co.uk/web/2012/05/08/working-from-home/#comments</comments>
		<pubDate>Tue, 08 May 2012 10:58:26 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=586</guid>
		<description><![CDATA[
Working from home sounds like most people’s idea of perfect, and in many ways it is, but it’s not without its pitfalls. Working from home can be a minefield of distractions, blurred boundaries and definitely not the sweet deal many people tethered to a cubicle might assume it to be.
Connectivity
Internet outages at the office are [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://jamiethompson.co.uk/wp-content/uploads/2012/05/lies.jpg"><img src="http://jamiethompson.co.uk/wp-content/uploads/2012/05/lies.jpg" alt="Working From Home" title="Working From Home" width="530" height="190" class="size-full wp-image-591" /></a></p>
<p>Working from home sounds like most people’s idea of perfect, and in many ways it is, but it’s not without its pitfalls. Working from home can be a minefield of distractions, blurred boundaries and definitely not the sweet deal many people tethered to a cubicle might assume it to be.</p>
<h2>Connectivity</h2>
<p>Internet outages at the office are an annoyance. They cause frustration and lost time, but at least you have the comfort of knowing that, hey, it’s not your fault, and that you and your coworkers are in the same metaphorical boat. When you’re a home-based employee it can be an altogether different kettle of fish.</p>
<p>Imagine this. Your team is on a tight deadline and you lose connectivity for an afternoon. You can’t continue to work until your internet connection comes back up. Are your colleagues or more importantly your boss going to be understanding? Hopefully; but possibly not. Maybe you just signed out of IM and you’re <a href="http://www.youtube.com/watch?v=ZZ5LpwO-An4&#038;feature=related">messing around</a> on YouTube. Who knows. Whatever the case, you’re probably already feeling more pressured to make up the lost time than you otherwise might.</p>
<p>A backup connection can be a godsend here. If you have an iPhone you can easily setup a wifi hotspot to keep you up and running. I’ve got an <a href="http://www.o2.co.uk/broadband">O2 Mobile Broadband </a>dongle as a backup. It’s pay and go so perfect to just keep in a drawer for emergencies. Even if you can’t get 3G at home, you can get connected, albeit slowly over GPRS. If you’re lucky enough to live in a cabled area you could go belt and braces and get a ADSL line as a backup to your cable connection, but that’s probably a little over-the-top.</p>
<h2>Boundaries</h2>
<p>When you work in an office environment there’s a very clear distinction between being at work and, well, not being at work. It seems obvious, but they’re quite simply two different places. Working from home can very easily destroy this important dividing line leaving you “always on”, and, eventually, burned out.</p>
<p>This is where your home environment can make a huge difference either way. It’s essential to be able to maintain a physical and psychological distinction between work and “not work”. If you’re lucky enough to have a spare room then make this a dedicated office. If you don’t have space for this then at the very least you need to form an enclave in an existing room. Preferably a room that’s big enough to accommodate this. If you’re lucky enough to have outbuildings, something like a summer house, then as Charlie Sheen would put it, you’re WINNING!</p>
<p>But in all seriousness, the key to winning is being able to psychologically compartmentalize those two conflicting states of work and non-work. If you fail at this then you can very easily wind up in a situation where you’re never really working to your full potential, but you’re never really off-duty either. This isn’t healthy for you or your career.</p>
<h2>Distractions</h2>
<p>It very much depends on both your home and office environments. Some offices I’ve worked in have been incredibly distracting. No air-conditioning, poor lighting, being cramped together with call-centre staff. Others have been perfectly fine environments for working in.</p>
<p>The same can be true of your home. Needless to say, it’s probably not a good idea to work from home if you have pre-school children unless you have an office setup that excludes you from day-to-day home life.</p>
<p>One of the biggest distractions there is comes in the form of social media. The pressure of knowing the finer details of exactly what each and every one of your casual acquaintances had for their most recent meal is surely going to bring about the downfall of our species. eventually. But for the time being, if left unchecked, it is undoubtedly one of the biggest drains on your productivity. If you lack the will power to stay away from Twitbook and FaceSpace for at least a couple of hours at a time then there are various apps such as <a href="http://getconcentrating.com/">Concentrate for OSX</a> that purport to help you focus on work by banning you from using non-work-related apps and websites for a specified chunk of time.</p>
<p>Social distractions aside,  it’s most likely that you’re a self-motivated individual and don’t need the pressure of a boss breathing down your neck to make you perform to the best of your abilities, but being at home is always going to offer additional opportunities for distraction that your cubicle simply doesn’t</p>
<p>You’ve got a sweet little office setup with a view out into the garden. It’s gonna be super-productive, but what’s that? The grass is looking a little long. Maybe you could just nip out and run the mower over it for a bit. One thing leads to another and before you know it you’ve lost an hour or two of valuable working time. That’s not to say that you’re going to be shirking your responsibilities. What it more likely means is that you’re going to be working even later tonight to finish your todo list and hit your targets.</p>
<p>In conclusion, working from home is something of a double-edged sword. Whilst it offers the flexibility to work in an often more relaxed environment, it brings with it its own unique set of challenges. As with most things in life, overcoming those challenges is your key to success.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2012/05/08/working-from-home/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Greasemonkey Script. Play BBC iPlayer via XBMC</title>
		<link>http://jamiethompson.co.uk/web/2010/09/09/greasemonkey-script-play-bbc-iplayer-via-xbmc/</link>
		<comments>http://jamiethompson.co.uk/web/2010/09/09/greasemonkey-script-play-bbc-iplayer-via-xbmc/#comments</comments>
		<pubDate>Thu, 09 Sep 2010 12:00:17 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=564</guid>
		<description><![CDATA[The BBC iPlayer plugin for XBMC works really well. In my experience, It&#8217;s much more stable (if less fancy looking) than the official Wii application. The only downside is that as with most XBMC video plugins, the navigation can be a little clunky.
I&#8217;ve written a small Greasemonkey script which adds a &#8216;Send to XBMC&#8217; button [...]]]></description>
			<content:encoded><![CDATA[<p>The BBC iPlayer plugin for <a href="http://www.xbmc.org">XBMC</a> works really well. In my experience, It&#8217;s much more stable (if less fancy looking) than the official Wii application. The only downside is that as with most XBMC video plugins, the navigation can be a little clunky.</p>
<p>I&#8217;ve written a small Greasemonkey script which adds a <strong>&#8216;Send to XBMC&#8217;</strong> button to any iPlayer episode page. The script has a couple of requirements but it&#8217;s fairly easy to get up and running in a matter of minutes. When clicked, the script will invoke the iPlayer plugin on the target XBMC and start playing the relevant episode.</p>
<p>This works for both TV and Radio streams.</p>
<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/09/iplayer_xbmc_page.png" alt="BBC iPlayer Send to XBMC Script" title="BBC iPlayer Send to XBMC Script" width="530" height="461" class="alignnone size-full wp-image-571" /></p>
<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/09/iplayer_xbmc_button.png" alt="BBC iPlayer Send to XBMC button" title="BBC iPlayer Send to XBMC button" width="530" height="148" class="alignnone size-full wp-image-565" /></p>
<h2>Requirements</h2>
<p>The first requirement is that obviously you&#8217;ll need an XBMC Media Center which is network accessible and can access the Internet. The second glaringly obviously requirement is that you need to have the <a href="http://code.google.com/p/xbmc-iplayerv2/">BBC iPlayer XBMC plugin</a> installed. This greasemonkey script assumes the default plugin folder name of &#8216;iPlayer&#8217;.</p>
<p>If you haven&#8217;t enabled the Web Server in your <a href="http://wiki.xbmc.org/index.php?title=Network_Settings">XBMC Network Settings</a>, you will need to do this. The script works by making an HTTP request to the XBMC <a href="http://wiki.xbmc.org/index.php?title=Web_Server_HTTP_API">HTTP API</a> in order to invoke the iPlayer plugin.</p>
<p>There&#8217;s a single configuration option for the host name or IP address of your XBMC. This is configurable via a User Script Command (Hint: right click the Greasemonkey status bar icon)</p>
<h2>Teh codez</h2>
<pre class="brush: js">
// ==UserScript==
// @name           BBC IPlayer Send to XBMC
// @namespace      http://userscripts.org/users/218421
// @include        http://www.bbc.co.uk/iplayer/episode/*
// ==/UserScript==

GM_registerMenuCommand("Change XBMC Host for IPlayer",set_xbmc_host);
if (GM_getValue("XBMC_HOST")==undefined) {
		set_xbmc_host;
}

function hasClass(ele,cls) {
	return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
}

function addClass(ele,cls) {
	if (!this.hasClass(ele,cls)) ele.className += " "+cls;
}

function removeClass(ele,cls) {
	if (hasClass(ele,cls)) {
    	var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
		ele.className=ele.className.replace(reg,' ');
	}
}

getpid = function(){
	return pid = document.location.toString().split('/')[5];
}

play = function(e){
	e.preventDefault();
	var xbmc_host = GM_getValue("XBMC_HOST");
	var i = new Image();
	i.src = 'http://'+xbmc_host+'/xbmcCmds/xbmcHttp?command=PlayFile(plugin://video/IPlayer/?pid='+getpid()+')';
}

init = function(){
	var tools = document.getElementById('episodeTools');

	var list = tools.getElementsByTagName('ul')[0];
        removeClass(list,'no-badge');

	var a = document.createElement('a');
	a.setAttribute('href','#');
	a.addEventListener('click', play, false);
	var p = document.createElement('p');
        p.setAttribute('class','hd-link');
	p.appendChild(a);

        a.style.backgroundImage = "url('data:image/png;base64,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')";

	tools.appendChild(p);
}

setTimeout(init,2000);

function set_xbmc_host() {
	GM_setValue("XBMC_HOST",window.prompt("Enter your XBMC IP address", "192.168.0."));
}
</pre>
<p>The script can be obtained from userscripts.org &#8211; <a href="http://userscripts.org/scripts/show/85753">http://userscripts.org/scripts/show/85753</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/09/09/greasemonkey-script-play-bbc-iplayer-via-xbmc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Code-Point Open &#8211; Northern Ireland Addendum</title>
		<link>http://jamiethompson.co.uk/web/2010/05/30/code-point-open-northern-ireland-addendum/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/30/code-point-open-northern-ireland-addendum/#comments</comments>
		<pubDate>Sun, 30 May 2010 21:19:47 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[postcode]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=548</guid>
		<description><![CDATA[
In April 2010 Ordnance Survey released The Code-Point Open dataset under a licence compatible with the Creative Commons Attribution Licence. The dataset locates, by OSGB grid reference every postcode unit in England, Scotland and Wales. Northern Ireland is missing. You can read more about the limitations of the Code-Point Open dataset in my previous post
All [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/cpo_ni.jpg" alt="Code-Point Open Northern Ireland" title="Code-Point Open Northern Ireland" width="530" height="190" class="alignnone size-full wp-image-559" /></p>
<p>In April 2010 Ordnance Survey released The Code-Point Open dataset under a licence compatible with the Creative Commons Attribution Licence. The dataset locates, by OSGB grid reference every postcode unit in England, Scotland and Wales. Northern Ireland is missing. You can read more about the limitations of the Code-Point Open dataset in <a href="http://jamiethompson.co.uk/web/2010/05/29/the-problem-with-code-point-open-from-ordnance-survey/">my previous post</a></p>
<p>All is not lost though. The Northern Ireland Statistics and Research Agency (NISRA) provide the necessary data. As far as I can tell this is freely reusable under the terms of the <a href="http://www.nationalarchives.gov.uk/information-management/our-services/click-use.htm">Click-Use PSI Licence</a>.</p>
<p>NISRA provide the data in MapInfo or ESRI Shapefile format. The coordinates are in <a href="http://en.wikipedia.org/wiki/Irish_grid_reference_system">Irish Grid Reference</a> format. For ease of use I have re-exported the data as a single CSV file.</p>
<table>
<thead>
<tr>
<th>Column</th>
<th>Length</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>7-8</td>
<td>Postcode</td>
</tr>
<tr>
<td>2</td>
<td>1</td>
<td>Active</td>
</tr>
<tr>
<td>3</td>
<td>6</td>
<td>OSI Easting (X)</td>
</tr>
<tr>
<td>4</td>
<td>6</td>
<td>OSI Northing (Y)</td>
</tr>
</tbody>
</table>
<p><a href="http://geo.jamiethompson.co.uk/download/nisra_cpd_points_may08.csv.zip">Download the CSV</a></p>
<p>Reproduced under the terms of the Click-Use PSI Licence.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/30/code-point-open-northern-ireland-addendum/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>The Problem With Code-Point Open From Ordnance Survey</title>
		<link>http://jamiethompson.co.uk/web/2010/05/29/the-problem-with-code-point-open-from-ordnance-survey/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/29/the-problem-with-code-point-open-from-ordnance-survey/#comments</comments>
		<pubDate>Fri, 28 May 2010 23:17:43 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[postcode]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=512</guid>
		<description><![CDATA[
Before I begin, let me just say that decision of Ordnance Survey to release a whole bunch of their data into the public domain is a massive leap in the right direction.  The number of freely available datasets is vast, but what I&#8217;m most interested in is the Code-Point Open dataset.
Code-Point Open purports to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/os_opendata.jpg" alt="OS Code-Point Open Data" title="OS Code-Point Open Data" width="530" height="190" class="alignnone size-full wp-image-524" /></p>
<p>Before I begin, let me just say that decision of Ordnance Survey to release a whole bunch of their data into the public domain is a massive leap in the right direction.  The number of <a href="https://www.ordnancesurvey.co.uk/opendatadownload/products.html">freely available datasets</a> is vast, but what I&#8217;m most interested in is the <a href="http://www.ordnancesurvey.co.uk/oswebsite/products/code-point-open/index.html">Code-Point Open</a> dataset.</p>
<p>Code-Point Open purports to be a dataset containing the geographical location of every postcode unit in the United Kingdom. Released into the public domain under a licence compatible with the Creative Commons Attribution 3.0 Licence, it sounds like exactly what we&#8217;ve all been waiting/campaigning for since literally forever. Postcode geodata without the Royal Mail PAF file price tag.</p>
<h2>Too Good to be True?</h2>
<p>Unfortunately yes. The Code-Point Open dataset is advertised with the bold statement that <a href="http://www.ordnancesurvey.co.uk/oswebsite/products/code-point-open/index.html">&#8220;Code-Point Open locates every postcode unit in the UK with precision&#8221;</a>. Unfortunately this is simply untrue, and as much as it pains me to point this out, they&#8217;ve fallen at the first hurdle. The reason? Northern Ireland, The Channel Islands and The Isle of Man are all missing.</p>
<p>They immediately go on to state:</p>
<blockquote><p>There are approximately 1.7 million postcode units in England, Scotland and Wales. Each postcode unit, such as KY12 8UP or PO14 2RS, contains an average of fifteen adjoining addresses.</p>
<p>Northern Ireland postcodes are not available with Code-Point Open.</p></blockquote>
<p>The omission of Channel Islands and The Isle of Man is forgiveable. Technically they&#8217;re not a part of the UK even though they&#8217;re covered by Royal Mail&#8217;s postcode system. There is absolutely no way however that Code-Point Open can be deemed a full &#8220;UK&#8221; dataset with Northern Ireland (BT postcodes) missing.</p>
<p>For those of you for whom geography is not a strong-point, let me clarify (political correctness aside). England + Scotland + Wales == Great Britain. Great Britain + Northern Ireland == The United Kingdom.</p>
<p>Let&#8217;s take a look at how the Open offering stacks up against the commercial product</p>
<table>
<thead>
<tr>
<th>Data element</th>
<th>Code-Point Open</th>
<th>Code-Point</th>
</tr>
</thead>
<tbody>
<tr>
<td>Coverage</td>
<td align="center">GB</td>
<td align="center">UK</td>
</tr>
<tr>
<td>Cost</td>
<td align="center">Free</td>
<td align="center">£5,852.75*</td>
</tr>
<tr>
<td  >Postcode unit</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Eastings</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Northings</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Positional quality indicator</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >PO box indicator</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Total number of delivery points</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Delivery points</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Domestic delivery points</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Non-domestic delivery points</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >PO box delivery points</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Matched address premises</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Unmatched delivery points</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
<tr>
<td  >NHS regional health authority code</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >NHS health authority code</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Country code</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Administrative county code</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Administrative district code</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Administrative ward code</td>
<td align="center">√</td>
<td align="center">√</td>
</tr>
<tr>
<td  >Postcode type</td>
<td align="center">&nbsp;</td>
<td align="center">√</td>
</tr>
</tbody>
</table>
<p>* £5,852.75 is based on the 101+ terminal licence (which would be the licence required for web use and comes without a discount for non-commercial use)</p>
<h2>In Conclusion</h2>
<p>In my opinion Code-Point Open is little more than a token effort. Code-Point Open <em>can</em> be used to freely and legally locate postcodes in England, Scotland and Wales. Channel Islands (JE and GY), Isle of Man (IM) and Northern Ireland (BT) postcodes are all entirely missing from the dataset, and for this reason It is not a viable option for commercial use or any application where you don&#8217;t want to exclude a sizeable portion of the UK population (just over 2 million people according by my Wikipedia based caclulations)</p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/29/the-problem-with-code-point-open-from-ordnance-survey/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Creating MySQL Dates From Integer day, month and year columns</title>
		<link>http://jamiethompson.co.uk/web/2010/05/21/creating-mysql-dates-from-integer-day-month-and-year-columns/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/21/creating-mysql-dates-from-integer-day-month-and-year-columns/#comments</comments>
		<pubDate>Fri, 21 May 2010 19:00:17 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=467</guid>
		<description><![CDATA[Granted, this is hardly a common occurrence, but recently I&#8217;ve had need to work with a database table that for historical reasons stores dates in three separate integer columns, one each for day, month and year. The need for special intervention here depends very much on your data, and I&#8217;m assuming that if you&#8217;re reading [...]]]></description>
			<content:encoded><![CDATA[<p>Granted, this is hardly a common occurrence, but recently I&#8217;ve had need to work with a database table that for historical reasons stores dates in three separate integer columns, one each for day, month and year. The need for special intervention here depends very much on your data, and I&#8217;m assuming that if you&#8217;re reading this your powerless the change the actual data structure, otherwise you would. And that&#8217;s okay.</p>
<p>If your year columns are YYYY and your month and day columns are zero padded then your solution is an easy one. Simply concatenate the values together using MySQL&#8217;s CONCAT_WS function (concatenate with separator).</p>
<pre class="brush: sql">
SELECT CONCAT_WS('-', '2001', '01','31')
--> '2001-01-31'
</pre>
<p>If this isn&#8217;t the case you could deal with the problem in code, using PHPs famously forgiving strtotime function for example, but my <abbr title="Obsessive Compulsive Disorder">OCD</abbr> got the better of me and I decided to revisit MySQL&#8217;s built in <a href="http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html">date and time functions</a></p>
<h2>An Elegant Solution</h2>
<p>The solution I found is to use the STR_TO_DATE function with the CONCAT_WS function. That way, even if the date parts aren&#8217;t correctly formatted as in the following example (2 digit year, 1 digit month), STR_TO_DATE will correctly interpret the string &#8216;1-1-31&#8242; and return a datetime value of &#8216;2001-01-31&#8242;. This also has the advantage of being an actual DATETIME value rather than a string.</p>
<pre class="brush: sql">
SELECT STR_TO_DATE(CONCAT_WS('-',1,1,31),'%Y-%m-%d') AS date
--> '2001-01-31'
</pre>
<p>Obviously, this is a solution to a problem that shouldn&#8217;t exist, but that&#8217;s just how we roll.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/21/creating-mysql-dates-from-integer-day-month-and-year-columns/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Yoda Syntax &#8211; A Backwards Design Pattern for If Statements</title>
		<link>http://jamiethompson.co.uk/web/2010/05/20/yoda-syntax-a-php-design-pattern-for-if-statements/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/20/yoda-syntax-a-php-design-pattern-for-if-statements/#comments</comments>
		<pubDate>Thu, 20 May 2010 15:00:58 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=483</guid>
		<description><![CDATA[
Sometimes the penny drops and you realise there&#8217;s a childishly simple solution to a problem that&#8217;s been bugging you for years. And no, I&#8217;m not talking about my wife, I&#8217;m talking about Yoda Syntax.
Have you ever spent far too long hunting down an impossible bug in your PHP only to eventually track it down to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/yoda_syntax.jpg" alt="Yoda Syntax" title="Yoda Syntax" width="530" height="190" class="alignnone size-full wp-image-486" /></p>
<p>Sometimes the penny drops and you realise there&#8217;s a childishly simple solution to a problem that&#8217;s been bugging you for years. And no, I&#8217;m not talking about my wife, I&#8217;m talking about Yoda Syntax.</p>
<p>Have you ever spent far too long hunting down an impossible bug in your PHP only to eventually track it down to a typo in an if statement. Chances are it was a misplaced &#8216;=&#8217;.</p>
<h2>Named must your fail be before banish it you can</h2>
<p>We all do it, and more often than we&#8217;d probably like to admit. Unless you don&#8217;t, in which case go pat yourself on the back, you&#8217;re a PHP rockstar. But as a simplified example say you wanted to write the following rather pointless function:</p>
<pre class="brush: php">
function is_it_red($colour) {
    if ($colour == 'red') {
         return true;
    }
}
</pre>
<p>but what you ended up writing was</p>
<pre class="brush: php">
function is_it_red($colour) {
    if ($colour = 'red') {
         return true;
    }
}
</pre>
<p>And as you know, whatever you pass into the second function (because you&#8217;re accidentally performing a variable assignment rather than testing for equality) it will return true.<br />
Obviously this is an oversimplified example, but typos like this nestled inside large classes can prove hair-removingly difficult to track down.</p>
<h2>Help you I can, yes</h2>
<p>The solution to this is simply to alter the way you write if statements:</p>
<pre class="brush: php">
function is_it_red($colour) {
    if ('red' == $colour) {
         return true;
    }
}
</pre>
<p>It looks odd, yeah, and you might have seen other people writing their if statements backwards in the past and wondered why. But the benefit of this is striking, and so simple that I&#8217;m left wondering why I never thought of it before.</p>
<p>Quite simply, if you make a typo and write the following:</p>
<pre class="brush: php">
function is_it_red($colour) {
    if ('red' = $colour) {
         return true;
    }
}
</pre>
<p>You will cause a big nasty syntax error that you simply cannot fail to notice.</p>
<p><strong>Parse error: syntax error, unexpected &#8216;=&#8217; in /var/www/vhosts/example.com/httpdocs/what_colour_is_it.php</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/20/yoda-syntax-a-php-design-pattern-for-if-statements/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google Streetview Postcode Thumbnails</title>
		<link>http://jamiethompson.co.uk/web/2010/05/19/google-streetview-postcode-thumbnails/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/19/google-streetview-postcode-thumbnails/#comments</comments>
		<pubDate>Wed, 19 May 2010 19:35:23 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[postcode]]></category>
		<category><![CDATA[Streetview]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=457</guid>
		<description><![CDATA[Following my explorations of Google&#8217;s undisclosed Street View Images API, I&#8217;ve put together a handy little webservice that mashes up postcode geodata with the Streetview Images API.
It&#8217;s handy in that it let&#8217;s you directly request a streetview thumbnail with nothing more than a postcode. The format of the request looks like this:

http://geo.jamiethompson.co.uk/streetview/[POSTCODE]_[WIDTH]x[HEIGHT].jpg

As far as the [...]]]></description>
			<content:encoded><![CDATA[<p>Following my explorations of Google&#8217;s undisclosed <a href="/web/2010/05/15/google-streetview-static-api/">Street View Images API,</a> I&#8217;ve put together a handy little webservice that mashes up <a href="/projects/2010/04/30/an-open-free-uk-postcode-geocoding-web-service/">postcode geodata</a> with the Streetview Images API.</p>
<p>It&#8217;s handy in that it let&#8217;s you directly request a streetview thumbnail with nothing more than a postcode. The format of the request looks like this:</p>
<p><code></p>
<p>http://geo.jamiethompson.co.uk/streetview/[POSTCODE]_[WIDTH]x[HEIGHT].jpg</p>
<p></code></p>
<p>As far as the postcode goes either strip out the space or escape it. The maximum dimensions are 416 x 208 pixels.</p>
<p><strong>Example:</strong><br />
<a href="http://geo.jamiethompson.co.uk/streetview/SW1W9TQ_416x208.jpg">http://geo.jamiethompson.co.uk/streetview/SW1W9TQ_416&#215;208.jpg</a><br />
<img src="http://geo.jamiethompson.co.uk/streetview/SW1W9TQ_416x208.jpg" /></p>
<p>As you reduce the thumbnail dimensions the image gets centre cropped accordingy. For the least distortion it&#8217;s best to use a very small portion cropped out of the center as Google do with the streetview thumbnails on Google Maps.</p>
<p>I&#8217;m interested in possibly taking this further with canvas and JavaScript. I&#8217;m fairly sure that if  the maths behind it were figured out you could, via cylindrical projection, un-distort the panorama to provide a natural 360 degree panorama.</p>
<p>That&#8217;s one for the todo list though.</p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/19/google-streetview-postcode-thumbnails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Expanding Short URLs with PHP: expand_url PHP function</title>
		<link>http://jamiethompson.co.uk/web/2010/05/18/expanding-short-urls-with-php-expand_url-php-function/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/18/expanding-short-urls-with-php-expand_url-php-function/#comments</comments>
		<pubDate>Tue, 18 May 2010 01:59:31 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=430</guid>
		<description><![CDATA[
URL shortening services work by redirecting a users browser from the shortened URL to the actual target URL. Some of these services provide means of reversing the shortening process. Some provide API methods for this.
The following function will take a shortened URL, from any service, and return the original URL. As it works by inspecting [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/301.jpg" alt="PHP Short URL Expander Function" title="PHP Short URL Expander Function" width="530" height="190" class="alignnone size-full wp-image-433" /></p>
<p>URL shortening services work by redirecting a users browser from the shortened URL to the actual target URL. Some of these services provide means of reversing the shortening process. <a href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation#/v3/expand">Some</a> provide API methods for this.</p>
<p>The following function will take a shortened URL, from <strong>any</strong> service, and return the original URL. As it works by inspecting the HTTP redirect headers it is 100% service independent, and does away with the need to query the API of services like bit.ly for url expansion.</p>
<pre class="brush: php">
function expand_url($url) {

	// Use curl to fetch the HTTP Headers
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_HEADER, 1); // just the header
	curl_setopt($ch, CURLOPT_NOBODY, 1); // not the body
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$output = curl_exec($ch);
	preg_match('/Location: (.*)\n/', $output, $matches);

	// if no redirect header then return the original url
	return isset($matches[1]) ? $matches[1] : $url;

}
</pre>
<h2>A Simpler PHP 5 Version</h2>
<p>I&#8217;ve used curl for portability. PHP 5 has a built in get_headers function which you could use to simplify the function a little. It would look something like this:</p>
<pre class="brush: php">
function expand_url($url) {

	$h = get_headers($url);

	// if no redirect header then return the original url
	return isset($h['Location']) ? $h['Location'] : $url;

}
</pre>
<div class="pullout">
<h2>Creating Short URLs With PHP</h2>
<p>For creating short urls on the fly with PHP see: <a href="http://tinyurl.com/php-shorten-url">PHP shorten_url function</a> </p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/18/expanding-short-urls-with-php-expand_url-php-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Create Short URLs with PHP: shorten_url PHP Function</title>
		<link>http://jamiethompson.co.uk/web/2010/05/18/create-short-urls-with-php-shorten_url-php-function/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/18/create-short-urls-with-php-shorten_url-php-function/#comments</comments>
		<pubDate>Tue, 18 May 2010 00:45:31 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=416</guid>
		<description><![CDATA[
Do you want to create short urls from within your own PHP application? Most url shortening services provide an API, it&#8217;s how apps like twitter clients provide built-in url shortening. I wrote a small PHP function to provide url shortening from two of the most popular services, is.gd and tinyurl.com. Where&#8217;s bit.ly I hear you [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/tape_measure.jpg" alt="Create Short URLs with PHP" title="tape_measure" width="530" height="190" class="size-full wp-image-425" /></p>
<p>Do you want to create short urls from within your own PHP application? Most url shortening services provide an API, it&#8217;s how apps like twitter clients provide built-in url shortening. I wrote a small PHP function to provide url shortening from two of the most popular services, <a href="http://is.gd">is.gd</a> and <a href="http://tinyurl.com">tinyurl.com</a>. Where&#8217;s <a href="http://bit.ly">bit.ly</a> I hear you ask. Well yeah, sure, that&#8217;s what all the cool kids are using these days, but bit.ly <a href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation#Authentication_and_Shared_Parameters">requires an API key</a>. That&#8217;s not a huge issue, it&#8217;s free. It just doesn&#8217;t sit well with creating a nice portable, drop in a go PHP function. So bit.ly didn&#8217;t get an invite to my super mega PHP function party.</p>
<p>If you want to get some bit.ly action on the go then feel free to modify the code below accordingly. I might update this at some point. I keep thinking I should, but meh.</p>
<pre class="brush: php">
function shorten_url($url,$service='tinyurl.com') {

	// create the request url based on the selected shortening service
	switch ($service) {
	    case 'tinyurl.com':
	       $service_url = 'http://tinyurl.com/api-create.php?url='.urlencode($url);
		   break;
	    case 'is.gd':
	        $service_url = 'http://is.gd/api.php?longurl='.urlencode($url);
	}

	/*
	 * use cURL to fetch the respons
	 * Feel free to swap this out for
	 * $output = file_get_contents($service_url)
	 * if you have fopen wrappers enabled
	 */
	$ch = curl_init($service_url);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	$output = curl_exec($ch);
	curl_close($ch);

	// return false on error
	return strtolower(substr($output,0,5))=='error' ? false : $output;

}
</pre>
<p>The function defaults to tinyurl. Yeah. Interesting choice you&#8217;re thinking, but I&#8217;m old school and that&#8217;s how I roll. I&#8217;ve used curl to make the HTTP requests for the simple fact that when it comes to hosting curl support is enabled more ofthen than fopen wrappers is on (and you need fopen wrappers on to be able to do a file_get_contents on an url). Either way the result is the same. Use whichever method you like.</p>
<div class="pullout">
<h2>Expanding Short URLs With PHP</h2>
<p>For expanding short urls on the fly with PHP see: <a href="http://tinyurl.com/php-expand-url">PHP expand_url function</a> </p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/18/create-short-urls-with-php-shorten_url-php-function/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google Streetview Static API</title>
		<link>http://jamiethompson.co.uk/web/2010/05/15/google-streetview-static-api/</link>
		<comments>http://jamiethompson.co.uk/web/2010/05/15/google-streetview-static-api/#comments</comments>
		<pubDate>Sat, 15 May 2010 21:19:37 +0000</pubDate>
		<dc:creator>Jamie Thompson</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[geocoding]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[postcode]]></category>
		<category><![CDATA[Streetview]]></category>

		<guid isPermaLink="false">http://jamiethompson.co.uk/?p=317</guid>
		<description><![CDATA[It is possible to extract both thumbnails and higher resolution images (tiles) from the Google Streetview service through an unpublished, undocumented API which I will document below. Google have not publicly released this API, but nor have they sought to secure or even obfuscate it in any way. To me, this is about as open [...]]]></description>
			<content:encoded><![CDATA[<p>It is possible to extract both thumbnails and higher resolution images (tiles) from the Google Streetview service through an unpublished, undocumented API which I will document below. Google have not publicly released this API, but nor have they sought to secure or even obfuscate it in any way. To me, this is about as open an invitation as it gets.</p>
<h2>Thumbnails (The Easy Bit)</h2>
<p>You might have noticed that more often than not, when viewing a location on Google Maps nowadays you get a little Streetview thumbnail linking to the appropriate location on Google Streetview. If you&#8217;ve ever wondered if you could get static streetview imaging out Google for your own use then read on.</p>
<p><a href="http://jamiethompson.co.uk/wp-content/uploads/2010/05/maps_sm_thumbnail1.png"><img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/maps_sm_thumbnail1.png" alt="Google Maps Showing Streetview Thumbnail" title="Google Maps Showing Streetview Thumbnail" width="530" height="340" class="alignnone size-full wp-image-320" /></a></p>
<p>Inspection of the image source reveals something quite surprising:<br />
<a href="http://cbk0.google.com/cbk?output=thumbnail&#038;w=90&#038;h=68&#038;ll=51.494966,-0.146674">http://cbk0.google.com/cbk?output=thumbnail&#038;w=90&#038;h=68&#038;ll=51.494966,-0.146674</a></p>
<p><code>http://cbk0.google.com/cbk?output=thumbnail&#038;w=[WIDTH]&#038;h=[HEIGHT]&#038;ll=[LAT,LNG]</code></p>
<p>Not exactly cryptic is it. We have a width, a height and a lat/lng pair. Playing with the values of width and height you will find the maximum dimensions available are 416&#215;208 pixels, giving you a full, albeit small, 360 degree panorama of your desired location. You can play with the coordinates too but specifying a location without a streetview panorama will result in a 404 error.</p>
<p><img src="http://cbk0.google.com/cbk?output=thumbnail&#038;w=416&#038;h=208&#038;ll=51.494966,-0.146674" /></p>
<h2>I think I&#8217;m panoid&#8230;</h2>
<p>Each Streetview panorama is uniquely identified by an panoid. I&#8217;m pretty sure this is a timecode hash but I haven&#8217;t looked into it any further. For the purposes of fetching Streetview images the only important thing to consider is that these are unique ids.</p>
<p>If you&#8217;re like me, you&#8217;ve been looking at the example above and wondering what other output types there are besides &#8216;thumbnail&#8217;. One of the other options is &#8216;xml&#8217;, which returns some handy metadata for a given location. You can use this data to determine if there is a streetview panorama available at your chosen location.</p>
<p><code>http://cbk0.google.com/cbk?output=xml&#038;ll=[LAT,LNG]</code></p>
<p><strong>Example:</strong><br />
<a href="http://cbk0.google.com/cbk?output=xml&#038;ll=51.494966,-0.146674">http://cbk0.google.com/cbk?output=xml&#038;ll=51.494966,-0.146674</a></p>
<pre class="brush: xml">
&lt;panorama&gt;
&lt;data_properties image_width=&quot;13312&quot; image_height=&quot;6656&quot; tile_width=&quot;512&quot; tile_height=&quot;512&quot; pano_id=&quot;sLaiF6Jex7mJmNol7tdOoA&quot; num_zoom_levels=&quot;3&quot; lat=&quot;51.495090&quot; lng=&quot;-0.146971&quot; original_lat=&quot;51.495098&quot; original_lng=&quot;-0.147000&quot;&gt;
&lt;copyright&gt;&#169; 2010 Google&lt;/copyright&gt;
&lt;text&gt;Eccleston Pl&lt;/text&gt;
&lt;region&gt;London, England&lt;/region&gt;
&lt;country&gt;United Kingdom&lt;/country&gt;
&lt;data_flag&gt;1&lt;/data_flag&gt;
&lt;/data_properties&gt;
&lt;projection_properties projection_type=&quot;spherical&quot; pano_yaw_deg=&quot;201.78&quot; tilt_yaw_deg=&quot;92.06&quot; tilt_pitch_deg=&quot;1.75&quot;/&gt;
&lt;annotation_properties&gt;
&lt;link yaw_deg=&quot;204.7&quot; pano_id=&quot;CeutxcyB2V74lfN_fJwRww&quot; road_argb=&quot;0x80ffffff&quot;&gt;
&lt;link_text&gt;Eccleston Pl&lt;/link_text&gt;
&lt;/link&gt;
&lt;link yaw_deg=&quot;24.7&quot; pano_id=&quot;t_mnKSugTLrQTEnJplXQ3A&quot; road_argb=&quot;0x80ffffff&quot;&gt;
&lt;link_text&gt;Eccleston Pl&lt;/link_text&gt;
&lt;/link&gt;
&lt;/annotation_properties&gt;
&lt;/panorama&gt;
</pre>
<p>This returns a lot of data, but for now we&#8217;ll simply concentrate on the <strong>panoid</strong> values. Generally there will be three panoids. One as an attribute of the <strong>data_properties</strong> element and two as the attributes of the two <strong>link</strong> elements of the <strong>annotation_properties</strong> element. As far as I can tell the supplemental two panoids relate to the previous and next panorama on the route.</p>
<p>So in this example we end up with a main panoid of <strong>&#8220;sLaiF6Jex7mJmNol7tdOoA&#8221;</strong></p>
<p>Finally we can plug this value into the thumbnail url as follows:</p>
<p><code>http://cbk0.google.com/cbk?output=thumbnail&#038;w=[WIDTH]&#038;h=[HEIGHT]&#038;panoid=[PID]</code></p>
<p><a href="http://cbk0.google.com/cbk?output=thumbnail&#038;w=416&#038;h=208&#038;panoid=sLaiF6Jex7mJmNol7tdOoA">http://cbk0.google.com/cbk?output=thumbnail&#038;w=416&#038;h=208&#038;panoid=sLaiF6Jex7mJmNol7tdOoA</a></p>
<p><img src="http://cbk0.google.com/cbk?output=thumbnail&#038;w=416&#038;h=208&#038;panoid=sLaiF6Jex7mJmNol7tdOoA" /></p>
<p>Notice how we end up with exactly the same panorama, but at a different offset.</p>
<p>With a little extra work, tying this into the <a href="/projects/2010/04/30/an-open-free-uk-postcode-geocoding-web-service/">Open Postcode Geocoding API</a>, I came up with a nice little wrapper around this accepting a UK postcode and directly returning the corresponding panorama thumbnail. I&#8217;ve added this to my geo webservice and it is callable as follows:</p>
<p><code>http://geo.jamiethompson.co.uk/streetview/[POSTCODE]_[WIDTH]x[HEIGHT].jpg</code></p>
<p><strong>Example</strong><br />
<a href="http://geo.jamiethompson.co.uk/streetview/SW1W9TQ_416x208.jpg">http://geo.jamiethompson.co.uk/streetview/SW1W9TQ_416&#215;208.jpg</a></p>
<h2>The high detail tiles</h2>
<p>So, you probably noticed some info relating to tiles in the xml data in the previous example. It&#8217;s possible to fetch a set of 512 pixel square tiles at various zoom levels for a given panorama using the following request.</p>
<p><code>http://cbk0.google.com/cbk?output=tile&#038;panoid=[PID]&#038;zoom=[ZOOM]&#038;x=[X]&#038;y=[Y]</code></p>
<p>[X] and [Y] relate to the horizontal and vertical tile positions, while [ZOOM] relates to the zoom level. If the XML data is to be believed there are 3 zoom levels, but I have found there to be 5. The number of X and Y positions increases with each zoom level. These are zero based.</p>
<p><strong>Zoom Level 0:</strong><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/zoom0.png" alt="Example of Streetview Tile Zoom Level 0" title="Example of Streetview Tile Zoom Level 0" width="263" height="263" class="alignnone size-full wp-image-366" /><br />
<a href="http://cbk0.google.com/cbk?output=tile&#038;panoid=sLaiF6Jex7mJmNol7tdOoA&#038;zoom=0&#038;x=0&#038;y=0">Single Tile &#8211; X=0, Y=0</a></p>
<p><strong>Zoom Level 1:</strong><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/zoom1.png" alt="Example of Streetview Tile Zoom Level 1" title="Example of Streetview Tile Zoom Level 1" width="530" height="263" class="alignnone size-full wp-image-367" /><br />
<a href="http://cbk0.google.com/cbk?output=tile&#038;panoid=sLaiF6Jex7mJmNol7tdOoA&#038;zoom=1&#038;x=0&#038;y=0">Tile 1 &#8211; X=0, Y=0</a> <a href="http://cbk0.google.com/cbk?output=tile&#038;panoid=sLaiF6Jex7mJmNol7tdOoA&#038;zoom=1&#038;x=1&#038;y=0">Tile 2 &#8211; X=1, Y=0</a></p>
<p><strong>Zoom Level 2</strong><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/zoom2.png" alt="Example of Streetview Tile Zoom Level 2" title="Example of Streetview Tile Zoom Level 2" width="530" height="263" class="alignnone size-full wp-image-369" /><br />
4 X positions (0-3), 2 Y positions (0-1)</p>
<p><strong>Zoom Level 3</strong><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/zoom3.png" alt="Example of Streetview Tile Zoom Level 3" title="Example of Streetview Tile Zoom Level 3" width="530" height="264" class="alignnone size-full wp-image-370" /><br />
6 X positions (0-5), 3 Y positions (0-2)</p>
<p><strong>Zoom Level 4</strong><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/zoom4.png" alt="Example of Streetview Tile Zoom Level 4" title="Example of Streetview Tile Zoom Level 4" width="530" height="288" class="alignnone size-full wp-image-371" /><br />
13 X positions (0-12), 7 Y positions (0-6)</p>
<p><strong>Zoom Level 5</strong><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/zoom5.png" alt="Example of Streetview Tile Zoom Level 5" title="Example of Streetview Tile Zoom Level 5" width="530" height="268" class="alignnone size-full wp-image-372" /><br />
26 X positions (0-25), 13 Y positions (0-12)</p>
<h2>Demo</h2>
<p>I&#8217;ve put together a very quick and dirty demo page that displays the  tiles re-assembled for any given UK postcode. Be warned, at zoom level 5 this will download 338 512&#215;512 pixel tiles, roughly 7-8MB.</p>
<p><a href="http://geo.jamiethompson.co.uk/streetview_tiles.php?postcode=SW1W+9TQ&#038;zoom=3"><br />
<img src="http://jamiethompson.co.uk/wp-content/uploads/2010/05/tile_viewer_demo.jpg" alt="Google Streetview Tile Viewer Demo" title="Google Streetview Tile Viewer Demo" width="530" height="264" class="alignnone size-full wp-image-364" /><br />
</a></p>
<p><a href="http://geo.jamiethompson.co.uk/streetview_tiles.php?postcode=SW1W+9TQ&#038;zoom=3">View the demo here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jamiethompson.co.uk/web/2010/05/15/google-streetview-static-api/feed/</wfw:commentRss>
		<slash:comments>55</slash:comments>
		</item>
	</channel>
</rss>

