简体   繁体   中英

How to get the in Delphi the chunk IDAT from a png image?

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项的ImageDataImageAlpha成员中。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM