<?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>ArtzStudio &#187; Code</title>
	<atom:link href="http://www.artzstudio.com/tags/code/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.artzstudio.com</link>
	<description>Dave Artz and his discoveries in web design and development.</description>
	<lastBuildDate>Thu, 24 Jun 2010 18:13:14 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>PNG Alpha Transparency &#8211; No Clear Winner</title>
		<link>http://www.artzstudio.com/2008/07/png-alpha-transparency-no-clear-winner/</link>
		<comments>http://www.artzstudio.com/2008/07/png-alpha-transparency-no-clear-winner/#comments</comments>
		<pubDate>Fri, 25 Jul 2008 21:58:36 +0000</pubDate>
		<dc:creator>ArtzStudio</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[graphics]]></category>

		<guid isPermaLink="false">http://www.artzstudio.com/?p=20</guid>
		<description><![CDATA[img { *ie6_-: [png]transparent; }

As a long time user of Adobe Photoshop, I missed the boat on a very important discovery in image optimization &#8211; PNG-8 supports full alpha transparency!
Alex Walker wrote a great article on PNG and included a nice example on creating PNG-8 images with a full alpha transparency layer with Fireworks &#8211; [...]]]></description>
			<content:encoded><![CDATA[<style type="text/css">img { *ie6_-: [png]transparent; }</style>
<p><img class="doodle" src="http://www.artzstudio.com/files/png-alpha-transparency/png-no-winner.png" alt="" width="193" height="169" /></p>
<p>As a long time user of Adobe Photoshop, I missed the boat on a very important discovery in image optimization &#8211; <b>PNG-8 supports full alpha transparency!</b></p>
<p>Alex Walker wrote a <a href="http://www.sitepoint.com/blogs/2007/09/18/png8-the-clear-winner/">great article on PNG</a> and included a nice example on creating PNG-8 images with a full alpha transparency layer with Fireworks &#8211; yes, <b>Fireworks</b>.  Stoyan Stefanov  points out this ability in his <a href="http://www.slideshare.net/stoyan/image-optimization-7-mistakes/">image optimization mistakes presentation</a> as well. Thanks to you both for enlightening me!</p>
<p>Before Stoyan and Alex, I like probably many other thousands of Photoshop users believed, or still believe, that PNG-8 is identical to GIF, i.e. an <i>all or nothing</i> scenario when it comes to transparent pixels. In Photoshop, we are left with the usually bloated, heavy PNG-24 format that I typically steer folks away from.</p>
<p>However, in applying PNG-8 to my favorite PNG transparency techniques, I came to a <b>different conclusion</b> than Alex and Stoyan. This article shows there is <b>no silver bullet</b> when it comes to saving out PNGs (<i>are you listening, Adobe?</i>).</p>
<h2>PNG Transparency Text Effects</h2>
<p>One cool technique we can do with alpha PNGs are <a href="http://www.webdesignerwall.com/tutorials/css-gradient-text-effect/">text effects, as detailed here by Nick La</a>. The technique involves layering an empty element containing the horizontally tiled background gradient over system text.</p>
<ul>
<li>Download the <a href="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text.psd">Glossy Text  PSD</a> (189 KB)</li>
</ul>
<p>Using this CSS and HTML, we can pull off the desired effect:</p>
<pre>&lt;style type=&quot;text/css&quot;&gt;
.glossy-text
{
	font: 45px 'arial rounded mt bold';
	margin: 0;
	position: relative;
	color: #f30;
}

.glossy-text b
{
	background: url(glossy-text-photoshop.png) repeat-x;
	position: absolute;
	width: 100%;
	height: 27px;
	top: 4px;
	display: block;
	_background: none;
	_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='glossy-text-photoshop.png', sizingMethod='scale');
}
&lt;/style&gt;

&lt;div class=&quot;example&quot;&gt;
&lt;h2 class=&quot;glossy-text&quot;&gt;&lt;b&gt;&lt;/b&gt;PNG Can Overlay Text&lt;/h2&gt;
&lt;/div&gt;</pre>
<p>Here are the results&#8230;</p>
<style type="text/css">
.glossy-text {font:45px 'arial rounded mt bold';margin:0;position:relative;color:#f30;}
.glossy-text b {background:url(http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-photoshop.png) repeat-x; position:absolute;width:100%;height:27px;top:4px;display:block;_background:none;
_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-photoshop.png', sizingMethod='scale');}
.example .cold {color:#06f;} 
</style>
<div class="example">
<h2 class="glossy-text"><b></b>PNG Can Overlay Text</h2>
</div>
<p>And another using the same image, with blue text&#8230;</p>
<div class="example">
<h2 class="glossy-text cold"><b></b>One Image for Every Heading!</h2>
</div>
<p>The optimization win here is clear &#8211; use <b>only 1 image</b> across multiple  headers to pull off a polished design for headings!</p>
<h3>The PNG Image</h3>
<p>I created the PNG image in Photoshop using a <i>Gradient Fill</i> layer. This gives us a fine deal of control over the gradient and the level of transparency to apply at each point. We can visually see how much transparency is applied by looking at the shade of the <i>Opacity Stops</i>. White is 0% Opacity (invisible), while black is 100% Opacity, or fully visible.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/photoshop-gradient-fill.png" width="625" height="282" alt="Photoshop Gradient Fill"></p>
<p>Now, we will head on over to our trustworthy Save For Web tool, and notice how our PNG-8 doesn&#8217;t support full alpha, as usual.</p>
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<th>PNG-8</th>
<th>PNG-24</th>
</tr>
<tr>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-photoshop-png8.png" width="162" height="162" alt="Glossy Text Photoshop Png8">&nbsp;</td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-photoshop-png24.png" width="162" height="162" alt="Glossy Text Photoshop Png24">&nbsp;</td>
</tr>
</table>
<p>I will save out the PNG-24 version, which comes out to <b>156 bytes</b>, not too bad at all. Let&#8217;s see if Fireworks and its PNG-8 format can do better.</p>
<p>Now, if you are new to Fireworks (like me), the workflow is a bit different than Photoshop. Let&#8217;s start by opening up our PNG-24 image saved out of Photoshop, and switching to the export <b>Preview</b> view.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/fireworks-export-preview-view.png" width="710" height="369" alt="Fireworks Export Preview View"></p>
<p>The <i>Export Preview</i> is essentially the same thing as Photoshop&#8217;s <i>Save for Web</i> tool. Look over to the right in the above graphic at the <i>Optimize and Align</i> panel &#8211; those are the settings it&#8217;s using. Let&#8217;s update that to <b>PNG-8</b>, and the <b>Alpha Transparency</b> option.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/fireworks-optimize-align-png.png" width="710" height="369" alt="Fireworks Optimize Align Png"></p>
<p>To export the image, we can go to <i>File&#8230;Export</i>, but we can also see the expected KB in the lower-left corner of the panel, a file size of 248 bytes. After exporting, we see it was actually 238 bytes. <i>(Adobe, why can&#8217;t this be completely accurate?)</i></p>
<table cellpadding="0" cellspacing="10" border="0" style="background-color:#123b8d; color:#fff;">
<tr>
<td align="right">Photoshop PNG-24, <b>156 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-photoshop.png" alt="glossy text from photoshop"></td>
</tr>
<tr>
<td align="right">Fireworks PNG-8, <b>238 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-fireworks-png8.png" alt="glossy text from fireworks"></td>
</tr>
<tr>
<td align="right">Fireworks PNG-8 (dithered), <b>278 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-fireworks-png8-dither.png" alt="glossy text dithered from fireworks"></td>
</tr>
</table>
<p>Now, this brings me pause, because the PNG-24 I saved out of Photoshop was a mere 156 bytes &#8211; <b>37% smaller in size</b>! You can also clearly see that the Fireworks image is banding, which I would not expect to happen on such a low color image. I also dithered it, and it got larger and the pattern was still noticable.</p>
<p>It would seem that for this design purpose, the glossy text overlay, <b>Photoshop&#8217;s PNG-24 is the better choice</b>. My luck indeed!</p>
<h2>Gradient Header Backgrounds</h2>
<p>Similar in design to the text overlay image, the same finding is bound to hold true for  gradient background techniques, right? <i>Read on&#8230;</i></p>
<ul>
<li>Download the <a href="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background.psd">Glossy Background  PSD</a> (40 KB)</li>
</ul>
<p>I&#8217;m going to create another<i> Gradient Fill </i>layer, and overlay a fade to white, and a fade to black over a layer filled with red. Notice I added a <i>Color Stop</i> in the center to ensure one side is white, and the other is black.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-gradient-fill.png" width="705" height="284" alt="Glossy Background Gradient Fill"></p>
<p>Just to be fancy, I will go ahead and add some fully opaque rounded corners using our selection tool. First, I&#8217;ll make a circle selection with a 10px diameter, giving us a 5px corner radius.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-1.png" alt="circle selection at the top left corner of the header" width="349" height="200"></p>
<p>Next, we&#8217;ll add to the selection along the top and left hand sides of the circle selection.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-3.png" alt="same thing on the left hand side" width="349" height="200"></p>
<p>Next, we&#8217;ll need to use <i>Select&#8230;Inverse</i> to flip the selection so we can fill it in.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-4-inverse.png" alt="menu select inverse" width="217" height="195"></p>
<p>Using our pencil tool with at least a 5px radius, we fill in our rounded corner with white.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-6.png" alt="filled in with white" width="349" height="200"></p>
<p>Notice that it also nicely anti-aliases against the layer below. For the other side, we&#8217;ll simply make a selection around it, and copy it over to the other side of the header.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-7.png" alt="copying the rounded corner" width="200" height="190"></p>
<p>Move it over to the other side and do <i>Edit&#8230;Transform&#8230;Flip Horizontal</i>.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-8-flip-horizontal.png" alt="menu flip horizontal" width="435" height="308"></p>
<p>And finally, position it in the right spot.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-9.png" alt="position the right corner" width="180" height="127"></p>
<p>It is time to save out our PNG. Let&#8217;s go ahead and disable our layers and crop the image.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-10.png" alt="before diabling layers" width="537" height="50"></p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-11.png" alt="after disabling the layers" width="537" height="50"></p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/rounded-corners-step-12.png" alt="cropped" width="537" height="50"></p>
<p>And now for the PNG-24 vs. PNG-8 test.</p>
<table cellpadding="0" cellspacing="10" border="0" style="background-color:#123b8d; color:#fff;">
<tr>
<td align="right">Photoshop PNG-24, <b>399 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-photoshop-png24.png" width="518" height="32" alt="Glossy Background Photoshop Png24" /></td>
</tr>
<tr>
<td align="right">Fireworks PNG-8, <b>397 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-fireworks-png8.png" width="518" height="32" alt="Glossy Background Fireworks Png8" /></td>
</tr>
<tr>
<td align="right">Fireworks PNG-8 (dithered), <b>411 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-fireworks-png8-dither.png" width="518" height="32" alt="Glossy Background Fireworks Png8" /></td>
</tr>
</table>
<p>The tables have turned &#8211; <b>PNG-8 wins by 2 bytes</b>! However, notice again there is <b>banding</b> going on, which is bothersome to me for such a low color image. I  played with all the settings I could in Fireworks to no avail, and the dither is larger in size and looks worse, so again I will have to hand this one to Photoshop&#8217;s PNG-24.</p>
<h2>ImageOptim, a  GUI PNG  Tool</h2>
<p>And then, I thought about messing around with some programs <a href="http://www.sitepoint.com/blogs/2007/09/18/png8-the-clear-winner/">Alex mentioned in his article</a>, the programs <b>PNGQuant</b> and  <b>PNGNQ</b>. <a href="http://www.libpng.org/pub/png/apps/pngquant.html">PNGQuant</a> and <a href="http://pngnq.sourceforge.net/">PNGNQ</a> take 32-bit or 24-bit PNG images and &quot;quantize&quot; them down to 8-bit, or PNG-8. Now, what sucks is that the tools are command line, although PNGQuant has a <a href="http://jedisthlm.com/2006/03/16/manfred-a-pngquant-gui/">GUI version for Windows</a>, it is difficult to install and doesn&#8217;t help OS X fans like myself and many other designers.</p>
<p>I couldn&#8217;t get either of these to work on OS X, because I am <a href="http://www.urbandictionary.com/define.php?term=chobo">chobo</a> and didn&#8217;t want to spend more then the 30 minutes I did trying to compile the source code on OS X.</p>
<p>In my Googling for GUIs, I discovered <a href="http://pornel.net/imageoptim">ImageOptim</a>. Now, I have no clue what language the developer speaks, or what the tool does exactly, but if you want to help me translate for my readers, be my guest:</p>
<p> <img src="http://www.artzstudio.com/files/png-alpha-transparency/imageoptim-homepage.png" alt="screen shot of imageoptim homepage with non english text" width="489" height="250"></p>
<p>If I had to guess, it appears to try various PNG algorithms until it gets one that compresses the best. The tool is very user-friendly, and would fit nicely into any process as you simply drag and drop your files into its window, and it takes care of the rest.</p>
<p>To see how we fare, let&#8217;s take our full quality Photoshop PNG-24, and drop it in.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/imagoptim-drag-png24.png" alt="dragging png24 into imageoptim window" width="717" height="239"></p>
<p>Viola! ImageOptim crunched our PNG-24 down to <b>355 bytes</b>, a savings of 11%. Recall this is also smaller than our Fireworks PNG-8 (397 bytes).</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/imageoptim-results.png" alt="imageoptim results window savings of 11%" width="423" height="209"></p>
<p>The resulting file was smaller and identical to the original:</p>
<table cellpadding="0" cellspacing="10" border="0" style="background-color:#123b8d; color:#fff;">
<tr>
<td align="right">Photoshop PNG-24, <b>399 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-photoshop-png24.png" width="518" height="32" alt="Glossy Background Photoshop Png24" /></td>
</tr>
<tr>
<td align="right">Fireworks PNG-8, <b>397 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-fireworks-png8.png" width="518" height="32" alt="Glossy Background Fireworks Png8" /></td>
</tr>
<tr>
<td align="right">ImageOptim PNG, <b>355 bytes</b></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-imageoptim.png" width="518" height="32" alt="image optim png"></td>
</tr>
</table>
<p>Let&#8217;s go back and see if we can save anything from our Glossy Text image.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/glossy-text-results.png" alt="glossy text results showing no gain" width="423" height="209"></p>
<p>Looks like we didn&#8217;t gain anything, oh well.</p>
<p>My one beef with ImageOptim is that I have no clue what it did. Did it throw away information? What program did it use, OptiPNG, PNGCrush, AdvPNG? And why is their logo of a man getting impaled by credit cards?</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/imageoptim-logo.png" alt="imageoptim logo" width="100" height="106"></p>
<p>Okay, with that we&#8217;ll use the ImageOptim version of the PNG to complete our design, along with the following CSS and HTML, for those interested.</p>
<pre>
&lt;style type=&quot;text/css&quot;&gt;
div.glossybg
{
	width: 250px;
	font-family: verdana;
	margin-bottom: 1em;
}
div.wide
{
	width:500px;
}
div.glossybg h2
{
	color: #fff;
	height: 32px;
	font: 18px/30px verdana;
	margin: 0;
	padding-left: 12px;
	background: #f30 url(glossy-background-imageoptim.png) repeat-x;
	text-align: center;
}
div.glossybg h2 b
{
	display: block;
	background: url(glossy-background-imageoptim.png) top right; /* Tricky bit! */
	background-color: #f30;
	padding-right: 12px;
	font-weight: normal;
}
div.glossybg h2.cold, div.glossybg h2.cold b
{
	background-color: #0066b3;
}
div.glossybg p
{
	border: 2px solid #ccc;
	border-width: 0 2px 2px;
	margin: 0;
	padding: 10px;
}
&lt;/style&gt;

&lt;div class=&quot;glossybg&quot;&gt;
&lt;h2&gt;&lt;b&gt;A Red Header&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;Some text inside the skinny box.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;glossybg wide&quot;&gt;
&lt;h2 class=&quot;cold&quot;&gt;&lt;b&gt;A Blue Header&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;Some text inside the fat box.&lt;/p&gt;
&lt;/div&gt;
</pre>
<style type="text/css">
div.glossybg
{
	width: 250px;
	font-family: verdana;
	margin-bottom: 1em;
}
div.wide 
{
	width:500px;
}
div.glossybg h2 
{
	color: #fff;
	height: 32px;
	font: 18px/30px verdana;
	margin: 0;
	padding-left: 12px;
	background: #f30 url(http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-imageoptim.png) repeat-x;
	_background-image:none
	text-align: center;
}
div.glossybg h2 b
{
	display: block;
	background: url(http://www.artzstudio.com/files/png-alpha-transparency/glossy-background-imageoptim.png) top right;
	_background-image:none;
	background-color: #f30;
	padding-right: 12px;
	font-weight: normal;
}
div.glossybg h2.cold, div.glossybg h2.cold b
{
	background-color: #0066b3;
}
div.glossybg p 
{
	border: 2px solid #ccc;
	border-width: 0 2px 2px;
	margin: 0;
	padding: 10px;
}
</style>
<div class="glossybg">
<h2><b>A Red Header</b></h2>
<p>Some text inside the skinny box.</p>
</div>
<div class="glossybg wide">
<h2 class="cold"><b>A Blue Header</b></h2>
<p>Some text inside the fat box.</p>
</div>
<p>Notice the tricky bit of CSS indicated above. We are layering the image in <code>&lt;b&gt;</code> element of the header to pull off a rounded corner on the right side, allowing us to stretch the image to various widths, a <a href="http://www.alistapart.com/articles/slidingdoors/">favorite technique</a> of mine.</p>
<h2>Transparent Image Overlays</h2>
<p>For my final experiment, I will create a banner header with a logo overlay, to demonstrate a more complex application of PNG.</p>
<ul>
<li>Download the <a href="http://www.artzstudio.com/files/png-alpha-transparency/obama-spirit.psd">Image Overlay PSD</a> (185 KB)</li>
<li>Download the <a href="http://www.artzstudio.com/files/png-alpha-transparency/glossy-banner.psd">Banner Artwork PSD</a> (1.13 MB)</li>
</ul>
<p>We&#8217;re going to create a website banner for a fan site of a well known American politician. I downloaded some free artwork from his campaign website.</p>
<p>For our transparent overlay, I will need to cut him out of his poster and <i>copy and paste</i> him on a <b>black background</b>.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-step-1.jpg" alt="obama cut out" width="470" height="250"></p>
<p>Then, we  switch our document to <i>Lab color</i> mode. </p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-step-2.png" alt="lab color mode switch" width="342" height="190"></p>
<p>This gives us a nice Lightness channel which we can use to create our overlay. In the <i>Channels</i> panel, select the <i>Lightness</i> channel, we&#8217;ll then make a selection using <i>Command + Click</i> (Windows <i>Ctrl + Click</i>).</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-step-3.png" alt="select lightness channel and make a selection from it" width="436" height="242"></p>
<p>This selects the light areas of the image, and also includes transparency information. Visually, you will see anything greater than 50% white with a marquee around it. If we wanted the dark pixels, we could simply select the inverse to obtain it. </p>
<p>This is also why we created him on a <b>black background</b>, to maintain the outline (transparent pixels are counted as white).</p>
<p>Now that I have my selection, I am going to switch back to RGB mode, create a new layer, and fill the selection in with white. I disabled the color layer to show the end result.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-step-4.png" alt="filled in the selection with white" width="436" height="242"></p>
<p>We now have a layer with white transparency information in the shape of our political figure. <i>Disable the black background</i>, and save it out as  Photoshop PNG-24. Export it through  Fireworks and ImageOptim as outlined above.</p>
<table cellpadding="0" cellspacing="10" border="0" style="background-color:#123b8d; color:#fff;">
<tr>
<td align="center">Photoshop PNG-24<br /><b>16764 bytes</b></td>
<td align="center">Fireworks PNG-8<br /><b>4542 bytes (73%)</b></td>
<td align="center">Fireworks PNG-8 (dithered)<br /><b>5265 bytes (69%)</b></td>
</tr>
<tr>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-photoshop-png24.png" width="200" height="194" alt="Obama Photoshop Png24"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-fireworks-png8.png" width="200" height="194" alt="Obama Fireworks Png8"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-fireworks-png8-dither.png" width="200" height="194" alt="Obama Fireworks Png8"></td>
</tr>
</table>
<p>ImageOptim was unable to gain any savings, so I didn&#8217;t include it. It seems as though ImageOptim doesn&#8217;t include a <i>quantizer</i> that will reduce the color palette like PNGQuant and PNGNQ, which is <b>what we really want</b>.</p>
<p>But  I think we are <b>finally getting somewhere</b> on the Fireworks front. Our Fireworks PNG-8 was <b>73% smaller</b> than our original PNG-24, though that banding is back (see his shoulder).</p>
<p>I exported another image out of Fireworks with a 100% dither, and think it looks much better. While a tad larger, I would recommend going with the <b>dithered Fireworks PNG-8 image</b>.</p>
<p>Let&#8217;s see how our finished product looks.</p>
<style type="text/css">
.overlay-header
{
	background-image: url(http://www.artzstudio.com/files/png-alpha-transparency/obama-spirit.jpg); 
	width: 760px;
	height: 180px;
	position:relative;
	overflow:hidden;
}
.overlay-image
{
	background-image: url(http://www.artzstudio.com/files/png-alpha-transparency/obama-fireworks-png8-dither.png);
	_filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='obama-fireworks-png8-dither.png', sizingMethod='scale');	
	position:absolute;
	right:0;
	top:20px;
	width: 200px;
	height: 194px;
}
.patriot
{
	background-image: url(http://www.artzstudio.com/files/png-alpha-transparency/obama-spirit-red.jpg); 
}
</style>
<div class="overlay-header">
<div class="overlay-image">
	</div>
</div>
<p>And if the boss said to make the background more patriotic, we can do so without affecting our transparent image.</p>
<div class="overlay-header patriot">
<div class="overlay-image">
	</div>
</div>
<p>What a catchy campaign slogan!</p>
<h2>The Drop Shadow</h2>
<p>I almost forgot the drop shadow! Well, I did forget it, I am editing this post just after I published it. Here is how a two color logo faired with a drop shadow.</p>
<table cellpadding="0" cellspacing="10" border="0" style="background-image:url(http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-bg.png); color:#000;">
<tr>
<td align="center">Photoshop PNG-24<br />
	<b>25232 bytes</b></td>
<td align="center">Fireworks PNG-8<br />
	<b>7150 bytes (72%)</b></td>
<td align="center">Fireworks PNG-8 (dithered)<br />	<br />
	<b>8615 bytes (66%)</b></td>
<td align="center">ImageOptim<br />	<br />
	<b>23255 bytes (8%)</b></td>
</tr>
<tr>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-photoshop.png" alt="obama logo with photoshop"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-fireworks-png8.png" alt="fireworks"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-fireworks-png8-dither.png" alt="fireworks dithered"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-imageoptim.png" alt="fireworks dithered"></td>
</tr>
</table>
<p>In this one, my vote is for the Fireworks PNG-8 dithered with a whopping savings of 66% and a decent looking shadow.</p>
<p> Let&#8217;s add a gradient to the logo, and see how that looks.</p>
<table cellpadding="0" cellspacing="10" border="0" style="background-image:url(http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-bg.png); color:#000;">
<tr>
<td align="center">Photoshop PNG-24<br />
	<b>42264 bytes</b></td>
<td align="center">Fireworks PNG-8<br />
	<b>11049 bytes (74%)</b></td>
<td align="center">Fireworks PNG-8 (dithered)<br />	<br />
	<b>13909 bytes (67%)</b></td>
</tr>
<tr>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-gradient-photoshop.png" alt="obama logo with photoshop"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-gradient-fireworks.png" alt="fireworks"></td>
<td><img src="http://www.artzstudio.com/files/png-alpha-transparency/obama-drop-shadow-gradient-fireworks-dither.png" alt="fireworks dithered"></td>
</tr>
</table>
<p>At first glance, the dithered version would be my choice. However, if you look close enough, you see some odd dark specks here that just don&#8217;t belong. I tried to get rid of them in Fireworks, but my skills there are lacking. In this situation I would probably modify the source image to get the result I wanted. 1/2 point for effort, Fireworks.</p>
<h2>PNG8 Graceful Degradation in IE 6</h2>
<p>The final thing I&#8217;d like to echo with Stoyan and Alex about PNG8, is how gracefully it degrades in IE6.</p>
<p><img src="http://www.artzstudio.com/files/png-alpha-transparency/ie-6-vs-ie-7-png8-transparency.png" width="477" height="298" alt="Ie 6 Vs Ie 7 Png8 Transparency"></p>
<p>Notice that all pixels that had transparency applied (the drop shadow) disappear, allowing for a graceful degradation in IE6. For most cases, this will be entirely acceptable and allow us to <b>avoid the performance penalty and CSS hack</b> associated with AlphaImageLoader, the traditional way to enable alpha transparency support in IE 6. </p>
<p>Take a look at how wide your IE6 audience is, and make a call on if it&#8217;s worth the design/performance tradeoff to fully support it.</p>
<h2>Findings and Conclusions</h2>
<p>At the end of the day, the score was +1 for Photoshop PNG-24, +1 for ImageOptim, and +2.5 for Fireworks PNG-8 (dithered). Because of Fireworks&#8217; poor performance on the first two scenarios, there is  <i>n</i><i>o clear winner</i>.</p>
<p>With my late discovery of Fireworks PNG-8, I went into this article thinking I would have the end all answer for saving out PNGs. If you&#8217;ve been reading, you know that it&#8217;s not quite so simple. We simply need better tools; preferably, <b>one tool</b>.</p>
<p>My final thought on a designer-friendly transparent PNG workflow:</p>
<ol>
<li>Save out your transparent PNG out of Photoshop as PNG-24, and take note of the size.</li>
<li>Open the PNG-24 in Fireworks, and export it as PNG-8 with Alpha Transparency (play with the <i>dither</i> option), and take note of the size(s).</li>
<li>Run your Photoshop PNG-24 through ImageOptim, and see if you saved anything.</li>
<li>Make a final decision based on quality, size and longevity (e.g. how long will the image be around, how important is it?).</li>
</ol>
<p>There seems to be a <b>big gap on the GUI PNG tool side</b> for saving out high quality, low file size PNGs. While command line tools exist, they are not a realistic answer for designers who haven&#8217;t ever launched a terminal window, and for developers who don&#8217;t have the time or patience to compile source code.</p>
<p>I want to encourage Adobe to look at the available open source PNG tools and <b>get them into Photoshop CS4&#8217;s Save For Web</b>, where it belongs.</p>
<p>Until that happens, I am going to have to respectfully disagree with Stoyan and Alex that PNG-8 is the clear winner, as in 2 of the important use cases above, it wasn&#8217;t.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artzstudio.com/2008/07/png-alpha-transparency-no-clear-winner/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Beating Blocking JavaScript: Asynchronous JS</title>
		<link>http://www.artzstudio.com/2008/07/beating-blocking-javascript-asynchronous-js/</link>
		<comments>http://www.artzstudio.com/2008/07/beating-blocking-javascript-asynchronous-js/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 19:03:51 +0000</pubDate>
		<dc:creator>ArtzStudio</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[engineering]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false">http://www.artzstudio.com/?p=10</guid>
		<description><![CDATA[
MSN is now implementing a technique for loading JavaScript in a way that doesn&#8217;t stall the rendering of the document. They use Dynodes, a technique I also recommend for loading functionality on demand so it only consumes bandwidth when it is needed.
JavaScript Blocks Everything
To see the problem, view a Pagetest waterfall report of pretty much [...]]]></description>
			<content:encoded><![CDATA[<p><img class="doodle" src="http://www.artzstudio.com/files/asynchronous-js/blocking-js.png" alt="" width="193" height="118" />
<p>MSN is now implementing a technique for loading JavaScript in a way that doesn&#8217;t stall the rendering of the document. They use <a href="http://www.mindsack.com/uxe/dynodes/"><i>Dynodes</i></a>, a technique I also recommend for loading functionality on demand so it only consumes bandwidth when it is needed.</p>
<h2>JavaScript Blocks Everything</h2>
<p>To see the problem, view a <a href="http://www.webpagetest.org">Pagetest waterfall report</a> of pretty much any website today, or see this <a href="http://pagetest.patrickmeenan.com:8080/results/ZB/">recent run of AOL.com</a>. Notice that <b>1 second </b>is spent downloading and executing JavaScript, <b>one at a time</b>.</p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/aol-blocking.png" alt="waterfall graphic of aol javascript blocking rendering" width="519" height="227" /></p>
<p> One by one, folks! This is how all browsers load JavaScript (unless the <code>defer</code> attribute is used in IE) when called from your standard <a href="http://www.w3schools.com/TAGS/tag_script.asp">HTML <code>&lt;script&gt;</code> element</a>.</p>
<p>However, viewing a <a href="http://pagetest.patrickmeenan.com:8080/results/1WD/waterfall.html?run=1">waterfall report of MSN</a>, we can see that they call 3 JavaScript files (dap.js, hptr.js, and hp.js) asynchronously, and  allow the subsequent CSS files to load right away. </p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/msn-no-blocking.png" alt="waterfall graphic of msn javascript not blocking" width="508" height="205" /></p>
<p>Had their scripts loaded in the standard way, dap.js, hptr.js, and hp.js would delay the page for <b>1.4 seconds!</b></p>
<h2>Loading JavaScript Asynchronously</h2>
<p>MSN is using standard DOM functions to create and append a script element to the HTML document&#8217;s <code>&lt;head&gt;</code> element. This technique, originally coined as <a href="http://www.mindsack.com/uxe/dynodes/"><i>Dynodes</i></a>, is encapsulated in a JavaScript loader, much like the one used by JS frameworks such as Dojo. </p>
<p>We downloaded and formatted the <a href="http://www.artzstudio.com/files/asynchronous-js/msn-source-code-formatted.html">MSN.com HTML source code</a> so you can have a closer look at it. Start on line 297 which kicks off a process to a function aptly named <code>JS</code>:</p>
<pre>(function(){}).JS(Msn.Page.Track).JS(Msn.Page.Js)</pre>
<p>Note that it is passed in two URLs defined back on Lines 13-19:</p>
<pre>
Msn={
	Page:{
		SignedIn:'False',
		Js:'<b>http://stj.msn.com/br/hp/en-us/js/46/hp.js</b>',
		Track:'<b>http://stj.msn.com/br/hp/en-us/js/46/hptr.js</b>',
</pre>
<p>The <code>JS</code> function kicks off a  method that  pulls down these two scripts. Take a look at line 130 to get to the heart of this technique:</p>
<pre>var c=g.createElement("script");
c.type="text/javascript";
c.onreadystatechange=n;
c.onerror=c.onload=k;
c.src=e;
p.appendChild(c)</pre>
<p>The <code>&lt;script&gt;</code> element (<code>c</code>) is appended to the <code>&lt;head&gt;</code> element (<code>p</code>), as defined back on line 113.</p>
<p>MSN also appears to be closely monitoring the load of all the scripts called by <code>JS</code>, in case something happens during the process. Event handlers are set on <code>readystatechange</code>, <code>error</code>, and <code>load</code> to stop the polling process (fired every 100ms) once the script is finished.</p>
<p>Their code is quite obfuscated and difficult to follow, but you can look for the timeout function on line 125. There also appears to be an optional parameter to kill the process after a specified period of time.</p>
<h2>JS Loader Prototype</h2>
<p>We designed a <a href="http://www.artzstudio.com/files/asynchronous-js/js-loader.html">JS Loader Prototype</a> (not nearly as fancy as MSN&#8217;s) that illustrates the benefits of this technique, and tested behaviors in IE and Firefox.</p>
<p>In our prototype (we strongly suggest you view the source now), the code is organized into 4 sections:</p>
<ul>
<li>JavaScript #1 and #2 are called from  a <code>&lt;script&gt;</code> block in the  <code>&lt;head&gt;</code> using our JS Loader function.</li>
<li>JavaScript #3 and #4 follow next, called by the JS Loader in a <code>&lt;script&gt;</code> block in the <code>&lt;body&gt;</code>.</li>
<li>JavaScript #5 and #6 are called after some text again by the JS Loader,  from a second <code>&lt;script&gt;</code> block in the <code>&lt;body&gt;</code>.</li>
<li>Finally, #7 and #8 are loaded in the traditional, HTML <code>&lt;script&gt;</code> element fashion.</li>
</ul>
<p>In Internet Explorer, the script files queued up normally and the screen was not blocked for any period of time (until #7 and #8). Notice a <b>very short Start Render time</b> in our <a href="http://pagetest.patrickmeenan.com:8080/results/1WT/waterfall.html?run=1">test run at Pagetest</a>, and JS loading <b>as fast as HTTP1.1&#8217;s 2 connection per domain limit will allow it</b>:</p>
<p><a href="http://pagetest.patrickmeenan.com:8080/results/1WT/waterfall.html?run=1"><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-ie.png" alt="waterfall chart of js loader prototype in ie showing full asynchronous load" width="731" height="160" /></a></p>
<p>In Firefox, however, any content below the <b>next</b> inline HTML <code>&lt;script&gt;</code> section is blocked until the scripts from the <b>previous</b> inline HTML <code>&lt;script&gt;</code> section called by the loader are complete. <a href="http://www.artzstudio.com/files/asynchronous-js/js-loader.html">You have to see it to believe it!</a></p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-ff.png" alt="waterfall chart of firefox blocking until all js has download in each script block" width="547" height="172" /></p>
<p>Notice in the above chart, within each script block both JavaScript must fully load before the next script block is allowed to start processing. The takeaway here is to include as many JS Loader calls as possible in one script block.</p>
<p>We developed a workaround for this issue by including a <b>timeout delay</b> before calling the script. This allows Firefox to continue rendering like IE and Safari, and affords the fastest possible download. <a href="http://www.artzstudio.com/files/asynchronous-js/js-loader-ff.html">See the updated JS Loader Prototype for Firefox here.</a></p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-ff-delay.png" alt="waterfall of updated prototype showing that firefox no longer blocks other scripts" width="553" height="168" /></p>
<p>We put a longer delay on the first script (10 seconds) so you can see that Firefox no longer waits until the script block has completed before loading others. The important bit of code looks like this:</p>
<pre>
js:function(url)
{
	// If you want to call IE and Safari straight up without the delay, uncomment this.
	// (navigator.userAgent.search('Firefox')) ? js = setTimeout("artz.create('"+url+"')", 0) : artz.create(url);
	js = setTimeout("artz.create('"+url+"')", 0);
},
create:function(url)
{
	s = artz.ce('script');
	s.type = 'text/javascript';
	s.src = url;
	artz.tag('head')[0].appendChild(s);
},
</pre>
<p>You will be pleased to know that Safari renders much like IE, with the added benefits of <b>4 open socket connections!</b></p>
<p><img src="http://www.artzstudio.com/files/asynchronous-js/js-loader-safari.png" alt="waterfall shot of safari with 4 open socket connections" width="508" height="270" /></p>
<p>Hopefully the benefits to this approach are clear. With a large site like MSN faithfully using Dynodes for their scripts, it might just be the time to <b>standardize on this approach</b>.</p>
<h2>Race Condition Challenges</h2>
<p>Not so fast! (pardon the pun) There are some additional considerations we will need to think through when moving in this direction.</p>
<ul>
<li>JavaScript <b>functions</b> in the external scripts <b>may not be available </b>when inline HTML JavaScript functions call for them.</li>
<li>Along the same lines, even if Script A is called before Script B, Script B may finish and execute before Script A. </li>
<li>DOM <b>elements may not yet be available</b> in the HTML should an external script need them to hook events, access data from, etc.</li>
</ul>
<p>In tackling the above, we would first recommend following the <a href="http://en.wikipedia.org/wiki/Progressive_enhancement">Progressive Enhancement</a> approach, and work to completely eliminate inline HTML JavaScript function calls. The external scripts can latch any events needed on to links, buttons, etc., once they are ready.</p>
<p>While race conditions may still exist, a way to solve this is using the <code>setInterval</code> function to initialize your functions where you know a race condition may exist.</p>
<pre>function id(id){return document.getElementById(id)}

var oranges =
{
	init: function()
	{
		if(id('oranges'))
		{
			clearInterval(oranges_init);
			alert('We have oranges!');
			// We may proceed with orange code!
		}
	}
}

oranges_init = setInterval("oranges.init()", 100);</pre>
<p>We recommend using a period of 100ms to go easy on the CPU, and <a href="http://www.useit.com/papers/responsetime.html">still feel instantaneous to users</a>. To see this code in action, have a look at our <a href="http://www.artzstudio.com/files/asynchronous-js/id-polling.html">ID Polling Prototype</a>.</p>
<h2>Document.Wrong</h2>
<p>External scripts loaded that include the infamous<code> document.write</code> method executed by the script  will cause problems with this technique. Be sure to wrap it in a function and call it  from the HTML if you decide to head down this path. We hope that by now, you have thrown this ancient tool away.</p>
<p>Advertising vendors&#8230;this means <b>you</b>!</p>
<h2>Final Thoughts</h2>
<p>This technique has been on the back shelf for some time due to the tricky Firefox and race condition issues. </p>
<p>That said, if we are careful, and with MSN proving its value, now just may be the time to <b>adopt Dynodes as a standard JavaScript loading practice</b>.</p>
<p>Leave us a comment with your thoughts, questions, and <b>concerns</b>, and post links to implementations that leverage this!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artzstudio.com/2008/07/beating-blocking-javascript-asynchronous-js/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
