<?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>andrewfreiday.com</title>
	<atom:link href="http://andrewfreiday.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://andrewfreiday.com</link>
	<description>Useless web programming tips and code snippets</description>
	<lastBuildDate>Mon, 12 Dec 2011 17:04:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Optimizing the PHP MP3 waveform generator</title>
		<link>http://andrewfreiday.com/2011/12/04/optimizing-the-php-mp3-waveform-generator/</link>
		<comments>http://andrewfreiday.com/2011/12/04/optimizing-the-php-mp3-waveform-generator/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 01:06:01 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=175</guid>
		<description><![CDATA[After some great comments in the original PHP MP3 Waveform Generator blog post, I decided to go ahead and do my best to optimize the script as much as possible. This included, as a commenter named Bruce pointed out, that it wasn&#8217;t very efficient on memory to perform a extraction of a large set of [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_10" class="wp-caption alignright" style="width: 260px"><a href="http://andrewfreiday.com/wp-content/uploads/2011/12/waveform.png"><img class="alignleft size-full wp-image-183" style="padding: 5px;" title="Stereo waveform" src="http://andrewfreiday.com/wp-content/uploads/2011/12/waveform.png" alt="" width="250" height="150" /></a><p class="wp-caption-text">Waveform generated using Dancing With Paris&#39; &quot;(Boardwalk)&quot; MP3.</p></div>
<p>After some great comments in the original <a href="http://andrewfreiday.com/2010/04/29/generating-mp3-waveforms-with-php/">PHP MP3 Waveform Generator</a> blog post, I decided to go ahead and do my best to optimize the script as much as possible. This included, as a commenter named Bruce pointed out, that it wasn&#8217;t very efficient on memory to perform a extraction of a large set of amplitude data points for the waveform only to discard them later when drawing on the canvas (given the DETAIL constant setting).</p>
<p>My revised script now estimates the number of amplitude points of the resulting decoded WAV file (data size) and extracts those points while at the same time plotting them onto the canvas. This eliminates the need for a second loop and reduces overall memory and performance.</p>
<p><strong>UPDATE 2012-12-08: I&#8217;ve also added support for stereo (2-channel) waveform processing!</strong></p>
<p><span id="more-175"></span>Based on a couple quick tests, the revised script reduced execution time by 20% and overall memory usage by 15%. Unfortunately the most time consuming portion of the script is still the lame resampling and decoding, but this really is a necessary evil: to take the MP3 and turn it into a usable, processable WAV file.</p>
<p>I also made a separate SVG version of the script which generates an SVG/XML file &#8212; this is definitely more usable for circumstances where you might not know the required dimensions of your image ahead of time. The resulting SVG can be resized any amount and will not lose quality.</p>
<p>In addition to optimizing the script, I&#8217;ve also added support (to both PNG and SVG versions) for generating 2-channel stereo waveforms. This can take a single MP3, split it into both left and right channels, and generate a single image with both waveforms.</p>
<p>These two projects have been uploaded (finally) to my github account:</p>
<p><a href="https://github.com/afreiday/php-waveform-png" target="_blank">php-waveform-png project on github</a></p>
<p><a href="https://github.com/afreiday/php-waveform-svg" target="_blank">php-waveform-svg project on github</a></p>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2011/12/04/optimizing-the-php-mp3-waveform-generator/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>&#8220;phrames&#8221; framework/ORM now on github</title>
		<link>http://andrewfreiday.com/2011/09/04/phrames-frameworkorm-now-on-github/</link>
		<comments>http://andrewfreiday.com/2011/09/04/phrames-frameworkorm-now-on-github/#comments</comments>
		<pubDate>Sun, 04 Sep 2011 23:30:48 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=170</guid>
		<description><![CDATA[While in the midst of readying some fairly large projects at work, I haven&#8217;t had too much time to progress with my last update of my &#8220;phrames&#8221; ORM/framework. However, I am happy to announce (to whoever is willing to listen) that I&#8217;ve published my work to github! I&#8217;m really hoping that, first and foremost, this [...]]]></description>
			<content:encoded><![CDATA[<p>While in the midst of readying some fairly large projects at work, I haven&#8217;t had too much time to progress with my <a href="http://andrewfreiday.com/2011/06/17/further-work-on-a-django-like-php-orm-framework-phrames/">last update of my &#8220;phrames&#8221; ORM/framework</a>. However, I am happy to announce (to whoever is willing to listen) that I&#8217;ve <a href="https://github.com/afreiday/phrames" target="_blank">published my work to github</a>! I&#8217;m really hoping that, first and foremost, this project can gain a little more ground to those that might be interested in it. Progress has been slow and steady, and quite obviously more a personal effort than anything, but I&#8217;ve been loving some of the feedback I&#8217;ve gotten. I believe that if there&#8217;s just 1 person out that that uses my code, contributes to it on github, or even just learns something from what I&#8217;ve offered then mission accomplished.</p>
<p>That being said, I&#8217;ve more been a lone developer for essentially all of my career to date. My experience with version control systems is limited at best, especially on a multi-developer level. I&#8217;ve only ever used it for keeping track of my personal changes/commits and versions, so if you would be so gracious as to make some changes to my project and share them with me, please bear with me while I learn and adjust to these new methods.</p>
<p><strong><a href="https://github.com/afreiday/phrames" target="_blank">Find my project phrames on github</a></strong>!</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2011/09/04/phrames-frameworkorm-now-on-github/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Further work on a django-like PHP ORM framework: &#8220;phrames&#8221;</title>
		<link>http://andrewfreiday.com/2011/06/17/further-work-on-a-django-like-php-orm-framework-phrames/</link>
		<comments>http://andrewfreiday.com/2011/06/17/further-work-on-a-django-like-php-orm-framework-phrames/#comments</comments>
		<pubDate>Fri, 17 Jun 2011 14:27:18 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=148</guid>
		<description><![CDATA[It&#8217;s been a long time since I have last posted and since I have had the time to develop my django-like PHP framework/ORM. However in last few days I was able to crack down and get quite a lot done from where I left off. I last left off considering what my ultimate plan was: [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a long time since I have last posted and since I have had the time to develop my django-like PHP framework/ORM. However in last few days I was able to crack down and get quite a lot done from where I left off.</p>
<p>I last left off considering what my ultimate plan was: do I want to sit and study the entire django codebase and create a line-for-line duplicate? Not really, but I was able to use the source for a lot of reference points. Please keep in mind that, more than a serious project, this iss more about an experiment in exploring some of the deeper functionality in PHP. I haven&#8217;t had a chance to refactor any of my code, so some of it is pure garbage, but I&#8217;ve commented as much as I could that didn&#8217;t seem immediately obvious. If this inspires one person or if one person uses even one class or one method of my code, then mission accomplished!</p>
<p>I&#8217;m now calling my ORM &#8220;phrames&#8221; (as in PHP Framework)&#8230; not original, but among the millions of PHP frameworks it wasn&#8217;t already taken.<span id="more-148"></span></p>
<h2>Models and Field Types</h2>
<p>My first goal of this project was simply to create a <em>lightweight</em> and <em>rapid-development</em> framework similar to Python&#8217;s django. I didn&#8217;t want to create a set of &#8220;rails&#8221; scripts, I didn&#8217;t want to sit and redefine all of my MySQL tables as models. I wanted to be able to whip together some quick ORM-style models and only define what needed to be defined. It doesn&#8217;t have (or need) all of the functionality that django has in its giant feature set.</p>
<p>Defining models is quite similar to django. You don&#8217;t need to define each database table column, you simply specify what your model represents (and, optionally, what the database table name is). Given the following table definitions:</p>
<pre>CREATE TABLE `manufacturers` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(250) DEFAULT NULL,
PRIMARY KEY (`id`)
);

CREATE TABLE `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `manufacturer` int(11) DEFAULT NULL,
  `name` varchar(250) DEFAULT NULL,
  `weight` int(11) DEFAULT NULL,
  `cost` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
);</pre>
<p>You could quickly define the following &#8220;phrames&#8221; models:</p>
<pre>require_once("phrames/Model.class.php");

class Manufacturer extends Model {}

class Product extends Model {}</pre>
<p>and right away you could begin querying these tables (read further below). The Model class will automatically determine what the table name should be (Product class looks for products table). Alternatively, the table name could easily be manually defined:</p>
<pre>class Product extends Model {
  const table_name = "my_products_table";
}</pre>
<p>Further, it is fully possible to quickly create foreign key and one-to-many relationships. These are defined by adding class constants of the table column or pseudo-field names:</p>
<pre>class Manufacturer extends Model {
  const products = "Product:"; // One-to-many field, returns all of the products of this manufacturer
}

class Product extends Model {
  const manufacturer = "Manufacturer"; // Uses the manufacturer table column to reference a Manufacturer object
}</pre>
<p>So now if you had a Product object (again, see section on querying below for how to obtain one), you could easily obtain it&#8217;s manufacturer as an object as well:</p>
<pre>print $some_product-&gt;manufacturer-&gt;name;</pre>
<p>Likewise, if you have a given manufacturer, you could easily obtain all of it&#8217;s products (however, it is required that the &#8216;manufacturer&#8217; foreign key definition of Product is defined, so it knows where to look):</p>
<pre>foreach($some_manufacturer-&gt;products as $product) {
  print $product-&gt;name . "&lt;br /&gt;";
}</pre>
<p>I have also added ability to support many-to-many relations between tables. Here is a new example:</p>
<pre>class Topping extends Model { }

class PizzaTopping extends Model {
  const the_topping = "Topping";
  const the_pizza = "Pizza";
}

class Pizza extends Model {
  const toppings = "Topping:PizzaTopping";
}</pre>
<p>In this example, a many-to-many relationship is created between pizzas and any combination of toppings, which could exist on any topping. The &#8216;toppings&#8217; constant of the Pizza model is not a column in the database table, however it uses the PizzaTopping model/table to find its toppings. The format is</p>
<pre>const some_virtual_field = "Find_Class:Through_Class";</pre>
<p>Obviously this is very similar to the one-to-many relationship example above.</p>
<h2>Querying</h2>
<p>I will use an example above to demonstrate some examples of how queries are performed, how they are retrieved and store, and how my intelligent table joining works.</p>
<p>First and foremost, I&#8217;ve done by best to copy most of django&#8217;s query types. A few examples of queries using the models above and what SQL statements they would generate <em>(a small note: these aren&#8217;t the exact statements generated. I use a number of table aliases to better support intelligent table joining, to only join foreign key relationships when absolutely necessary):</em></p>
<pre>$m = Manufacturer::objects()-&gt;get(1);
// SELECT ... FROM manufacturers WHERE id = 1
// (returns a single object)

$ms = Manufacturer::objects()-&gt;all();
// SELECT ... FROM manufacturers

$ms = Manufacturer::objects()-&gt;filter(Field::name__contains('S'));
// SELECT ... FROM manufacturers WHERE name LIKE '%S%'

$ms = Manufacturer::objects()-&gt;exclude(Field::name__startswith('S'));
// SELECT ... FROM manufacturers WHERE NOT (name LIKE 'S%')</pre>
<p>All of the examples above (except the first), return a QuerySet object which can be iterated over:</p>
<pre>foreach($ms as $m)
  print $m-&gt;name;</pre>
<p>In cases where foreign keys are used, you are able to query the table joins by the foreign key. SQL joins are only created when necessary</p>
<pre>$ps = Product::objects()-&gt;filter(Field::name__contains('A'));
// SELECT ... FROM products WHERE name LIKE '%A%'

$ps = Product::objects()-&gt;filter(Field::manufacturer__name__contains('S'));
// SELECT ... FROM products LEFT JOIN manufacturers ON products.manufacturer = manufacturers.id
// WHERE manufacturers.name LIKE '%S%'</pre>
<p>Additionally, with many-to-many relationships, SQL sub-queries are only performed when needed:</p>
<pre>$pizza = Pizza::objects()-&gt;get(101);
// SELECT ... FROM pizzas WHERE id=101
$toppings = $pizza-&gt;toppings;
foreach($toppings as $topping)
  print $topping-&gt;name;
// SELECT ... FROM toppings WHERE id IN (SELECT the_topping FROM pizzatoppings WHERE the_pizza=101)</pre>
<h3>Alternative/Experimental Syntax</h3>
<p>I&#8217;ve also been playing around with a bit of an alternative syntax for query expressions (i.e. Field::somefield__contains($testval)) where using the Field class static method call isn&#8217;t necessary. This helps to create a more native django-like feel (with reduced PHP verbage):</p>
<pre>Products::objects()-&gt;filter(name__contains('A'));

Products::objects()-&gt;filter(manufacturer__name__contains('S'));</pre>
<p>Basically, how this works is when the objects() method is called on a class (returning a QuerySet manager), a list of all possible combinations of fields/table columns (obtained by performing a INFORMATION_SCHEMA query on the table) and query types (__in, __contains, __exact, __gte, __startswith, etc) are created as functions (using <a href="http://php.net/manual/function.eval.php" target="_blank">eval()</a>).</p>
<p>This is still a bit experimental, but in my limited number of tests it has worked well. For small table sets (such as the manufacturer/product table definitions) I was able to create all required query functions in less than 0.05 seconds.</p>
<h3>More Query Features</h3>
<p>I&#8217;ve also since added the ability to create more complex expressions with ANDs and ORs using predefined functions. <a href="http://andrewfreiday.com/2010/08/10/an-experiment-django-framework-like-queryingmodel-interface-in-php/" target="_blank">Last time</a> I was experimenting with the idea of operator overloading using the <a href="http://pecl.php.net/package/operator" target="_blank">PECL operator package</a>. It worked, and it worked really well, but it simply wasn&#8217;t stable or reliable for production or long-term use. Instead I&#8217;ve implemented _AND_() and _OR_() functions, as borrowed from <a href="https://storm.canonical.com/" target="_blank">Python&#8217;s Storm ORM</a>, brought up by a insightful reader.</p>
<p>Here is a quick example:</p>
<pre>Manufacturer::objects()-&gt;filter(_OR_(name__contains('Sony'),
    name__contains('Toshiba'));
// SELECT ... FROM manufacturers WHERE (name LIKE '%Sony%' OR name LIKE '%Toshiba%'))</pre>
<p>The _AND_() functions works the same way, and the two can be nested if necessary:</p>
<pre>Product::objects()-&gt;filter(
    _AND_(cost__gte(10),
        _OR_(weight__lte(5), name__contains('P'))
    )
);
// SELECT ... FROM products WHERE (cost &gt;= 10 AND (weight &lt;= 5 OR name LIKE '%P%'))</pre>
<h3>Query Arithmetic</h3>
<p>Lastly, I have added basic functionality for performing basic field arithmetic in queries:</p>
<pre>Product::objects()-&gt;filter(cost__lt(selling__divided_by(2));
// SELECT ... FROM products WHERE cost &lt;= (cost / 2)</pre>
<p>Supported arithmetic functions: times, divided_by, plus, minus. I haven&#8217;t had much time to run tests on this feature, so it is still a bit experimental.</p>
<h3>Ordering &amp; Limiting</h3>
<p>My favourite functionality that I&#8217;ve implemented thus far is the ability to order queries and extract sections of the results (using SQL LIMIT operators). QuerySet splicing was implemented using PHP&#8217;s <a href="http://php.net/manual/en/class.arrayaccess.php" target="_blank">ArrayAccess</a> interface to create a much cleaner and easier to read coding style:</p>
<pre>Product::objects()-&gt;all()-&gt;order_by("-name");
// SELECT ... FROM products ORDER BY name DESC

Product::objects()-&gt;all()-&gt;order_by("weight", "-cost");
// SELECT ... FROM products ORDER BY weight ASC, cost DESC

$products = Product::objects()-&gt;all();
$p = $products[1];
// returns the second item in the result set

$some_subset_of_products = $products[":5"];
// SELECT ... FROM products LIMIT 5

$another_subset = $products["2:5"];
// SELECT ... FROM products LIMIT 4 OFFSET 1

$last_subset = $products["5:"];
// SELECT ... FROM products LIMIT 18446744073709551610 OFFSET 4
// this is a bit of a dirty trick <a href="http://stackoverflow.com/questions/255517/mysql-offset-infinite-rows" target="_blank">explained over at Stack Overflow</a></pre>
<h2>Conclusions</h2>
<p>I still have quite a ways to go before I would ever be able to completely replicate all of django&#8217;s ORM features, but I&#8217;m fairly happy with my progress and it&#8217;s been a great learning experience.</p>
<p>I am offering my source for this little project, but please understand<strong> a lot of this was hacked together on a whim without much code clean-up</strong>. It <strong>desperately needs a refactoring</strong> and better documentation (read: <em>any</em> documentation). All of the<strong> internals could be better abstracted</strong> for code clarity and portability. I want to stress these statements for two reasons: 1) I don&#8217;t come off as a terrible programmer in regards to something I piece together in very small bits at a time, more as a proof-of-concept than anything; and 2) people know what they&#8217;re getting into when they look at my source.</p>
<p>If there&#8217;s interest, I wouldn&#8217;t mind tossing it up on <a href="http://www.github.com" target="_blank">github</a> and seeing what other sorts of things people can contribute. As much as I would love to start a large open source project (if it could ever turn into that), my fear is that it would encompass too much functionality/bloat and become just like every other PHP framework out there. As I mentioned in my introduction, my original goal was simply to develop a flexible and lightweight ORM (possibly later on with Smarty template integration and forms) for someone that needs to develop, for example, a quick and dirty <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete" target="_blank">CRUD interface</a> without hacking together a lot of unmaintainable spaghetti code strewn with MySQL statements and (sometimes at best) a poorly-implemented database abstraction/wrapper class.</p>
<h2>Down the Source</h2>
<p><a href="http://andrewfreiday.com/code/phrames_b20110617.zip">Download my latest source as a ZIP file: phrames_b20110617.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2011/06/17/further-work-on-a-django-like-php-orm-framework-phrames/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>A slightly better/slightly worse imagefill algorithm for PHP</title>
		<link>http://andrewfreiday.com/2010/11/06/a-slightly-betterslightly-worse-imagefill-algorithm-for-php/</link>
		<comments>http://andrewfreiday.com/2010/11/06/a-slightly-betterslightly-worse-imagefill-algorithm-for-php/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 02:48:33 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[gd]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=127</guid>
		<description><![CDATA[In my last post I was looking for a way to give simple images transparent backgrounds. I noted that PHP GD&#8217;s imagefill function wasn&#8217;t quite what I was looking for as it only replaced exact colours based on your starting image coordinates. I gave this problem some brief thought and came up with a slightly [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://andrewfreiday.com/wp-content/uploads/2010/11/test.jpg"></a>In <a href="http://andrewfreiday.com/2010/11/05/give-a-simple-image-a-transparent-background-transparentize/">my last post</a> I was looking for a way to give simple images transparent backgrounds. I noted that PHP GD&#8217;s <a href="http://php.net/manual/en/function.imagefill.php" target="_blank">imagefill function</a> wasn&#8217;t quite what I was looking for as it only replaced exact colours based on your starting image coordinates. I gave this problem some brief thought and came up with a slightly better algorithm using <a href="http://www.splitbrain.org/blog/2008-09/18-calculating_color_contrast_with_php" target="_blank">colour distance calculation</a> and simple recursion.</p>
<h2><span id="more-127"></span>The Better</h2>
<p>First of all, what&#8217;s better is the result (well, for my purposes at least). See below:</p>
<p>&nbsp;</p>
<div class="wp-caption alignnone" style="width: 310px"><a href="http://andrewfreiday.com/wp-content/uploads/2010/11/test.jpg"><img title="original" src="http://andrewfreiday.com/wp-content/uploads/2010/11/test.jpg" alt="" width="300" height="118" /></a><p class="wp-caption-text">Original image </p></div>
<p>&nbsp;</p>
<div id="attachment_129" class="wp-caption alignnone" style="width: 310px"><a href="http://andrewfreiday.com/wp-content/uploads/2010/11/test.png"><img class="size-full wp-image-129 " title="imagefill" src="http://andrewfreiday.com/wp-content/uploads/2010/11/test.png" alt="" width="300" height="118" /></a><p class="wp-caption-text">PHP GD imagefill function</p></div>
<p>&nbsp;</p>
<div id="attachment_130" class="wp-caption alignnone" style="width: 310px"><a href="http://andrewfreiday.com/wp-content/uploads/2010/11/test2.png"><img class="size-full wp-image-130 " title="imagefillthreshold" src="http://andrewfreiday.com/wp-content/uploads/2010/11/test2.png" alt="" width="300" height="118" /></a><p class="wp-caption-text">My imagefillthreshold algorithm</p></div>
<h2>The Worse</h2>
<p>It&#8217;s slower. Much, much, much slower. The built-in imagefill function took approximately 0.0007 seconds. My algorithm took 2.485 seconds. This is pretty much unacceptable. This sort of programming isn&#8217;t my forte, so I don&#8217;t know if I should attribute this to my algorithm itself (which I whipped up rather quickly without much thought), or if it&#8217;s because the PHP GD library is a built-in, compiled C library and mine is simple uncompiled PHP.</p>
<p>Secondly, it kept crashing my Apache (XAMPP 1.7.3, PHP 5.3.1, Apache 2.2.14). It worked great as a command line script and output my new image beautifully. <strong>It might/probably will crash your Apache, so use caution.</strong> It shouldn&#8217;t need to be said, but <strong>don&#8217;t try this on your production boxes</strong>.</p>
<p>Thirdly, with large images, it will probably eat up loads of memory or seg fault. I had to adjust my xdebug.max_nesting_level configuration variable to get this working properly (value to something huge like 50,000).</p>
<p>Like my <a href="http://andrewfreiday.com/2010/11/05/give-a-simple-image-a-transparent-background-transparentize/" target="_blank">Transparentizer class/algorithm</a>, it could definitely use some sort of anti-aliasing, but that&#8217;s a whole other beast.</p>
<pre><a href="http://andrewfreiday.com/source.php?f=imagefill/imagefill.php" target="_blank">View/download my imagefillthreshold function</a>.</pre>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/11/06/a-slightly-betterslightly-worse-imagefill-algorithm-for-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Give a simple image a transparent background: &#8220;Transparentize&#8221;</title>
		<link>http://andrewfreiday.com/2010/11/05/give-a-simple-image-a-transparent-background-transparentize/</link>
		<comments>http://andrewfreiday.com/2010/11/05/give-a-simple-image-a-transparent-background-transparentize/#comments</comments>
		<pubDate>Fri, 05 Nov 2010 19:11:35 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[gd]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=110</guid>
		<description><![CDATA[I needed a quick and dirty script (that I took a few minutes to clean up and throw together in a class) that can take a basic JPEG and turn it into a transparent PNG around the edges. I called it &#8220;Transparentize&#8221; &#8212; only because I couldn&#8217;t find any proper term for this. I looked [...]]]></description>
			<content:encoded><![CDATA[<p>I needed a quick and dirty script (that I took a few minutes to clean up and throw together in a class) that can take a basic JPEG and turn it into a transparent PNG around the edges. I called it &#8220;Transparentize&#8221; &#8212; only because I couldn&#8217;t find any proper term for this.</p>
<p>I looked into PHP GD library&#8217;s <a href="http://php.net/manual/en/function.imagefill.php" target="_blank">imagefill</a> function but it wasn&#8217;t quite giving me the results I needed. It only filled for exact colours, and in a JPEG with millions of colours, there are a number of variations of what the average set of eyes perceives as &#8220;white.&#8221; I need something where a threshold could be specified and find the edges of an image on a high contract background (for example, a basic black square on a white background).</p>
<h2><span id="more-110"></span>How it works</h2>
<p>Now I knew ahead of time that the images I was transparentizing were of pretty basic shapes, so I kept this in mind. My small script starts from the top image and processes from left to right until it reaches the contrasted edge of the object (as defined by the threshold) and then makes its way from right to left on the same Y axis. Here are some example results with varying thresholds:</p>
<table style="text-align: center; background-color: #ff00ff;" cellspacing="5" cellpadding="5" width="100%">
<tbody>
<tr>
<td><img class="size-medium wp-image-111 aligncenter" title="Original" src="http://andrewfreiday.com/wp-content/uploads/2010/11/original-170x300.jpg" alt="" width="85" height="150" />Original Image</td>
<td><img class="size-medium wp-image-112 aligncenter" title="threshold1" src="http://andrewfreiday.com/wp-content/uploads/2010/11/trans2-170x300.png" alt="" width="85" height="150" />Threshold: 1</td>
<td><img class="size-medium wp-image-113 aligncenter" title="threshold50" src="http://andrewfreiday.com/wp-content/uploads/2010/11/trans21-170x300.png" alt="" width="85" height="150" />Threshold: 50</td>
<td><img class="size-medium wp-image-114 aligncenter" title="threshold145" src="http://andrewfreiday.com/wp-content/uploads/2010/11/trans22-170x300.png" alt="" width="85" height="150" />Threshold: 145</td>
</tr>
</tbody>
</table>
<h2>What needs to be done</h2>
<p>Firstly, it could certainly use some sort of anti-aliasing, but I haven&#8217;t yet looked into this. I experimented a bit, but it might take some deeper research.</p>
<p>Secondly, it only works with images of a basic shape (like a box), it won&#8217;t work with more complex images that overlap their own background (like the letter &#8216;C&#8217;). I didn&#8217;t need this for my purposes, but if I have time I&#8217;ll write it out.</p>
<h2>Download the code</h2>
<pre><a href="http://andrewfreiday.com/source.php?f=trans/trans.php" target="_blank">View/download the Transparentizer PHP class</a>.
<a href="http://andrewfreiday.com/code/trans/trans.php" target="_blank">Try it yourself online</a>.</pre>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/11/05/give-a-simple-image-a-transparent-background-transparentize/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Experiment update: revised Django-like PHP (5.3 compatible) querying interface</title>
		<link>http://andrewfreiday.com/2010/08/23/experiment-update-revised-django-like-php-5-3-compatible-querying-interface/</link>
		<comments>http://andrewfreiday.com/2010/08/23/experiment-update-revised-django-like-php-5-3-compatible-querying-interface/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 19:12:09 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[5.2]]></category>
		<category><![CDATA[5.3]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[storm]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=102</guid>
		<description><![CDATA[After some research, discussion and a bit of hacking together some poorly organized code, I&#8217;ve come up with a revised interface from my previous post An experiment: Django Framework-like querying/model interface in PHP. Now there existed a few problems I was well aware that I wanted to address if I was going to spend any [...]]]></description>
			<content:encoded><![CDATA[<p>After some research, discussion and a bit of hacking together some poorly organized code, I&#8217;ve come up with a revised interface from my previous post <a href="http://andrewfreiday.com/2010/08/10/an-experiment-django-framework-like-queryingmodel-interface-in-php/"><em>An experiment: Django Framework-like querying/model interface in PHP</em></a>.</p>
<p>Now there existed a few problems I was well aware that I wanted to address if I was going to spend any more time on a good, clean interface that promoted rapid development and readable code:</p>
<ul>
<li>It was dependent on a PECL extension that was nearly 4 years old</li>
<li>It only worked with PHP 5.2.x (as per above)</li>
<li>The actual query-building interface wasn&#8217;t pretty and hindered readability</li>
</ul>
<p>I sat down and revised a good portion of the old code I had put together and came up with something that fixes these problems. I wrote a new collection of classes with PHP 5.3 in mind and it uses a lot of the new language features (especially <a href="http://php.net/manual/en/language.oop5.late-static-bindings.php" target="_blank">late static bindings</a> and the <a href="http://php.net/manual/en/language.oop5.overloading.php" target="_blank">__callStatic magic method</a>). Now, because of the use of these new features my code is now dependent on PHP version 5.3 (developed using 5.3.1) &#8212; but, I suppose it&#8217;s better to code looking to the future rather than being locked into an older version.<span id="more-102"></span>Thanks to reader Robert P who introduced me to Python&#8217;s <a href="https://storm.canonical.com/FrontPage" target="_blank">Storm ORM</a> and how it&#8217;s querying interface looked and functioned. After digging my way through its docs, I came up with something that is quite like a <span style="text-decoration: line-through;">hybrid</span> morbid mix of Django and Storm for use in PHP.</p>
<p>Let&#8217;s get to it: here&#8217;s how my interface has changed.</p>
<p><strong>Basic Querying</strong></p>
<p>I wanted to get away from what I hated the most: an unreadable querying interface that prevented the creation of self-explainable queries. What before was like:</p>
<pre>Product::get(<strong>array("make__contains" =&gt; "Sony")</strong>);</pre>
<p>has now become:</p>
<pre>Product::get(<strong>Field::make__contains("Sony")</strong>);</pre>
<p>which, using the __callStatic method, allowed me to create an interface that is actually quite readable aloud: &#8220;get <strong>Products</strong> where <strong>field</strong> <strong>make</strong> <strong>contains &#8220;Sony</strong>.&#8221; This is quite a bit better than using the array() function, where in reality it is completely unnecessary to the interface. This also works when combining expressions:</p>
<pre>$q = Product::get(Field::make__contains("Sony"), Field::price__gt(100));
print $q-&gt;create_statement();
// output: SELECT id FROM products WHERE (make LIKE '%Sony%' AND price &gt; '100')</pre>
<p><strong>Complex Expressions</strong></p>
<p>One of the things I love about Django is the ability to create more complex AND/OR queries using the Q interface and operator overloading (which I was using before, dependent on the PECL operator extension). Storm has this too, but it also offered up an <a href="https://storm.canonical.com/Manual#Expressions" target="_blank">alternative interface using AND() and OR() functions</a>.</p>
<p>I wasn&#8217;t able to do this exactly in PHP (&#8220;and&#8221; and &#8220;or&#8221; are reserved keywords), but I was able to make something slightly similar:</p>
<pre>require_once("Model.class.php");

class Product extends Model { }

$q = Product::get(_AND(Field::make__contains("Sony"), Field::price__gt(100)));
print $q-&gt;create_statement();
// output: SELECT id FROM products WHERE make LIKE '%Sony%' AND price &gt; '100'

$q = Product::get(_OR(Field::make__contains("Panasonic"), Field::make__contains("LG")));
print $q-&gt;create_statement();
// output: SELECT id FROM products WHERE make LIKE '%Panasonic%' OR make LIKE '%LG%'</pre>
<p><strong>Self-Referencing Fields in Expressions</strong></p>
<p>Again, another favourite feature of Django was the ability to use F objects to create expressions that references a table&#8217;s own fields. My basic research didn&#8217;t show anything like this in Storm, but using the __callStatic method and the same style interface, I was able to create a readable interface for these sorts of queries:</p>
<pre>$q = Product::get(Field::price__gt(<strong>Field::cost__times(2)</strong>));
print $q-&gt;create_statement();
// output: SELECT id FROM products WHERE price &gt; cost * 2

$q = Product::get(Field::price__gt(Field::cost__times("quantity_sold")));
print $q-&gt;create_statement();
// output: SELECT id FROM products WHERE price &gt; cost * quantity_sold</pre>
<p>Using [field]__times (or __plus, __minus, __divided_by), complex field-references can be created and is still fairly readable, as for the above example: &#8220;get <strong>Products</strong> where <strong>field price</strong> is <strong>greater than field cost times 2,&#8221;</strong> and the output should be as expected.</p>
<p>I&#8217;m still not entirely happy with this portion of my code at the moment. It is fairly limited in the sorts of queries you can create (for example, it&#8217;s not possible to create an expression such as &#8220;cost * 2 &#8211; price&#8221;).</p>
<p>I&#8217;m more than happy to offer up what code I have to date. I tried to document as much as possible, but some of the code is admittedly messy and could use a clean-up &#8212; which I&#8217;m sure I&#8217;ll get to at some point or another.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django2/Expression.class.php" target="_blank">Download/view Expression.class.php</a> &#8212; defines how Expressions are created and handled using the Field interface</p>
<p><a href="http://andrewfreiday.com/source.php?f=django2/ExpressionNode.class.php" target="_blank">Download/view ExpressionNode.class.php</a> &#8212; slightly revised from the previous code, defines classes for Q and F objects, along with _AND() and _OR() functions for creating more complex expressions.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django2/Model.class.php" target="_blank">Download/view Model.class.php</a> &#8212; basic class for creating models and queries.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django2/QuerySet.class.php" target="_blank">Download/view QuerySet.class.php</a> &#8212; defines how filter/exclude/get queries are chained together in a linked list structure.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/08/23/experiment-update-revised-django-like-php-5-3-compatible-querying-interface/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An experiment: Django Framework-like querying/model interface in PHP</title>
		<link>http://andrewfreiday.com/2010/08/10/an-experiment-django-framework-like-queryingmodel-interface-in-php/</link>
		<comments>http://andrewfreiday.com/2010/08/10/an-experiment-django-framework-like-queryingmodel-interface-in-php/#comments</comments>
		<pubDate>Tue, 10 Aug 2010 20:08:36 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[5.2]]></category>
		<category><![CDATA[5.3]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[operator]]></category>
		<category><![CDATA[overloading]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=84</guid>
		<description><![CDATA[I have continued with this experiment and created a new querying interface compatible with PHP 5.3 and has no dependent PECL extensions: Experiment update: revised Django-like PHP (5.3 compatible) querying interface. So this is an experiment I&#8217;ve had in the making for quite some time. I&#8217;ve been working for years trying to build a reusable [...]]]></description>
			<content:encoded><![CDATA[<pre>I have continued with this experiment and created a new querying interface compatible with PHP 5.3 and has no dependent PECL extensions: <a href="http://andrewfreiday.com/2010/08/23/experiment-update-revised-django-like-php-5-3-compatible-querying-interface/" target="_blank"><em><strong>Experiment update: revised Django-like PHP (5.3 compatible) querying interface</strong></em></a>.</pre>
<p>So this is an experiment I&#8217;ve had in the making for quite some time. I&#8217;ve been working for years trying to build a reusable &#8220;generic object&#8221; querying framework that I made my PHP applications easier to maintain and faster to develop. I originally started with a small library of classes, including a &#8216;GenericObject&#8217; class and a &#8216;Collection&#8217;, which allowed for proper iteration using the Iterator interface &#8212; all wrapped around a very messy Factory design pattern.</p>
<p>Up until about a year, I used hacked and modified versions of these classes for all of my projects and was getting tired of the mess. After doing some casual research I finally came across the <a href="http://www.djangoproject.com/" target="_blank">Django Framework</a> and found the object creation and database <a href="http://docs.djangoproject.com/en/1.2/topics/db/queries/" target="_blank">querying</a> quite phenomenal as a programming interface. I didn&#8217;t want to spend years trying to get my Python up to par with my abilities with PHP, so I decided to try and replicate it. For the last year, again, I&#8217;ve been using a pretty hacked up version of what seemed to me like a &#8220;Django-like&#8221; interface, combined together with my old GenericObject and Collection classes from long before. With this, I was previously able to perform really simple database queries with an interface like so:</p>
<pre>$users = User::get(array("fullname__contains" =&gt; "Andrew"));

foreach($users as $user) {
  // ...
}</pre>
<p><span id="more-84"></span>Extending this interface, I could further create more complex queries with AND and OR&#8217;s by how I passed a series of function arguments and array items. This worked pretty great actually, definitely increased my productivity when adding to an existing application, but made maintenance somewhat difficult due to hard-to-read queries that took a lot of pausing and mental analysis.</p>
<p>My research went deeper into the Django documentation and I decided: what&#8217;s stopping me from making an <em>almost</em> (this being the key word here) identical interface/framework for PHP, complete with complex querying using <a href="http://docs.djangoproject.com/en/1.2/topics/db/queries/#complex-lookups-with-q-objects" target="_blank">Q()</a> and <a href="http://docs.djangoproject.com/en/1.2/topics/db/queries/#query-expressions" target="_blank">F()</a> objects? Well, ultimately: a lot. But I&#8217;ve started, and I&#8217;m proud of my work that I want to share.</p>
<p><strong>The Problems</strong></p>
<p>First and foremost, the biggest hurdle in my goal was the lack of <a href="http://en.wikipedia.org/wiki/Operator_overloading" target="_blank">operator overloading</a> in PHP. This is what I would need in order to successfully achieve complex querying with Q() and F() objects, such as listed in the Django examples:</p>
<pre>Q(question__startswith='Who') | Q(question__startswith='What')</pre>
<p>I also discovered this topic has been brought up <a href="http://bugs.php.net/46128" target="_blank">many</a> <a href="http://bugs.php.net/bug.php?id=9331" target="_blank">times</a> <a href="http://bugs.php.net/bug.php?id=50969" target="_blank">before</a>, with the final word being an unquestionable <em>&#8220;never.&#8221; </em>This was obviously disappointing for two reason: 1) it meant my goal was out of reach; and 2) PHP is a mature language which I have based my career around up to this point, and now I&#8217;ve come across what I believe to be a major limitation for the future.</p>
<p>Some more research turned up the PECL <a href="http://pecl.php.net/package/operator" target="_blank">operator Package</a>, which does override PHP&#8217;s functionality and allow for some basic operator overloading. Perfect! But another roadblock: it took me long enough to dig up a precompiled version of the package (since PECL doesn&#8217;t compile on Windows systems) and I only had a version that was compatible with PHP 5.2.x. Tough news. This meant I didn&#8217;t have access to beautiful things in PHP 5.3 such as <a href="http://php.net/manual/en/language.oop5.late-static-bindings.php" target="_blank">late static bindings</a> and other new additions to the language. I was able to overcome this by writing my own hacked-up, squirrely version of the <a href="http://php.net/manual/en/function.get-called-class.php" target="_blank">get_called_class function</a> and <span style="text-decoration: line-through;">gratuitous</span> cringe-worthy use of the <a href="http://php.net/manual/en/function.eval.php" target="_blank">eval function</a>.</p>
<p>My final problem was Python&#8217;s beautiful ability to pass arguments to functions/methods in a format such as:</p>
<pre>Entry.objects.filter(<strong>headline__startswith="What"</strong>)</pre>
<p>As much research as I could possibly stand to do, there really is no way around this in PHP. there is no way of passing a variable name a value as a function argument. My work around, despite being what I originally wanted to get away from, was to do something as follows:</p>
<pre>Entry::get(<strong>array("headline__startswith" =&gt; "What")</strong>);</pre>
<p>Obviously this creates some unfortunate coding overhead and reduces fast readability, it&#8217;s my only solution thus far.</p>
<p>Despite these trade-offs, I now had just about everything I needed to create a respectable PHP equivalent of Django querying.</p>
<p><strong>The Solution</strong></p>
<p>I went through the Django document on making queries up and down, left and right, and tried to get the best grasp the concepts of the interface and how they could be applied in PHP. Before even getting to code, I spent a couple nights just thinking about how this could be done in the back-end code of my framework/interface, and finally began coding backwards: first I started writing out some of the Django examples in PHP, then writing backwards through all the classes and objects that I would require in order for these examples to output what I wanted.</p>
<p>Before I get into the nitty gritty of how all the code works together, I&#8217;ll provide a few examples of my interface looks like so far and the queries it&#8217;s able to generate. I&#8217;m not yet at the point where I have QuerySets and usable objects, but I&#8217;ve done the hard part by creating the MySQL statement query building.</p>
<p>First I start by creating my initial database Model:</p>
<pre>require_once("<a href="http://andrewfreiday.com/source.php?f=django/Model.class.php" target="_blank">Model.class.php</a>");

class Product extends Model {
// optional: table name is automatically generated
// using the class name and pluralizing it
//const table_name = "products";
}</pre>
<p>From here, I can use my static get() method to create queries:</p>
<pre>$r = Product::get();
print $r-&gt;create_statement();
// output: SELECT id FROM products

$r = Product::get(array("make__contains" =&gt; "Sony"));
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE make LIKE '%Sony%'

$r = Product::get(array("make__contains" =&gt; "Sony"), array("category__exact" =&gt; "TV"));
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE (make LIKE '%Sony%' AND category = 'TV')</pre>
<p>I can then filter() and exclude() these Query objects like with Django:</p>
<pre>$r = Product::get(array("make__contains" =&gt; "Sony"));
$r = $r-&gt;exclude(array("model__contains" =&gt; "RD3"));
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE make LIKE '%Sony%' AND NOT model LIKE '%RD3%'

$r = Product::get(array("category__contains" =&gt; "Stereo"));
$r = $r-&gt;filter(array("make__exact" =&gt; "Panasonic"));
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE category LIKE '%Stereo%' AND make = 'Panasonic'</pre>
<p>And I can also use the critical Q() and F() functions, along with operator overloading to create complex queries:</p>
<pre>$r = Product::get(Q(array("make__contains" =&gt; "Sony")) | ~Q(array("category__exact" =&gt; "TV")));
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE (make LIKE '%Sony%' OR  NOT category = 'TV')

$r = Product::get(array("selling_price__gte" =&gt; F("cost") * 2));
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE selling_price &gt;= cost * 2</pre>
<p>Of course, this isn&#8217;t as perfectly pretty as the Django interface, but it is quite readable and more maintainable than any other existing PHP solution I am aware of.</p>
<p>Additionally, I also added basic functionality for delete() and update() methods:</p>
<pre>$r = Product::get(array("selling_price__gte" =&gt; F("cost") * 2));

print $r-&gt;delete();
// output: DELETE FROM products WHERE selling_price &gt;= cost * 2

print $r-&gt;update(array("make" =&gt; "Sony", "category" =&gt; "TV"));
// output: UPDATE products SET make = 'Sony', category = 'TV' WHERE selling_price &gt;= cost * 2</pre>
<p>Use of limiting (through the <a href="http://php.net/manual/en/class.arrayaccess.php" target="_blank">ArrayAccess interface</a>) and order_by() methods is also available:</p>
<pre>$r = Product::get(array("make__exact" =&gt; "Sony"))-&gt;order_by("-model");
print $r-&gt;create_statement();
// output: SELECT id FROM products WHERE make = 'Sony' ORDER BY model DESC

$r = Product::get(array("make__exact" =&gt; "Sony"));
print $r["5:10"]-&gt;create_statement();
// output: SELECT id FROM products WHERE make = 'Sony' LIMIT 5 OFFSET 5

print $r[":10"]-&gt;create_statement();
// output: SELECT id FROM products WHERE make = 'Sony' LIMIT 10</pre>
<p>At the moment, as mentioned previously, this interface is only good for creating MySQL queries. But now that my base functionality exists, applying this to full iterable query sets and database objects should be easy in comparison.</p>
<p>I still have a lot of work to go to round this all together, but I&#8217;m quite happy with my progress so far with a couple days of on-and-off investment of time.</p>
<p>I&#8217;m more than happy to offer up my code so far, but before there is any severe judgment in the quality of it, I should point out that I made little to no reference to the core Django code (except for <a href="http://code.djangoproject.com/svn/django/trunk/django/db/models/query_utils.py" target="_blank">one small piece</a> that originally lead me to object overloading). If any readers show interest in my code, then I&#8217;ll do a small explanatory write-up of the classes and design patterns in another blog at a later date.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django/Model.class.php" target="_blank">View/download the Model abstract class</a>.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django/get_called_class.php" target="_blank">View/download my hacked up get_called_class function</a>.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django/Query.class.php" target="_blank">View/download the Query class</a>.</p>
<p><a href="http://andrewfreiday.com/source.php?f=django/S.class.php" target="_blank">View/download the S class</a> (used for Q and F objects, shows operator overloading).</p>
<p><a href="http://andrewfreiday.com/source.php?f=django/examples.php" target="_blank">View/download the examples used in this blog entry</a>.</p>
<p>Of course, please let me know if any of this code piques any interest in you or if you use any of the code in your applications.</p>
<p><strong>Update &#8211; August 11, 2010</strong> &#8211; So I caved and took a good hard look at the <a href="http://www.djangoproject.com/download/">Django source</a>. It&#8217;s not nearly as complicated as I imagined and my suspicions about how the back-end works just from looking at the docs is pretty close. I&#8217;m now either considering a full line-for-line port of Django to PHP or continuing with what I currently have and making it my own.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/08/10/an-experiment-django-framework-like-queryingmodel-interface-in-php/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Google Charts-like Provincial Data Map For Canada</title>
		<link>http://andrewfreiday.com/2010/05/03/google-charts-like-provincial-data-map-for-canada/</link>
		<comments>http://andrewfreiday.com/2010/05/03/google-charts-like-provincial-data-map-for-canada/#comments</comments>
		<pubDate>Mon, 03 May 2010 14:51:55 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[charts]]></category>
		<category><![CDATA[gd]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=49</guid>
		<description><![CDATA[This is PHP class I developed for work when I needed a Canada-specific map chart in some reporting tools I was creating. Obviously Google&#8217;s Map Charts API would&#8217;ve been my first choice, but it didn&#8217;t support Canada as it&#8217;s zoom level for reporting province-based data sets. This is where I sat down, thought about a [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_52" class="wp-caption alignright" style="width: 214px"><a href="http://andrewfreiday.com/wp-content/uploads/2010/05/canada.chart_.php_.png"><img class="size-medium wp-image-52 " style="margin: 10px;" title="canada.chart.php" src="http://andrewfreiday.com/wp-content/uploads/2010/05/canada.chart_.php_-300x290.png" alt="" width="204" height="197" /></a><p class="wp-caption-text">Map of Canada chart with province value colour coding.</p></div>
<p>This is PHP class I developed for work when I needed a Canada-specific map chart in some reporting tools I was creating. Obviously Google&#8217;s Map Charts API would&#8217;ve been my first choice, but it didn&#8217;t support Canada as it&#8217;s zoom level for reporting province-based data sets.</p>
<p>This is where I sat down, thought about a quick and dirty way to create this chart and went to work. I was able to create a chart as show on the right, with full control of output dimensions and colours.</p>
<p>Before I jump right into the full code, I want give a brief explanation of some of the techniques I used to accomplish this task.</p>
<p><span id="more-49"></span></p>
<div id="attachment_66" class="wp-caption alignleft" style="width: 231px"><a href="http://andrewfreiday.com/wp-content/uploads/2010/05/canada.png"><img class="size-full wp-image-66 " style="margin: 10px;" title="Canada" src="http://andrewfreiday.com/wp-content/uploads/2010/05/canada.png" alt="" width="221" height="214" /></a><p class="wp-caption-text">Map of Canada chart with each province uniquely coloured</p></div>
<p>The idea I had was to have a pre-coloured map of Canada such that each province has it&#8217;s own very distinct colour (as shown on left). From this starting point, I could replace each unique province colour with a degree of color based on a primary foreground color (e.g. red, #FF0000, as in the example above). To do this properly, I set up an array based on province short-forms (for data entry) and their unique colour on the base map:</p>
<pre>$provs = array(
  "AB" =&gt; "00DF6A",
  "BC" =&gt; "8AC707",
  "MB" =&gt; "3D5DFE",
  "NB" =&gt; "FF6BAA",
  "NL" =&gt; "C0FF00",
  "NT" =&gt; "FF8029",
  "NS" =&gt; "FFE26B",
  "NU" =&gt; "FFE328",
  "ON" =&gt; "D43CFF",
  "PE" =&gt; "6BFF7C",
  "QC" =&gt; "FF3DC0",
  "SK" =&gt; "01D7DF",
  "YT" =&gt; "FE293D"
);
</pre>
<p>and I was able to use <a href="http://www.php.happycodings.com/Graphics/code8.html" target="_blank">an excellent function that I found</a> which can take a HTML/hex color code and make it lighter by a percentage factor:</p>
<pre>function hexLighter($hex,$factor = 30) {
  $new_hex = '';

  $base['R'] = hexdec($hex{0}.$hex{1});
  $base['G'] = hexdec($hex{2}.$hex{3});
  $base['B'] = hexdec($hex{4}.$hex{5});

  foreach ($base as $k =&gt; $v)
      {
      $amount = 255 - $v;
      $amount = $amount / 100;
      $amount = round($amount * $factor);
      $new_decimal = $v + $amount;

      $new_hex_component = dechex($new_decimal);
      if(strlen($new_hex_component) &lt; 2)
          { $new_hex_component = "0".$new_hex_component; }
      $new_hex .= $new_hex_component;
      }

  return $new_hex;
}
</pre>
<p>From here, <a href="http://stackoverflow.com/questions/1548534/php-replace-colour-within-image" target="_blank">replacing one colour with another</a> is quite a simple task:</p>
<pre>function colorReplace($image, $oldcolor, $newcolor) {
  // find old color
  $oldcolor = $this-&gt;html2rgb($oldcolor);
  $old = imagecolorexact($image, $oldcolor['r'], $oldcolor['g'], $oldcolor['b']);
  // replace with new color
  $newcolor = $this-&gt;html2rgb($newcolor);
  imagecolorset($image, $old, $newcolor['r'], $newcolor['g'], $newcolor['b']);
}
</pre>
<p>&#8230;the rest is simply basic PHP image manipulation.</p>
<pre><a href="http://andrewfreiday.com/source.php?f=chart_canada/canada.chart.php" target="_blank">View/download the complete Canada Chart PHP class.</a>
<a href="http://andrewfreiday.com/code/chart_canada/canada.png" target="_blank">Click here to download the full-size coloured map of Canada required by the class.</a></pre>
<p>Now since I was already using Google&#8217;s Charts API, I wanted to make my own URL API to be relatively similar in fashion. So you could use this class like so, click to see result:</p>
<pre><a href="http://andrewfreiday.com/code/chart_canada/canada.chart.php?chld=ON,QC,AB,NL,BC,NB,MB,PE,NS,SK&amp;chd=1000,450,132,56,6,775,320,950,100,645&amp;chf=ff0000&amp;w=450&amp;h=450" target="_blank">canada.chart.php?chld=ON,QC,AB,NL,BC,NB,MB,PE,NS,SK&amp;chd=1000,450,132,56,6,775,320,950,100,645&amp;chf=ff0000&amp;w=450&amp;h=450</a></pre>
<p>This should make using this class in a project in which you&#8217;re already using Google Charts API fairly consistent.</p>
<p>I did add basic support for data labeling, but this wasn&#8217;t something I specifically needed so I didn&#8217;t pretty it up too much, but you can see an example here:</p>
<pre><a href="http://andrewfreiday.com/code/chart_canada/canada.chart.php?chld=ON,QC,AB,NL,BC,NB,MB,PE,NS,SK&amp;chd=1000,450,132,56,6,775,320,950,100,645&amp;chf=ff0000&amp;w=450&amp;h=450&amp;clb=1" target="_blank">canada.chart.php?chld=ON,QC,AB,NL,BC,NB,MB,PE,NS,SK&amp;chd=1000,450,132,56,6,775,320,950,100,645&amp;chf=ff0000&amp;w=450&amp;h=450&amp;<strong>clb=1</strong></a></pre>
<p>This requires a <a href="http://andrewfreiday.com/code/chart_canada/arial.gdf" target="_blank">GDF conversion of the Arial font</a> for use with <a href="http://php.net/manual/en/function.imageloadfont.php" target="_blank">PHP&#8217;s GD library</a>. Feel free to never use this functionality, take it out completely, or make it better.</p>
<p>If you successfully use this code, take it apart, or make it better &#8212; please let me know! I love to be constantly improving reusable classes like this, and it&#8217;s great to share good code with everyone.</p>
<h2>Addendum</h2>
<p>I&#8217;ve been so kind as to release this code under the Apache License v2.0, which means you&#8217;re more than welcome to use, distribute, and modify this code as long as you follow the terms of the license (which includes keeping the license with the modified source code).</p>
<p>If this code has been useful to you, and if you can find it in your heart, please donate a dollar or two. If you can buy me a coffee I&#8217;d be eternally grateful. Below is a donate button for my PayPal account.</p>
<p>&nbsp;</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_donations">
<input type="hidden" name="business" value="JCTT2M2JJLDTE">
<input type="hidden" name="lc" value="CA">
<input type="hidden" name="item_name" value="Andrew Freiday">
<input type="hidden" name="item_number" value="canadachart">
<input type="hidden" name="currency_code" value="CAD">
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donateCC_LG.gif:NonHosted">
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1"><br />
</form>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/05/03/google-charts-like-provincial-data-map-for-canada/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Retrieving coordinates of two addresses using Google Maps and calculating distance</title>
		<link>http://andrewfreiday.com/2010/04/30/retrieving-coordinates-of-two-addresses-using-google-maps-and-calculating-distance/</link>
		<comments>http://andrewfreiday.com/2010/04/30/retrieving-coordinates-of-two-addresses-using-google-maps-and-calculating-distance/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 17:31:51 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=27</guid>
		<description><![CDATA[So here&#8217;s a quick couple snippets of code that will allow you to retrieve the coordinates of two locations using Google Maps API &#8212; no API key necessary. This first function will return the coordinates of specific address (I find pretty much anything works, whether it&#8217;s a full address with street number, or just a [...]]]></description>
			<content:encoded><![CDATA[<p>So here&#8217;s a quick couple snippets of code that will allow you to retrieve the coordinates of two locations using Google Maps API &#8212; no API key necessary.</p>
<p>This first function will return the coordinates of specific address (I find pretty much anything works, whether it&#8217;s a full address with street number, or just a postal code, or simply a city name) as an array of coordinates:</p>
<pre style="background: transparent;">
<div class="codesnip-container" >
<div class="php codesnip" style="font-family:monospace;"><span class="kw2">function</span> getCoordinates<span class="br0">&#40;</span><span class="re0">$address</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; <span class="re0">$url</span> <span class="sy0">=</span> <span class="st0">&quot;http://maps.google.com/maps/geo?q=&quot;</span> <span class="sy0">.</span> <a href="http://www.php.net/urlencode"><span class="kw3">urlencode</span></a><span class="br0">&#40;</span><span class="re0">$address</span><span class="br0">&#41;</span>
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">.</span> <span class="st0">&quot;&amp;amp;output=json&quot;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$result</span> <span class="sy0">=</span> <a href="http://www.php.net/file_get_contents"><span class="kw3">file_get_contents</span></a><span class="br0">&#40;</span><span class="re0">$url</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$result</span> <span class="sy0">=</span> <a href="http://www.php.net/json_decode"><span class="kw3">json_decode</span></a><span class="br0">&#40;</span><span class="re0">$result</span><span class="sy0">,</span> 1<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/isset"><span class="kw3">isset</span></a><span class="br0">&#40;</span><span class="re0">$result</span><span class="br0">&#91;</span><span class="st_h">'Placemark'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <a href="http://www.php.net/list"><span class="kw3">list</span></a><span class="br0">&#40;</span><span class="re0">$lat</span><span class="sy0">,</span> <span class="re0">$long</span><span class="br0">&#41;</span> <span class="sy0">=</span> <span class="re0">$result</span><span class="br0">&#91;</span><span class="st_h">'Placemark'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'Point'</span><span class="br0">&#93;</span><span class="br0">&#91;</span><span class="st_h">'coordinates'</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
&nbsp; &nbsp; <span class="re0">$lat</span> <span class="sy0">=</span> <span class="re0">$long</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span>
&nbsp; <span class="br0">&#125;</span>
&nbsp; <span class="kw1">return</span> <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="re0">$lat</span><span class="sy0">,</span> <span class="re0">$long</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></div>
</div>
</pre>
<p><span id="more-27"></span>and the following function will accept the lat/long coordinates of two separate points and return their distance (not road/traveling distance, but straight-shot distance) in KM:</p>
<pre style="background: transparent;">
<div class="codesnip-container" >
<div class="php codesnip" style="font-family:monospace;"><span class="kw2">function</span> calculateDistance<span class="br0">&#40;</span><span class="re0">$lat1</span><span class="sy0">,</span> <span class="re0">$long1</span><span class="sy0">,</span> <span class="re0">$lat2</span><span class="sy0">,</span> <span class="re0">$long2</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp; <span class="re0">$R</span> <span class="sy0">=</span> <span class="nu0">6371</span><span class="sy0">;</span> <span class="co1">// earth's mean radius in km</span>
&nbsp; <span class="re0">$dLat</span> <span class="sy0">=</span> <a href="http://www.php.net/deg2rad"><span class="kw3">deg2rad</span></a><span class="br0">&#40;</span><span class="re0">$lat2</span><span class="sy0">-</span><span class="re0">$lat1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$dLon</span> <span class="sy0">=</span> <a href="http://www.php.net/deg2rad"><span class="kw3">deg2rad</span></a><span class="br0">&#40;</span><span class="re0">$long2</span><span class="sy0">-</span><span class="re0">$long1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$lat1</span> <span class="sy0">=</span> <a href="http://www.php.net/deg2rad"><span class="kw3">deg2rad</span></a><span class="br0">&#40;</span><span class="re0">$lat1</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$lat2</span> <span class="sy0">=</span> <a href="http://www.php.net/deg2rad"><span class="kw3">deg2rad</span></a><span class="br0">&#40;</span><span class="re0">$lat2</span><span class="br0">&#41;</span><span class="sy0">;</span>

&nbsp; <span class="re0">$a</span> <span class="sy0">=</span> <a href="http://www.php.net/sin"><span class="kw3">sin</span></a><span class="br0">&#40;</span><span class="re0">$dLat</span><span class="sy0">/</span>2<span class="br0">&#41;</span> <span class="sy0">*</span> <a href="http://www.php.net/sin"><span class="kw3">sin</span></a><span class="br0">&#40;</span><span class="re0">$dLat</span><span class="sy0">/</span>2<span class="br0">&#41;</span> <span class="sy0">+</span>
&nbsp; &nbsp; &nbsp; <a href="http://www.php.net/cos"><span class="kw3">cos</span></a><span class="br0">&#40;</span><span class="re0">$lat1</span><span class="br0">&#41;</span> <span class="sy0">*</span> <a href="http://www.php.net/cos"><span class="kw3">cos</span></a><span class="br0">&#40;</span><span class="re0">$lat2</span><span class="br0">&#41;</span> <span class="sy0">*</span>
&nbsp; &nbsp; &nbsp; <a href="http://www.php.net/sin"><span class="kw3">sin</span></a><span class="br0">&#40;</span><span class="re0">$dLon</span><span class="sy0">/</span>2<span class="br0">&#41;</span> <span class="sy0">*</span> <a href="http://www.php.net/sin"><span class="kw3">sin</span></a><span class="br0">&#40;</span><span class="re0">$dLon</span><span class="sy0">/</span>2<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$c</span> <span class="sy0">=</span> 2 <span class="sy0">*</span> <a href="http://www.php.net/atan2"><span class="kw3">atan2</span></a><span class="br0">&#40;</span><a href="http://www.php.net/sqrt"><span class="kw3">sqrt</span></a><span class="br0">&#40;</span><span class="re0">$a</span><span class="br0">&#41;</span><span class="sy0">,</span> <a href="http://www.php.net/sqrt"><span class="kw3">sqrt</span></a><span class="br0">&#40;</span>1<span class="sy0">-</span><span class="re0">$a</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp; <span class="re0">$d</span> <span class="sy0">=</span> <span class="re0">$R</span> <span class="sy0">*</span> <span class="re0">$c</span><span class="sy0">;</span>

&nbsp; <span class="co1">// return distance in KM</span>
&nbsp; <span class="kw1">return</span> <span class="re0">$d</span><span class="sy0">;</span>
<span class="br0">&#125;</span></div>
</div>
</pre>
<p>Now it certainly may be worthwhile to cache coordinates for a given location, depending on your usage, because retrieving the coordinates from Google for a large quantity of addresses at once can take some time.</p>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/04/30/retrieving-coordinates-of-two-addresses-using-google-maps-and-calculating-distance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating MP3 waveforms with PHP</title>
		<link>http://andrewfreiday.com/2010/04/29/generating-mp3-waveforms-with-php/</link>
		<comments>http://andrewfreiday.com/2010/04/29/generating-mp3-waveforms-with-php/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 14:49:16 +0000</pubDate>
		<dc:creator>Andrew</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[charts]]></category>
		<category><![CDATA[gd]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://andrewfreiday.com/?p=4</guid>
		<description><![CDATA[UPDATE: After some great comments, I have optimized the performance of this script and made some brief commentary available here. I have also updated any source code links below to the new github project page. I don&#8217;t quite know what gave me the desire to ever generate audio (specifically MP3) waveforms with PHP &#8212; it&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-size: medium;"><strong>UPDATE</strong>: After some great comments, I have optimized the performance of this script and made some brief commentary available <a href="http://andrewfreiday.com/2011/12/04/optimizing-the-php-mp3-waveform-generator/">here</a>. I have also updated any source code links below to the new github project page.</span></p>
<p>I don&#8217;t quite know what gave me the desire to ever generate audio (specifically MP3) waveforms with PHP &#8212; it&#8217;s not something I&#8217;ll likely ever use &#8212; but after doing some research and coming up a bit short I decided to make it happen.</p>
<div id="attachment_10" class="wp-caption alignright" style="width: 260px"><img class="size-full wp-image-10 " style="margin: 10px;" title="MP3 waveform" src="http://andrewfreiday.com/wp-content/uploads/2010/04/waveform.png" alt="" width="250" height="100" /><p class="wp-caption-text">Waveform generated using Dancing With Paris&#39; &quot;(Boardwalk)&quot; MP3.</p></div>
<p>A few days of Googling, I did come up with a couple solutions but none seemed to really produce the results I wanted. All I was looking to generate was a simple waveform like that in Cubase or other recording software. I don&#8217;t need axis labels or left/right audio splits, just a simple mono waveform from an MP3. I also didn&#8217;t want to go through hundreds of audio files and convert them into WAV files just to do this &#8212; if I was going to do this as an experiment, I wanted it on the fly. I did come across some interesting links though:</p>
<p><span id="more-4"></span></p>
<p>The <a href="http://sox.sourceforge.net/" target="_blank">Sound eXchange</a> (SoX) audio tool kit has a lot of great features that might come in handy later on, including audio effects, but support for MP3 wasn&#8217;t built-in and seemed a bit too much work to bother<a href="http://www.codeproject.com/KB/aspnet/Compiling_SOX_with_Lame.aspx" target="_blank"> compiling</a> just for a side experiment. SoX can generate spectrograms, but this wasn&#8217;t particularly what I was looking for.</p>
<p>I did find this <a href="http://phpclasses.cfappsinc.ca/browse/file/1582.html" target="_blank">classAudioFile.php</a>, which does support generating waveforms from WAV files, but this seemed a bit more hefty than I really needed &#8212; and not as accomplishing as doing it myself. That being said, and though I never bothered testing it out, it does seem (based on the code) to create a simple waveform image that I was aiming to create.</p>
<p>Ultimately, I wanted something flexible: upload MP3s files without pre-converting them, adjust size of the image easily, and change foreground and background colours. The key that makes my script different, and most flexible, is converting the files to WAV on the fly. Though this is time consuming, it&#8217;s ultimately a lot easier than batch processing them on my computer first.</p>
<pre><a href="https://github.com/afreiday/php-waveform-png" target="_blank"><strong>Click here to see the source code for the script.</strong></a></pre>
<p>The key to making this convenient has been using the <a href="http://lame.sourceforge.net/index.php" target="_blank">LAME MP3 encoder/decoder</a> through the command line (on Windows for my script, I haven&#8217;t yet tested with any flavour of Linux). I simply downloaded a windows build of LAME, threw the executable into my script directory and ran the following command:</p>
<pre>lame original_file.mp3 -f -m m -b 16 --resample 8 resampled.mp3 &amp;&amp; lame --decode resampled.mp3 final_file_for_processing.wav</pre>
<p>Because you don&#8217;t really need a high quality audio file for generating a waveform, this set of commands will resample the original MP3 to a 16 bit, 8 KHz, mono MP3 file and then turn that into a WAV file for processing the image from. Processing does take some time, but it&#8217;s significantly faster than processing a huge 40+ MB WAV file from the start. Also, no amount of research showed a way to directly downsample an MP3 straight to a WAV file, hence the intermediary step.</p>
<p>After that, I used an <a href="http://forums.devshed.com/php-development-5/reading-16-bit-wav-file-318740.html?" target="_blank">algorithm I found on the DevShed forums</a> for processing 16 bit WAV files, and used the data it generates to create the waveform (which, ultimately, is pretty simple).</p>
<p>If this is something you have a use for, feel free to use it as you wish and give credit where it&#8217;s due (see the source comments for where I pulled some code snippets from to make this work). You may want to fix it up a bit for better error checking and so forth though.</p>
<p>A note of warning: it&#8217;s not fast. Far from it. A couple basic tests showed anywhere between 10-30+ seconds to generate the waveforms for an average sized MP3 (decent quality, 2-4 minutes in length). If you will be generating and re-generating waveforms multiple times for the same audio file, you may want to cache the WAV data in a database for future use, as using that data to create the image itself is comparatively quite quick.</p>
<p>I may use this, along with the SoX library, later on to create &#8212; simply for fun and discovery &#8212; an online audio mixer/editor similar to Cubase, which I&#8217;ve been working with quite a lot lately. This would be a great way to create a new web-based interface with a lot of widgets and controls not commonly used, as well as using SoX to add audio effects, mix, combine files, in a multi-layered audio interface. I&#8217;ll see if I ever get around to this however.</p>
<p>Environment tested in, your results may vary:</p>
<ul>
<li>Windows Server 2003</li>
<li>PHP 5.2.10</li>
<li>LAME 3.98.4</li>
</ul>
<h2>Addendum</h2>
<p>I&#8217;ve been so kind as to release this code under the Apache License v2.0, which means you&#8217;re more than welcome to use, distribute, and modify this code as long as you follow the terms of the license (which includes keeping the license with the modified source code).</p>
<p>This is by far my most popular blog entry &#8212; and thus I can assume the most desired piece of code that I&#8217;ve so far provided. If this code has been useful to you, and if you can find it in your heart, please donate a dollar or two. If you can buy me a coffee I&#8217;d be eternally grateful. Below is a donate button for my PayPal account.</p>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_donations" />
<input type="hidden" name="business" value="JCTT2M2JJLDTE" />
<input type="hidden" name="lc" value="CA" />
<input type="hidden" name="item_name" value="Andrew Freiday" />
<input type="hidden" name="item_number" value="mp3waveform" />
<input type="hidden" name="currency_code" value="CAD" />
<input type="hidden" name="bn" value="PP-DonationsBF:btn_donateCC_LG.gif:NonHosted" />
<input type="image" name="submit" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" alt="PayPal - The safer, easier way to pay online!" /> <img src="https://www.paypal.com/en_US/i/scr/pixel.gif" alt="" width="1" height="1" border="0" /></form>
]]></content:encoded>
			<wfw:commentRss>http://andrewfreiday.com/2010/04/29/generating-mp3-waveforms-with-php/feed/</wfw:commentRss>
		<slash:comments>65</slash:comments>
		</item>
	</channel>
</rss>

