This is the closest thread topic to my newest problem, I finally realised why I've been failing to extract the right raw image from png files, turns out I misunderstood the IDAT chunk, after correcting that I found that my bit stream function is faulty, it somehow works for "<= bitsof(uintmax_t) " (to be accurate I've only read upto 32 bits at a time so far) but as soon as it was need for a larger block it resulted in it the bits being ignored, here's the code for the stream functions 1st:
Code:
void StreamUsed( STREAM *Stream, uint bits )
{
intmax_t max = BUFSIZ;
max *= CHAR_MAX;
Stream->took += bits;
Stream->used += bits;
if ( Stream->eod && Stream->took >= max )
Stream->err = EOF;
}
long StreamBlock( STREAM * Stream )
{
void *src = Stream->feed;
long add = -1;
memset( src, 0, BUFSIZ );
if ( Stream->eod )
Stream->err = EOF;
else
{
add = Stream->DataCB( src, Stream->data, Stream->byte, BUFSIZ );
Stream->eod = (add < BUFSIZ);
}
return add;
}
int StreamData( STREAM *Stream, void *dst, intmax_t get, bool use )
{
BIT d, s;
intmax_t const max = ((intmax_t)BUFSIZ) * CHAR_BIT;
intmax_t num = max - Stream->took;
void * src = Stream->feed;
SetBit( &d, dst, 0 );
if ( Stream->byte < 1 )
{
Stream->took = 0;
num = StreamBlock( Stream );
if ( num < 0 )
return EOF;
if ( !num )
return ENODATA;
Stream->byte = num;
num *= CHAR_BIT;
}
while ( d.abs < get )
{
intmax_t take = get - d.abs, bits = Stream->took;
while ( bits >= max )
{
num = StreamBlock( Stream );
if ( num < 0 )
return EOF;
if ( !num )
return ENODATA;
Stream->byte += num;
num *= CHAR_BIT;
bits -= max;
Stream->took = 0;
EchoStreamDetails( stdout, Stream );
}
SetBit( &s, src, Stream->took );
if ( num < take )
take = num;
for ( bits = 0; bits < take; ++bits )
{
if ( *(s.byte) & s.mask )
*((uchar*)(d.byte)) |= d.mask;
IncBit( &d, dst );
IncBit( &s, src );
}
if ( use )
StreamUsed( Stream, take );
else if ( get > num )
return ERANGE;
}
return 0;
}
And here's what is being passed to it when I noticed it was ignoring the bits:
Code:
else if ( ansi_cmpi( Entry->Type, "IDAT" ) == 0 )
{
uint cmf = StreamBits( Stream, 8, true );
uint mod = StreamBits( Stream, 8, true );
uint chk;
idat = ExpandBuffer( IDAT, 1, IDAT->used + leng );
if ( !idat )
{
fprintf( errout, "Not enough space to append IDAT data\n" );
return NULL;
}
leng -= 4;
err = StreamData( &StreamFile, idat + IDAT->used, leng * 8, true );
chk = StreamBits( &StreamFile, 8, true ) << 8;
chk |= StreamBits( &StreamFile, 8, true );
IDAT->used += leng;
if ( verbose )
{
EchoStreamDetails( verbose, &StreamFile );
ECHO
(
verbose,
fprintf
(
verbose,
"cmf = %02X, mod = %02X, chk = %04X, "
"leng = %5" PRIuMAX ", IDAT->used = %7u\n",
cmf, mod, chk, leng, IDAT->used
)
);
EchoStreamDetails( verbose, &StreamFile );
}
if ( err )
{
ECHO( errors, ECHO_ERR( errors, err ) );
return NULL;
}
}
Local Output:
Code:
view/png.c:309: 2 'IDAT' 111
Stream Details: End Of Data = true, End Of Stream = false, data = 0x7ffc4e9fd188, byte = 184, took = 1328, used = 1328
view/png.c:356: cmf = 00, mod = 00, chk = 5220, leng = 107, IDAT->used = 107
Stream Details: End Of Data = true, End Of Stream = false, data = 0x7ffc4e9fd188, byte = 184, took = 1328, used = 1328
That 1st line in the output represents chunk number, chunk type and the leng variable you see mentioned in the code (leng of the chunk), anyone have any ideas what's causing StreamData() to ignore the bits it's supposed to be putting in "idat"?
Edit: Never mind, failed to notice that I was only printing after the readout, moving the first printout to before the readout gave me the expected output for the details, didn't resolve my issue with IDAT somehow being read wrong though.
Edit 2: If anyone was planning to help me understand what's going wrong with the IDAT readout the current upload is here:
Files * d700e396122a99a8ab07a489accbb5596abd6c49 * Lee Shallis / glEngine * GitLab
Look for png.c then LoadImagePNG(), then just look for the if statement that compares the entry type to the string IDAT, that should be the highest code statement you need to look at, stream code is in stream.h/stream.c, BIT is defined in common.h (forgive the somewhat poorly organised code, my focus has been getting the images extracted right and learning opengl, cleaner versions will eventually be put in paw with minimal header dependencies)