2017-03-20 32 views
0

pngファイルの解凍に問題があります。これは、IDATチャンクを処理するコードである:inflateを使用してpngファイルを解凍する

Atは、PNGファイルのバッファ内の現在の位置であり、そして PngImageは画像の幅、高さ、及び深さを保持して有するだけ構造体である
case PNG_CHUNK_IDAT: { 
      z_stream Stream = {}; 
      int Error = inflateInit(&Stream); 

      if(Error == Z_OK) { 
       Stream.avail_in = ChunkLength; 
       Stream.next_in = At; 
       Stream.avail_out = PngImage.Width * PngImage.Height * PngImage.Depth; 
       Stream.next_out = PngImage.Pixels; 

       do { 
        Error = inflate(&Stream, Z_NO_FLUSH); 
        if(Error != Z_OK) { 
         break; 
        } 
       } while(Stream.avail_out != 0); 
       inflateEnd(&Stream); 
      } 

      At += ChunkLength; 
      break; 
     } 

サイズがwidth*height*depthの符号なしchar配列。

私は解凍しようとしている画像はこれです:それは、フィルタリング(0)を持っていないとアルファとpngのトゥルーカラーであるarial.png

。 IDATチャンクも1つだけ含まれています。

しかし、その代わりに、私はこのような何かを得る:私は画像が逆さまであることを認識してんだincorrect png

を、それは私のレンダラというボトムアップとPNGはトップダウンであることの問題です。それは私が今懸念しているものではありません。

inflateは実際には1回だけ実行され、Z_OKを返すことに注意する必要があります。そのため、スキャンラインフィルタを処理しないという問題はないと思います。私は行ごとに1バイト追加して、Pixels配列に各行の最初のバイトをコピーしようとしなかったが、それは違いの多くをしませんでした。

私が間違っていると思われるアイデアはありますか?

答えて

0

最初にオフにすると、最後の呼び出しでZ_OKが返されます。 Z_STREAM_ENDが返されない場合は、完全圧縮データを解凍して検証しませんでした。

第2に、avail_outは、各スキャンラインの開始時にフィルタバイトを使用できません。高さをavail_outに追加して、それに余裕を与えてください。

第3に、元の512x512 RGBAイメージから643x514 RGBイメージをどのように取得したかわかりません。各行のフィルタバイトをスキップする必要があります。次に、各ピクセルは、4つのバイトです。

+0

不適切な画像は、私がレンダリングする画面のスクリーンショットで、640x480です。私はそれを言及すべきだった。しかし、この問題はフィルタリングバイトの後にあったので、ありがたいです。 –

0

各スキャンラインの開始時にフィルタメソッドバイトを無視しているようです。それは、私はあなたがそれ限り、z.avail_outがゼロに等しくなるようwhile(Stream.avail_out == 0);

が、それは解凍されたデータとinflate()ために利用可能な圧縮データ埋めバイトが再び呼び出される必要があることを意味するべきだと思う、それは0

0

だ場合でも、あります。

常にその意味を考えると、出力のために利用可能な(塗りつぶされていない)バイトがある場合には、それを中止してavail_out > 0とする必要があります。

関連する問題