forked from len0rd/rockbox
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:
parent
772eff8ca6
commit
64ad7354b6
6 changed files with 1339 additions and 0 deletions
56
apps/plugins/imageviewer/jpegp/GETC.h
Normal file
56
apps/plugins/imageviewer/jpegp/GETC.h
Normal 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();
|
134
apps/plugins/imageviewer/jpegp/idct.c
Normal file
134
apps/plugins/imageviewer/jpegp/idct.c
Normal 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 ];
|
||||
}
|
||||
|
6
apps/plugins/imageviewer/jpegp/idct.h
Normal file
6
apps/plugins/imageviewer/jpegp/idct.h
Normal 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;
|
995
apps/plugins/imageviewer/jpegp/jpeg81.c
Normal file
995
apps/plugins/imageviewer/jpegp/jpeg81.c
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
147
apps/plugins/imageviewer/jpegp/jpeg81.h
Normal file
147
apps/plugins/imageviewer/jpegp/jpeg81.h
Normal 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);
|
|
@ -771,3 +771,4 @@ The microtar team (rxi and others)
|
|||
The UnifontEX and GNU Unifont teams
|
||||
The xrick team
|
||||
The Terminus Font team
|
||||
Attila Tarpai (The RAINBOW image decoder lib author)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue