//jpg header lookup //itouh //Time-stamp: // '*marker' means necessary segments // マーカー名の前に「*」がついているものは必須セグメント #include #include #include #include #define errret { fprintf(stderr, "err\n"); exit(1); } int main(int argc, char *argv[]); unsigned char *segskip(unsigned char *p); size_t filelen; unsigned char *src; int main(int argc, char *argv[]){ unsigned char *p; FILE *fin; struct stat info; char *fname; const unsigned char *marker[] = { "\xd8 *SOI(start of image)", "\xc4 *DHT(define huffman table)", "\xdb *DQT(define Quantization table)", //"\xe0 APP0(JFIF segment marker)", "\xfe COM(comment)", "\xcc DAC(define arithmetic table)", "\xc8 JPG(reserved)", }; if(argc<=1 || argc >=3){ fprintf(stderr, "Please specify one argument.\n"); return 1; } fname = argv[1]; /* * file open & memory allocate */ if((fin=fopen(fname,"rb")) == NULL) errret; if(stat(fname, &info) != 0) errret; filelen = info.st_size; if((src=malloc(filelen)) == NULL) errret; if(fread(src,1,filelen,fin) != filelen){ free(src); errret; } /* * validity check * 最初の2バイトは SOI というmarker。 * marker とは、各セグメント最初の2バイトにある識別子。 * PNGでいうchunkname。 */ if(*src==0xff && *(src+1)==0xd8){ p = src + 2; //SOI(start of image)(2bytes) printf("ff d8 *SOI(start of image) Length: 0 bytes\n"); }else{ free(src); errret; } for(;;){ int i; int flag; /* * セグメント先頭の 'ff'をサーチ */ if(*p!=0xff){ //ヘッダ部ではなく、圧縮データ部 //printf(" compressed data\n"); while(*p!=0xff) p++; } /* * セグメント種を調べる */ flag = 0; for(i=0; i=0xc0 && n<=0xcf){ printf("ff %02x *SOF%d(start of frame)", n, n-0xc0); p = segskip(p); }else if(n>0xe0 && n<=0xef){ char *str = calloc(5, sizeof(char)); memcpy(str, p+4, 4); printf("ff %02x APP%d('%s' application data)", n, n-0xe0, str); p = segskip(p); }else if(n==0xd9){ printf("ff d9 *EOI(end of image)\n"); free(src); return 0; }else if(n==0xda){ printf("ff da *SOS(start of scan)"); p = segskip(p); printf(" compressed data\n"); }else if(n==0xdd){ //restart printf("ff dd DRI(define restart interval)"); p = segskip(p); }else if(n>=0xd0 && n<=0xd7){ printf("ff %02x RST%d(restart interval termination)\n", n, n-0xd0); p += 2; printf(" compressed data\n"); }else if(n==0x00 || n==0xff){ // markerじゃなくて圧縮データの一部 //must be skipped //printf("ff %02x not marker, but compress data\n", n); p += 2; }else{ printf("ff %02x unknown marker\n", n); p += 2; } }//if(!flag }//for(;; } unsigned char *segskip(unsigned char *p){ unsigned short next; //次のセグメントまでの相対距離 /* * セグメントの長さを調べる * segment lengthの示す長さは、marker(0xff 0x??)の2バイトを * 含んでいない。 * segment length 自身の2バイトは含まれている。 */ p += 2; //skip marker next = *p<<8 | *(p+1); printf(" Length: %d bytes\n", next); if(p+next >= src+filelen){ fprintf(stderr, "filesize err\n"); exit(1); } return p + next; //skip this segment } //end of file