mercredi 28 mai 2014

Delphi : Lecture JPEG Image de DefineBitsJPEG3 tag sur le fichier SWF - Stack Overflow


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.



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.


0 commentaires:

Enregistrer un commentaire