2017-03-29 17 views
0

PNG 이미지 파일의 IDAT 블록에서 데이터를 부풀려 보는데 문제가있었습니다. 지금까지 IHDR 블록을 읽고 정확한 데이터를 반환 할 수있었습니다. 그러나, 내가 파일의 원시 RGB 값을 얻으려고 압축을 풀려고했을 때, 나는 다른 것들로부터 0을 얻는 동안 오직 하나의 이미지에서만 성공할 수있었습니다. 이것은 zlib에서 팽창시키기 위해 사용한 코드입니다. 상기로부터 PNG의 팽창 데이터는 특정 이미지에서만 성공합니까?

unsigned char temp[4]; 
fread(&temp,1,4,pf); 
unsigned int ihdr_size = convert_endian(temp); 

unsigned char blk[ihdr_size + 8]; 
fread(blk,1,ihdr_size + 8,pf); 

if (check_ihdr(blk) == -1){ 
    fclose(pf); 
    return -1; 
} 
this->width = convert_endian(blk+4); 
this->height = convert_endian(blk+8); 
long area = this->width*this->height*3 +this->height+1; 
printf("%ld x %ld\n",this->width, this->height); 
printf("Bit depth: %1x\n", (unsigned char)blk[12]); 
printf("Color type: %1x\n", (unsigned char)blk[13]); 

while(fread(&temp,1,4,pf) > 0){ 
    unsigned int bsize = convert_endian(temp); 
    unsigned char chunk[bsize+8] = {0}; 
    fread(chunk,1, bsize+8,pf); //8 extra for block name and CRC 
    if (chunk_type(chunk)== 1){ //IDAT 
     this->picture = new unsigned char[area]; 

     z_stream infstream; 
     infstream.zalloc = Z_NULL; 
     infstream.zfree = Z_NULL; 
     infstream.opaque = Z_NULL; 
     infstream.avail_in = bsize; // size of input 
     infstream.next_in = chunk+4; // input char array (without chunk name) 
     infstream.avail_out = area; // size of output 
     infstream.next_out = this->picture; // output char array 

     inflateInit(&infstream); 
     if (int er = inflate(&infstream, Z_NO_FLUSH) != Z_STREAM_END){ 
      printf("Error!\n"); 
     } 
     inflateEnd(&infstream); 
     printf("OUT:%d %ld\n", infstream.avail_out, area); 
     for (long i = 0; i < 1000; i+=4){ 
      printf("%x %x %x\n",this->picture[i], this->picture[i+1], this->picture[i+2]); 
     } 


    } 
    printf("B:%x\n",bsize); 
    printf("%c%c%c%c\n",chunk[0], chunk[1], chunk[2], chunk[3]); 
} 

, 나는이 이미지 image2 와 시도 (같은 이미지 만 잘립니다) 때, image#1 그러나이 이미지에 RGB 값을 얻는 데 성공했다, 프로그램은 단지를 반환 할 수 있었다 RGB 데이터의 처음 3 바이트 (나머지는 0 임). 이 코드로 잘못 구현 한 것이 있습니까?

답변

1

결과가 올바르게 해석되지 않습니다. +this->height의 이유는 이미지의 각 줄 앞에 필터 바이트가 오기 때문입니다. "성공"한 이미지의 경우 필터 바이트는 모두 0이며 필터링 안함을 나타냅니다. 즉, 픽셀 값이 압축 해제 된 데이터에 직접 표시됩니다. 이 경우에도 필터 바이트를보고 이동하지 않으므로 픽셀 값의 잘못된 바이트가 표시됩니다.

"성공"하지 않은 이미지의 경우 첫 번째 줄은 필터 1을 사용하고 후속 줄은 필터 2를 사용합니다. 필터 1은 하위 필터로, 첫 번째 이후의 이전 픽셀 값을 빼서 나타냅니다 이전의 픽셀 값 2는 위로 필터를 나타내며, 첫 번째 행 다음의 각 픽셀 값은 그 위치에서 이전 행의 픽셀 값을 뺍니다. 그래서 첫 번째 값 이후의 거의 모든 값 (은 아니요,이 아닙니다)이 0입니다. 결과를 더주의 깊게보십시오.