unsigned int abitreader::read( int nbits ) { unsigned int retval = 0; // safety check for eof if ( eof ) { peof += nbits; return 0; } while ( nbits >= cbit ) { nbits -= cbit; retval |= ( RBITS( data[cbyte], cbit ) << nbits ); cbit = 8; if ( ++cbyte >= lbyte ) { peof = nbits; eof = true; return retval; } } if ( nbits > 0 ) { retval |= ( MBITS( data[cbyte], cbit, (cbit-nbits) ) ); cbit -= nbits; } return retval; }
/* ----------------------------------------------- Parse routines for JFIF segments ----------------------------------------------- */ bool parse_jfif_jpg( unsigned char type, unsigned int len, unsigned char* segment ) { unsigned int hpos = 4; // current position in segment, start after segment header int lval, rval; // temporary variables int cmp; int i; switch ( type ) { case 0xC4: // DHT segment // build huffman trees & codes // nothing to do here! return true; case 0xDB: // DQT segment // copy quantization tables to internal memory while ( hpos < len ) { lval = LBITS( segment[ hpos ], 4 ); rval = RBITS( segment[ hpos ], 4 ); if ( (lval < 0) || (lval >= 2) ) break; if ( (rval < 0) || (rval >= 4) ) break; hpos++; if ( lval == 0 ) { // 8 bit precision for ( i = 0; i < 64; i++ ) { qtables[ rval ][ i ] = ( unsigned short ) segment[ hpos + i ]; if ( qtables[ rval ][ i ] == 0 ) break; } hpos += 64; } else { // 16 bit precision for ( i = 0; i < 64; i++ ) { qtables[ rval ][ i ] = B_SHORT( segment[ hpos + (2*i) ], segment[ hpos + (2*i) + 1 ] ); if ( qtables[ rval ][ i ] == 0 ) break; } hpos += 128; } } if ( hpos != len ) { // if we get here, something went wrong sprintf( errormessage, "size mismatch in dqt marker" ); errorlevel = 2; return false; } return true; case 0xDD: // DRI segment // define restart interval rsti = B_SHORT( segment[ hpos ], segment[ hpos + 1 ] ); return true; case 0xDA: // SOS segment // prepare next scan cs_cmpc = segment[ hpos ]; if ( cs_cmpc > cmpc ) { sprintf( errormessage, "%i components in scan, only %i are allowed", cs_cmpc, cmpc ); errorlevel = 2; return false; } hpos++; for ( i = 0; i < cs_cmpc; i++ ) { for ( cmp = 0; ( segment[ hpos ] != cmpnfo[ cmp ].jid ) && ( cmp < cmpc ); cmp++ ); if ( cmp == cmpc ) { sprintf( errormessage, "component id mismatch in start-of-scan" ); errorlevel = 2; return false; } cs_cmp[ i ] = cmp; cmpnfo[ cmp ].huffdc = LBITS( segment[ hpos + 1 ], 4 ); cmpnfo[ cmp ].huffac = RBITS( segment[ hpos + 1 ], 4 ); if ( ( cmpnfo[ cmp ].huffdc < 0 ) || ( cmpnfo[ cmp ].huffdc >= 4 ) || ( cmpnfo[ cmp ].huffac < 0 ) || ( cmpnfo[ cmp ].huffac >= 4 ) ) { sprintf( errormessage, "huffman table number mismatch" ); errorlevel = 2; return false; } hpos += 2; } cs_from = segment[ hpos + 0 ]; cs_to = segment[ hpos + 1 ]; cs_sah = LBITS( segment[ hpos + 2 ], 4 ); cs_sal = RBITS( segment[ hpos + 2 ], 4 ); // check for errors if ( ( cs_from > cs_to ) || ( cs_from > 63 ) || ( cs_to > 63 ) ) { sprintf( errormessage, "spectral selection parameter out of range" ); errorlevel = 2; return false; } if ( ( cs_sah >= 12 ) || ( cs_sal >= 12 ) ) { sprintf( errormessage, "successive approximation parameter out of range" ); errorlevel = 2; return false; } return true; case 0xC0: // SOF0 segment // coding process: baseline DCT case 0xC1: // SOF1 segment // coding process: extended sequential DCT case 0xC2: // SOF2 segment // coding process: progressive DCT // set JPEG coding type if ( type == 0xC2 ) jpegtype = 2; else jpegtype = 1; // check data precision, only 8 bit is allowed lval = segment[ hpos ]; if ( lval != 8 ) { sprintf( errormessage, "%i bit data precision is not supported", lval ); errorlevel = 2; return false; } // image size, height & component count imgheight = B_SHORT( segment[ hpos + 1 ], segment[ hpos + 2 ] ); imgwidth = B_SHORT( segment[ hpos + 3 ], segment[ hpos + 4 ] ); cmpc = segment[ hpos + 5 ]; if ( cmpc > 4 ) { sprintf( errormessage, "image has %i components, max 4 are supported", cmpc ); errorlevel = 2; return false; } hpos += 6; // components contained in image for ( cmp = 0; cmp < cmpc; cmp++ ) { cmpnfo[ cmp ].jid = segment[ hpos ]; cmpnfo[ cmp ].sfv = LBITS( segment[ hpos + 1 ], 4 ); cmpnfo[ cmp ].sfh = RBITS( segment[ hpos + 1 ], 4 ); cmpnfo[ cmp ].qtable = qtables[ segment[ hpos + 2 ] ]; cmpnfo[ cmp ].qtblno = segment[ hpos + 2 ]; hpos += 3; } return true; case 0xC3: // SOF3 segment // coding process: lossless sequential sprintf( errormessage, "sof3 marker found, image is coded lossless" ); errorlevel = 2; return false; case 0xC5: // SOF5 segment // coding process: differential sequential DCT sprintf( errormessage, "sof5 marker found, image is coded diff. sequential" ); errorlevel = 2; return false; case 0xC6: // SOF6 segment // coding process: differential progressive DCT sprintf( errormessage, "sof6 marker found, image is coded diff. progressive" ); errorlevel = 2; return false; case 0xC7: // SOF7 segment // coding process: differential lossless sprintf( errormessage, "sof7 marker found, image is coded diff. lossless" ); errorlevel = 2; return false; case 0xC9: // SOF9 segment // coding process: arithmetic extended sequential DCT sprintf( errormessage, "sof9 marker found, image is coded arithm. sequential" ); errorlevel = 2; return false; case 0xCA: // SOF10 segment // coding process: arithmetic extended sequential DCT sprintf( errormessage, "sof10 marker found, image is coded arithm. progressive" ); errorlevel = 2; return false; case 0xCB: // SOF11 segment // coding process: arithmetic extended sequential DCT sprintf( errormessage, "sof11 marker found, image is coded arithm. lossless" ); errorlevel = 2; return false; case 0xCD: // SOF13 segment // coding process: arithmetic differntial sequential DCT sprintf( errormessage, "sof13 marker found, image is coded arithm. diff. sequential" ); errorlevel = 2; return false; case 0xCE: // SOF14 segment // coding process: arithmetic differential progressive DCT sprintf( errormessage, "sof14 marker found, image is coded arithm. diff. progressive" ); errorlevel = 2; return false; case 0xCF: // SOF15 segment // coding process: arithmetic differntial lossless sprintf( errormessage, "sof15 marker found, image is coded arithm. diff. lossless" ); errorlevel = 2; return false; case 0xE0: // APP0 segment case 0xE1: // APP1 segment case 0xE2: // APP2 segment case 0xE3: // APP3 segment case 0xE4: // APP4 segment case 0xE5: // APP5 segment case 0xE6: // APP6 segment case 0xE7: // APP7 segment case 0xE8: // APP8 segment case 0xE9: // APP9 segment case 0xEA: // APP10 segment case 0xEB: // APP11 segment case 0xEC: // APP12segment case 0xED: // APP13 segment case 0xEE: // APP14 segment case 0xEF: // APP15 segment case 0xFE: // COM segment // do nothing - return true return true; case 0xD0: // RST0 segment case 0xD1: // RST1segment case 0xD2: // RST2 segment case 0xD3: // RST3 segment case 0xD4: // RST4 segment case 0xD5: // RST5 segment case 0xD6: // RST6 segment case 0xD7: // RST7 segment // return errormessage - RST is out of place here sprintf( errormessage, "rst marker found out of place" ); errorlevel = 2; return false; case 0xD8: // SOI segment // return errormessage - start-of-image is out of place here sprintf( errormessage, "soi marker found out of place" ); errorlevel = 2; return false; case 0xD9: // EOI segment // return errormessage - end-of-image is out of place here sprintf( errormessage, "eoi marker found out of place" ); errorlevel = 2; return false; default: // unknown marker segment // return warning sprintf( errormessage, "unknown marker found: FF %2X", type ); errorlevel = 1; return true; } }