<?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>The choreography of color and code &#187; Actionscript / Flash</title>
	<atom:link href="http://www.quietless.com/kitchen/category/actionscript-flash/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.quietless.com/kitchen</link>
	<description>The personal writings &#38; experiments of Stephen Braitsch</description>
	<lastBuildDate>Mon, 16 Jan 2012 04:59:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Extract EXIF data using PHP to display GPS-tagged Images in Google Maps</title>
		<link>http://www.quietless.com/kitchen/extract-exif-data-using-php-to-display-gps-tagged-images-in-google-maps/</link>
		<comments>http://www.quietless.com/kitchen/extract-exif-data-using-php-to-display-gps-tagged-images-in-google-maps/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 03:51:16 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/?p=373</guid>
		<description><![CDATA[While cycling around the city this past weekend with my girlfriend I shot a couple quick photos with my iPhone to play with some of the encoded EXIF/GPS data for an upcoming project I am working on. After creating some quick thumbnails, I built the following Google Maps prototype to display the images where I [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fextract-exif-data-using-php-to-display-gps-tagged-images-in-google-maps%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fextract-exif-data-using-php-to-display-gps-tagged-images-in-google-maps%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>While cycling around the city this past weekend with my girlfriend I shot a couple quick photos with my iPhone to play with some of the encoded EXIF/GPS data for an upcoming project I am working on. After creating some quick thumbnails, I built the following Google Maps prototype to display the images where I photographed them extracting the GPS data with a PHP script I have running on the server.</p>
<p><a title="Extract EXIF data using PHP to display GPS-tagged Images in Google Maps" rel="shadowbox;width=1200;height=500;" href="http://www.quietless.com/php/gmaps-gps-images/GoogleMapImageGPS.swf"><img src="http://www.quietless.com/kitchen/wp-content/uploads/2010/01/gmap-gps-cycling.jpg" alt="" /></a></p>
<p>In the process of building this simple example I came across a strange phenomenon where the GPS data wasn&#8217;t being preserved if the original iPhone image was altered in any way. This was happening whenever I saved an edited version of the image in Photoshop CS4 including the creation of a thumbail. <strong><em>Even with the preserve metadata flag selected when saving for web</em></strong>.<br />
<span id="more-373"></span><br />
This was especially annoying because I typically like to use the popular <a href="http://www.nevercenter.com/camerabag/">CameraBag</a> app to easily treat my images before saving them on the phone. An <a href=" http://www.nevercenter.com/camerabag/support/?helptext=exif.txt#text">explanation from their website</a> suggests that Apple does not allow third party applications to preserve the EXIF data on save. Seriously? Not sure if this is true although a very quick search through Apple&#8217;s iPhone dev portal hasn&#8217;t yielded any suggestions one way or the other.</p>
<p>Nonetheless, Apple&#8217;s own photo editing application Aperture <strong>does</strong> preserve the EXIF data when exporting out a version however this is a less than optimal solution as I find cropping and exporting batch sequences of thumbnails to a be a clumsy and tedious operation in Aperture.</p>
<p>So what to do? After some searching for a solution I came across Phil Harvey&#8217;s impressive ExifTool which can read/write/copy image metadata across files ala the command line.</p>
<p>After going <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/">here</a> and installing the package and adding it to my path I can run the following script and copy the GPS data from my source iPhone image1.jpg to my treated version or thumbnail image2.jpg.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">exiftool -overwrite_original <span style="color: #660033;">-tagsfromfile</span> image1.jpg -gps:all image2.jpg</pre></div></div>

<p>Awesome, and there are a whole list of tags, arguments, etc that you can pass into the tool all outlined in the <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/exiftool_pod.html#copying_examples">documentation</a>. One thing to note though is that I have been unsuccessful in copying over the data that describes when the source image was created &amp; last modified. Having tried all of the following commands without success I&#8217;m still searching for a solution to copy the timestamp over. If anyone has any ideas I&#8217;d love to hear how you did it.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># none of these worked for me...</span>
exiftool -overwrite_original <span style="color: #660033;">-tagsfromfile</span> image1.jpg -all:all image2.jpg
exiftool -overwrite_original <span style="color: #660033;">-tagsfromfile</span> image1.jpg <span style="color: #660033;">-createdate</span> image2.jpg
<span style="color: #666666; font-style: italic;"># attempt to alter the existing date by a few hours...</span>
exiftool -overwrite_original -createdate+=<span style="color: #000000;">3</span> image2.jpg
exiftool -overwrite_original -alldates+=<span style="color: #000000;">1</span>:<span style="color: #000000;">30</span> image2.jpg</pre></div></div>

<p>So after treating the images and banging out some thumbnails, I added the GPS data back in via the ExifTool and pushed everything up my server to try working with the metadata inside of Flash.</p>
<p>The larger project that I am building this prototype for will require the image data to come to Flash via a DB which is why I wrote up a PHP solution instead of reading the image headers right out of the jpeg file using the methods of the AS3 ByteArray.</p>
<p>In my test case here I am communicating with the backend using AMFPHP and wrote a simple service class that includes the main ExifReader class, collects all the EXIF data and sends the results back to Flash.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> AMFDirectoryReader<span style="color: #009900;">&#123;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
   <span style="color: #666666; font-style: italic;">// relative path to the ExifReader script //</span>
     <span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'../../php/gmaps-gps-images/ExifReader.php'</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>    
&nbsp;
   <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getEXIFImageData<span style="color: #009900;">&#40;</span><span style="color: #000088;">$args</span><span style="color: #009900;">&#41;</span>
   <span style="color: #009900;">&#123;</span>
     <span style="color: #000088;">$target</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
     <span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$args</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #000088;">$exif</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ExifReader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_file</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$target</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$exif</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">readImage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$target</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>        
     <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_dir</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$target</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #000088;">$exif</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">readDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$target</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
     <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ERROR: Target Does Not Exist'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>     
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>I can then call getEXIFImageData() from Flash using my <a href="http://github.com/braitsch/internal/blob/master/code/com/quietless/remoting/RemotingCall.as">RemotingCall</a> class passing in the $target file or directory I want to read and an array of strings that describe what metadata tags I want to get back.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">display</span>.<span style="color: #006600;">Sprite</span>;
<span style="color: #0066CC;">import</span> com.<span style="color: #006600;">quietless</span>.<span style="color: #006600;">remoting</span>.<span style="color: #006600;">RemotingCall</span>;
<span style="color: #0066CC;">import</span> com.<span style="color: #006600;">quietless</span>.<span style="color: #006600;">events</span>.<span style="color: #006600;">HTTPRequestEvent</span>;
&nbsp;
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AppMain <span style="color: #0066CC;">extends</span> Sprite <span style="color: #66cc66;">&#123;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _rc	        :RemotingCall;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _params	:<span style="color: #0066CC;">Array</span> = <span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'gps'</span>, <span style="color: #ff0000;">'date'</span>, <span style="color: #ff0000;">'size'</span><span style="color: #66cc66;">&#93;</span>;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">_target</span>	:<span style="color: #0066CC;">String</span> = <span style="color: #ff0000;">'../../php/gmaps-gps-images/thumbs'</span>;
&nbsp;
   <span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> AppMain<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
   <span style="color: #66cc66;">&#123;</span>		
     _rc = <span style="color: #000000; font-weight: bold;">new</span> RemotingCall<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'http://quietless.com/amfphp/gateway.php'</span><span style="color: #66cc66;">&#41;</span>;
     _rc.<span style="color: #0066CC;">call</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'AMFDirectoryReader'</span>, <span style="color: #ff0000;">'getEXIFImageData'</span>, <span style="color: #66cc66;">&#91;</span><span style="color: #0066CC;">_target</span>, _params.<span style="color: #0066CC;">join</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>;
     _rc.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>HTTPRequestEvent.<span style="color: #006600;">COMPLETE</span>, onRequestComplete<span style="color: #66cc66;">&#41;</span>;
   <span style="color: #66cc66;">&#125;</span>
&nbsp;
   <span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onRequestComplete<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>:HTTPRequestEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
   <span style="color: #66cc66;">&#123;</span>
     <span style="color: #000000; font-weight: bold;">var</span> exif:<span style="color: #0066CC;">Array</span> = <span style="color: #0066CC;">e</span>.<span style="color: #0066CC;">target</span>.<span style="color: #006600;">response</span>;
   <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>The real work happens inside of ExifReader where the target image or all images in a target directory are read using calls to <a href="http://php.net/manual/en/function.exif-read-data.php">exif_read_data()</a>. Currently the class only supports the $params arguments &#8216;gps&#8217;, &#8216;date&#8217;, &#8216;size&#8217; but if you take a look at what&#8217;s going on and reference the method&#8217;s <a href="http://php.net/manual/en/function.exif-read-data.php">man page</a> you can easily extend this to send back what you need.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ExifReader<span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
  * Returns an array of EXIF data objecta for all jpgs in the target directory 
  **/</span>	
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> readDirectory<span style="color: #009900;">&#40;</span><span style="color: #000088;">$dir</span><span style="color: #339933;">,</span> <span style="color: #000088;">$props</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// $dir points to this directory from amfphp //</span>
    <span style="color: #000088;">$files</span> <span style="color: #339933;">=</span> <span style="color: #990000;">scandir</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$dir</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$images</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #666666; font-style: italic;">// loop over the files array and look for images</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$files</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">stristr</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$files</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// if the jpeg has gps data add it to the images array //	</span>
      <span style="color: #000088;">$img</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">readImage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$dir</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$files</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$props</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$img</span><span style="color: #009900;">&#41;</span> <span style="color: #990000;">array_push</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$images</span><span style="color: #339933;">,</span> <span style="color: #000088;">$img</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$images</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Returns the EXIF data object of a single image 
**/</span>	
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> readImage<span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #339933;">,</span> <span style="color: #000088;">$props</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$exif</span> <span style="color: #339933;">=</span> <span style="color: #990000;">exif_read_data</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$exif</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'FILE'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'FileName'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$props</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$val</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>				
  <span style="color: #666666; font-style: italic;">// return an array [lat, lng] //</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$val</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'gps'</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'gps'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getGPS</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #666666; font-style: italic;">// return date value in milliseconds //</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$val</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'date'</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'date'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'FILE'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'FileDateTime'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">*</span><span style="color: #cc66cc;">1000</span><span style="color: #339933;">;</span>
  <span style="color: #666666; font-style: italic;">// return size in kilobytes //	</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$val</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'size'</span><span style="color: #009900;">&#41;</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'size'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">floor</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'FILE'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'FileSize'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">/</span> <span style="color: #cc66cc;">1024</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">10</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot;KB&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$data</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>	<span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
* Returns GPS latitude &amp; longitude as decimal values
**/</span>	
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> getGPS<span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$exif</span> <span style="color: #339933;">=</span> <span style="color: #990000;">exif_read_data</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$exif</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$lat</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPS'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPSLatitude'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> 
      <span style="color: #000088;">$log</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPS'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPSLongitude'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$lat</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #000088;">$log</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
  <span style="color: #666666; font-style: italic;">// latitude values //</span>
      <span style="color: #000088;">$lat_degrees</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">divide</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lat</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$lat_minutes</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">divide</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lat</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$lat_seconds</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">divide</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lat</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$lat_hemi</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPS'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPSLatitudeRef'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// longitude values //</span>
      <span style="color: #000088;">$log_degrees</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">divide</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$log</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$log_minutes</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">divide</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$log</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$log_seconds</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">divide</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$log</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$log_hemi</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$exif</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPS'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'GPSLongitudeRef'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$lat_decimal</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toDecimal</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lat_degrees</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lat_minutes</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lat_seconds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$lat_hemi</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$log_decimal</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">toDecimal</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$log_degrees</span><span style="color: #339933;">,</span> <span style="color: #000088;">$log_minutes</span><span style="color: #339933;">,</span> <span style="color: #000088;">$log_seconds</span><span style="color: #339933;">,</span> <span style="color: #000088;">$log_hemi</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$lat_decimal</span><span style="color: #339933;">,</span> <span style="color: #000088;">$log_decimal</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>	<span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span>  <span style="color: #000000; font-weight: bold;">function</span> toDecimal<span style="color: #009900;">&#40;</span><span style="color: #000088;">$deg</span><span style="color: #339933;">,</span> <span style="color: #000088;">$min</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sec</span><span style="color: #339933;">,</span> <span style="color: #000088;">$hemi</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$d</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$deg</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$min</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">60</span> <span style="color: #339933;">+</span> <span style="color: #000088;">$sec</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">3600</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$hemi</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'S'</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$hemi</span><span style="color: #339933;">==</span><span style="color: #0000ff;">'W'</span><span style="color: #009900;">&#41;</span> ? <span style="color: #000088;">$d</span><span style="color: #339933;">*=-</span><span style="color: #cc66cc;">1</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$d</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> divide<span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// evaluate the string fraction and return a float //	</span>
    <span style="color: #000088;">$e</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$a</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #666666; font-style: italic;">// prevent division by zero //</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #000088;">$e</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>	<span style="color: #b1b100;">else</span><span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$e</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">/</span> <span style="color: #000088;">$e</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>At some point in the future I&#8217;d like to write an elegant way to load a batch of thumbnails and just extract the image metadata right from within Flash. This solution does allow you to read the image tags first though before you load them, ideal for querying a DB to collect a result set of images that meet a specific requirement say like falling within a coordinate boundary, before actually loading them into Flash.  </p>
<p><a href='http://www.quietless.com/kitchen/wp-content/uploads/2010/01/gmaps-source.zip'>As always downloads of the above classes.</a><br />
Comment and suggestions are most welcome.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/extract-exif-data-using-php-to-display-gps-tagged-images-in-google-maps/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Dynamically Create an Image in Flash and Save it to the Desktop or Server</title>
		<link>http://www.quietless.com/kitchen/dynamically-create-an-image-in-flash-and-save-it-to-the-desktop-or-server/</link>
		<comments>http://www.quietless.com/kitchen/dynamically-create-an-image-in-flash-and-save-it-to-the-desktop-or-server/#comments</comments>
		<pubDate>Fri, 11 Dec 2009 23:10:29 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/?p=321</guid>
		<description><![CDATA[This is an update to my earlier post where I demonstrated how to dynamically generate an image of a DisplayObject in Flash and push it up to the server using PHP. I&#8217;ve cleaned up and extended the code here to now allow you to also save an image to the desktop using the new save( [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fdynamically-create-an-image-in-flash-and-save-it-to-the-desktop-or-server%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fdynamically-create-an-image-in-flash-and-save-it-to-the-desktop-or-server%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>This is an update to my <a href="http://www.quietless.com/kitchen/upload-bitmapdata-snapshot-to-server-in-as3/">earlier post</a> where I demonstrated how to dynamically generate an image of a DisplayObject in Flash and push it up to the server using PHP. I&#8217;ve cleaned up and extended the code here to now allow you to also save an image to the desktop using the new save( ) method of the FileReference class introduced in Flash Player 10.</p>
<p><a href="http://www.quietless.com/kitchen/wp-content/uploads/2009/12/bitmap-snapshot.swf" rel="shadowbox;width=800;height=550;" title="Generate an Image from Flash and Save it to the Desktop or Remote Server"><img src="http://www.quietless.com/kitchen/wp-content/uploads/2009/12/bitmap-snapshot.jpg" alt="bitmap-snapshot-demo" title="bitmap-snapshot-demo" /></a></p>
<p>To use this class <a href="http://www.quietless.com/kitchen/wp-content/uploads/2009/12/bitmap-snapshot.zip">download the source files</a> and create a new BitmapSnapshot object passing in the DisplayObject you want to create an image of as well as an optional file name, width and height. If width and height are omitted BitmapSnapshot will use the full width and height of the object you are passing in.</p>
<p>Note : BitmapSnapshot will generate a jpg or a png based on the extension of the filename you pass in.<br />
The default output will be a png because it&#8217;s encoding algorithm is much faster than that of jpeg&#8217;s.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> saveToDesktop<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
<span style="color: #000000; font-weight: bold;">var</span> img.<span style="color: #006600;">BitmapSnapshot</span> = <span style="color: #000000; font-weight: bold;">new</span> BitmapSnapshot<span style="color: #66cc66;">&#40;</span>_canvas, _filename<span style="color: #66cc66;">&#41;</span>;
    img.<span style="color: #006600;">saveToDesktop</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;			
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> saveOnServer<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
<span style="color: #000000; font-weight: bold;">var</span> img:BitmapSnapshot = <span style="color: #000000; font-weight: bold;">new</span> BitmapSnapshot<span style="color: #66cc66;">&#40;</span>_canvas, _filename<span style="color: #66cc66;">&#41;</span>;
    img.<span style="color: #006600;">saveOnServer</span><span style="color: #66cc66;">&#40;</span>_phpscript, _destination<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>A note on dependencies : BitmapSnapshot does rely on the fantastic jpeg and png encoder classes written by <a href="http://www.kaourantin.net/">Tinic Uro</a> as part of the <a href="http://code.google.com/p/as3corelib/">AS3CoreLibrary</a>. These files are included in the &#8216;libs&#8217; directory along with BitmapSnapshot so be sure this folder is in your class path when you go to compile. </p>
<p>To see the generated image saved to the server, be sure to clear your cache and <a href="http://quietless.com/kitchen/wp-content/uploads/2009/12/bitmap-snapshots/colored-balls.png">view the image here</a>.</p>
<p>As always please leave any questions or problems in the comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/dynamically-create-an-image-in-flash-and-save-it-to-the-desktop-or-server/feed/</wfw:commentRss>
		<slash:comments>38</slash:comments>
		</item>
		<item>
		<title>Easy Full-Screen Gradients in Flash &#8211; AS3</title>
		<link>http://www.quietless.com/kitchen/easy-full-screen-gradients-in-flash-as3/</link>
		<comments>http://www.quietless.com/kitchen/easy-full-screen-gradients-in-flash-as3/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 19:17:49 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/?p=82</guid>
		<description><![CDATA[Here&#8217;s a handy class that takes an array of hex values and creates a full screen radial or linear gradient that automatically scales to the width and height of the screen. Implementation is simple. // create an array of string hex values var colors:Array = &#91;'0xFFFFFF', '0xF57E04', '0xC64D18', '0xA95354'&#93;; &#160; // constrains width to height, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Feasy-full-screen-gradients-in-flash-as3%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Feasy-full-screen-gradients-in-flash-as3%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Here&#8217;s a handy class that takes an array of hex values and creates a full screen radial or linear gradient that automatically scales to the width and height of the screen.</p>
<p>Implementation is simple.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">// create an array of string hex values</span>
<span style="color: #000000; font-weight: bold;">var</span> colors:<span style="color: #0066CC;">Array</span> = <span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'0xFFFFFF'</span>, <span style="color: #ff0000;">'0xF57E04'</span>, <span style="color: #ff0000;">'0xC64D18'</span>, <span style="color: #ff0000;">'0xA95354'</span><span style="color: #66cc66;">&#93;</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// constrains width to height, convenient for radial gradients</span>
<span style="color: #808080; font-style: italic;">// to keep them circular, default is true</span>
<span style="color: #000000; font-weight: bold;">var</span> constrain:<span style="color: #0066CC;">Boolean</span> = <span style="color: #000000; font-weight: bold;">true</span>;
&nbsp;
<span style="color: #808080; font-style: italic;">// valid types are FullScreenGradient.RADIAL</span>
<span style="color: #808080; font-style: italic;">// or FullScreenGradient.LINEAR, default is RADIAL</span>
<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">type</span>:<span style="color: #0066CC;">String</span> = FullScreenGradient.<span style="color: #006600;">RADIAL</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">var</span> grad:FullScreenGradient =
--<span style="color: #66cc66;">&amp;</span>gt; <span style="color: #000000; font-weight: bold;">new</span> FullScreenGradient<span style="color: #66cc66;">&#40;</span>colors, <span style="color: #0066CC;">type</span>, constrain<span style="color: #66cc66;">&#41;</span>;
addChild<span style="color: #66cc66;">&#40;</span>grad<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>You can use the tool below to drop in color values using the pickers to preview your gradient and check for &#8216;banding&#8217; which seems to be a weird phenomenon that occurs on linear gradients when Flash attempts to interpolate between color values that are too far apart.</p>
<p><a href="http://www.quietless.com/kitchen/wp-content/uploads/2009/02/fs-gradient-example.swf" rel="shadowbox;width=1000;height=500;" title="Easy Full-Screen Gradients in Flash - AS3"><img src="http://www.quietless.com/kitchen/wp-content/uploads/2009/02/fs-gradient-preview.jpg" alt="" /></a></p>
<p>Enjoy.</p>
<p><a href="http://www.quietless.com/zip/FullScreenGradient.zip">Download the Class File</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/easy-full-screen-gradients-in-flash-as3/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>AS3 Image Batch Loader with PHP Directory Browsing</title>
		<link>http://www.quietless.com/kitchen/as3-image-batch-loader-with-php-directory-browsing/</link>
		<comments>http://www.quietless.com/kitchen/as3-image-batch-loader-with-php-directory-browsing/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 01:50:51 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/?p=42</guid>
		<description><![CDATA[Updated: February 4. 2009 &#8211; Much cleaner implementation with added comments to hopefully help you understand what is going on In this being a utility I have been meaning to improve on for awhile, this post attempts to tackle two tasks that are especially common in Flash Platform development. 1st the need to load in [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fas3-image-batch-loader-with-php-directory-browsing%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fas3-image-batch-loader-with-php-directory-browsing%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><em>Updated: February 4. 2009 &#8211; Much cleaner implementation with added comments to hopefully help you understand what is going on</em></p>
<p>In this being a utility I have been meaning to improve on for awhile, this post attempts to tackle two tasks that are especially common in Flash Platform development. 1st the need to load in a batch of images sequentially and 2nd the ability for Flash to be able to &#8216;see&#8217; inside of a directory on the filesystem and load all the available images within.</p>
<p>As is common knowledge, Flash by itself cannot measure the contents of a directory but PHP conveniently can and report back to Flash its findings. This is all accomplished by loading the included PHP script &#8216;directory-reader.php&#8217; into an AS3 URLLoader object and capturing the variables PHP echoes back to it.</p>
<p>Consider the following:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ImageLoadManager <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">var</span> dr = <span style="color: #000000; font-weight: bold;">new</span> DirectoryReader<span style="color: #66cc66;">&#40;</span>_pathToDirectory,  <span style="color: #ff0000;">'*'</span><span style="color: #66cc66;">&#41;</span>;
   dr.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>HTTPRequestEvent.<span style="color: #006600;">COMPLETE</span>, onDirectoryRead<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>We create a DirectoryReader object and pass into it the path to the directory we want to read <strong><em>relative to the location of the php script on the filesystem.</em></strong> (We&#8217;ll talk about where that script goes in a second). It should be noted that many PHP installations have URL file-access disabled in the server configuration by default which may throw errors if you try to provide absolute URL&#8217;s. You many need to change your config file to get around this or just use a relative URL as the sample files provided do instead.</p>
<p>Since this utility was designed to gather all of the image files from a directory that Flash supports, (jpg, png, and gif), it will do just that if you leave the second parameter blank. If you are interested in seeing every visible file in the directory (not including sub-directories) you can pass in a wildcard flag ( * ) as shown in the example above. <strong><em>Note the array of file names this returns will include non-image filetypes which will throw IO errors if you pass them into the ImageBatchLoader in the next step.</em></strong></p>
<p>After we&#8217;ve created our DirectoryReader we&#8217;ll want to listen for the &#8216;HTTPRequestEvent.COMPLETE&#8217; event that gets fired when the PHP script is successfully executed. In the onDirectoryRead function below we can access the array of file names that came back from PHP through the data property of HTTPRequestEvent object.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onDirectoryRead<span style="color: #66cc66;">&#40;</span>evt:HTTPRequestEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
  _files = evt.<span style="color: #0066CC;">data</span> as <span style="color: #0066CC;">Array</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>We can then take this list of files and pass it into a new ImageBatchLoader object that will naturally go and load up our images.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onDirectoryRead<span style="color: #66cc66;">&#40;</span>evt:HTTPRequestEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
  _files = evt.<span style="color: #0066CC;">data</span> as <span style="color: #0066CC;">Array</span>;
<span style="color: #808080; font-style: italic;">// load a batch of images //</span>
  _loader = <span style="color: #000000; font-weight: bold;">new</span> ImageBatchLoader<span style="color: #66cc66;">&#40;</span>_files, _swfToImages<span style="color: #66cc66;">&#41;</span>;
  _loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ImageBatchEvent.<span style="color: #006600;">IMAGE_PROGRESS</span>, 
   onImageLoadProgress<span style="color: #66cc66;">&#41;</span>;
  _loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ImageBatchEvent.<span style="color: #006600;">BATCH_PROGRESS</span>, 
   onImageBatchProgress<span style="color: #66cc66;">&#41;</span>;
  _loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ImageBatchEvent.<span style="color: #006600;">BATCH_COMPLETE</span>, 
   onImageBatchComplete<span style="color: #66cc66;">&#41;</span>;	
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>An instance of the ImageBatchLoader class expects at least one parameter, an array of file names to load. Once it has this it will load each image one by one and trace out a whole slew of loader event info to the console so you can monitor each image load&#8217;s progress. <em>(Note: To view this output set the debug property of _loader to true)</em> The second parameter is a relative path to the directory where the images to be loaded reside. It should be noted that this path will almost always be different from the path you fed to DirectoryReader since <strong><em>it needs to be relative to the location of the published SWF on the filesystem, NOT the location of the PHP file as we noted above.</em></strong></p>
<p>Of course you can create a list of files names via a remoting call that polls a database or by reading in an XML file. The purpose of this technique to address those situations where you need a fast and lightweight solution to &#8216;peek&#8217; inside a directory and grab however many images are in it.</p>
<p>This can all be accomplished with the following sample of code:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;">package <span style="color: #66cc66;">&#123;</span>
<span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">display</span>.<span style="color: #006600;">Sprite</span>;
<span style="color: #0066CC;">import</span> flash.<span style="color: #006600;">events</span>.<span style="color: #006600;">MouseEvent</span>;
&nbsp;
<span style="color: #0066CC;">import</span> com.<span style="color: #006600;">quietless</span>.<span style="color: #006600;">utils</span>.<span style="color: #006600;">DirectoryReader</span>;
<span style="color: #0066CC;">import</span> com.<span style="color: #006600;">quietless</span>.<span style="color: #006600;">bitmap</span>.<span style="color: #006600;">ImageBatchLoader</span>;
<span style="color: #0066CC;">import</span> com.<span style="color: #006600;">quietless</span>.<span style="color: #006600;">events</span>.<span style="color: #006600;">ImageBatchEvent</span>;
<span style="color: #0066CC;">import</span> com.<span style="color: #006600;">quietless</span>.<span style="color: #006600;">events</span>.<span style="color: #006600;">HTTPRequestEvent</span>;
&nbsp;
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ImageLoadManager <span style="color: #0066CC;">extends</span> Sprite
<span style="color: #66cc66;">&#123;</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _loader:ImageBatchLoader;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _files:<span style="color: #0066CC;">Array</span>; <span style="color: #808080; font-style: italic;">// all files names returned by php //</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _bitmaps:<span style="color: #0066CC;">Array</span>;<span style="color: #808080; font-style: italic;">// all bitmaps successfully loaded //</span>
<span style="color: #808080; font-style: italic;">// path from the published swf to the image folder //</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _swfToImages:<span style="color: #0066CC;">String</span> = <span style="color: #ff0000;">'images/'</span>;	
<span style="color: #808080; font-style: italic;">// path from the php script to the directory you want to browse //	</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _phpToImages:<span style="color: #0066CC;">String</span> = <span style="color: #ff0000;">'../images'</span>;	
&nbsp;
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ImageLoadManager <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">var</span> dr = <span style="color: #000000; font-weight: bold;">new</span> DirectoryReader<span style="color: #66cc66;">&#40;</span>_phpToImages, <span style="color: #ff0000;">'*'</span><span style="color: #66cc66;">&#41;</span>;
   dr.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>HTTPRequestEvent.<span style="color: #006600;">COMPLETE</span>, onDirectoryRead<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onDirectoryRead<span style="color: #66cc66;">&#40;</span>evt:HTTPRequestEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
   _files = evt.<span style="color: #0066CC;">data</span> as <span style="color: #0066CC;">Array</span>;
<span style="color: #808080; font-style: italic;">// load a batch of images //</span>
   _loader = <span style="color: #000000; font-weight: bold;">new</span> ImageBatchLoader<span style="color: #66cc66;">&#40;</span>_files, _swfToImages<span style="color: #66cc66;">&#41;</span>;
   _loader.<span style="color: #006600;">debug</span> = <span style="color: #000000; font-weight: bold;">false</span>;
   _loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ImageBatchEvent.<span style="color: #006600;">IMAGE_PROGRESS</span>, 
   onImageLoadProgress<span style="color: #66cc66;">&#41;</span>;
   _loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ImageBatchEvent.<span style="color: #006600;">BATCH_PROGRESS</span>, 
   onImageBatchProgress<span style="color: #66cc66;">&#41;</span>;
   _loader.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>ImageBatchEvent.<span style="color: #006600;">BATCH_COMPLETE</span>, 
   onImageBatchComplete<span style="color: #66cc66;">&#41;</span>;			    
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onImageLoadProgress<span style="color: #66cc66;">&#40;</span>evt:ImageBatchEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">var</span> bl:<span style="color: #0066CC;">Number</span> = evt.<span style="color: #0066CC;">data</span>.<span style="color: #0066CC;">loaded</span>;
   <span style="color: #000000; font-weight: bold;">var</span> bt:<span style="color: #0066CC;">Number</span> = evt.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">total</span>;
   <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'Loading Image # '</span>+evt.<span style="color: #0066CC;">data</span>.<span style="color: #0066CC;">position</span>+<span style="color: #ff0000;">' : '</span>+bl+<span style="color: #ff0000;">' of
   --&gt; '</span>+bt+<span style="color: #ff0000;">' Bytes Loaded = '</span>+<span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">ceil</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>bl<span style="color: #66cc66;">/</span>bt<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">*</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span>+<span style="color: #ff0000;">' %'</span> <span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onImageBatchProgress<span style="color: #66cc66;">&#40;</span>evt:ImageBatchEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
   <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Successfully Loaded '</span>+evt.<span style="color: #0066CC;">data</span>.<span style="color: #0066CC;">loaded</span>+<span style="color: #ff0000;">' of 
   --&gt; '</span>+evt.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">total</span>+<span style="color: #ff0000;">' Images In This Batch'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> onImageBatchComplete<span style="color: #66cc66;">&#40;</span>evt:ImageBatchEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
   _bitmaps = evt.<span style="color: #0066CC;">data</span> as <span style="color: #0066CC;">Array</span>;
   <span style="color: #000000; font-weight: bold;">var</span> img = _bitmaps<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#93;</span>; 		
   addChild<span style="color: #66cc66;">&#40;</span>img<span style="color: #66cc66;">&#41;</span>;
   <span style="color: #0066CC;">log</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Image Batch Load Complete!!'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>As for the business of where to put the PHP script that can actually read the directory you specify? I have it set as a constant variable inside of the DirectoryReader class:</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #0066CC;">static</span> const PATH_TO_DIRECTORY_READER:<span style="color: #0066CC;">String</span> =
   <span style="color: #ff0000;">'http://localhost:8888/php/directory-reader.php'</span>;</pre></div></div>

<p>My <a href="http://www.mamp.info">Mamp</a> installation points to my project root folder which contains a &#8216;php&#8217; folder (containing &#8216;directory-reader.php&#8217;), an &#8216;images&#8217; folder that contains my images and of course the published swf and an html page. <strong><em>Note you will need to have a server running PHP 5 locally if you want to test the sample files from the Flash IDE.</em></strong></p>
<p>If you have any questions please post in the comments below.</p>
<p><a href="http://www.quietless.com/zip/ImageLoadManager.zip">Sample Files</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/as3-image-batch-loader-with-php-directory-browsing/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Tracy Chapman wins FWA!</title>
		<link>http://www.quietless.com/kitchen/tracy-chapman-wins-fwa/</link>
		<comments>http://www.quietless.com/kitchen/tracy-chapman-wins-fwa/#comments</comments>
		<pubDate>Fri, 19 Dec 2008 18:56:21 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>
		<category><![CDATA[General News]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/?p=38</guid>
		<description><![CDATA[I just got the call from Jason that the site I built for Tracy&#8217;s new album, &#8216;Our Bright Future&#8217; has won the FWA for December 28, 2008! Very special thanks to Jason, Adam, Sanaz and Hampus at Ordinary Kids and of course Tracy and Gretchen for making it happen. What a great Xmas present!!]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Ftracy-chapman-wins-fwa%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Ftracy-chapman-wins-fwa%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I just got the call from Jason that the site I built for Tracy&#8217;s new album, &#8216;Our Bright Future&#8217; has won the <a href="http://www.thefwa.com/">FWA</a> for December 28, 2008! </p>
<p>Very special thanks to Jason, Adam, Sanaz and Hampus at <a href="http://ordinarykids.com/">Ordinary Kids</a> and of course Tracy and Gretchen for making it happen. What a great Xmas present!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/tracy-chapman-wins-fwa/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Transform Tool &#8211; Drag, Scale and Rotate in Flash at Runtime</title>
		<link>http://www.quietless.com/kitchen/transform-tool-drag-scale-and-rotate-at-runtime/</link>
		<comments>http://www.quietless.com/kitchen/transform-tool-drag-scale-and-rotate-at-runtime/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 17:39:30 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/transform-tool-drag-scale-and-rotate-at-runtime/</guid>
		<description><![CDATA[On a recent project I created a Transform Tool similar to the one you might find in a typical CS3 application like Photoshop, Illustrator or Flash. Once you instantiate this tool and and assign it a target, you can easily scale, drag and rotate it around the Stage at runtime. Optional properties include a min [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Ftransform-tool-drag-scale-and-rotate-at-runtime%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Ftransform-tool-drag-scale-and-rotate-at-runtime%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>On a recent project I created a Transform Tool similar to the one you might find in a typical CS3 application like Photoshop, Illustrator or Flash. Once you instantiate this tool and and assign it a target, you can easily scale, drag and rotate it around the Stage at runtime. Optional properties include a min and max scale value, a boundaries Rectangle object to constrain where the target can be dragged and custom scale and rotate handle icons that you can specify via a linked MovieClip in the library.</p>
<p><a href="http://www.quietless.com/kitchen/wp-content/uploads/2008/08/transform-tool.swf" rel="shadowbox;width=575;height=360;" title="Transform Tool - Drag, Scale and Rotate in Flash at Runtime"><img src="http://www.quietless.com/kitchen/wp-content/uploads/2008/08/transform-tool.jpg" alt="TransformTool" /></a></p>
<p>In a future version I will combine scale and rotate into one mode eliminating the need to select between them.</p>
<p><a href="http://www.quietless.com/docs/transform-tool.html">View the documentation here</a><br />
<a href="http://www.quietless.com/zip/TransformTool.zip">View the source files here</a></p>
<p>Update 11/24/09 : This class has been refactored for improved legibility. Also added now is the ability to register specific targets on the stage via an internal _targets array. <a href="http://www.quietless.com/docs/transform-tool.html">See documentation for details.</a></p>
<p>Update 11/24/08 : There was a syntax bug that was confusing placement of the transform handles which subsequently was throwing the selected object off screen at times. This has been fixed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/transform-tool-drag-scale-and-rotate-at-runtime/feed/</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
		<item>
		<title>Upload BitmapData Snapshot to Server in AS3</title>
		<link>http://www.quietless.com/kitchen/upload-bitmapdata-snapshot-to-server-in-as3/</link>
		<comments>http://www.quietless.com/kitchen/upload-bitmapdata-snapshot-to-server-in-as3/#comments</comments>
		<pubDate>Fri, 30 May 2008 18:11:39 +0000</pubDate>
		<dc:creator>Stephen Braitsch</dc:creator>
				<category><![CDATA[Actionscript / Flash]]></category>
		<category><![CDATA[as3]]></category>
		<category><![CDATA[bitmapdata]]></category>
		<category><![CDATA[fileupload]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[snapshot]]></category>

		<guid isPermaLink="false">http://www.quietless.com/kitchen/upload-bitmapdata-snapshot-to-server-in-as3/</guid>
		<description><![CDATA[Note : This class has been updated, you can view the new post here. Here is a very simple wrapper class I wrote last night that allows you to take a BitmapData snapshot of a Display Object on the Stage, convert it to a .png or .jpg and upload it to your server in a [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fupload-bitmapdata-snapshot-to-server-in-as3%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.quietless.com%2Fkitchen%2Fupload-bitmapdata-snapshot-to-server-in-as3%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><em>Note : This class has been updated, <a href="http://www.quietless.com/kitchen/save-an-image-from-flash-to-the-desktop-or-server/">you can view the new post here</a>.</em></p>
<p>Here is a very simple wrapper class I wrote last night that allows you to take a BitmapData snapshot of a Display Object on the Stage, convert it to a .png or .jpg and upload it to your server in a directory you can specify at runtime. All in about 10 lines of code.</p>
<p>The technique is quite simple. You instantiate a new &#8216;DynamicBitmap&#8217; and pass in the target DisplayObject you want to snapshot as well as a string of the filename you want to call it. e.g. &#8216;MyBitmapSnapshot.png&#8217;</p>
<p>In the following example I created two buttons on the stage which snapshot and upload the bitmap separately however you can combine this all into one action if you like.</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _dbmp:DynamicBitmap;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _uploadScript:<span style="color: #0066CC;">String</span> = <span style="color: #ff0000;">'uploads/upload.php'</span>;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _uploadDirectory:<span style="color: #0066CC;">String</span> = <span style="color: #ff0000;">'images/'</span>; <span style="color: #808080; font-style: italic;">// optional //</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">_target</span>; <span style="color: #808080; font-style: italic;">// some display object on the stage //</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> _filename:<span style="color: #0066CC;">String</span> = <span style="color: #ff0000;">'myBitmapSnapshot.png'</span>;
&nbsp;
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ApplicationMain <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
     snapshot_btn.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>MouseEvent.<span style="color: #006600;">CLICK</span>, takeSnapshot<span style="color: #66cc66;">&#41;</span>;
     upload_btn.<span style="color: #006600;">addEventListener</span><span style="color: #66cc66;">&#40;</span>MouseEvent.<span style="color: #006600;">CLICK</span>, uploadSnapshot<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> takeSnapshot<span style="color: #66cc66;">&#40;</span>evt:MouseEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
     _dbmp = <span style="color: #000000; font-weight: bold;">new</span> DynamicBitmap<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">_target</span>, _filename<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> uploadSnapshot<span style="color: #66cc66;">&#40;</span>evt:MouseEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
     _dbmp.<span style="color: #006600;">upload</span><span style="color: #66cc66;">&#40;</span>_uploadscript, _directory<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>Underneath the _target DisplayObject is drawn into a BitmapData object and then based on the file extension you give it in the filename it is converted into either a JPEG or PNG byteArray using the <a href="http://code.google.com/p/as3corelib/">AS3CoreLib</a> encoding classes by <a href="http://www.kaourantin.net/2005/10/png-encoder-in-as3.html">Tinic Uro</a>.</p>
<p>These encoding classes return a raw byteArray which by itself cannot be uploaded to the server as the <a href="http://en.wikipedia.org/wiki/MIME#Multipart_messages">MIME</a> protocol requires precisely defined headers to accompany the raw image data and instruct the server what to do with it.</p>
<p>Enter the URLRequestWrapper class which is a slightly modified version of the UploadPostHelper class written by <a href="http://marstonstudio.com/index.php/2007/08/19/how-to-take-a-snapshot-of-a-flash-movie-and-automatically-upload-the-jpg-to-a-server-in-three-easy-steps">Jonathan Marston</a> which adds in the necessary headers required by the server:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #660033;">--pfhchaivbrmxhcighexxsspxpxhepeea</span>
&nbsp;
Content-Disposition: form-data; <span style="color: #007800;">name</span>=<span style="color: #ff0000;">&quot;Filename&quot;</span>
&nbsp;
myBitmapSnapshot.png
&nbsp;
<span style="color: #660033;">--pfhchaivbrmxhcighexxsspxpxhepeea</span>
&nbsp;
Content-Disposition: form-data; <span style="color: #007800;">name</span>=<span style="color: #ff0000;">&quot;dir&quot;</span>
&nbsp;
images<span style="color: #000000; font-weight: bold;">/</span>
&nbsp;
<span style="color: #660033;">--pfhchaivbrmxhcighexxsspxpxhepeea</span>
&nbsp;
Content-Disposition: form-data; <span style="color: #007800;">name</span>=<span style="color: #ff0000;">&quot;Filedata&quot;</span>; <span style="color: #007800;">filename</span>=<span style="color: #ff0000;">&quot;myBitmapSnapshot.png&quot;</span>
&nbsp;
Content-Type: application<span style="color: #000000; font-weight: bold;">/</span>octet-stream
&nbsp;
PNG</pre></div></div>

<p>The URLRequestWrapper is simply a modified URLRequest with a data property that contains the image data and all the necessary headers required by the server, including the optional destination directory you specified for the image. When this URLRequest is loaded into a URLLoader object it arrives at the server via the global $_POST array.</p>
<p>I&#8217;ve included a simple upload script &#8216;uploads.php&#8217; that looks for a &#8216;dir&#8217; property in the header information which contains the _uploadDirectory variable you specified in Flash. It is entirely optional, if no directory is specified it will install the image in the default directory as specified in the upload.php script. This may prove handy in an application where the you&#8217;d like to be able to change the destination directory of the newly created image at runtime.</p>
<p>Note:  If you specify a directory that does not exist on the server it will be created via the new <a href="http://us.php.net/mkdir">recursive flag</a> introduced in php5. Be sure to have php5 installed and enabled on your server or the script will throw an argument error and possibly not run.</p>
<p><a href='http://www.quietless.com/kitchen/wp-content/uploads/2008/05/bitmapuploader.zip' title='Source Example Files Here'>Source Example Files Here</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.quietless.com/kitchen/upload-bitmapdata-snapshot-to-server-in-as3/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
	</channel>
</rss>

