Update this shit.
This commit is contained in:
parent
8d0c3e84f2
commit
cc65edd617
8 changed files with 786 additions and 21 deletions
178
pngread.c
Normal file
178
pngread.c
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
|
||||
uint32_t endianswap( uint32_t n )
|
||||
{
|
||||
// if we're in a big endian system, we don't need this
|
||||
uint16_t testme = 0x1234;
|
||||
if ( *(uint8_t*)(&testme) == 0x12 ) return n;
|
||||
uint32_t on;
|
||||
for ( int i=0; i<4; i++ )
|
||||
*(((uint8_t*)(&on))+i) = *(((uint8_t*)(&n))+(3-i));
|
||||
return on;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t highbitcheck;
|
||||
char sig[3];
|
||||
char crlf[2];
|
||||
char dosstop;
|
||||
char lf;
|
||||
} pnghead_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t length;
|
||||
char type[4];
|
||||
uint8_t *data;
|
||||
uint32_t crc;
|
||||
} pngchunk_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t width, height;
|
||||
uint8_t depth, type, compression, filter, interlace;
|
||||
} ihdr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t xppu, yppu;
|
||||
uint8_t unit;
|
||||
} phys_t;
|
||||
|
||||
int exitval = 0;
|
||||
FILE *f = 0;
|
||||
int nchunk = 0;
|
||||
pnghead_t hdr = {0,0,0,0,0};
|
||||
pngchunk_t chk = {0,0,0,0}; // make sure this is null at the very start
|
||||
uint32_t curcrc = 0;
|
||||
int validcrc = 0;
|
||||
uint8_t *tdat = 0; // accumulated data for all IDAT chunks
|
||||
uint32_t tdatsiz = 0; // size of it
|
||||
|
||||
void readIHDR( ihdr_t* ihdr )
|
||||
{
|
||||
printf(" width: %u\n height: %u\n depth: %u\n type: %u\n compression: %u\n filter: %u\n interlace: %u\n",
|
||||
endianswap(ihdr->width),endianswap(ihdr->height),ihdr->depth,ihdr->type,ihdr->compression,ihdr->filter,ihdr->interlace);
|
||||
}
|
||||
|
||||
// read up a stream chunk
|
||||
void readIDAT( uint8_t* dat, uint32_t len )
|
||||
{
|
||||
if ( tdat ) tdat = realloc(tdat,tdatsiz+len);
|
||||
else tdat = malloc(len);
|
||||
memcpy(tdat+tdatsiz,dat,len);
|
||||
tdatsiz += len;
|
||||
}
|
||||
|
||||
// process the whole thing
|
||||
void processIDAT( void )
|
||||
{
|
||||
}
|
||||
|
||||
void readpHYs( phys_t* phys )
|
||||
{
|
||||
printf(" xppu: %u\n yppu: %u\n unit: %u\n",endianswap(phys->xppu),endianswap(phys->yppu),phys->unit);
|
||||
}
|
||||
|
||||
void readtEXt( uint8_t* data, uint32_t len )
|
||||
{
|
||||
uint8_t *key = data;
|
||||
uint8_t *val = data+strlen(data)+1;
|
||||
uint32_t vallen = len-(val-key);
|
||||
printf(" '%s' :: '%.*s'\n",key,vallen,val);
|
||||
}
|
||||
|
||||
void readchunkdata( pngchunk_t* chk )
|
||||
{
|
||||
if ( !strncmp(chk->type,"IHDR",4) )
|
||||
readIHDR((ihdr_t*)chk->data);
|
||||
else if ( !strncmp(chk->type,"pHYs",4) )
|
||||
readpHYs((phys_t*)chk->data);
|
||||
else if ( !strncmp(chk->type,"tEXt",4) )
|
||||
readtEXt(chk->data,chk->length);
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
if ( argc < 2 )
|
||||
{
|
||||
printf("No file supplied.\n");
|
||||
exitval = 0;
|
||||
goto endmii;
|
||||
}
|
||||
f = fopen(argv[1],"rb");
|
||||
if ( !f )
|
||||
{
|
||||
printf("Failed to open file.\n");
|
||||
exitval = 1;
|
||||
goto endmii;
|
||||
}
|
||||
fread(&hdr,1,sizeof(hdr),f);
|
||||
if ( hdr.highbitcheck != 0x89 )
|
||||
{
|
||||
printf("High bit check failed.\n");
|
||||
exitval = 2;
|
||||
goto endmii;
|
||||
}
|
||||
if ( strncmp(hdr.sig,"PNG",3) )
|
||||
{
|
||||
printf("PNG signature check failed.\n");
|
||||
exitval = 4;
|
||||
goto endmii;
|
||||
}
|
||||
if ( strncmp(hdr.crlf,"\r\n",2) )
|
||||
{
|
||||
printf("CRLF check failed.\n");
|
||||
exitval = 8;
|
||||
goto endmii;
|
||||
}
|
||||
if ( hdr.dosstop != '\032' )
|
||||
{
|
||||
printf("EOF check failed.\n");
|
||||
exitval = 16;
|
||||
goto endmii;
|
||||
}
|
||||
if ( hdr.lf != '\n' )
|
||||
{
|
||||
printf("LF check failed.\n");
|
||||
exitval = 32;
|
||||
goto endmii;
|
||||
}
|
||||
readchunk:
|
||||
fread(&chk,1,8,f); // read size and type first
|
||||
chk.length = endianswap(chk.length); // swap from BE
|
||||
if ( (nchunk == 0) && strncmp(chk.type,"IHDR",4) )
|
||||
{
|
||||
printf("First chunk is not IHDR.\n");
|
||||
exitval = 64;
|
||||
goto endmii;
|
||||
}
|
||||
// (re)allocate data
|
||||
if ( chk.data ) chk.data = realloc(chk.data,chk.length);
|
||||
else chk.data = malloc(chk.length);
|
||||
fread(chk.data,1,chk.length,f); // read data
|
||||
fread(&(chk.crc),1,4,f); // read CRC
|
||||
chk.crc = endianswap(chk.crc);
|
||||
curcrc = crc32(0,chk.type,4);
|
||||
if ( chk.length ) curcrc = crc32(curcrc,chk.data,chk.length);
|
||||
validcrc = (curcrc == chk.crc);
|
||||
printf("%.4s chunk of length %u (CRC32: %08X, %s).\n",chk.type,chk.length,chk.crc,validcrc?"OK":"FAILED");
|
||||
if ( !validcrc ) printf(" CRC32 ACTUAL: %08X\n",curcrc);
|
||||
else readchunkdata(&chk);
|
||||
nchunk++;
|
||||
if ( strncmp(chk.type,"IEND",4) ) goto readchunk;
|
||||
long cpos = ftell(f);
|
||||
fseek(f,0,SEEK_END);
|
||||
long epos = ftell(f);
|
||||
if ( epos > cpos ) printf("%lu bytes of extra data after IEND.\n",epos-cpos);
|
||||
endmii:
|
||||
if ( f ) fclose(f);
|
||||
if ( chk.data ) free(chk.data);
|
||||
return exitval;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue