<!DOCTYPE html>
<!-- ========================================== kroc camen of camen design ============================================= -->
<title>code · Under the Hood #1:  Is a PNG 32-Bit? in One Line</title>
<link rel="stylesheet" type="text/css" href="/design/design.css" />
<meta name="viewport" content="width=device-width, maximum-scale=1.0, user-scalable=no" />
<link rel="alternate" type="application/rss+xml" href="/code/rss" title="Just code" />
<link rel="canonical" href="/code/uth1_is-png-32bit" />
<!-- =================================================================================================================== -->
	<h1><a href="/" rel="index">
		Camen Design
		<li><a href="/">all</a></li>
		<li><a href="/projects">projects</a></li>
		<li><a href="http://forum.camendesign.com">forum</a></li>
		<li><a href="/quote/">quote</a></li>
		<li><a href="/writing/">writing</a></li>
		<li><a href="/blog/">blog</a></li>
		<li><a href="/photo/">photo</a></li>
		<li><a href="/code/" rel="tag">code</a></li>
		<li><a href="/art/">art</a></li>
		<li><a href="/link/">link</a></li>
		<li><a href="/poem/">poem</a></li>
		<li><a href="/audio/">audio</a></li>
		<li><a href="/web-dev/">web-dev</a></li>
		<li><a href="/annoyances/">annoyances</a></li>
		<li><a href="/eve/">eve</a></li>
		<li><a href="/code-is-art/">code-is-art</a></li>
		<li><a href="/inspiration/">inspiration</a></li>
		<li><a href="/windows/">windows</a></li>
		<li><a href="/gaming/">gaming</a></li>
		<li><a href="/gift/">gift</a></li>
		<li><a href="/mac/">mac</a></li>
		<li><a href="/osnews/">osnews</a></li>
		<li><a href="/c64/">c64</a></li>
		<li><a href="/linux/">linux</a></li>
	<a rel="previous" href="/code/cleanly-grouping-by">
		older article →
	</a><a rel="next" href="/code/uth2_css3-hyperlinks">
		← newer article
<!-- =================================================================================================================== -->
	<!-- date published or updated -->
	<time pubdate datetime="2008-07-05T18:06:00+01:00">
		<sup>6:06<abbr>pm</abbr> • 2008</sup>
		<abbr title="July">Jul</abbr> 5
	<!-- categories -->
		<li><a href="/code/uth1_is-png-32bit" rel="bookmark tag">code</a></li>
		<li><a href="/code-is-art/uth1_is-png-32bit">code-is-art</a></li>
		<li><a href="/web-dev/uth1_is-png-32bit">web-dev</a></li>
	<!-- licence -->
		<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_GB">c</a>
		share + remix
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h1>Under the Hood #1: <br />Is a PNG 32-Bit? in One Line</h1>
	“Under The Hood” is a series breaking down many of the PHP and CSS tricks used in this website to make it more compact and artistically coded
	<strong>To begin</strong> with, I wanted to showcase something very simple, that one could spend many lines of code
	on. For the <a href="?art">art</a> and <a href="?photo">photo</a> sections of the site, I have an upload form
	that attaches an image as an RSS enclosure to the post, and resizes the image for a preview on the home page.
	I’m touchy when it comes to image quality and use PNG wherever possible. I compress my PNGs with PNGCrush
	(Specifically an excellent Dashboard widget called <a href="http://www.plasticvicar.com/PNGpong/">PNGPong</a>)
	But I also love transparency in PNGs. It’s incredibly flexible, and I’d rather (for maintenance reasons) be able
	to upload 32-bit images when possible. Thankfully PHP can resize 32-bit PNGs without destroying the alpha channel,
	via the
	<a href="http://uk3.php.net/manual/en/function.imagealphablending.php"><code>imagealphablending</code></a> /
	<a href="http://uk3.php.net/manual/en/function.imagesavealpha.php"><code>imagesavealpha</code></a> commands.

<h2>Choosing the Right Preview</h2>
	The programming issue is of being able to choose the right file type for the preview image shown on the site.
	<dt id="">JPG upload → JPG preview</dt>
	<dt id="">PNG (without transparency) upload → JPG preview</dt>
		Why would I want to save the preview image as a JPG if I’m fussy about quality?<br />
		Simply because this site is also supposed to be fast to load, and a PNG image that is resized has many more
		colours due to the anti-aliasing when resizing, causing the file size to bloat massively.
	<dt id="">PNG (with transparency) upload → PNG preview</dt>
		A resized transparent PNG, without keeping the transparency would just have a horrible black background. We
		can’t be having that

<h2>The Code</h2>
	All credit for this however goes to Wesley Gunn who posted a
	<a href="http://uk3.php.net/manual/en/function.imagecolortransparent.php#79145">solution</a> on the PHP website,
	and that I improved upon to condense it into one line. Here’s the original:

<pre><code>$readPng = fopen  ($argSourceImagePath, "rb");
$readAlp = fread  ($readPng, 52);
           fclose ($readPng);

if(substr(bin2hex($readAlp),50,2) == "04" || substr(bin2hex($readAlp),50,2) == "06")
echo("Png has alpha");</code></pre>

	Here’s a break down of what’s happening here:

<pre><code>//open the image file, "Read Binary"
$readPng = fopen  ($argSourceImagePath, "rb");
//read 52 Bytes. this is the PNG header up to the byte(s) that specify transparency
$readAlp = fread  ($readPng, 52);
//close the file
           fclose ($readPng);

//`bin2hex` converts the PNG header to hexadecimal codes, and `substr` strips out the two bytes that
//specify the PNG transparency - "04" is for a greyscale PNG with transparency, and "06" for a 32-bit PNG
if(substr(bin2hex($readAlp),50,2) == "04" || substr(bin2hex($readAlp),50,2) == "06")
echo("Png has alpha");</code></pre>

	Whilst this is a very good way to achieve the task, I hate spawning temporary variables and would like to do this
	same thing inline so that it could be combined with any <code>if</code> statement. The first thing to do is to read
	the file without having to use a file handle to open and close the file.
	<br /><br />
	Here is my redesign of this code:

<pre><code>$is_alpha = ord (file_get_contents ($file_path, false, null, 25, 1)) &amp; 4;</code></pre>

	<q><a href="http://uk.php.net/file_get_contents"><code>file_get_contents</code></a></q> returns the contents of a
	file without having to open and close handles, but has the added ability to return a chosen number of bytes,
	starting at a set offset. Perfect! This isn’t binary however, and thus each pair of bytes is treated as a single
	‘letter’, meaning that the transparency flag is the 25<sup>th</sup> along using <code>file_get_contents</code>
	instead of 50. We return just one ‘letter’, and
	<a href="http://uk2.php.net/manual/en/function.ord.php"><code>ord</code></a> returns the <abbr>ASCII</abbr>
	numerical representation of that ‘letter’, either 4 or 6.
	This is also a super fast solution, as <code>file_get_contents</code> is only reading two bytes and that’s it,
	this operation is also cached by PHP.
	Finally the “<code>&amp; 4;</code>” bitwise ANDs the result ignoring all other values that do not contain
	transparency. An example below demonstrates the bitwise operation filtering out both values 4 and 6, and ignoring
	other values

<pre>00000110 = Binary 6 - a transparent PNG
00000100 = “&amp; 4” mask, only a 1 on the top row and 1 on the bottom row pass through, giving:
00000100 = 4

00000100 = Binary 4 - a greyscale transparent PNG
00000100 = “&amp; 4”
00000100 = 4

An example of an unwanted value
00000011 = Binary 3 - not a transparent PNG
00000100 = “&amp; 4”
00000000 = 0</pre>

	Therefore my code will return 4 if the PNG is transparent, and 0 if not. In PHP, zero is considered false, and any
	number higher than zero is considered true. Thus you can easy place this code in an <code>if</code> without having
	to specifically check for <q>4</q>, e.g.

<pre><code>if (ord (file_get_contents ($file_path, false, null, 25, 1)) &amp; 4) {
	//PNG is transparent...
} else {
	//PNG is not transparent...

	This code will not detect a 256 colour (8-bit) PNG, with transparency (like a <abbr>GIF</abbr>). The normal
	transparency flag is not set in this instance; instead this could be detected by the presence of both “PLTE”
	(‘Palette’ - 256 colours) and “tRNS” in the file. Although the precise location of these is not fixed
	because the size of the palette can vary.
	In order to work around this, I’d just re-save any 8-bit PNG with transparency as a 32-bit one - it’d increase
	file size, but not by a painful amount.
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
	<nav><a href="http://forum.camendesign.com">‹ Discuss this in the Forum ›</a></nav>
	<a href="mailto:kroc@camendesign.com">kroc@camendesign.com</a>
		<a href="/code/uth1_is-png-32bit.rem">Rem</a> •
		<a href="/code/uth1_is-png-32bit.html">HTML</a> •
		<a href="/design/">CSS</a> •
		<a href="/.system/">PHP</a> •
		<a href="/.htaccess">.htaccess</a>
	<form method="get" action="https://duckduckgo.com">
		<input type="hidden" name="sites" value="camendesign.com" />
		<input type="search" name="q" placeholder="search…" />
		<input type="submit" value="Go" />
<!-- =================================================================================================== code is art === -->