Code:
int print_png_sig( FILE *out )
{
char sig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
size_t bytes = fwrite( sig, 1, 8, out );
return (bytes != 8) ? ferror(out) : 0;
}
void flip_bytes( void *buff, size_t size )
{
for ( char *a = buff, *b = buff + (size-1); a < b; ++a, --b )
{
char t = *a;
*a = *b;
*b = t;
}
}
void* flip_words( void *buff, size_t size )
{
for ( short *a = buff, *b = buff + (size-2); a < b; ++a, --b )
{
short t = *a;
*a = *b;
*b = t;
}
return buff;
}
void* set_little_endian( void *buff, size_t size )
{
long val = 0x12345678;
char *ptr = (char*)&val;
bool go = true;
while ( 1 )
{
switch ( *ptr )
{
case 0x78: return buff;
case 0x12: flip_bytes( buff, size ); return buff;
case 0x34:
flip_words( buff, size );
case 0x56:
for ( size_t i = 0; i < size; i += 2 )
{
flip_bytes( ptr + i, 2 );
}
return buff;
}
if ( !go ) return buff;
flip_bytes( buff, size );
go = false;
}
return buff;
}
struct png_IHDR
{
size_t length : 32;
size_t type : 32;
size_t crc : 32;
size_t width : 32;
size_t height : 32;
size_t bit_depth : 8;
size_t color_type : 8;
size_t comparison_method : 8;
size_t filter_method : 8;
size_t interlace_method : 8;
};
#define PNG_COLOR_TYPE_GREYSCALE 0
#define PNG_COLOR_TYPE_TRUECOLOR 2
#define PNG_COLOR_TYPE_INDEXED 3
#define PNG_COLOR_TYPE_GREYSCALE_WITH_ALPHA 4
#define PNG_COLOR_TYPE_TRUECOLOR_WITH_ALPHA 6
#define PNG_COMPRESSION_SLIDING_WINDOW_OF_AT_MOST_0x7fff 0
#define PNG_FILTER_ADAPTIVE_WITH_5_TYPES 0
#define PNG_INTERLACE_NONE 0
#define PNG_INTERLACE_ADAM7 1
size_t set_png_IHDR_color_type( struct *png_IHDR chunk, size_t color_type )
{
switch ( color_type )
{
case PNG_COLOR_TYPE_GREYSCALE:
case PNG_COLOR_TYPE_TRUECOLOR:
case PNG_COLOR_TYPE_INDEXED:
case PNG_COLOR_TYPE_GREYSCALE_WITH_ALPHA:
case PNG_COLOR_TYPE_TRUECOLOR_WITH_ALPHA:
break;
default:
color_type = PNG_COLOR_TYPE_TRUECOLOR_WITH_ALPHA;
}
chunk->color_type = color_type;
return color_type;
}
size_t set_png_IHDR_bit_depth
(
struct *png_IHDR chunk
, size_t color_type
, size_t bit_depth
)
{
switch ( bit_depth )
{
case 3:
bit_depth = 4;
case 1: case 2: case 4:
bit_depth =
(
color_type == PNG_COLOR_TYPE_GREYSCALE
|| color_type == PNG_COLOR_TYPE_INDEXED
) ? bit_depth : 8;
break;
case 6: case 7:
bit_depth = 8;
case 8: break;
default:
bit_depth = (color_type != PNG_COLOR_TYPE_INDEXED) ? 16 : 8;
}
chunk->bit_depth = bit_depth;
return bit_depth;
}
int print_png_chunk_IHDR( FILE *out, struct png_IHDR *chunk )
{
// Ignored CRC
int ret = 1;
char type[4] = { 73, 72, 68, 82 };
size_t leng = sizeof(png_IHDR) - 4, crc = 0;
size_t bytes;
struct { size_t size, void *addr } ptrs[] =
{
{ 4, &(chunk->leng) }
, { 4, memcpy( &(chunk->type), type, 4 ) }
, { 4, &(chunk->crc) }
, { 0, NULL }
};
set_little_endian( &leng, 4 );
(void)memcpy( &(chunk->leng), &leng, 4 )
for ( int i = 0; ptrs[i].addr; ++i )
{
bytes = fwrite( ptrs[i], 1, ptrs[i].size, out );
if ( bytes != ptrs[i].size )
return ferror(out);
}
return ret;
}
Anyone see any problems?