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
This commit is contained in:
Roman Artiukhin 2024-10-09 17:31:17 +03:00 committed by Solomon Peachy
parent 772eff8ca6
commit 64ad7354b6
6 changed files with 1339 additions and 0 deletions

View file

@ -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();

View file

@ -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 ];
}

View file

@ -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;

View file

@ -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 <malloc.h> // calloc() called once
#include <stdio.h> // 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<<s) - ~x; // 0xxxxxx means neg //x= ~x & ((1<<s)-1);
return x << j->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<<r); // ((1<<r)-1); -1 included
return;
}//else ZRL
}
k+=r;
coef[k]= s;
if (k==j->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<<r); //=((1<<r)-1), -1 included
break;
}//else ZRL
}
for (; ;k++) if (!ac_refine(j, coef+k)) if (!r--) break;
coef[k]= s;
if (k==j->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; y<C->Vi; y++) for (x=0; x<C->Hi; 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; i<j->Nf; 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; i<j->Nf; 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<<U
j->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<<U;
j->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; i<N; i++) S[i]= GETC();
}
}
else if ( (marker & 0xf0) == 0xC0 ) // START OF FRAME SOFn C0..CF (C4, CC, C8 checked before)
{
GETWbi();//Lf
j->P= 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; i<j->Nf; 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; i<j->Nf; 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; i<j->Nf; 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; ci<j->Ns; 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<<j->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");
}
}
}

View file

@ -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<<Al
int ScanByte;
int ScanBit;
int (*Byte_in)(struct JPEGD *j); // huffman/arithmetic
void (*DecodeDataUnit)(struct JPEGD *j, struct COMP *sc, TCOEF *coef); // DCT huffman/arithmetic
// LOSSLESS
int LineNo; // Ri clears this
void (*decode_lossless)(struct JPEGD *j, struct COMP *C, int x, int y, TSAMP *coef); // huffman/arithmetic
// Arith
// DAC, ArithmeticConditioning
int U[4], L[4], Kx[4];
unsigned short C; //CodeRegister; // C <-- from bit stream
unsigned short A; //ProbabilityIntervalRegister; // A <--
// AVC-style (JPEG 'statictical area')
struct CABACSTATE DCST[4][49];
struct CABACSTATE ACST[4][245];
};
extern int JPEGDecode(struct JPEGD *j);

View file

@ -771,3 +771,4 @@ The microtar team (rxi and others)
The UnifontEX and GNU Unifont teams The UnifontEX and GNU Unifont teams
The xrick team The xrick team
The Terminus Font team The Terminus Font team
Attila Tarpai (The RAINBOW image decoder lib author)