I was trying to read the dimensions of some very large image files today when I bumped into the Flash Player 10 limitations regarding maximum image sizes. (More info about this is available here.) Since an image file that is too big will not be shown correctly, there is no use in uploading and using it. I wanted to provide detailed feedback about the image dimensions and how they exceeded the allowed sizes, but that was not possible unfortunately since the width and height properties of the loaded image would remain 0. (I posted a question on StackOverflow about this issue here.)
The JPGSizeExtractor class by Antti Kupila enables you to read the width and height of a JPG by reading the image's bytecode. Since we also need to support PNG files, I thought I'd create a simple PNGSizeExtractor myself.
Here's the code:
-
package com.herrodius.utils {
-
-
import flash.utils.ByteArray;
-
-
/**
-
* Reads the width and height from a PNG image.
-
*
-
* http://en.wikipedia.org/wiki/Portable_Network_Graphics
-
* http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html
-
*
-
* @author Christophe Herreman
-
*/
-
public class PNGSizeExtractor {
-
-
private static const SIGNATURE_BYTES:Array = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
-
-
private static const CHUNK_TYPE_SIZE:uint = 4;
-
-
// --------------------------------------------------------------------
-
//
-
// Constructor
-
//
-
// --------------------------------------------------------------------
-
-
public function PNGSizeExtractor(byteArray:ByteArray) {
-
decode(byteArray);
-
}
-
-
// --------------------------------------------------------------------
-
//
-
// Public Properties
-
//
-
// --------------------------------------------------------------------
-
-
// ----------------------------
-
// width
-
// ----------------------------
-
-
private var _width:uint;
-
-
public function get width():uint {
-
return _width;
-
}
-
-
// ----------------------------
-
// height
-
// ----------------------------
-
-
private var _height:uint;
-
-
public function get height():uint {
-
return _height;
-
}
-
-
// --------------------------------------------------------------------
-
//
-
// Private Methods
-
//
-
// --------------------------------------------------------------------
-
-
private function decode(data:ByteArray):void {
-
readSignature(data);
-
readIHDR(data);
-
}
-
-
private function readSignature(data:ByteArray):void {
-
for (var i:uint = 0; i<SIGNATURE_BYTES.length; i++) {
-
if (data.readUnsignedByte() != SIGNATURE_BYTES[i]) {
-
throw new Error("File is not a PNG file.");
-
}
-
}
-
}
-
-
private function readIHDR(data:ByteArray):void {
-
var size:uint = data.readUnsignedInt();
-
var type:String = data.readUTFBytes(CHUNK_TYPE_SIZE);
-
_width = data.readUnsignedInt();
-
_height = data.readUnsignedInt();
-
}
-
-
}
-
}
And here's how to use it. (byteArray is the data of the loaded PNG):
-
var pngDecoder:PNGSizeExtractor = new PNGSizeExtractor(byteArray);
-
trace(pngDecoder.width, pngDecoder.height);
And here is a small sample application that loads the file locally:
-
<?xml version="1.0"?>
-
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="left">
-
-
<mx:Script>
-
<![CDATA[
-
import com.herrodius.utils.PNGSizeExtractor;
-
-
import mx.controls.Alert;
-
-
private var _fileReference:FileReference;
-
-
private function browseButton_clickHandler(event:MouseEvent):void {
-
_fileReference = new FileReference();
-
_fileReference.addEventListener(Event.SELECT, fileReference_selectHandler);
-
_fileReference.addEventListener(Event.COMPLETE, fileReference_completeHandler);
-
_fileReference.browse();
-
}
-
-
private function fileReference_selectHandler(event:Event):void {
-
_fileReference.load();
-
}
-
-
private function fileReference_completeHandler(event:Event):void {
-
fileNameTextInput.text = _fileReference.name;
-
-
try {
-
var pngDecoder:PNGSizeExtractor = new PNGSizeExtractor(_fileReference.data);
-
textArea.text = "Width: " + pngDecoder.width + "\n";
-
textArea.text += "Height: " + pngDecoder.height;
-
} catch (e:Error) {
-
Alert.show(e.message, "Error decoding image");
-
}
-
}
-
-
]]>
-
</mx:Script>
-
-
<mx:Label text="Browse for a PNG file." fontWeight="bold"/>
-
-
<mx:HBox width="100%">
-
<mx:TextInput id="fileNameTextInput" width="100%" editable="false"/>
-
<mx:Button id="browseButton" label="..." click="browseButton_clickHandler(event)"/>
-
</mx:HBox>
-
-
<mx:TextArea id="textArea" width="100%" height="100%"/>
-
-
</mx:Application>
Add to Bloglines - Digg This! - del.icio.us - Stumble It! - Twit This! - Technorati links - Share on Facebook - Feedburner
On November 18th, I'll be doing a presentation on
Christophe Herreman is a software developer living in Belgium. He's working on high-end Flex and AIR solutions at 
Recent Comments