diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/sam2p/jpegdump_main.cpp |
Initial commit
Diffstat (limited to 'graphics/sam2p/jpegdump_main.cpp')
-rw-r--r-- | graphics/sam2p/jpegdump_main.cpp | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/graphics/sam2p/jpegdump_main.cpp b/graphics/sam2p/jpegdump_main.cpp new file mode 100644 index 0000000000..804d89fbdd --- /dev/null +++ b/graphics/sam2p/jpegdump_main.cpp @@ -0,0 +1,306 @@ +\/* + * jpegdump_main.cpp -- dump a JPEG stream + * by pts@math.bme.hu at Tue Jun 4 13:19:00 CEST 2002 + */ + + +/* Structure of a typical JPEG file: +(D8:SOI) (E0:APP0) (FE:COM)? (DB:DQT)*2 (C0:SOF0) (C4:DHT)*4 (DA:SOS) +... (D9:EOI) +*/ + +#ifdef __GNUC__ +#ifndef __clang__ +#pragma implementation +#endif +#endif + +#include "config2.h" +#include <stdio.h> + +#if OBJDEP +#warning PROVIDES: jpegdump_main +#endif + +typedef slen_t dimen_t; +static const unsigned char + CS_UNKNOWN=0, /* error/unspecified */ + CS_GRAYSCALE=1, /* monochrome */ + CS_RGB=2, /* red/green/blue */ + CS_YCbCr=3, /* Y/Cb/Cr (also known as YUV) */ + CS_CMYK=4, /* C/M/Y/K */ + CS_YCCK=5, /* Y/Cb/Cr/K */ + CS_Indexed_RGB=12; + + +/* --- The following code is based on standard/image.c from PHP4 */ + +/* some defines for the different JPEG block types */ +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_COM 0xFE /* comment */ +#define M_DQT 0xDB /* QuantTables */ +#define M_DHT 0xC4 /* HuffTables */ +#define M_APP0 0xe0 +#define M_APP1 0xe1 +#define M_APP2 0xe2 +#define M_APP3 0xe3 +#define M_APP4 0xe4 +#define M_APP5 0xe5 +#define M_APP6 0xe6 +#define M_APP7 0xe7 +#define M_APP8 0xe8 +#define M_APP9 0xe9 +#define M_APP10 0xea +#define M_APP11 0xeb +#define M_APP12 0xec +#define M_APP13 0xed +#define M_APP14 0xee +#define M_APP15 0xef + + +static unsigned short jai_read2(FILE *fp) { + unsigned char a[ 2 ]; + + /* just return 0 if we hit the end-of-file */ + if (fread(a,sizeof(a),1,fp) != 1) return 0; + + return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]); +} + +static unsigned int jai_next_marker(FILE *fp) + /* get next marker byte from file */ +{ + int c; + + /* skip unimportant stuff */ + + c = MACRO_GETC(fp); + + while (c != 0xff) { + if ((c = MACRO_GETC(fp)) == EOF) + return M_EOI; /* we hit EOF */ + } + + /* get marker byte, swallowing possible padding */ + do { + if ((c = MACRO_GETC(fp)) == EOF) + return M_EOI; /* we hit EOF */ + } while (c == 0xff); + + // printf("marker=%02X\n", c); + return (unsigned int) c; +} + +static void jai_skip_variable(FILE *fp) + /* skip over a variable-length block; assumes proper length marker */ +{ + unsigned short length; + + printf("%lu: skip variable\n", ftell(fp)); + + length = jai_read2(fp); + length -= 2; /* length includes itself */ + if (length>0) { + printf("... variable length=%u\n", length); + #if 0 + fseek(fp, (long) length, SEEK_CUR); /* skip the header */ + #endif + while (length--!=0) MACRO_GETC(fp); /* make feof(fp) correct */ + printf("%lu: skipped variable; feof=%u\n", ftell(fp), feof(fp)); + } +} + +struct gfxinfo { + unsigned char bad, bpc, cpp, had_jfif, colortransform, id_rgb; + dimen_t height, width; + /** Offset of byte just _after_ the first SOF marker (FF C0 or alike) + * from the beginning of the file. + */ + slen_t SOF_offs; +}; + +/** main loop to parse JPEG structure */ +static void jai_handle_jpeg(struct gfxinfo *result, FILE *fp) { + unsigned int length, marker; + unsigned char had_adobe, id, hvs, qtn; + + result->bad=1; /* signal invalid return value */ + result->id_rgb=0; + result->had_jfif=0; + result->colortransform=127; /* no Adobe marker yet */ + // fseek(fp, 0L, SEEK_SET); /* position file pointer on SOF */ + + if (MACRO_GETC(fp) != 0xFF || MACRO_GETC(fp)!=M_SOI) return; /* JPEG header... */ + printf("2: marker D8 (SOI)\n"); + + for (;;) { + assert(!feof(fp)); + printf("... %lu\n", ftell(fp)); + marker=jai_next_marker(fp); + printf("%lu: marker %02X\n", ftell(fp), marker); + switch (marker) { + case M_SOF0: + if (result->bad!=1) { result->bad=4; return; } /* only one M_SOF allowed */ + result->SOF_offs=ftell(fp); + /* handle SOFn block */ + length=jai_read2(fp); + result->bpc = MACRO_GETC(fp); + result->height = jai_read2(fp); + result->width = jai_read2(fp); + result->cpp = MACRO_GETC(fp); + if ((length-=8)!=3U*result->cpp) return; + if (result->cpp==3) { + result->id_rgb =(id=MACRO_GETC(fp)=='R'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp); + printf("Comp#1 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n", + id, hvs>>4, hvs&15, qtn); + result->id_rgb&=(id=MACRO_GETC(fp)=='G'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp); + printf("Comp#2 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n", + id, hvs>>4, hvs&15, qtn); + result->id_rgb&=(id=MACRO_GETC(fp)=='B'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp); + printf("Comp#3 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n", + id, hvs>>4, hvs&15, qtn); + } else while (length--!=0) MACRO_GETC(fp); + if (result->cpp!=1 && result->cpp!=3 && result->cpp!=4) { + result->bad=5; return; + } + if (feof(fp)) { result->bad=8; return; } + result->bad=2; + break; + case M_SOF1: + case M_SOF2: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + // fprintf(stderr, "SOF%u\n", marker-M_SOF0); assert(0); + result->bad=3; + return; + case M_SOS: /* we are about to hit image data. We're done. */ + jai_skip_variable(fp); /* anything else isn't interesting */ + if (feof(fp)) { result->bad=8; return; } + if (result->bad==2 && !feof(fp)) result->bad=0; + /* Dat: we should really return() here, because the SOS marker is + * followed by binary data, not surrounded by markers. + */ + break; + case M_EOI: /* end of image or EOF */ + if (feof(fp)) result->bad=6; + else if (MACRO_GETC(fp)!=EOF) result->bad=7; + return; + case M_APP0: /* JFIF application-specific marker */ + length=jai_read2(fp); + if (length==2+4+1+2+1+2+2+1+1) { + result->had_jfif=MACRO_GETC(fp)=='J' && MACRO_GETC(fp)=='F' && MACRO_GETC(fp)=='I' && + MACRO_GETC(fp)=='F' && MACRO_GETC(fp)==0; + length-=7; + } else length-=2; + while (length--!=0) MACRO_GETC(fp); + if (feof(fp)) { result->bad=8; return; } + break; + case M_APP14: /* Adobe application-specific marker */ + length=jai_read2(fp); + if ((length-=2)==5+2+2+2+1) { + had_adobe=MACRO_GETC(fp)=='A' && MACRO_GETC(fp)=='d' && MACRO_GETC(fp)=='o' && + MACRO_GETC(fp)=='b' && MACRO_GETC(fp)=='e' && ((unsigned char)MACRO_GETC(fp))>=1; + MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); + if (had_adobe) result->colortransform=MACRO_GETC(fp); + else MACRO_GETC(fp); + } else while (length--!=0) MACRO_GETC(fp); + if (feof(fp)) { result->bad=8; return; } + break; + case M_APP1: + case M_APP2: + case M_APP3: + case M_APP4: + case M_APP5: + case M_APP6: + case M_APP7: + case M_APP8: + case M_APP9: + case M_APP10: + case M_APP11: + case M_APP12: + case M_APP13: + case M_APP15: + /* fall through */ + default: + jai_skip_variable(fp); /* anything else isn't interesting */ + if (feof(fp)) { result->bad=8; return; } + break; + } } +} + +static char *jai_errors[]={ + (char*)NULLP, + /*1*/ "missing SOF0 marker", + /*2*/ "EOF|EOI before SOS", /* "premature EOF", */ + /*3*/ "not a Baseline JPEG (SOF must be SOF0)", + /*4*/ "more SOF0 markers", + /*5*/ "bad # components", + /*6*/ "EOF before EOI", + /*7*/ "extra bytes after EOI", + /*8*/ "EOF before end of parametric marker", +}; + +int main(int argc, char **argv) { + struct gfxinfo gi; + FILE *f=argc>=2 ? fopen(argv[1], "rb"): stdin; + jai_handle_jpeg(&gi, f); + if (gi.bad==1) { + printf("JAI: Warning: %s.\n", jai_errors[gi.bad]); + gi.cpp=1; + gi.width=0; + gi.height=0; + gi.SOF_offs=0; + gi.bpc=0; + } else if (gi.bad!=0) { printf("JAI: %s.\n", jai_errors[gi.bad]); if (gi.bad!=1) return 1; } + unsigned char colorspace; + if (gi.cpp==1) { + colorspace=CS_GRAYSCALE; + } else if (gi.cpp==3) { + colorspace=CS_YCbCr; + if (gi.had_jfif!=0) ; + else if (gi.colortransform==0) colorspace=CS_RGB; + else if (gi.colortransform==1) ; + else if (gi.colortransform!=127) { printf("JAI: unknown ColorTransform: %u\n", (unsigned)gi.colortransform); return 2; } + else if (gi.id_rgb!=0) colorspace=CS_RGB; + /* Imp: check for id_ycbcr */ + else printf("JAI: assuming YCbCr color space\n"); + } else if (gi.cpp==4) { + colorspace=CS_CMYK; + if (gi.colortransform==0) ; + else if (gi.colortransform==2) colorspace=CS_YCCK; + else if (gi.colortransform!=127) { printf("JAI: unknown ColorTransform: %u\n", (unsigned)gi.colortransform); return 2; } + } else assert(0); + fseek(f, 0L, 2); /* EOF */ + long flen=ftell(f); /* skip extra bytes after EOI */ + fclose(f); + printf("%lu: flen\n", flen); + printf("bpc=%u cpp=%u had_jfif=%u colortransform=%u id_rgb=%u colorspace=%u\n", + gi.bpc, gi.cpp, gi.had_jfif, gi.colortransform, gi.id_rgb, colorspace); + printf("wd=%u ht=%u SOF_offs=%u\n", gi.width, gi.height, gi.SOF_offs); + return 0; +} + +/* __EOF__ */ |