/************************************************************************ jpeg81.c An ITU T.81 JPEG coefficient-decoder - without de-quantization and IDCT. Used for conformance testing of ITU T.83 data (a little verbose output). Allocates full image coefficient buffer. Supports: - JPEG Interchange Format (JIF) - DCT- and Lossless operation - Huffman- and arithmetic coding - Sequential- and progressive mode - max. 4 components - all sub-sampling - 8/12 - bit samples for DCT - 2-16 - bit for Lossless It does not support the Hierarchial mode. TODO: more error checking. * Copyright (c) 2017 A. Tarpai * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "GETC.h" #include "rb_glue.h" #include "jpeg81.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #if (__GNUC__ >= 6) #pragma GCC diagnostic ignored "-Wshift-negative-value" #endif ///////////////////////////////////////// LOSSLESS ///////////////////////////////////////// static int P1(struct COMP *C, TSAMP *samp) // Px = Ra { return samp[-1]; } static int P2(struct COMP *C, TSAMP *samp) // Px = Rb { return samp[-C->du_width]; } static int P3(struct COMP *C, TSAMP *samp) // Px = Rc { return samp[-C->du_width-1]; } static int P4(struct COMP *C, TSAMP *samp) // Px = Ra + Rb - Rc { return samp[-1] + samp[-C->du_width] - samp[-C->du_width-1]; } static int P5(struct COMP *C, TSAMP *samp) // Px = Ra + ((Rb - Rc)/2) { return samp[-1] + ( (samp[-C->du_width] - samp[-C->du_width-1]) >> 1 ); } static int P6(struct COMP *C, TSAMP *samp) // Px = Rb + ((Ra - Rc)/2) { return samp[-C->du_width] + ( (samp[-1] - samp[-C->du_width-1]) >> 1 ); } static int P7(struct COMP *C, TSAMP *samp) // Px = (Ra + Rb)/2 { return (samp[-1] + samp[-C->du_width]) >> 1; } static int (*PN[])(struct COMP *C, TSAMP *samp) = { 0, P1, P2, P3, P4, P5, P6, P7 }; static int Predx(struct JPEGD *j, struct COMP *C, int x, int y, TSAMP *samp) { int Px; if (!x) { if (y) Px= samp[-C->du_width]; // Px = Rb (P2) else Px= 1<<(j->P-1); // 'P0' } else { if (y) Px= PN[j->Ss](C, samp); // (PN) else Px= samp[-1]; // Px = Ra (P1) } return Px; } //////////////////////////////////// HUFFMAN //////////////////////////////////////////////// static int Byte_in_huff(struct JPEGD *j) { j->ScanByte = GETC(); if ( 0xFF == j->ScanByte ) { int marker = GETC(); if ( marker ) // DEBUG: ERR in Huffman: { printf("%08X: FF%02x\n", TELL()-2, marker); printf("STREAM ERROR: marker found in Huffman ECS\n"); } //else skip zero-stuffing } return j->ScanByte; } static int GetBit(struct JPEGD *j) { if ( j->ScanBit ) return (j->ScanByte >> --j->ScanBit) & 1; j->ScanBit=7; return j->Byte_in(j) >> 7; // arith/huff } static int Getnbit(struct JPEGD *j, int n) // n>0 { int v= GetBit(j); while (--n) v= 2*v + GetBit(j); return v; } static int ReadDiff(struct JPEGD *j, int s) // JPEG magnitude stuff. One way to do this.. { int x= Getnbit(j, s); if ( 0 == (x >> (s-1)) ) x= (-1<Al; // point transform included PRED??? seems ok. } static int ReadHuffmanCode(struct JPEGD *j, int *pb) // index into the sym-table { int v= GetBit(j); while ( v >= *pb ) v= 2*v + GetBit(j) - *pb++; return v; } static void dc_succ_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { *coef |= GetBit(j) << j->Al; } static void dc_decode_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int s= sc->DCS[ReadHuffmanCode(j, sc->DCB)]; if (s) sc->DC+= ReadDiff(j, s); *coef= sc->DC; } static void ac_decode_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int k= j->Ss; if (0==sc->EOBRUN) { for (; ;k++) { int s= sc->ACS[ReadHuffmanCode(j, sc->ACB)]; int r= s>>4; if ( s&=15 ) s= ReadDiff(j, s); else { if (r < 15) { // EOBn? if (r) sc->EOBRUN= Getnbit(j, r) + ~(-1<Se) return; } } else sc->EOBRUN--; } static int ac_refine(struct JPEGD *j, TCOEF *coef) { if (*coef) if (GetBit(j)) *coef+= (*coef > 0)? j->Al2 : -j->Al2; return *coef; } static void ac_succ_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int k= j->Ss; if (0==sc->EOBRUN) { for (; ;k++) { int s= sc->ACS[ReadHuffmanCode(j, sc->ACB)]; int r= s>>4; if ( s&=15 ) s= GetBit(j)? j->Al2 : -j->Al2; else { if (r < 15) { // EOBn? if (r) sc->EOBRUN= Getnbit(j, r) + ~(-1<Se) return; } } else sc->EOBRUN--; for (; k<=j->Se; k++) ac_refine(j, coef+k); // Refine EOBRUN } static void du_sequential_huff(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int s, k; dc_decode_huff(j, sc, coef); for (k=1; (s=sc->ACS[ReadHuffmanCode(j, sc->ACB)]); k++) { // EOB? k+= s>>4; if (s==0xf0) continue; // ZRL coef[k]= ReadDiff(j, s&15); if (k==63) return; } } static void decode_lossless_huff(struct JPEGD *j, struct COMP *sc, int x, int y, TSAMP *samp) // TODO: Pt { int DIFF= sc->DCS[ReadHuffmanCode(j, sc->DCB)]; *samp= Predx(j, sc, x, y, samp); if (DIFF) *samp+= (DIFF==16)? 32768 : ReadDiff(j, DIFF); } static void Reset_decoder_huff(struct JPEGD *j) { int c; for (c=0; c < j->Ns; c++) j->ScanComponents[c]->DC=0; // DC/EOBRUN j->ScanBit=0; // trigger next byte read (skipping stuffing '1'-s) } static void Reset_decoder_huff_lossless(struct JPEGD *j) { j->LineNo=0; j->ScanBit=0; // trigger next byte read } /////////////////////////////////// ARITHMETIC ////////////////////////////////////////////// static int Byte_in_arith(struct JPEGD *j) { j->ScanByte = GETC(); if ( 0xFF == j->ScanByte ) { if ( GETC() ) { // Marker detection SEEK(-2); // Arith: "zero byte fed to decoder" j->ScanBit=~0; // Seems like 8 was not enough.. TODO j->ScanByte=0; } //else skip zero-stuffing } return j->ScanByte; } static void ResetStat(struct CABACSTATE *st, int n) // Initialize statistics areas { while (--n >= 0) st[n].valMPS= st[n].StateIdx=0; } static void InitDecoder(struct JPEGD *j) { j->ScanBit=0; // trigger next byte read j->A=0; j->C= Byte_in_arith(j) << 8; j->C|= Byte_in_arith(j); } static void Reset_decoder_arith(struct JPEGD *j) { int c; for (c=0; c < j->Ns; c++) { struct COMP *sc= j->ScanComponents[c]; if (j->Se) ResetStat(sc->ACST+1, 245); // AC in Scan (+1 adjusted) if (!j->Ss) // DC in Scan { ResetStat(sc->DCST, 49); sc->DC= 0; sc->DIFF= 0; // extra in Arith } } InitDecoder(j); } static void Reset_decoder_arith_lossless(struct JPEGD *j) { int c; for (c=0; c < j->Ns; c++) ResetStat(j->ScanComponents[c]->LLST, 158); j->LineNo=0; // Special in lossless InitDecoder(j); } static struct _STATE { int Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS; } STATE[] = {{0x5A1D,1,1,1},{0x2586,14,2,0},{0x1114,16,3,0},{0x080B,18,4,0},{0x03D8,20,5,0},{0x01DA,23,6,0},{0x00E5,25,7,0},{0x006F,28,8,0},{0x0036,30,9,0},{0x001A,33,10,0},{0x000D,35,11,0},{0x0006,9,12,0},{0x0003,10,13,0},{0x0001,12,13,0},{0x5A7F,15,15,1},{0x3F25,36,16,0},{0x2CF2,38,17,0},{0x207C,39,18,0},{0x17B9,40,19,0},{0x1182,42,20,0},{0x0CEF,43,21,0},{0x09A1,45,22,0},{0x072F,46,23,0},{0x055C,48,24,0},{0x0406,49,25,0},{0x0303,51,26,0},{0x0240,52,27,0},{0x01B1,54,28,0},{0x0144,56,29,0},{0x00F5,57,30,0},{0x00B7,59,31,0},{0x008A,60,32,0},{0x0068,62,33,0},{0x004E,63,34,0},{0x003B,32,35,0},{0x002C,33,9,0},{0x5AE1,37,37,1},{0x484C,64,38,0},{0x3A0D,65,39,0},{0x2EF1,67,40,0},{0x261F,68,41,0},{0x1F33,69,42,0},{0x19A8,70,43,0},{0x1518,72,44,0},{0x1177,73,45,0},{0x0E74,74,46,0},{0x0BFB,75,47,0},{0x09F8,77,48,0},{0x0861,78,49,0},{0x0706,79,50,0},{0x05CD,48,51,0},{0x04DE,50,52,0},{0x040F,50,53,0},{0x0363,51,54,0},{0x02D4,52,55,0},{0x025C,53,56,0},{0x01F8,54,57,0},{0x01A4,55,58,0},{0x0160,56,59,0},{0x0125,57,60,0},{0x00F6,58,61,0},{0x00CB,59,62,0},{0x00AB,61,63,0},{0x008F,61,32,0},{0x5B12,65,65,1},{0x4D04,80,66,0},{0x412C,81,67,0},{0x37D8,82,68,0},{0x2FE8,83,69,0},{0x293C,84,70,0},{0x2379,86,71,0},{0x1EDF,87,72,0},{0x1AA9,87,73,0},{0x174E,72,74,0},{0x1424,72,75,0},{0x119C,74,76,0},{0x0F6B,74,77,0},{0x0D51,75,78,0},{0x0BB6,77,79,0},{0x0A40,77,48,0},{0x5832,80,81,1},{0x4D1C,88,82,0},{0x438E,89,83,0},{0x3BDD,90,84,0},{0x34EE,91,85,0},{0x2EAE,92,86,0},{0x299A,93,87,0},{0x2516,86,71,0},{0x5570,88,89,1},{0x4CA9,95,90,0},{0x44D9,96,91,0},{0x3E22,97,92,0},{0x3824,99,93,0},{0x32B4,99,94,0},{0x2E17,93,86,0},{0x56A8,95,96,1},{0x4F46,101,97,0},{0x47E5,102,98,0},{0x41CF,103,99,0},{0x3C3D,104,100,0},{0x375E,99,93,0},{0x5231,105,102,0},{0x4C0F,106,103,0},{0x4639,107,104,0},{0x415E,103,99,0},{0x5627,105,106,1},{0x50E7,108,107,0},{0x4B85,109,103,0},{0x5597,110,109,0},{0x504F,111,107,0},{0x5A10,110,111,1},{0x5522,112,109,0},{0x59EB,112,111,1}}; static void Renorm(struct JPEGD *j) { do j->C= 2*j->C | GetBit(j); while ( (short)(j->A*=2) >= 0); } static int tr_MPS(struct JPEGD *j, struct CABACSTATE *st) { Renorm(j); st->StateIdx= STATE[ st->StateIdx ].Next_Index_MPS; return st->valMPS; } static int tr_LPS(struct JPEGD *j, struct CABACSTATE *st) { int D= st->valMPS^1; st->valMPS ^= STATE[ st->StateIdx ].Switch_MPS; st->StateIdx= STATE[ st->StateIdx ].Next_Index_LPS; Renorm(j); return D; } static int DecodeBin(struct JPEGD *j, struct CABACSTATE *st) { unsigned short A= j->A - STATE[ st->StateIdx ].Qe_Value; if ( j->C < A ) { j->A = A; if ((short)A<0) return st->valMPS; return ( A < STATE[ st->StateIdx ].Qe_Value )? tr_LPS(j, st) : tr_MPS(j, st); } j->C -= A; j->A= STATE[ st->StateIdx ].Qe_Value; return ( A < j->A )? tr_MPS(j, st) : tr_LPS(j, st); } static int DecodeFIX(struct JPEGD *j) { unsigned short A= j->A - 0x5A1D; if ( j->C < A ) { if ((short)(j->A = A)<0) return 0; Renorm(j); return ( A < 0x5A1D ) ? 1 : 0; } else { j->C = 2*( j->C - A ) | GetBit(j); j->A= 0x5A1D*2; return ( A < 0x5A1D ) ? 0 : 1; } } static int DC_Context(struct COMP *sc, int D) // DC + LOSSLESS { if (D < 0) { if ( D < -sc->U ) return 16; // large neg if ( D < -sc->L ) return 8; } else { if ( D > sc->U ) return 12; // large pos if ( D > sc->L ) return 4; } return 0; } static int Decode_V(struct JPEGD *j, struct CABACSTATE *ST, int SNSP, int X1, int X2) // DC/AC { int Sz, M; if ( !DecodeBin(j, ST+SNSP) ) return 1; if ( !DecodeBin(j, ST+X1) ) return 2; M=2, ST+=X2; while ( DecodeBin(j, ST) ) M <<= 1, ST++; Sz= M; ST += 14; while (M>>=1) if (DecodeBin(j, ST)) Sz |= M; return Sz+1; } static int Decode_DIFF(struct JPEGD *j, struct CABACSTATE *ST, int S0, int X1) // DC + LOSSLESS { if ( DecodeBin(j, ST+S0) ) // (S0) { int sign= DecodeBin(j, ST + S0 + 1); // (SS) int DIFF= Decode_V(j, ST, S0 + 2 + sign, X1, X1+1); return (sign)? -DIFF : DIFF; } return 0; } static void dc_decode_arith(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int S0= DC_Context(sc, sc->DIFF); sc->DIFF= Decode_DIFF(j, sc->DCST, S0, 20); sc->DC+= sc->DIFF << j->Al; *coef= sc->DC; } static void ac_band(struct JPEGD *j, struct COMP *sc, TCOEF *coef, int k) // NB: we re-arrange contexts a little (so indexing simply by k) { while ( !DecodeBin(j, sc->ACST+k) ) // EOB? { int V, sign; while ( !DecodeBin(j, sc->ACST+k+63) ) k++; // S0 sign= DecodeFIX(j); V= Decode_V(j, sc->ACST, k+126, k+126, (k>sc->Kx)? (217+1) : (189+1) ); if (sign) V = -V; coef[k]= V << j->Al; if (k==j->Se) return; k++; } } static void du_sequential_arith(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { dc_decode_arith(j, sc, coef); ac_band(j, sc, coef, 1); } static void ac_decode_arith(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { ac_band(j, sc, coef, j->Ss); } static void dc_succ_arith(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { *coef |= DecodeFIX(j) << j->Al; } static void ac_succ_arith(struct JPEGD *j, struct COMP *sc, TCOEF *coef) { int k= j->Ss; int EOBx= j->Se; // actually index of last non-zero coeff already decoded in band while ( !coef[EOBx] && EOBx >= k ) EOBx--; for (; k <= EOBx; k++) { if ( coef[k]) { if (DecodeBin(j, sc->ACST+k+126)) coef[k] += (coef[k] > 0)? j->Al2 : -j->Al2; // SC: correction bit? } else { if (DecodeBin(j, sc->ACST+k+63)) coef[k]= DecodeFIX(j)? -j->Al2 : j->Al2; // New coeff? } } for (; k <= j->Se && !DecodeBin(j, sc->ACST+k); k++) // SE: EOB? { while (!DecodeBin(j, sc->ACST+k+63)) k++; coef[k]= DecodeFIX(j)? -j->Al2 : j->Al2; } } static void decode_lossless_arith(struct JPEGD *j, struct COMP *sc, int x, int y, TSAMP *samp) // TODO: Pt { int Da= x? 5 * DC_Context(sc, sc->diffLeft[y]) : 0; int Db= y? DC_Context(sc, sc->diffAbove[x]) : 0; int DIFF= Decode_DIFF(j, sc->LLST, Da + Db, (Db>8)? 129 : 100); sc->diffAbove[x]= DIFF; sc->diffLeft[y]= DIFF; *samp= Predx(j, sc, x, y, samp) + DIFF; } /////////////////////////// SCAN DECODING /////////////////////////////////////////////////////////////////////////////// //static int LocateMarker(struct JPEGD *j) static int NextMarker(struct JPEGD *j) // at expected location - this is not LocateMarker() { int Marker; printf("%08X: ", TELL()); while ( 0xFF == (Marker=GETC()) ) printf("FF"); // marker stuffing FF printf("%02X ", Marker); return Marker; } static void Ri(struct JPEGD *j, int n) { if (j->Ri) // Restart enabled? { if ( 0 == n % j->Ri ) { int Marker= NextMarker(j); if ( (Marker & 0xf8) == 0xD0 ) // RSTn expected { printf("RST%d\n", Marker&7); printf("%08X: ECS\n", TELL()); } else { printf("STREAM ERROR: expected RSTn missing from ECS\n"); } j->Reset_decoder(j); } } } static void DecodeInterleaved_DCT(struct JPEGD *j) { int n=0, c, x, y; for(;;) { int mcuy = n / j->mcu_width; int mcux = n % j->mcu_width; for (c=0; c < j->Ns; c++) { struct COMP *C= j->ScanComponents[c]; DU *du= C->du + mcuy * C->du_width * C->Vi + mcux * C->Hi; for (y=0; yVi; y++) for (x=0; xHi; x++) j->DecodeDataUnit(j, C, du[ C->du_width * y + x ]); // Huff/arith } if (++n==j->mcu_total) return; // We count MCU-s. No RST after the last Ri(j, n); } } static void DecodeSingle_DCT(struct JPEGD *j) { int n=0; struct COMP *C= j->ScanComponents[0]; for (;;) { j->DecodeDataUnit(j, C, C->du[ (n / C->du_w) * C->du_width + n % C->du_w ]); // Huff/arith if ( ++n == C->du_size ) return; // We count DU-s. No RST after the last Ri(j, n); } } static void DecodeSingle_LL(struct JPEGD *j) { int n=0, x; struct COMP *C= j->ScanComponents[0]; TSAMP *samp= C->samp; j->LineNo=0; for (;;) { for (x=0; x < C->du_w; x++) j->decode_lossless(j, C, x, j->LineNo, samp+x); // Huff/arith if ( (n+=C->du_w) == C->du_size ) return; // we count by lines j->LineNo=1; Ri(j, n); // Lossless restart interval is one mcu-line samp+=C->du_width; } } static void DecodeInterleaved_LL(struct JPEGD *j) { int n=0, c; int x, mcux; int y, mcuy; j->LineNo=0; for (mcuy=0; ; mcuy++) { for (mcux=0; mcux < j->mcu_width; mcux++) { for (c=0; c < j->Ns; c++) { struct COMP *C= j->ScanComponents[c]; int xs= mcux * C->Hi; TSAMP *samp= C->samp + C->du_width * (mcuy * C->Vi) + xs; for (y=0; y < C->Vi; y++, samp+=C->du_width) { for (x=0; x < C->Hi; x++) j->decode_lossless(j, C, xs+x, j->LineNo+y, samp + x); // Huff/arith } } } if ( (n+=j->mcu_width) == j->mcu_total ) return; // we count by lines j->LineNo=1; Ri(j, n); // Lossless restart interval is one mcu-line } } ////////////////////////////// PARSING ////////////////////////////////////////////////////////////////////////////// static char *SOFSTRING[] = { // debug // non-differential, Huffman coding "Baseline DCT", "Huffman Extended sequential DCT", "Huffman Progressive DCT", "Huffman Lossless sequential", // differential, Huffman coding (Hierarchial) "", // DHT "-Differential sequential DCT", "-Differential progressive DCT", "-Differential lossless (sequential)", // non-differential, arithmetic coding "", // JPG "Arithmetic Extended sequential DCT", "Arithmetic Progressive DCT", "Arithmetic Lossless sequential", // differential, arithmetic coding (Hierarchial) "", // DAC "-Arithmetic Differential sequential DCT", "-Arithmetic Differential progressive DCT", "-Arithmetic Differential lossless sequential", }; static int div_up(int a, int b) // ~ciel([a/b]) { return (a + b - 1) / b; } static int set_dim(struct JPEGD *j, int d) // d= 1 (LL) or 8 (DCT) { int i, TotalDU=0; j->Hmax= j->Vmax= 0; for (i=0; iNf; i++) // read component data, set Hmax/Vmax { struct COMP *C= j->Components + i; C->Ci= GETC(); //Cid C->Vi= GETC(); //HV C->Hi= C->Vi>>4; C->Vi&= 15; C->Qi= GETC(); if ( C->Hi > j->Hmax ) j->Hmax = C->Hi; if ( C->Vi > j->Vmax ) j->Vmax = C->Vi; printf(" Ci=%3d HV=%dx%d Qi=%d\n", C->Ci, C->Hi, C->Vi, C->Qi); } printf("\n"); // Full Image MCU cover: j->mcu_width= div_up(j->X, j->Hmax*d); j->mcu_height= div_up(j->Y, j->Vmax*d); j->mcu_total= j->mcu_width * j->mcu_height; // now set parameters based on Hmax/Vmax for (i=0; iNf; i++) { struct COMP *C= j->Components + i; int xi= div_up(j->X*C->Hi, j->Hmax); // as Standard: sample rectangle (from image X,Y and Sampling factors) int yi= div_up(j->Y*C->Vi, j->Vmax); // used to compute single scan 'coverage' // Single scan DU-cover (LL: d=1) C->du_w= div_up(xi, d); C->du_h= div_up(yi, d); C->du_size= C->du_w * C->du_h; // Interleaved scan DU-cover C->du_width= j->mcu_width*C->Hi; C->du_total= C->du_width * j->mcu_height*C->Vi; TotalDU+= C->du_total; //printf(" %d\n", i); //printf(" Sample: x=%d+%d (1:%d) y=%d+%d (1:%d)\n", C->xi, C->dux*8-C->xi, j->Hmax/C->Hi, C->yi, C->duy*8-C->yi, j->Vmax/C->Vi); //printf(" 8x8 Data Unit: %d (X=%d Y=%d)\n", C->duN, C->dux, C->duy); //printf(" MCU Data Unit: %d (X=%d Y=%d)\n", C->du_total, C->du_width, C->duyI); // LL //printf(" Sample: x=%d (1:%d) y=%d (1:%d)\n", C->du_xi, j->Hmax/C->Hi, C->du_yi, j->Vmax/C->Vi); } return TotalDU; } extern enum JPEGENUM JPEGDecode(struct JPEGD *j) { int marker, i; j->jpeg_mem= 0; marker = NextMarker(j); if ( marker != 0xD8 ) return JPEGENUMERR_MISSING_SOI; printf("SOI\n"); // The 'Decoder_setup' procedure j->Ri=0; // Arithmetic capable Decoder this is: // default DC bounds: L = 0 and U = 1, Kx=5 j->U[0]= j->U[1]= j->U[2]= j->U[3]= 2; // 1<L[0]= j->L[1]= j->L[2]= j->L[3]= 0; j->Kx[0]= j->Kx[1]= j->Kx[2]= j->Kx[3]= 5; // Set first to zero for scaled quantization // Also for QT entry redefinition (not implemented, see remarks) j->QT[0][0]=j->QT[1][0]=j->QT[2][0]=j->QT[3][0]=0; for (;;) { marker = NextMarker(j); if ( marker == 0xCC ) // DAC { int La= GETWbi(); printf("DAC\n"); printf(" Arithmetic Conditioning\n parameters:\n"); for (La-=2; La; La-=2) { int CB= GETC(); int Tc= CB>>4; int Tb= CB&15; int Cs= GETC(); if (Tc) // AC { printf(" AC%d Kx=%d\n", Tb, Cs); j->Kx[Tb]= Cs; } else { int L= Cs&15; int U= Cs>>4; printf(" DC%d L=%d U=%d\n", Tb, Cs&15, Cs>>4); j->U[Tb]= 1<L[Tb]= L? 1 << (L-1) : 0; } } } else if ( marker == 0xC8 ) // T.851?? { return JPEGENUMERR_MARKERC8; } else if ( marker == 0xC4 ) // DHT { int N; int Lh= GETWbi(); printf("DHT\n"); for (Lh-=2; Lh; Lh -= 17 + N) { int CH= GETC(); int Tc= CH>>4; int Th= CH&15; int *B= j->HTB[Tc][Th]; unsigned char *S= j->HTS[Tc][Th]; printf(" %s%d\n", Tc?"AC":"DC", Th); printf(" N: "); for (i=N=0; i<16; i++) { int n= GETC(); N+= n; printf("%d ", n); B[i]= N; // running total } printf("\n"); printf(" S: %d symbol bytes\n", N); for (i=0; iP= GETC();//P j->Y= GETWbi();//Y: Number of lines j->X= GETWbi();//X: Number of samples per line j->Nf= GETC();//Nf printf("SOF%d (%s)\n", marker&15, SOFSTRING[marker&15]); printf(" P=%d Y=%d X=%d\n", j->P, j->Y, j->X); printf(" Nf=%d\n", j->Nf); if (*SOFSTRING[marker&15] == '-') return JPEGENUMERR_UNKNOWN_SOF; if (j->Nf>4) return JPEGENUMERR_COMP4; if (!j->Y) return JPEGENUMERR_ZEROY; // I have no idea about this DNL stuff j->SOF= marker; if ( (j->SOF&3)==3 ) // LOSSLESS-mode { int TotalDU= set_dim(j, 1); // for malloc: in samples as coeff; if (j->SOF > 0xC8) { // arithmetic: j->Reset_decoder= Reset_decoder_arith_lossless; j->decode_lossless= decode_lossless_arith; j->Byte_in= Byte_in_arith; // Arithmetic: need a line to store DIFF, where??? for (i=0; iNf; i++) { struct COMP *C= j->Components + i; C->du_total += C->du_width; TotalDU+= C->du_width; } } else { // Huffman j->Reset_decoder= Reset_decoder_huff_lossless; j->decode_lossless= decode_lossless_huff; j->Byte_in= Byte_in_huff; } // malloc sample storage { TSAMP *samp; int mallocTotalCoef= sizeof(TSAMP) * TotalDU; j->jpeg_mem= calloc(mallocTotalCoef, 1); if ( 0 == j->jpeg_mem ) return JPEGENUMERR_MALLOC; samp= j->jpeg_mem; for (i=0; iNf; i++) { struct COMP *C= j->Components + i; C->samp= samp; samp+= C->du_total; C->diffAbove= samp - C->du_width; // 1 line DIFF-BUFFER for Arith } } } else // DCT-mode { int TotalDU= set_dim(j, 8); // for malloc in DU; printf(" %d MCU (%d x %d)\n", j->mcu_total, j->mcu_width, j->mcu_height); // malloc DU-s { DU *du; int mallocTotalCoef= sizeof(DU) * TotalDU; j->jpeg_mem= calloc(mallocTotalCoef, 1); if ( 0 == j->jpeg_mem ) return JPEGENUMERR_MALLOC; du= j->jpeg_mem; for (i=0; iNf; i++) { struct COMP *C= j->Components + i; C->du= du; du+= C->du_total; } } printf(" Malloc for %d Data Units (%lu bytes)\n\n", TotalDU, sizeof(DU)*TotalDU); if (j->SOF > 0xC8) { // DCT Arithmetic j->Reset_decoder= Reset_decoder_arith; j->Byte_in= Byte_in_arith; } else { // DCT Huffman j->Reset_decoder= Reset_decoder_huff; j->Byte_in= Byte_in_huff; } } } /*else if ( (marker & 0xf8) == 0xD0 ) // RSTn D0..D7 { printf("RST%d\n", marker&7); printf("%08X: ....\n", TELL()); }*/ else if ( marker == 0xD9 ) // EOI { printf("EOI\n"); return JPEGENUM_OK; } else if ( marker == 0xDA ) // SOS { int ci; GETWbi(); //Ls printf("SOS\n"); j->Ns= GETC();//Ns printf(" Ns: %d (%s scan)\n", j->Ns, (j->Ns>1)?"Interleaved":"Single"); for (ci=0; ciNs; ci++) { struct COMP *sc; int Cs= GETC(); // Cs -> Cid (Scan component selector) int T= GETC(); int Td= T>>4; int Ta= T&15; printf(" Cs=%d Td=%d Ta=%d\n", Cs, Td, Ta); {// safe search for ( i=0; i<4 && j->Components[i].Ci != Cs; i++ ) ; if ( 4 == i ) return JPEGENUMERR_COMPNOTFOUND; j->ScanComponents[ci]= sc= j->Components+i; } if (j->SOF > 0xC8) // arithmetic { sc->U= j->U[Td]; sc->L= j->L[Td]; sc->Kx= j->Kx[Ta]; if ((j->SOF&3)==3) sc->LLST= j->ACST[Td]; // LOSSLESS: ACST re-used to save storage (lossles stat. area little less than AC, but more than DC) else { sc->ACST= j->ACST[Ta]-1; // DCT. Modified for speed: use 'k' to index the 63 increments for S0, SN,SP... sc->DCST= j->DCST[Td]; } } else { // Huffman sc->ACB= j->HTB[1][Ta]; sc->ACS= j->HTS[1][Ta]; sc->DCB= j->HTB[0][Td]; sc->DCS= j->HTS[0][Td]; } } j->Ss= GETC();//Ss (DCT) or Px (LL) j->Se= GETC();//Se j->Al= GETC();//AhAl j->Ah= j->Al>>4; j->Al&= 15; j->Al2= 1<Al;//pre-computed printf(" %s: %d\n", ((j->SOF&3)==3)?"Px":"Ss", j->Ss); printf(" Se: %d\n", j->Se); printf(" Ah: %d\n", j->Ah); printf(" %s: %d\n", ((j->SOF&3)==3)?"Pt":"Al", j->Al); printf("%08X: ECS\n", TELL()); // Entropy-Coded Segment j->Reset_decoder(j); // arithmetic/huffman/lossless if ((j->SOF&3)==3) // LOSSLESS { if (j->Ns>1) { DecodeInterleaved_LL(j); } else { DecodeSingle_LL(j); } } else { // DCT-type if (j->SOF > 0xC8) // arithmetic: { j->DecodeDataUnit= j->Ss? (j->Ah? ac_succ_arith : ac_decode_arith) : (j->Se? du_sequential_arith : (j->Ah? dc_succ_arith : dc_decode_arith)); } else { j->DecodeDataUnit= j->Ss? (j->Ah? ac_succ_huff : ac_decode_huff) : (j->Se? du_sequential_huff : (j->Ah? dc_succ_huff : dc_decode_huff)); } if (j->Ns>1) { DecodeInterleaved_DCT(j); } else { DecodeSingle_DCT(j); } } } else if ( marker == 0xDB ) // DQT { // Just read in (this is a coeff-decoder) int Pq; int Lq= GETWbi(); printf("DQT\n"); for (Lq-=2; Lq; Lq -= 65 + 64*Pq) { int (*get)(void); int T= GETC(); int Tq= T&3; int *qt= j->QT[Tq]; Pq= T>>4; printf(" Tq=%d Pq=%d (%d-bit)\n", Tq, Pq, Pq?16:8); get= Pq? GETWbi : GETC; if (*qt) return JPEGENUMERR_QTREDEF; // re-defined quant table? Can be, not implemented. for (i=0; i<64; i++) qt[i]= get(); } } else if ( marker == 0xDC ) // DNL { printf("DNL\n"); return JPEGENUMERR_MARKERDNL; } else if ( marker == 0xDD ) // DRI { GETWbi();//Lr j->Ri= GETWbi(); printf("DRI\n"); printf(" Ri: %d\n", j->Ri); } else if ( (marker & 0xf0) == 0xE0 ) // APPn E0..EF { int La= GETWbi(); SEEK(La-2); printf("APP%d\n", marker&15); } else if ( marker == 0xFE ) // COM { SEEK(GETWbi()-2); printf("COM\n"); } else { printf("???\n"); } } } #pragma GCC diagnostic pop