From 64ad7354b6bbc61782935f64873afdf2c0a18bc1 Mon Sep 17 00:00:00 2001 From: Roman Artiukhin Date: Wed, 9 Oct 2024 17:31:17 +0300 Subject: [PATCH] imageviewer: Initial support for JPEG progressive images. Add lib sources Added unmodified files from RAINBOW library by Attila Tarpai Full sources: https://github.com/Halicery/vc_rainbow Change-Id: I356486b6a332aa3f610ddcae57f8a2044653b051 --- apps/plugins/imageviewer/jpegp/GETC.h | 56 ++ apps/plugins/imageviewer/jpegp/idct.c | 134 ++++ apps/plugins/imageviewer/jpegp/idct.h | 6 + apps/plugins/imageviewer/jpegp/jpeg81.c | 995 ++++++++++++++++++++++++ apps/plugins/imageviewer/jpegp/jpeg81.h | 147 ++++ docs/CREDITS | 1 + 6 files changed, 1339 insertions(+) create mode 100644 apps/plugins/imageviewer/jpegp/GETC.h create mode 100644 apps/plugins/imageviewer/jpegp/idct.c create mode 100644 apps/plugins/imageviewer/jpegp/idct.h create mode 100644 apps/plugins/imageviewer/jpegp/jpeg81.c create mode 100644 apps/plugins/imageviewer/jpegp/jpeg81.h diff --git a/apps/plugins/imageviewer/jpegp/GETC.h b/apps/plugins/imageviewer/jpegp/GETC.h new file mode 100644 index 0000000000..d17cdb9857 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/GETC.h @@ -0,0 +1,56 @@ +/* + "GETC" Interface for byte input (i.e. started as a wrapper for getc()) + + For image- and video decoders I needed a transparent mechanism for + opening and reading the input data: + + - either from streams (eg. coded video) + - or preloaded into memory (eg. small GIF/PNG images) + + RAINBOW is only dependent on the GETC Interface for byte input. + + File stream input is used during development and testing (FILEGETC.C). + In the OS image Rainbow can be linked with MEMGETC.C for memory input. + No other changes necessary in RAINBOW. + +* 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. +*/ + + +// For decoders + +extern int GETC(); + +// Multibyte helpers +extern int GETWbi(); // read word (16-bit) big-endian +extern int GETWli(); // little-endian +extern int GETDbi(); // read double word (32-bit) big-endian +extern int GETDli(); // little-endian + +// positioning +extern void SEEK(int); // move relative to current +extern void POS(int); // move absolute position (TIFF) +extern int TELL(); // read actual position + + +// For RAINBOW clients to implement outside of Rainbow Library +extern void *OPEN(char*); +extern void CLOSE(); diff --git a/apps/plugins/imageviewer/jpegp/idct.c b/apps/plugins/imageviewer/jpegp/idct.c new file mode 100644 index 0000000000..7db1658546 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/idct.c @@ -0,0 +1,134 @@ +/********************************************************************************** +* +* Scaled Integer 1-D IDCT based on the LLM-method that +* reduces the number of multiplications from 11 to to 6. +* Here further reduced to 3 using some dyadic decomposition. +* +* The real scaling vector: +* v[0] = v[4] = 1.0; +* v[2] = beta; +* v[6] = alpha; +* v[5] = v[3] = theta*M_SQRT2; +* v[1] = v[7] = theta; +* +* The integer scaling matrix is derived as SCALEM = [v vt] << 12. +* +* +* 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. +*/ + + +int SCALEM[64] = { // theta,12 + 4096, 2276, 5352, 3218, 4096, 3218, 2217, 2276, + 2276, 1264, 2973, 1788, 2276, 1788, 1232, 1264, + 5352, 2973, 6992, 4205, 5352, 4205, 2896, 2973, + 3218, 1788, 4205, 2529, 3218, 2529, 1742, 1788, + 4096, 2276, 5352, 3218, 4096, 3218, 2217, 2276, + 3218, 1788, 4205, 2529, 3218, 2529, 1742, 1788, + 2217, 1232, 2896, 1742, 2217, 1742, 1200, 1232, + 2276, 1264, 2973, 1788, 2276, 1788, 1232, 1264, +}; + +static unsigned char clip_table[3*256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +}; +unsigned char *CLIP = clip_table + 256; + + +#define XADD(a,b,c,d) p=a+b, n=a-b, a=p+d, b=n+c, c=n-c, d=p-d + +static void idct1(int *F, int *f) +{ + int p, n; + + XADD(F[1],F[7],F[5],F[3]); + + p= F[5]*45, n= F[3]*45; //XROT(F[5],F[3],90,542,362); + F[5]= ( n+p + (p<<2) + F[5] ) >> 7; // *181 = 45*4+1 + F[3]= ( n-p + (n<<2) + F[3] ) >> 7; // *181 + + p=F[1]<<8, n=F[7]<<8; //XROT(F[1],F[7],256,639,127); + F[1]= ( n+p + (F[1]<<7) - F[1] ) >> 8; // *127 + F[7]= ( n-p + (F[7]<<7) - F[7] ) >> 8; // *127 + + p= F[6]; + F[6]+= F[2]; + F[2]= ((F[2]-p) * 181 >> 7) - F[6]; + + XADD(F[0],F[4],F[2],F[6]); + + f[0*8]= F[0]+F[1]; + f[1*8]= F[4]+F[5]; + f[2*8]= F[2]+F[3]; + f[3*8]= F[6]+F[7]; + f[4*8]= F[6]-F[7]; + f[5*8]= F[2]-F[3]; + f[6*8]= F[4]-F[5]; + f[7*8]= F[0]-F[1]; +} + + +/////////////// SCALED INTEGER IDCT AND MODIFIED LLM METHOD /////////////////////////// +// +// Input: de-quantized coefficient block + +extern void idct_s(int *t, short *y) +{ + int i, R[64], C[64]; + R[0]= ( t[0] + 4 ) * SCALEM[0]; + for (i=1; i<64; i++) R[i] = t[i] * SCALEM[i]; + + for (i=0; i<8; i++) idct1(R+i*8, C+i); + for (i=0; i<8; i++) idct1(C+i*8, R+i); + + for (i=0; i<64; i++) y[i] = CLIP[ R[i] >> 15 ]; +} + + +/////////////// SCALED IDCT WITH DEQUANTIZATION IN ONE STEP ///////////////////////// +// +// Input: raw (un-zigzagged) coefficient block and the scaled quantization table + +int zigzag[64] = { + 0,1,8,16,9,2,3,10, + 17,24,32,25,18,11,4,5, + 12,19,26,33,40,48,41,34, + 27,20,13,6,7,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63, +}; + +extern void idct_sq(short *coef, int *sq) +{ + int i, R[64], C[64]; + R[0]= coef[0] * sq[0] + ((1024+4)<<12); // DC dequant + scale + level-shift + rounding bias + for (i=1; i<64; i++) R[zigzag[i]] = coef[i] * sq[i]; // AC dequant + scale (with zigzag) + + for (i=0; i<8; i++) idct1(R+i*8, C+i); + for (i=0; i<8; i++) idct1(C+i*8, R+i); + + for (i=0; i<64; i++) coef[i] = CLIP[ R[i] >> 15 ]; +} + diff --git a/apps/plugins/imageviewer/jpegp/idct.h b/apps/plugins/imageviewer/jpegp/idct.h new file mode 100644 index 0000000000..3cc9c54a0b --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/idct.h @@ -0,0 +1,6 @@ +extern void idct_sq(short *coef, int *q); // <-- scaled integer idct WITH de-quantization +extern void idct_s(int *t, short *y); // <-- scaled integer idct + +extern int zigzag[64]; +extern int SCALEM[64]; +extern unsigned char *CLIP; diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.c b/apps/plugins/imageviewer/jpegp/jpeg81.c new file mode 100644 index 0000000000..95e46dbd17 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/jpeg81.c @@ -0,0 +1,995 @@ +/************************************************************************ +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 "jpeg81.h" +#include // calloc() called once +#include // debug only + + +///////////////////////////////////////// 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 (%d 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)(); + 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"); + } + } +} diff --git a/apps/plugins/imageviewer/jpegp/jpeg81.h b/apps/plugins/imageviewer/jpegp/jpeg81.h new file mode 100644 index 0000000000..fa71b10113 --- /dev/null +++ b/apps/plugins/imageviewer/jpegp/jpeg81.h @@ -0,0 +1,147 @@ +/* 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. +*/ + +enum JPEGENUM { + JPEGENUM_OK=1, + JPEGENUMERR_MISSING_SOI = -999, // file doesnt start with SOI + JPEGENUMERR_UNKNOWN_SOF, // differential frame? + JPEGENUMERR_COMP4, // more than 4 components in file + JPEGENUMERR_MALLOC, // malloc failed + JPEGENUMERR_NODHT, // no DHT found + JPEGENUMERR_NODQT, // no DQT found + JPEGENUMERR_QTREDEF, // not implemented (*) + JPEGENUMERR_MARKERC8, // JPG-1 extension? + JPEGENUMERR_MARKERDNL, // DNL marker found (not supported) + JPEGENUMERR_ZEROY, // Y in SOFn is zero (DNL?) + JPEGENUMERR_COMPNOTFOUND, // Scan component selector (Csj) not found among Component identifiers (Ci) +}; + +typedef short TCOEF; // 16-bit coefficients +typedef TCOEF DU[64]; // The DATA UNIT +typedef unsigned short TSAMP; // Lossless 'coefficients' are unsigned + +struct CABACSTATE { // borrowed from the AVC decoder + int StateIdx; + int valMPS; +}; + +struct COMP { // Image Component Info and variables + + // from SOF + int Ci; // Component identifier + int Hi; // Horizontal sampling factor + int Vi; // Vertical sampling factor + int Qi; // Quantization table destination selector + + // Computed parameters + int du_w, du_h; // width/height in data units for single scans and for idct/conversion + int du_size; // = du_w * du_h + + int du_width; // total width in DU (storage and interleaved scans) + int du_total; // -> for malloc + + // Component coefficient buffer + union { + DU *du; // DCT: pointer to DU + TSAMP *samp; // LL + }; + + // In scans + union { // either/or + int DC; // jpeg's differential encoded DC (per scan-component) + int EOBRUN; // Only in AC-single scan (Huffman) + }; + + // Huffman + int *ACB; // AC-'base-values' + unsigned char *ACS; // AC-symbols + int *DCB; + unsigned char *DCS; + + // Arithmetic + struct CABACSTATE *DCST; // DC-statistical area + struct CABACSTATE *ACST; // with -1 offset (we use 'k' itself for addressing) + struct CABACSTATE *LLST; + int U, L, Kx; + int DIFF; // diff value for the previous DC + + // Lossless + short *diffAbove; // stored DIFF for LOSSLESS (an MCU line - 1?) + int diffLeft[4+1]; // LineNo added (to fast test for zero) +}; + + +struct JPEGD { // The JPEG DECODER OBJECT + + struct COMP Components[4]; + + // SOFn: Frame Header + int Nf; + int P; + int Y, X; // "number of samples per line in the component with the maximum number of horizontal samples" and vertical + int SOF; // save marker to make decisions + int QT[4][64]; // Q-tables from stream + + void *jpeg_mem; // <-- free me + + int Hmax, Vmax; // for conversion + int mcu_width; + int mcu_height; + int mcu_total; // covers the whole image + + int HTB[2][4][16]; // Huffman 'base' values + unsigned char HTS[2][4][256]; // Huffman 'symbol' values + + + int Ri; // Restart interval + + void (*Reset_decoder)(struct JPEGD *j); // huffman/arithmetic/lossless + + // Actual Scan + int Ns; + struct COMP *ScanComponents[4]; // --> pointer to COMP in order of scan component definition + int Ss, Se, Al, Ah; + int Al2; // =1<