2017-03-20 17 views
0

png 파일의 압축을 푸는 데 문제가 있습니다. 이것은 IDAT 청크 처리하는 코드이다 At은 PNG 파일 버퍼의 현재 위치 인inflate를 사용하여 png 파일 압축 해제

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; 
     } 

, 그리고 PngImage 이미지의 폭, 높이 및 깊이를 보유하고 있습니다 막 구조체이며 크기가 width*height*depth 인 부호없는 char 배열

전 압축을 시도하고,이 이미지이다 arial.png

그것은 (0)에는 필터링이 없으며 알파 PNG로 트루이다. 또한 하나의 IDAT 덩어리 만 포함합니다.

는하지만 그 대신 나는 이런 식으로 뭔가 얻을 : incorrect png

나는 이미지가 거꾸로 것으로 알고 있어요, 그건 내 렌더러는 하향식 (top-down)되는 상향식 (bottom-up) 및 PNG 인에 문제가이다를; 내가 지금 염려하고있는 게 아니야.

실제로는 inflate이 실제로 한 번만 실행되어 Z_OK를 반환하므로 스캔 라인 필터를 처리하지 않는 문제는 아닌 것으로보아야합니다. 행 당 1 바이트를 추가 한 다음 각 행의 첫 번째 바이트를 Pixels 배열로 복사하지 않았지만 그 차이가별로 없었습니다.

내가 잘못 생각한 아이디어가 있습니까?

답변

0

먼저 꺼지고 마지막 통화에서 Z_OK이 반환됩니다. Z_STREAM_END을 반환하지 않으면 전체 압축 데이터를 압축 해제하고 확인하지 않은 것입니다.

둘째, avail_out은 각 스캔 라인의 시작 부분에 필터 바이트를 허용하지 않습니다. avail_out에 높이를 추가하고 그 자리를 마련하십시오.

셋째, 원래의 512x512 RGBA 이미지에서 643x514 RGB 이미지를 얻는 방법에 대해 잘 모릅니다. 각 행의 필터 바이트를 건너 뛰고 각각의 픽셀은 , 네 개는 바이트입니다.

+0

잘못된 이미지는 내가 렌더링 할 화면의 스크린 샷으로 640x480입니다. 나는 그것을 언급 했어야했다. 그러나 문제는 필터링 바이트로 인한 것이므로 감사합니다. –

0

각 스캔 라인의 시작 부분에서 필터 방법 바이트를 무시하는 것처럼 보입니다. 그것은 당신이 그것을 한, z.avail_out 제로로 동등하게 while(Stream.avail_out == 0);

, 즉 압축 해제 데이터와 inflate()에 사용할 수있는 압축 된 데이터 채워진 바이트 다시 호출 할 필요가 의미 있도록해야한다고 생각은 0

0

경우에도, 거기에 .

항상 의미를 생각하면 출력에 사용 가능한 (채워지지 않은) 바이트가있을 때 (즉, avail_out > 0) 멈춰야합니다.