2

I've got some errors while reading JPEG image from DefineBitsJPEG3 tag in SWF file.

On SWF Documentation the tag structure of DefineBitsJPEG3 as follow :

Header : long  //Tag type = 35.
Chastrong textracterID : UI16  //ID for this character.
AlphaDataOffset :UI32  //Count of bytes in ImageData.
ImageData : UI8[data size]  //Compressed image data in either JPEG, PNG, or GIF89a format
BitmapAlphaData : UI8[alpha data size]  //ZLIB compressed array of alpha data.
Only supported when tag contains JPEG data. One byte per pixel. Total size after decompression must equal (width * height) of JPEG image.

When the image data contains JPEG data, i use regular load from stream to get The Image as follow :

procedure BufferToImg(Buffer:Pchar; BufSize:Integer; Img:TBitmap);
var
  JPG:TJpegImage;
  Mem:TStream;
begin
  JPG:=TJpegImage.Create;
  Mem:=TMemoryStream.Create;
  try
    mem.Write(Buffer^,BufSize);
    mem.Position:=0;
    JPG.LoadFromStream(mem);
    Img.Assign(JPG);
  finally
    mem.Free;
    JPG.Free;
  end;
end;

This code sometimes doesn't work. While debugging I found that there were two types of JPEG data on DefineBitsJPEG3 tag :

  1. JPEG Image with this header on Hex Viewer would work fine
    FF D8 FF E0 00 10 4A 46 49 46  |  ÿØÿà.JFIF
    00 01 01 00 00 01 00 01 00 00  |  ......  
    FF DB 00 43 00 06 04 05 06 05  |  ÿÛ.C.  
  1. JPEG Image with this header on Hex viewer would failed
    FF D8 FF DB 00 43 00 06 04 05  |  ÿØÿÛ.C.  
    06 05 04 06 06 05 06 07 07 06  |    
    08 0A 10 0A 0A 09 09 0A 14 0E  |  ..  

My question is how to load the image stored with header on second preview?

any help would be appreciated. Thanks.

UPDATE :

I should write this in comment section but it's too long.

Pardon me if i was wrong.

Just for information, This problem didn't show up while coding with java. i found this problem only with Delphi.
So lets talk about it in Delphi environment.

I didn't found any problem with DefineBits tag while using separated JPEGTablestag. The problem is DefineBitsJPEG3.
The specs says : DefineBitsJPEG3 is extends DefineBitsJPEG2 (page 139) but differs from DefineBits(page 138) in that it contains both the JPEG encoding table and the JPEG image data.

I found two types of data stored on DefineBitsJPEG3 tag, Both with SOI marker(of JFIF/JPEG) but one had APP0 marker(and the rest of all members of JFIF header segment) while the other one did not.
The main problem is : Delphi's TJPEGimage will only load data with APP0 marker successfully. The other one without APP0 marker will failed.
If that means i should read through the data and load the image using TJPEGImage if APP0 exists and make another function to load the image data without APP0, then i have another problem : i didn't find any documentation about JPEG/JFIF image data without APP0 marker.
Any suggestion? (but please don't suggest me not to use Delphi).

UPDATE 2 :

With assistance from @FreeConsulting i finally get the solution.

Here are the rules for reading image from SWF Buffer :

  • DefineBitsTag : Read the JPEGTablesTag first and used it to create JPEG Stream before loading with TJPEGImage.
  • TTagDefineBitsLossLess and TTagDefineBitsLossLess2 : Read the data With ZLib decompression and set the pixels using scanline
  • DefineBitsJPEG2 and DefineBitsJPEG3 : Read the first and second JFIF marker. If you find DQT immediately following SOI then use it as JPEGTablesTag to create JPEG Stream before loading with TJPEGImage (similar to DefineBitsTag). But if you don't find DQT immediately following SOI just load it to the TJPEGImage.
Theo
  • 454
  • 1
  • 7
  • 21
  • 1
    Did you read the [specs](http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf-file-format-spec.pdf)? "*DefineBits This tag defines a bitmap character with JPEG compression. It contains only the JPEG compressed image data (from the Frame Header onward). A separate JPEGTables tag contains the JPEG encoding data used to encode this image (the Tables/Misc segment).*" – Free Consulting Nov 29 '13 at 02:28
  • @FreeConsulting Thanks and Pardon me... i've read the spec and made some update to the question. Any other suggestion would be appreciated. – Theo Nov 29 '13 at 17:38
  • I see you problem now. Sorry, I didn't notice what second variation has DQT immediately following SOI. – Free Consulting Nov 30 '13 at 01:50
  • But keep in mind, what as per JPEG/JFIF specs APP0 segment can be in the arbitrary position within the stream between SOI and EOI, explained [there](http://stackoverflow.com/questions/5413022/). I'd take a closer look at extracted stream to confirm the absence of APP0 either manually or with some tool like jpegsnoop. – Free Consulting Nov 30 '13 at 02:01
  • @FreeConsulting : Thanks a lot for your help. Now I really understand whats wrong with my code. Actually the DQT immediately following SOI is the JPEGTable. On DefineBitsTags it stored separately but on DefineBitsJPEG2 and DefineBitsJPEG3 it stored in the tag itself. So i made some modification on DefineBitsTags' code to be used on DefineBitsJPEG2 and DefineBitsJPEG3. And not it works perfectly. Thanks again. – Theo Nov 30 '13 at 17:52

0 Answers0