Antti Kupila

Personal Blog, Portfolio and Online playground

View over the green room at Sid Lee, Montreal

Getting JPG dimensions with AS3 without loading the entire file

Does this sound familiar: You’re loading a JPG file, and want to know what size it is before it has loaded? This can be useful if you’re for example drawing a border/background, which will contain the image. If you don’t know what size the image is, you don’t know what size the box should be. I’m sure there are better & more common uses to this, but i know for sure it can be really useful.

Anyway, I decided to solve this problem. If you don’t care about how it works, fine, i’ll give you the short version first. After all the class i’ve created does all the heavy lifting for you, so if you just want to have it work, you can just use it without worrying about what’s under the hood.

Here’s the class: JPGSizeExtractor.as. Download it and put it in a folder com/anttikupila/utils in your classpath. Then you can just use it like this:

[as]
var je : JPGSizeExtractor = new JPGSizeExtractor( );
je.addEventListener( JPGSizeExtractor.PARSE_COMPLETE, sizeHandler );
je.extractSize( your_jpg_file.jpg );

function sizeHandler( e : Event ) : void {
trace( “Dimensions: ” + je.width + ” x ” + je.height );
}
[/as]

To trace out debug information, you can say je.debug = true;

What it actually does is that it starts loading the JPG file and analyzes every byte that has loaded. When it find the jpg’s JFIF headers (according to the JPEG specs), it will be able to determine the dimension of the file and close the stream. The dimensions in a jpg are before the actual image info, meaning that you can load a 10mb file and get it’s dimensions in a fraction of a second, instead of waiting for the entire file to load.

Note: This doesn’t work for all files. Some files i tried with were not according to the JPEG specs (or then i misunderstood something, which is more likely since other software showed the correct dimensions). Don’t use this in mission critical projects, unless you have control over the JPG files. I don’t take any responsibility of it working correctly.

Download the class, with an example

If you’re not so much interested in “the what”, but more “the how”? Read on. Let’s see what we can do about that .. ;)

What we need to do is look at the JPEG specs to see where the image dimensions are stored. Then just go to that place in the file and read out those dimensions. Simple enough, ‘aye? Well, it pretty much is, but there are some bumps on the road..

First we have to know how a JPEG file is structured. Luckily JPEG is a very common file format, and there’s plenty of documentation online. Fire up a hex editor and open a jpg image to see what’s actually happening. Note that 0x stands for a hex number, 0x0A = 10, 0xA0 = 160

This is the basic structure (a jpg can contain more sections, but these are the most common ones):

Identifier Name Description
0xFF 0xD8 SOI Start of Image
0xFF 0xE0 APP0 First JFIF segment
0xFF 0xEn APPn An application specific segment, where n = 1—F
0xFF 0xDB DQT Define Quantization Table
0xFF 0xC0 SOF0 Start of frame 0
0xFF 0xC4 DHT Define Huffman Table
0xFF 0xDA SOS Start Of Scan
0xFF 0xDD DRI Define Restart Interval
0xFF 0xD9 EOI End of Image

If we take a closer look at SOF0′s structure, we’ll notice something we want to see..

  1. 0xFF 0xC0 (SOF0 identifier)
  2. length (high byte, low byte), 8+components*3
  3. data precision (1 byte) in bits/sample, usually 8 (12 and 16 not supported by most software)
  4. image height (2 bytes, Hi-Lo), must be >0 if DNL not supported
  5. image width (2 bytes, Hi-Lo), must be >0 if DNL not supported
  6. number of components (1 byte), usually 1 = grey scaled, 3 = color YCbCr or YIQ, 4 = color CMYK)
  7. for each component: 3 bytes
    1. component id (1 = Y, 2 = Cb, 3 = Cr, 4 = I, 5 = Q)
    2. sampling factors (bit 0-3 vert., 4-7 hor.)
    3. quantization table number

So, what we want to look for is SOF0 and from there get the width & height of the image. SOF0 is identified by 0xFF 0xC0, so if we find that, we’re pretty much done. The following image shows you the header of an actual 200x200px jpg file (0x00 0xC8 = 200) with the header info highlighted.

JPG SOF header information - FF C0 00 11 08 00 C8 00 C8 03 01 11 00 02 11 01 03 11 01

The other info we don’t really need, but it makes it easier to find the correct address in the file when we have more info. Now we know where & how the information is stored. Now we just need to find it :)

What we want to look for is 0xFF 0xC0, but since the length in most cases will be 0x11 (17) bytes (8 + 3×3 as we’re assuming it’s an RGB image) and the bitdepth is 8bit (12bit jpg’s exist in medical imaging, but they are rarely supported by consumer software), we can require those too. In other words we can look for 0xFF 0xC0 0x00 0x11 0x08.

[as]
protected static const SOF0 : Array = [ 0xFF, 0xC0 , 0x00 , 0x11 , 0x08 ];
[/as]

What we do is simply to examine every incoming byte and check if it matches with the SOF0′s first byte. If it does, we take the next byte, and the next, until we have matched all the bytes in the header and know we’re at the correct place. After this we can just read the height & width of the file.

[as]
var index : int = 0;
while ( bytesAvailable >= SOF0.length + 4 ) {
if ( byte == SOF0[ index ] ) {
index++;
if ( index >= SOF0.length ) {
jpgHeight = readUnsignedShort( );
jpgWidth = readUnsignedShort( );
break;
}
}
}
[/as]

The code is pretty straightforward if you’ve worked with ByteArrays before. In order for us not to go outside the range of the file that has loaded so far (as we’re running this on progress–not on complete–we know a portion of the file has loaded, not the whole file), we check that enough bytes are available. We create a loop that compares every byte with the array and moves on the the next byte if a match is found. When the position matches the length of the array, we know that we’ve matched the entire header and can read out the dimensions. As you can see from the image & specs earlier in this post, the dimension are stored as shorts (2 bytes each, hence the + 4 in the while loop). If you try this, it actually works..

..in most cases. The problem is that a jpg file may contain more than just one image. Why? Well, a jpg may have other info embedded, such as thumbnails also stored as jpgs inside the jpg. This means that if we just pick the first SOF0, we might end up with a thumbnail’s SOF0. Save for web in photoshop, for example, doesn’t embed a thumbnail while the normal save as does. Hence you might get different (wrong) results on the normally saved file if you just pick the first SOF0. Now, how can we solve this?

Taking a closer look at the JPEG specs we notice something called APPn segments. These are segments that contain additional info, such as EXIF information. The thumbnail is in here, if it exists. So, what we need to look for first is the APPn sections, and if we find any, skip them as all the image info in there is wrong anyway. As every other JPEG segment, the APPn segment’s identifiers are always followed by the segment’s length, so when we find an APPn section’s identifier, we can just read the next short and skip that amount of bytes. Seems simple enough :)

Here’s the complete function from the class, which does just that

[as]
protected function progressHandler( e : ProgressEvent ) : void {
dataLoaded = bytesAvailable;
var APPSections : Array = new Array( );
for ( var i : int = 1; i < 16; i++ ) {
APPSections[ i ] = [ 0xFF, 0xE0 + i ];
}
var index : uint = 0;
var byte : int = 0;
var address : int = 0;
while ( bytesAvailable >= SOF0.length + 4 ) {
var match : Boolean = false;
// Only look for new APP table if no jump is in queue
if ( jumpLength == 0 ) {
byte = readUnsignedByte( );
address++;
// Check for APP table
for each ( var APP : Array in APPSections ) {
if ( byte == APP[ index ] ) {
match = true;
if ( index+1 >= APP.length ) {
if ( traceDebugInfo ) trace( “APP” + Number( byte – 0xE0 ).toString( 16 ).toUpperCase( ) + ” found at 0x” + address.toString( 16 ).toUpperCase( ) );
// APP table found, skip it as it may contain thumbnails in JPG (we don’t want their SOF’s)
jumpLength = readUnsignedShort( ) – 2; // -2 for the short we just read
}
}
}
}
// Jump here, so that data has always loaded
if ( jumpLength > 0 ) {
if ( traceDebugInfo ) trace( “Trying to jump ” + jumpLength + ” bytes (available ” + Math.round( Math.min( bytesAvailable / jumpLength, 1 ) * 100 ) + “%)” );
if ( bytesAvailable >= jumpLength ) {
if ( traceDebugInfo ) trace( “Jumping ” + jumpLength + ” bytes to 0x” + Number( address + jumpLength ).toString( 16 ).toUpperCase( ) );
jumpBytes( jumpLength );
match = false;
jumpLength = 0;
index = 0;
} else break; // Load more data and continue
} else {
// Check for SOF
if ( byte == SOF0[ index ] ) {
match = true;
if ( index+1 >= SOF0.length ) {
// Matched SOF0
if ( traceDebugInfo ) trace( “SOF0 found at 0x” + address.toString( 16 ).toUpperCase( ) );
jpgHeight = readUnsignedShort( );
jpgWidth = readUnsignedShort( );
if ( traceDebugInfo ) trace( “Dimensions: ” + jpgWidth + ” x ” + jpgHeight );
removeEventListener( ProgressEvent.PROGRESS, progressHandler ); // No need to look for dimensions anymore
if ( stopWhenParseComplete && connected ) close( );
dispatchEvent( new Event( PARSE_COMPLETE ) );
break;
}
}
if ( match ) {
index++;
} else {
index = 0;
}
}
}
}

protected function jumpBytes( count : uint ) : void {
for ( var i : uint = 0; i < count; i++ ) {
readByte( );
}
}
[/as]

Yep, gets a hell of a lot more complicated because of this. But it works. I won't go through every single line here, as a lot of it is by now pretty self explanatory. What it basically does is it tries to find an APPn section (0xFF 0xE1, 0xFF 0xE2, 0xFF 0xE3 etc, up to 0xFF 0xEF), and if it does, it reads the following short and jumps that amount of bytes. Because of the nature flash where we're loading files over the network, we might not have that amount of info available yet so we have to queue up that jump until we have the info we need. Isn't working with networks just pure fun? ;)

Sidenote: I think it's quite weird that the URLStream does not extend ByteArray since it works almost the same way. Here the position property of ByteArray would have been useful for jumping bytes, but when it didn't exist, i had to do it with a for loop. Can anybody come up with a reason why it doesn't extend ByteArray?

Alright, we're pretty much done here. As I said in the beginning, this works almost every time. I found images that don't give any dimensions at all (when looking at the file they're not according to the specs, but still render fine in software, hmm..). If anybody has an idea of what's common to these files and how to solve this problem, i'd love to hear it :)

What all this shows to me–in addition to being a super useful class in real life projects–is the power of actionscript 3. I mean, getting jpg information (one could get exif info with this technique?) is just one thing, you could actually read and analyze any file. With this you could for example bring in formats that are not natively supported by flash. And well, a hell of a lot more. The sky is truly the limit.

Hope you found this useful, good luck :)

Download the class, with an example

Update Apr 10, 2007: the length in the description (11) should be 0x11. Fixed to avoid confusion

Update Sept 14, 2009: There was a bug that caused wrong dimensions sometimes to be returned for very large images. This has been fixed now.

Comments

76 Comments
  1. 2007-04-09, 4:59 by sike

    yeah, maybe we can use this to checked the flv size before load it to the stage.

  2. 2007-04-27, 2:54 by Kenneth Woodruff

    Or EXIF data! Nice work.

  3. 2007-04-27, 9:15 by Torben

    Thanks for this helpfully class – nice work!!!

  4. 2007-06-21, 14:09 by Getting JPG dimensions with AS3 without loading the entire file « Flash Enabled - Get Ready With Flash…

    [...] Read More. [...]

  5. 2007-06-21, 15:49 by Kevin Hoyt

    I actually just wrote an application that does exactly this same thing, though your is a bit cleaner. Here’s a twist though, I wrote it using the File IO features of AIR against local images on disk. Good times to have so many options!

    Nice work,
    Kevin

  6. 2007-06-21, 16:35 by Jaap Kooiker

    Excellent work! Thanx…

  7. 2007-06-21, 16:55 by Theo

    Good work, this could be really useful. But if I understand it correctly you stop loading as soon as you know the dimensions? Given that the overhead of establishing the connection is often the bottleneck for images that are not big (say over 1000 pixels to one side) it would be useful if this worked more like a regular loader, that is, instead of just notifying me when the image was loaded it first notifies me when the image size is available. Having to do two connections to get the image would in many cases double the load time (because establishing the connection takes almost as long as sending a couple of 100 K).

    On the other hand your implementation is great if I want to choose whether or not to load the image based on the dimensions.

  8. 2007-06-21, 18:55 by Jon B

    I agree with Theo, it would be cool if this was a regular loader which could fire an event as soon as the dimensions were downloaded and then optionally continue to load the rest of the image – although I imagine that if you did this the image wouldn’t get cached either (you are stream bytes rather than loading a whole image) – in some situations this would be a huge bonus – in others it wouldn’t be at all – but I think the option would be nice :)

  9. 2007-06-22, 17:38 by Antti Author comment

    Actually stopping the load progress is optional, so using it as a loader at the same time is already implemented (although not all events are fired, but that’s easy for anybody to add anyway, also a Event.COMPLETE probably shouldn’t be fired when the dimensions have been found, but when the file has completely loaded..). . Just put the second parameter to false in the extractSize function and it will continue loading (default is true)

  10. 2007-06-22, 20:17 by Mario Klingemann

    That’s a great idea – thanks for sharing it!

  11. 2007-06-26, 22:26 by Jon B

    Would I be right in thinking that the loaded image wouldn’t be cached? I’m not too sure on how URLStream works…

    This is really cool :)

  12. 2007-08-12, 19:02 by Matt W

    Dude – You are a genius – this is the cleverest class I’ve found to date and mega usefull! Much appreciate the public use of it – Will defo use this alot.

    You are a walking Legend!

  13. 2008-02-08, 12:28 by Barry

    Fantastic!

    Do you know what the max size image you are allowed to load is? I got an 8400x600px image, loads but just shows a black box …

    Sorry if this is off topic.

  14. 2008-02-08, 16:08 by Pawel

    Thanks a lot! That’s a very useful thing. I think I’m gonna use this class in my upcoming new portfolio site :]

  15. 2008-02-08, 18:48 by Antti Author comment

    Barry: There shouldn’t be a max limit, but i’m sure there can be problems with this. Have you looked at the actual hex chunks of the image, trying to figure out what’s wrong? If you find out what it is, please let me know.

    One common problem (that i mentioned above too) is that a jpg can contain multiple within itself. Try resaving the file with photoshop’s save for web.

    I can also take a look at the image if you want, trying to see what may cause the problem?

  16. 2008-02-23, 7:08 by Sachi

    How to work out with sub samling factor in SOF0?

  17. 2008-03-18, 18:56 by UnkemptRich

    Hi – i am new to this as3 and class stuff.

    Could someone help me and give me a .zip file with an .fla in it that calls this Main.as file or the JPGExtractor – i just cant figure out how to import this as or get it to work.

    Really sorry for my lack of knowledge
    My email address is unkemptrich@hotmail.com
    Cheers

    Rich

  18. 2008-03-19, 11:24 by Antti Author comment

    Rich: Check your mail.

    I updated the zip to contain a .fla (it just sets Main as it’s document class).

  19. 2008-03-19, 20:34 by JPGSizeExtractor multi image example – Antti Kupila

    [...] made a quick example to demonstrate the power of the JPGSizeExtractor class i wrote about a year ago. This is a demo that came up from a brief mail exchange with Richard Bacon [...]

  20. 2008-04-02, 0:24 by jamie

    I can’t get this to output the correct image size? my image was output in photoshop and is 350×255 but the trace says 160×139? any help would be great

  21. 2008-04-02, 0:36 by Antti Author comment

    Jamie: I haven’t run into this issue but it’s fully possible something still breaks. Do you think you could send me the jpg that’s causing problems so that i can take a look at it?

    Have you tried ‘save for web’ in photoshop? It only saves the jpg data (stripping all meta data, thumbnails etc) and is less likely to cause problems. Still, even if you get it to work i’d like to take a look at the image that’s causing problems so that i can fix the class.

  22. 2008-07-10, 3:55 by betamakz

    Great stuff, thanks a bunch. Can this be used to determine file size in bytes without loading the JPEG?

  23. 2008-07-10, 4:07 by Antti Author comment

    betamakz: For just determining the filesize this is a bit overkill. You can just use an URLLoader and listen to the first ProgressEvent.PROGRESS. By that time you can retrieve bytesTotal from the loader and call close( ) to stop downloading.

    Since flash is running on the client and not on the server flash will still have to download (a part of) the image to know anything about it.

  24. 2008-08-21, 0:09 by danny

    Hey… im trying to check if whats being loaded is actually an image and not a swf. I can read through the bytes and check for 0xC0 and assume its an image… im wondering if its possible for a swf to have 0xC0 or not… any ideas on that? or a better way to check if the file is an image or swf

  25. 2008-08-21, 0:40 by Antti Author comment

    danny: Add a check for the jpg SOI (0xFF 0xD8). If those aren’t the first bytes, the file is not a JPG.

  26. 2008-08-21, 17:18 by danny

    Ok thanks.

    I was also checking out the specs for swfs… and I realized I could also check for either 0×46, 0×57, 0×53 (“FWS”); or 0×43, 0×57, 0×53 (“CWS”)…. to figure out if its a swf or not…. instead of checking if its an image or not

  27. 2008-08-21, 17:24 by Antti Author comment

    That’s true, assuming only swfs or jpgs are loaded.

    Psst. You could also parse out the swf’s stage size with the same technique (although they won’t always be as accurate as graphics outside of the stage won’t be cropped as in images) ;)

  28. 2008-08-21, 18:57 by danny

    Hmmm… It doesn’t seem that (0xFF 0xD8) is part of PNG

  29. 2008-08-21, 19:00 by Antti Author comment

    Well yes, since a png is not a jpg. The png structure is very different from the one in jpgs. This code won’t work with any other file format.

  30. 2008-10-28, 2:44 by Ron

    This is great…learning a lot about Hex and Jpeg Structure. How do you go about reading or converting EXIF data? Any other resources on this?

  31. 2008-11-18, 14:58 by Thomas

    Hi,

    as the Loader.unload() method is buggy it is not possible to laod an swf to extract its header data only. As I am not firm with handling binary it would be nice to at least get a hint how to achive that with a class like yours. All I need is the total frame amount and optional the framerate of the file.

    Best regards from windy Norway,

    Thomas

  32. 2008-11-24, 9:14 by rn

    gr8 example!
    can you please explain how to get the resolution(in dpi) of the image
    thanks in advance

  33. 2009-01-16, 10:31 by aap

    I can’t get this to output the correct image size. My image size is 5130 X 3420 but the trace says 107×160? any help would be great

  34. 2009-01-16, 10:57 by Antti Author comment

    aap: It’s probably reading the thumbnail for some reason. If you want to send me the image i could take a look at it?

  35. 2009-01-19, 7:19 by aap

    i have send it to your gmail id

  36. 2009-01-27, 8:23 by aap

    Can we use these thumbnail data to show previews?

  37. 2009-01-27, 11:55 by Antti Author comment

    aap: As it’s right now, no. Still, this would be possible to do with the same technique used here. Excellent idea!

  38. 2009-01-27, 13:55 by aap

    ya the dimension extraction is working fine now .thanks ….
    But about showing the thumbnail , flex is throwing error of invalid structure.Any idea about that

  39. 2009-02-04, 21:43 by James

    Thank you so much for making this. Made my life SO much easier.

  40. 2009-02-16, 0:10 by Aaron

    I had the same problem with the thumbnail dimensions being spit out. I just did like you said and resaved the giant photo using photoshop save for web.
    Thanks for the solution and the awesome class. I’m working on a super slideshow! With your help I may just make it.

  41. 2009-02-23, 13:26 by Flüge Bangkok

    Thanks a lot for your awesome description how to get JPG dimensions with AS3 without loading the entire file. I was really helpless while trying it and now, after finding your page, I made it step by step. Thanks a lot. Really great stuff!!!

  42. 2009-03-19, 14:28 by randygland

    I tried using this but just get:

    Error #2044: Unhandled IOErrorEvent:. text=Error #2032: Stream Error.
    at com.ssg.designer.controls::UploadPage/upload()[C:\ssg\dev\assets\trunk\flash\RnD\as3\CapitalOneUS_Affinities_fp9\src\com\ssg\designer\controls\UploadPage.as:429]

    line 429 is the constructor call:

    var je:JPGSizeExtractor = new JPGSizeExtractor();

  43. 2009-05-17, 22:07 by Extracting image binary info without loading the entire file « My Flash Lab!

    [...] Before anything I must thank to Antti, who wrote the beautiful class of how we can read and use binary data of jpg file. you may read his artical here. [...]

  44. 2009-07-22, 14:59 by Wayne

    I’ve been using this script for a number of projects now – top stuff if I may say!

    I’ve now got a project where the jpeg created has to be in CMYK and I was wondering whether you knew of any means to do this?

    I’ve found a cracking script that converts individual rgb ‘points’ to CMYK values but I’m getting stuck when trying to amend the RGB2YUV function – obviously this has to change to allow the four values but should I use another colour profile other than YUV?

    Any help would be fantastic.

    Keep up the good work!

    Wayne

  45. 2009-07-23, 1:08 by Antti Author comment

    Hi Wayne,

    This script was more a study/example of the ByteArray, not so much JPEG as a compression algorithm. Because of this i don’t really have an answer for you as i never even looked into the details. Also i’m not sure i understand your question/problem :)

    For this script though it shouldn’t matter if the image is RGB or CMYK, the whole block with image info is skipped anyway

  46. 2009-07-29, 11:25 by Wayne

    Hi Antii,

    Thansk for the reply – much appreciated and understood.

    I’m still banging my head against a brick wall here – have made a little progress but I was wondering if you could offer any links to some of the areas you may have researched – i.e. the graphic above where you break down the hex code of a jpeg all wrapped up in FFD8 – FFD9.

    I’m really more concerned with encoding a CMYK jpeg – all the available AS3 encoders write RGB’s – so if you could post me a couple of links to where you garnered this info I’m sure it could be of some help to me!

    Many thanks again,

    Wayne

  47. 2009-07-29, 15:06 by Antti Author comment

    Wayne, most of the info was from these specs: http://www.bsdg.org/swag/GRAPHICS/0143.PAS.html and wikipedia. There’s a lot more info there that what i needed here, including info that should help you with what you’re doing.

  48. 2009-08-21, 13:05 by René

    Would be cool, if this could be adapted to the usual .jpg-format. I hate waiting for pictures. Although i´ve a fast online connection. But as a travel agency you need fast loading pictures for your clients…

  49. 2009-09-10, 10:59 by Vino

    Thanks for the wonderful post.. i tried using this but i am facing the same issue that aap described. For some jpg files the height and width of thumbnails are showing up instead of original dimensions.
    Could you please let me know what the solution was.

  50. 2009-09-10, 12:01 by Antti Author comment

    Vino: As i described this can happen if there’s a JPG embedded within the JPG (such as a thumbnail). The easiest way to solve is to get rid of the thumbnail (if you control the source files). You can do this by for example using “Save for web” in photoshop. I’m sure there are plenty of other tools out there that do the same too.

    I did solve the issue here for me by skipping the APPn sections in the file (these are the ones that contain the thumbnails etc). Still, as i noted in the post before too, i also had some problems with incorrect dimensions showing up sometimes. If you send me the file i can take a look at what might be causing the problem.

  51. 2009-09-14, 12:10 by Antti Author comment

    Some people have reported problems of wrong dimensions showing up. This should be fixed now (finally)! :)

  52. 2009-09-30, 0:05 by Illusion Sector

    Hmm. Not a single occurrence of the word “progressive” on this page. ^___^

  53. 2009-10-16, 8:51 by dan-o

    No reason – but if you wanted to use the ByteArray position property, why not add this to your code?

    var bytes:ByteArray = new ByteArray();
    readBytes(bytes, 0, bytesAvaliable);

    great code btw!

  54. 2009-10-22, 23:16 by graham

    Being a user of Liberty Basic, I didn’t understand any of the code that you pasted up, but I could see from your header analysis that when I want width and height info, I should start with the decimal numbers 255, 192, 0, 17, 8 when it’s standard JPEGs – and just grab the next four bytes… so that info was great. Works a treat. Many thanks!

  55. 2009-10-29, 19:16 by Wrapping text around an image or movieclip in Flash

    [...] There are many situations where getting an image’s dimensions before loading it is desireable, and Flash doesn’t ship with any built-in methods for this. Thankfully, Antti Kupila has written an excellent class for exactly this purpose, called JPGSizeExtractor. [...]

  56. 2009-10-30, 15:03 by Hussein

    Brilliant work mate! is their a way to do the same for png ?

  57. 2009-11-05, 21:45 by Как получить данные о ширине и высоте JPG-изображения не загружая само изображение?

    [...] же и нашел решение, которым со мной любезно поделился. Ответ оказался достаточно прост, но к сожалению не [...]

  58. 2009-11-24, 7:37 by Geoffrey McRae

    Or, if you want to do it in a simple nice self-contained static function without all this extra overhead…

    private static function getImageSize_JPEG(data: ByteArray): Point {
    if (data.length < 4) return null;
    data.endian = Endian.BIG_ENDIAN;
    data.position = 0;

    var magic : uint;
    var marker : uint;
    var length : uint;
    var x : uint;
    var y : uint;

    magic = data.readUnsignedShort();
    marker = data.readUnsignedShort();
    if (magic != 0xFFD8) return null;

    while(data.position < data.length – 1) {
    switch(marker) {
    case 0xFFC0:
    data.position += 3;
    y = data.readUnsignedShort();
    x = data.readUnsignedShort();
    return new Point(x, y);

    default:
    length = data.readUnsignedShort() – 2;
    data.position += length;
    marker = data.readUnsignedShort();
    break;
    }
    }

    return null;
    }

  59. 2009-12-02, 16:09 by MEM

    hello, and sorry for my english

    I want to ask you, can I use this library for not commercial project.
    I create data dispetcher, when I load JPG and another files like tasks, and I wont get JPG size before loading

    Now, this is project is used by only me, but I’m thinking about sharing

  60. 2010-01-11, 13:05 by Ali

    Hi Antti,

    Thanks for the really great information pal, but how did you get that the length(0×11) is 17 bytes!? on what base did you calculated the bytes (8 + 3×3 as we’re assuming it’s an RGB image)

    Is there a way to get more info about the photos and files binary data and in what base identifiers get together or something like that?

    Thanks

  61. 2010-01-23, 9:12 by ‌Zari

    Hi Antti,
    Thanks for great information. I want to extract RGB data for one pixel from one image.
    for example I have a 1000X1000 pixel image, and I want value of a pixel that is in (100,100). It is (255,0,125). [It is a value that returned by Getpixel() method in Bitmap class.]
    How can I do that?
    Thanks a lot

  62. 2010-01-26, 2:20 by Antti Author comment

    MEM: Sure, go ahead!

    Ali: It’s 8 + number of components * 3, see the numbered list in the post. Count the bytes in the image with the hex and i think you’ll see how it’s built up :)

    Zari: Unfortunately this only supports reading the meta data of a jpg, not the actual pixel data A similar approach could probably be applied to achieve what you want though, but it would get more complicated

  63. 2010-02-12, 23:16 by Christophe Herreman

    Hi, thanks for this class. I created a simple size extractor for PNG files and thought you might be interested. More info: http://www.herrodius.com/blog/265

  64. 2010-02-13, 18:11 by Antti Author comment

    Excellent, thanks for sharing Christophe!

  65. 2010-04-01, 0:34 by Alyda

    Hi Antti, thanks for this great class, this might seem like a silly question, since I know enough AS3 to actually implement this code and make it work in a loop, but after changing the “stopWhenParsed” variable to “false”, I’m unable to figure out how to actually add the loaded file (via JPGSizeExtractor) to the stage from an Event.Complete listener i am added to the “je” variable.

    thanks in advance!

  66. 2010-06-23, 5:48 by locust

    if i want to know what length(bytes) it is before it has loaded
    How can I do that?
    Thanks a lot

  67. 2010-07-14, 0:50 by Ali

    it was very useful for me.
    thanks

  68. 2011-01-20, 23:37 by Dew

    Hi,
    thanks for the class it’s very useful.
    you asked “…If anybody has an idea of what’s common to these files…”
    well I discovered it wouldnt work with progressive JPG’s.

  69. 2011-02-05, 3:45 by Ryan

    Hi,

    I’m trying to modify this so I can check to see if the image is using a CMYK color profile. Anyway you could help with this, as all my attempts so far are unsuccessful? Thanks in advance!

  70. 2011-02-13, 17:01 by Asger

    @Dew: but that seems it would very easy to extend it to that. It just marker 0xFF 0xC2 in stead of 0xC0. I don’t know if the rest of the payload is similar though, but I could imagine :)

  71. 2011-05-10, 13:17 by Wrapping text around an image or movieclip in Flash | Making Waves Labs

    [...] There are many situations where getting an image’s dimensions before loading it is desireable, and Flash doesn’t ship with any built-in methods for this. Thankfully, Antti Kupila has written an excellent class for exactly this purpose, called JPGSizeExtractor. [...]

  72. 2011-07-06, 18:42 by BryOnRye

    Your post helped me to write code to find the difference between RGB and CMYK jpgs. Very useful. Thanks :)

  73. 2012-06-06, 16:38 by Determination of width and height of image without it’s fully loading | Pastila

    [...] me with this issue, and later he himself had found a solution, which has kindly shared with me. The solution for .jpg was quite simple, but unfortunately not universal. However, data from the files of other image formats is not [...]

  74. 2014-01-13, 22:24 by VendSmart

    How complicated do you need to make it? Thanks for the info :)

    public static function getJPEGSize(bytes:ByteArray):Dimension
    {
    bytes.position = 0;
    var match:Boolean;
    var height:int = 0;
    var width:int = 0;

    var tLastBytes:Vector. = new Vector.();
    var tSigBytes:Vector. = new Vector.();
    tSigBytes.push(0xFF);
    tSigBytes.push(0xC0);
    tSigBytes.push(0×00);
    tSigBytes.push(0×11);
    tSigBytes.push(0×08);

    while (bytes.bytesAvailable>0)
    {
    tLastBytes.push(bytes.readUnsignedByte());
    if (tLastBytes.length>5)
    {
    tLastBytes.shift();
    }
    match = VectorUtils.compareVectorInt(tLastBytes,tSigBytes);
    if (match)
    {
    height = bytes.readUnsignedShort();
    width = bytes.readUnsignedShort();
    }
    }
    return new Dimension(width,height);
    }

  75. 2014-01-14, 9:34 by Antti Author comment

    Hi VendSmart,

    Thanks for this. I wrote this in 2007 when compareVectorInt wasn’t available. Time passes though and i’m happy to see there are easier options :)

  76. 2014-01-22, 11:09 by Raj

    Thanks dude…. Really helpful

Post a comment