I am trying to get the data from the chunk IDATA data from this png picture. When this picture is opened in a TextEditor I can appreciate the chunk IDAT after PLTE and before IEND, the length is about 336, of course is not 0, but when I get the datasize width Delphi the result is 0 and data is empty.
This is my code:
procedure TForm1.Button1Click(Sender: TObject);
var
png: TPngImage;
i,size: Integer;
Buffer: Pointer;
begin
for i := 0 to pred(png.Chunks.Count) do
begin
if(png.Chunks.Item[i].Name='IDAT')then
begin
Buffer := png.Chunks.Item[i].Data;//this is empty
size:= png.Chunks.Item[i].DataSize;// is 0, How is that possible ?
break;
end;
end;
end;
@TLama, @Remy I try this but not working:
procedure TForm1.Button1Click(Sender: TObject);
var
png: TPngImage;
i,size: Integer;
Buffer: Pointer;
stream: TStream;
begin
png := TPngImage.Create;
png.LoadFromFile('C:\temp\example.png');
stream := TMemoryStream.Create;
for i := 0 to pred(png.Chunks.Count) do
begin
if(png.Chunks.Item[i] is TChunkIDAT )then
begin
TChunkIDAT(Png.Chunks.Item[I]).SaveToStream(stream);
if Assigned(Stream) then
begin
Buffer := AllocMem(Stream.Size);
Stream.Position := 0;
Stream.Read(Buffer^, Stream.Size);
end;
end;
end;
The result of Buffer is:
IDATxÚíÙÙƒ Ðæÿ?Ú.V¥H åN|r_„„ ‹þÞTË»Vn†Á„s[dHÁ¬T¶1c•…®=Õ¨Íèì#½Z˜q+–'Š£–,‡Æ¬Ù2sñ`KPÖ÷bïÔoÏÓͬ´ãËfZÒôwSîjE¸‰w6bÜ<îQî)R´{î~MŠww” îGEÂñî›Â÷%/xÁ~0ÆòS/xx¾ßâ„[Ü.·¯Æ$pg'Üiw>Æep9wšÍú8˵<—#ÝÈìyÑ‚\\¦-ÌÞZÓùjKº3CodÔ$ôöxF«ëN#¸Y¥MÎ;Թת¦Z^0ø Cý?Dã2k‚
But if you open the image, the IDAt is this one:
X…íØÙ Ã0Ðì¿tEŽ6vt'jsgèÇ¢–eÆœ×"Õ‹€„ð´ y<£Æí¼²«X']É:èjÖH#XbŸh¤Û'±l›Æ»÷2ý“9î¯Ìr¿ež{•™îY溇ÌvwYóݬ‚î[žð„Q°ÆrÔ ï[põÑm™º½Z×$tÝI×uýXwÐÝ@àt“Ë=H?°(ÚÀ"h#[M;ØJÚÉÙ5oÇÕžF#xjçdë$ê/²‚¯©Œ
IDAT
块包含实际的图像数据,但是该块的TChunkIDAT
项未在其内部保留图像数据的副本,这就是其DataSize
为0的原因。当加载IDAT
块时, TChunkIDAT
解码图像数据并存储它在IHDR
块的TChunkIHDR
项的ImageData
和ImageAlpha
成员中。
After the whole investigation day, I was able to create my own function to get IDAT chunk, I post for everyone needs it.
function GetChunk(fileName,chunkName:String;var chunkLen:Integer):Pointer;
var
bytes,iData: TArray<byte>;
data,chunkType: AnsiString;
i,p,cont:Integer;
function getBytes(data:AnsiString;pos,num:Integer):Integer;
var
i:Integer;
begin
Result := 0;
for i := 1 to num do
begin
Result := Result * 256;
Result := Result + ORD(data[pos+i]);
end;
end;
begin
if(not FileExists(FileName))then
Exit(nil);
data := '';
bytes := System.IOUtils.TFile.ReadAllBytes(fileName);
for i := Low(bytes) to High(bytes) do
data := data + chr(bytes[i]);
p := 8;
while (p<Length(bytes)) do
begin
chunkLen := getBytes(data,p,4);
chunkType := copy(data,p+5,4);
if(chunkType=chunkName)then
begin
inc(p,8);
break;
end;
inc(p,chunkLen+12);
end;
SetLength(iData,chunkLen+1);
cont := 0;
for i := p to p+chunkLen do
begin
iData[cont] := bytes[i];
inc(cont);
end;
Result := iData;
end;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.