| User | Revision | Line number | New contents of line |
| XkLi |
0:c546b51ecf0b
|
1
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
2
|
// picojpeg v1.0 - Public domain, Rich Geldreich <richgel99@gmail.com>
|
| XkLi |
0:c546b51ecf0b
|
3
|
// Last modified Nov. 27, 2010
|
| XkLi |
0:c546b51ecf0b
|
4
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
5
|
#include "picojpeg.h"
|
| XkLi |
0:c546b51ecf0b
|
6
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
7
|
typedef unsigned char uint8;
|
| XkLi |
0:c546b51ecf0b
|
8
|
typedef unsigned short uint16;
|
| XkLi |
0:c546b51ecf0b
|
9
|
typedef signed char int8;
|
| XkLi |
0:c546b51ecf0b
|
10
|
typedef signed short int16;
|
| XkLi |
0:c546b51ecf0b
|
11
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
12
|
// Change as needed - the PJPG_MAX_WIDTH/PJPG_MAX_HEIGHT checks are only present
|
| XkLi |
0:c546b51ecf0b
|
13
|
// to quickly detect bogus files.
|
| XkLi |
0:c546b51ecf0b
|
14
|
#define PJPG_MAX_WIDTH 16384
|
| XkLi |
0:c546b51ecf0b
|
15
|
#define PJPG_MAX_HEIGHT 16384
|
| XkLi |
0:c546b51ecf0b
|
16
|
|
| XkLi |
0:c546b51ecf0b
|
17
|
#define PJPG_MAXCOMPSINSCAN 3
|
| XkLi |
0:c546b51ecf0b
|
18
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
19
|
typedef enum
|
| XkLi |
0:c546b51ecf0b
|
20
|
{
|
| XkLi |
0:c546b51ecf0b
|
21
|
M_SOF0 = 0xC0,
|
| XkLi |
0:c546b51ecf0b
|
22
|
M_SOF1 = 0xC1,
|
| XkLi |
0:c546b51ecf0b
|
23
|
M_SOF2 = 0xC2,
|
| XkLi |
0:c546b51ecf0b
|
24
|
M_SOF3 = 0xC3,
|
| XkLi |
0:c546b51ecf0b
|
25
|
|
| XkLi |
0:c546b51ecf0b
|
26
|
M_SOF5 = 0xC5,
|
| XkLi |
0:c546b51ecf0b
|
27
|
M_SOF6 = 0xC6,
|
| XkLi |
0:c546b51ecf0b
|
28
|
M_SOF7 = 0xC7,
|
| XkLi |
0:c546b51ecf0b
|
29
|
|
| XkLi |
0:c546b51ecf0b
|
30
|
M_JPG = 0xC8,
|
| XkLi |
0:c546b51ecf0b
|
31
|
M_SOF9 = 0xC9,
|
| XkLi |
0:c546b51ecf0b
|
32
|
M_SOF10 = 0xCA,
|
| XkLi |
0:c546b51ecf0b
|
33
|
M_SOF11 = 0xCB,
|
| XkLi |
0:c546b51ecf0b
|
34
|
|
| XkLi |
0:c546b51ecf0b
|
35
|
M_SOF13 = 0xCD,
|
| XkLi |
0:c546b51ecf0b
|
36
|
M_SOF14 = 0xCE,
|
| XkLi |
0:c546b51ecf0b
|
37
|
M_SOF15 = 0xCF,
|
| XkLi |
0:c546b51ecf0b
|
38
|
|
| XkLi |
0:c546b51ecf0b
|
39
|
M_DHT = 0xC4,
|
| XkLi |
0:c546b51ecf0b
|
40
|
|
| XkLi |
0:c546b51ecf0b
|
41
|
M_DAC = 0xCC,
|
| XkLi |
0:c546b51ecf0b
|
42
|
|
| XkLi |
0:c546b51ecf0b
|
43
|
M_RST0 = 0xD0,
|
| XkLi |
0:c546b51ecf0b
|
44
|
M_RST1 = 0xD1,
|
| XkLi |
0:c546b51ecf0b
|
45
|
M_RST2 = 0xD2,
|
| XkLi |
0:c546b51ecf0b
|
46
|
M_RST3 = 0xD3,
|
| XkLi |
0:c546b51ecf0b
|
47
|
M_RST4 = 0xD4,
|
| XkLi |
0:c546b51ecf0b
|
48
|
M_RST5 = 0xD5,
|
| XkLi |
0:c546b51ecf0b
|
49
|
M_RST6 = 0xD6,
|
| XkLi |
0:c546b51ecf0b
|
50
|
M_RST7 = 0xD7,
|
| XkLi |
0:c546b51ecf0b
|
51
|
|
| XkLi |
0:c546b51ecf0b
|
52
|
M_SOI = 0xD8,
|
| XkLi |
0:c546b51ecf0b
|
53
|
M_EOI = 0xD9,
|
| XkLi |
0:c546b51ecf0b
|
54
|
M_SOS = 0xDA,
|
| XkLi |
0:c546b51ecf0b
|
55
|
M_DQT = 0xDB,
|
| XkLi |
0:c546b51ecf0b
|
56
|
M_DNL = 0xDC,
|
| XkLi |
0:c546b51ecf0b
|
57
|
M_DRI = 0xDD,
|
| XkLi |
0:c546b51ecf0b
|
58
|
M_DHP = 0xDE,
|
| XkLi |
0:c546b51ecf0b
|
59
|
M_EXP = 0xDF,
|
| XkLi |
0:c546b51ecf0b
|
60
|
|
| XkLi |
0:c546b51ecf0b
|
61
|
M_APP0 = 0xE0,
|
| XkLi |
0:c546b51ecf0b
|
62
|
M_APP15 = 0xEF,
|
| XkLi |
0:c546b51ecf0b
|
63
|
|
| XkLi |
0:c546b51ecf0b
|
64
|
M_JPG0 = 0xF0,
|
| XkLi |
0:c546b51ecf0b
|
65
|
M_JPG13 = 0xFD,
|
| XkLi |
0:c546b51ecf0b
|
66
|
M_COM = 0xFE,
|
| XkLi |
0:c546b51ecf0b
|
67
|
|
| XkLi |
0:c546b51ecf0b
|
68
|
M_TEM = 0x01,
|
| XkLi |
0:c546b51ecf0b
|
69
|
|
| XkLi |
0:c546b51ecf0b
|
70
|
M_ERROR = 0x100
|
| XkLi |
0:c546b51ecf0b
|
71
|
} JPEG_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
72
|
|
| XkLi |
0:c546b51ecf0b
|
73
|
#define RST0 0xD0
|
| XkLi |
0:c546b51ecf0b
|
74
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
75
|
const int8 ZAG[] =
|
| XkLi |
0:c546b51ecf0b
|
76
|
{
|
| XkLi |
0:c546b51ecf0b
|
77
|
0, 1, 8, 16, 9, 2, 3, 10,
|
| XkLi |
0:c546b51ecf0b
|
78
|
17, 24, 32, 25, 18, 11, 4, 5,
|
| XkLi |
0:c546b51ecf0b
|
79
|
12, 19, 26, 33, 40, 48, 41, 34,
|
| XkLi |
0:c546b51ecf0b
|
80
|
27, 20, 13, 6, 7, 14, 21, 28,
|
| XkLi |
0:c546b51ecf0b
|
81
|
35, 42, 49, 56, 57, 50, 43, 36,
|
| XkLi |
0:c546b51ecf0b
|
82
|
29, 22, 15, 23, 30, 37, 44, 51,
|
| XkLi |
0:c546b51ecf0b
|
83
|
58, 59, 52, 45, 38, 31, 39, 46,
|
| XkLi |
0:c546b51ecf0b
|
84
|
53, 60, 61, 54, 47, 55, 62, 63,
|
| XkLi |
0:c546b51ecf0b
|
85
|
};
|
| XkLi |
0:c546b51ecf0b
|
86
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
87
|
// 128 bytes
|
| XkLi |
0:c546b51ecf0b
|
88
|
static int16 gCoeffBuf[8*8];
|
| XkLi |
0:c546b51ecf0b
|
89
|
|
| XkLi |
0:c546b51ecf0b
|
90
|
// 8*8*4 bytes * 3 = 768
|
| XkLi |
0:c546b51ecf0b
|
91
|
static uint8 gMCUBufR[256];
|
| XkLi |
0:c546b51ecf0b
|
92
|
static uint8 gMCUBufG[256];
|
| XkLi |
0:c546b51ecf0b
|
93
|
static uint8 gMCUBufB[256];
|
| XkLi |
0:c546b51ecf0b
|
94
|
|
| XkLi |
0:c546b51ecf0b
|
95
|
// 256 bytes
|
| XkLi |
0:c546b51ecf0b
|
96
|
static int16 gQuant0[8*8];
|
| XkLi |
0:c546b51ecf0b
|
97
|
static int16 gQuant1[8*8];
|
| XkLi |
0:c546b51ecf0b
|
98
|
|
| XkLi |
0:c546b51ecf0b
|
99
|
// 6 bytes
|
| XkLi |
0:c546b51ecf0b
|
100
|
static int16 gLastDC[3];
|
| XkLi |
0:c546b51ecf0b
|
101
|
|
| XkLi |
0:c546b51ecf0b
|
102
|
typedef struct HuffTableT
|
| XkLi |
0:c546b51ecf0b
|
103
|
{
|
| XkLi |
0:c546b51ecf0b
|
104
|
uint16 mMinCode[16];
|
| XkLi |
0:c546b51ecf0b
|
105
|
uint16 mMaxCode[16];
|
| XkLi |
0:c546b51ecf0b
|
106
|
uint8 mValPtr[16];
|
| XkLi |
0:c546b51ecf0b
|
107
|
} HuffTable;
|
| XkLi |
0:c546b51ecf0b
|
108
|
|
| XkLi |
0:c546b51ecf0b
|
109
|
// DC - 192
|
| XkLi |
0:c546b51ecf0b
|
110
|
static HuffTable gHuffTab0;
|
| XkLi |
0:c546b51ecf0b
|
111
|
|
| XkLi |
0:c546b51ecf0b
|
112
|
static uint8 gHuffVal0[16];
|
| XkLi |
0:c546b51ecf0b
|
113
|
|
| XkLi |
0:c546b51ecf0b
|
114
|
static HuffTable gHuffTab1;
|
| XkLi |
0:c546b51ecf0b
|
115
|
static uint8 gHuffVal1[16];
|
| XkLi |
0:c546b51ecf0b
|
116
|
|
| XkLi |
0:c546b51ecf0b
|
117
|
// AC - 672
|
| XkLi |
0:c546b51ecf0b
|
118
|
static HuffTable gHuffTab2;
|
| XkLi |
0:c546b51ecf0b
|
119
|
static uint8 gHuffVal2[256];
|
| XkLi |
0:c546b51ecf0b
|
120
|
|
| XkLi |
0:c546b51ecf0b
|
121
|
static HuffTable gHuffTab3;
|
| XkLi |
0:c546b51ecf0b
|
122
|
static uint8 gHuffVal3[256];
|
| XkLi |
0:c546b51ecf0b
|
123
|
|
| XkLi |
0:c546b51ecf0b
|
124
|
static uint8 gValidHuffTables;
|
| XkLi |
0:c546b51ecf0b
|
125
|
static uint8 gValidQuantTables;
|
| XkLi |
0:c546b51ecf0b
|
126
|
|
| XkLi |
0:c546b51ecf0b
|
127
|
static uint8 gTemFlag;
|
| XkLi |
0:c546b51ecf0b
|
128
|
#define MAX_IN_BUF_SIZE 256
|
| XkLi |
0:c546b51ecf0b
|
129
|
static uint8 gInBuf[MAX_IN_BUF_SIZE];
|
| XkLi |
0:c546b51ecf0b
|
130
|
static uint8 gInBufOfs;
|
| XkLi |
0:c546b51ecf0b
|
131
|
static uint8 gInBufLeft;
|
| XkLi |
0:c546b51ecf0b
|
132
|
|
| XkLi |
0:c546b51ecf0b
|
133
|
static uint16 gBitBuf;
|
| XkLi |
0:c546b51ecf0b
|
134
|
static uint8 gBitsLeft;
|
| XkLi |
0:c546b51ecf0b
|
135
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
136
|
static uint16 gImageXSize;
|
| XkLi |
0:c546b51ecf0b
|
137
|
static uint16 gImageYSize;
|
| XkLi |
0:c546b51ecf0b
|
138
|
static uint8 gCompsInFrame;
|
| XkLi |
0:c546b51ecf0b
|
139
|
static uint8 gCompIdent[3];
|
| XkLi |
0:c546b51ecf0b
|
140
|
static uint8 gCompHSamp[3];
|
| XkLi |
0:c546b51ecf0b
|
141
|
static uint8 gCompVSamp[3];
|
| XkLi |
0:c546b51ecf0b
|
142
|
static uint8 gCompQuant[3];
|
| XkLi |
0:c546b51ecf0b
|
143
|
|
| XkLi |
0:c546b51ecf0b
|
144
|
static uint16 gRestartInterval;
|
| XkLi |
0:c546b51ecf0b
|
145
|
static uint16 gNextRestartNum;
|
| XkLi |
0:c546b51ecf0b
|
146
|
static uint16 gRestartsLeft;
|
| XkLi |
0:c546b51ecf0b
|
147
|
|
| XkLi |
0:c546b51ecf0b
|
148
|
static uint8 gCompsInScan;
|
| XkLi |
0:c546b51ecf0b
|
149
|
static uint8 gCompList[3];
|
| XkLi |
0:c546b51ecf0b
|
150
|
static uint8 gCompDCTab[3]; // 0,1
|
| XkLi |
0:c546b51ecf0b
|
151
|
static uint8 gCompACTab[3]; // 0,1
|
| XkLi |
0:c546b51ecf0b
|
152
|
|
| XkLi |
0:c546b51ecf0b
|
153
|
static pjpeg_scan_type_t gScanType;
|
| XkLi |
0:c546b51ecf0b
|
154
|
|
| XkLi |
0:c546b51ecf0b
|
155
|
static uint8 gMaxBlocksPerMCU;
|
| XkLi |
0:c546b51ecf0b
|
156
|
static uint8 gMaxMCUXSize;
|
| XkLi |
0:c546b51ecf0b
|
157
|
static uint8 gMaxMCUYSize;
|
| XkLi |
0:c546b51ecf0b
|
158
|
static uint16 gMaxMCUSPerRow;
|
| XkLi |
0:c546b51ecf0b
|
159
|
static uint16 gMaxMCUSPerCol;
|
| XkLi |
0:c546b51ecf0b
|
160
|
static uint16 gNumMCUSRemaining;
|
| XkLi |
0:c546b51ecf0b
|
161
|
static uint8 gMCUOrg[6];
|
| XkLi |
0:c546b51ecf0b
|
162
|
|
| XkLi |
0:c546b51ecf0b
|
163
|
static pjpeg_need_bytes_callback_t g_pNeedBytesCallback;
|
| XkLi |
0:c546b51ecf0b
|
164
|
static void *g_pCallback_data;
|
| XkLi |
0:c546b51ecf0b
|
165
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
166
|
static uint8 fillInBuf(void)
|
| XkLi |
0:c546b51ecf0b
|
167
|
{
|
| XkLi |
0:c546b51ecf0b
|
168
|
unsigned char status;
|
| XkLi |
0:c546b51ecf0b
|
169
|
|
| XkLi |
0:c546b51ecf0b
|
170
|
// Reserve a few bytes at the beginning of the buffer for putting back ("stuffing") chars.
|
| XkLi |
0:c546b51ecf0b
|
171
|
gInBufOfs = 4;
|
| XkLi |
0:c546b51ecf0b
|
172
|
gInBufLeft = 0;
|
| XkLi |
0:c546b51ecf0b
|
173
|
|
| XkLi |
0:c546b51ecf0b
|
174
|
status = (*g_pNeedBytesCallback)(gInBuf + gInBufOfs, MAX_IN_BUF_SIZE - gInBufOfs, &gInBufLeft, g_pCallback_data);
|
| XkLi |
0:c546b51ecf0b
|
175
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
176
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
177
|
|
| XkLi |
0:c546b51ecf0b
|
178
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
179
|
}
|
| XkLi |
0:c546b51ecf0b
|
180
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
181
|
static uint8 getChar(void)
|
| XkLi |
0:c546b51ecf0b
|
182
|
{
|
| XkLi |
0:c546b51ecf0b
|
183
|
if (!gInBufLeft)
|
| XkLi |
0:c546b51ecf0b
|
184
|
{
|
| XkLi |
0:c546b51ecf0b
|
185
|
fillInBuf();
|
| XkLi |
0:c546b51ecf0b
|
186
|
if (!gInBufLeft)
|
| XkLi |
0:c546b51ecf0b
|
187
|
{
|
| XkLi |
0:c546b51ecf0b
|
188
|
gTemFlag = ~gTemFlag;
|
| XkLi |
0:c546b51ecf0b
|
189
|
return gTemFlag ? 0xFF : 0xD9;
|
| XkLi |
0:c546b51ecf0b
|
190
|
}
|
| XkLi |
0:c546b51ecf0b
|
191
|
}
|
| XkLi |
0:c546b51ecf0b
|
192
|
|
| XkLi |
0:c546b51ecf0b
|
193
|
gInBufLeft--;
|
| XkLi |
0:c546b51ecf0b
|
194
|
return gInBuf[gInBufOfs++];
|
| XkLi |
0:c546b51ecf0b
|
195
|
}
|
| XkLi |
0:c546b51ecf0b
|
196
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
197
|
static void stuffChar(uint8 i)
|
| XkLi |
0:c546b51ecf0b
|
198
|
{
|
| XkLi |
0:c546b51ecf0b
|
199
|
gInBufOfs--;
|
| XkLi |
0:c546b51ecf0b
|
200
|
gInBuf[gInBufOfs] = i;
|
| XkLi |
0:c546b51ecf0b
|
201
|
gInBufLeft++;
|
| XkLi |
0:c546b51ecf0b
|
202
|
}
|
| XkLi |
0:c546b51ecf0b
|
203
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
204
|
static uint8 getOctet(uint8 FFCheck)
|
| XkLi |
0:c546b51ecf0b
|
205
|
{
|
| XkLi |
0:c546b51ecf0b
|
206
|
uint8 c = getChar();
|
| XkLi |
0:c546b51ecf0b
|
207
|
|
| XkLi |
0:c546b51ecf0b
|
208
|
if ((FFCheck) && (c == 0xFF))
|
| XkLi |
0:c546b51ecf0b
|
209
|
{
|
| XkLi |
0:c546b51ecf0b
|
210
|
uint8 n = getChar();
|
| XkLi |
0:c546b51ecf0b
|
211
|
|
| XkLi |
0:c546b51ecf0b
|
212
|
if (n)
|
| XkLi |
0:c546b51ecf0b
|
213
|
{
|
| XkLi |
0:c546b51ecf0b
|
214
|
stuffChar(n);
|
| XkLi |
0:c546b51ecf0b
|
215
|
stuffChar(0xFF);
|
| XkLi |
0:c546b51ecf0b
|
216
|
}
|
| XkLi |
0:c546b51ecf0b
|
217
|
}
|
| XkLi |
0:c546b51ecf0b
|
218
|
|
| XkLi |
0:c546b51ecf0b
|
219
|
return c;
|
| XkLi |
0:c546b51ecf0b
|
220
|
}
|
| XkLi |
0:c546b51ecf0b
|
221
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
222
|
static uint16 getBits(uint8 numBits, uint8 FFCheck)
|
| XkLi |
0:c546b51ecf0b
|
223
|
{
|
| XkLi |
0:c546b51ecf0b
|
224
|
uint8 origBits = numBits;
|
| XkLi |
0:c546b51ecf0b
|
225
|
uint16 ret = gBitBuf;
|
| XkLi |
0:c546b51ecf0b
|
226
|
|
| XkLi |
0:c546b51ecf0b
|
227
|
if (numBits > 8)
|
| XkLi |
0:c546b51ecf0b
|
228
|
{
|
| XkLi |
0:c546b51ecf0b
|
229
|
numBits -= 8;
|
| XkLi |
0:c546b51ecf0b
|
230
|
|
| XkLi |
0:c546b51ecf0b
|
231
|
gBitBuf <<= gBitsLeft;
|
| XkLi |
0:c546b51ecf0b
|
232
|
|
| XkLi |
0:c546b51ecf0b
|
233
|
gBitBuf |= getOctet(FFCheck);
|
| XkLi |
0:c546b51ecf0b
|
234
|
|
| XkLi |
0:c546b51ecf0b
|
235
|
gBitBuf <<= (8 - gBitsLeft);
|
| XkLi |
0:c546b51ecf0b
|
236
|
|
| XkLi |
0:c546b51ecf0b
|
237
|
ret = (ret & 0xFF00) | (gBitBuf >> 8);
|
| XkLi |
0:c546b51ecf0b
|
238
|
}
|
| XkLi |
0:c546b51ecf0b
|
239
|
|
| XkLi |
0:c546b51ecf0b
|
240
|
if (gBitsLeft < numBits)
|
| XkLi |
0:c546b51ecf0b
|
241
|
{
|
| XkLi |
0:c546b51ecf0b
|
242
|
gBitBuf <<= gBitsLeft;
|
| XkLi |
0:c546b51ecf0b
|
243
|
|
| XkLi |
0:c546b51ecf0b
|
244
|
gBitBuf |= getOctet(FFCheck);
|
| XkLi |
0:c546b51ecf0b
|
245
|
|
| XkLi |
0:c546b51ecf0b
|
246
|
gBitBuf <<= (numBits - gBitsLeft);
|
| XkLi |
0:c546b51ecf0b
|
247
|
|
| XkLi |
0:c546b51ecf0b
|
248
|
gBitsLeft = 8 - (numBits - gBitsLeft);
|
| XkLi |
0:c546b51ecf0b
|
249
|
}
|
| XkLi |
0:c546b51ecf0b
|
250
|
else
|
| XkLi |
0:c546b51ecf0b
|
251
|
{
|
| XkLi |
0:c546b51ecf0b
|
252
|
gBitsLeft = (uint8)(gBitsLeft - numBits);
|
| XkLi |
0:c546b51ecf0b
|
253
|
gBitBuf <<= numBits;
|
| XkLi |
0:c546b51ecf0b
|
254
|
}
|
| XkLi |
0:c546b51ecf0b
|
255
|
|
| XkLi |
0:c546b51ecf0b
|
256
|
return ret >> (16 - origBits);
|
| XkLi |
0:c546b51ecf0b
|
257
|
}
|
| XkLi |
0:c546b51ecf0b
|
258
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
259
|
static uint16 getBits1(uint8 numBits)
|
| XkLi |
0:c546b51ecf0b
|
260
|
{
|
| XkLi |
0:c546b51ecf0b
|
261
|
return getBits(numBits, 0);
|
| XkLi |
0:c546b51ecf0b
|
262
|
}
|
| XkLi |
0:c546b51ecf0b
|
263
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
264
|
static uint16 getBits2(uint8 numBits)
|
| XkLi |
0:c546b51ecf0b
|
265
|
{
|
| XkLi |
0:c546b51ecf0b
|
266
|
return getBits(numBits, 1);
|
| XkLi |
0:c546b51ecf0b
|
267
|
}
|
| XkLi |
0:c546b51ecf0b
|
268
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
269
|
static uint8 getBit(void)
|
| XkLi |
0:c546b51ecf0b
|
270
|
{
|
| XkLi |
0:c546b51ecf0b
|
271
|
uint8 ret = 0;
|
| XkLi |
0:c546b51ecf0b
|
272
|
if (gBitBuf & 0x8000)
|
| XkLi |
0:c546b51ecf0b
|
273
|
ret = 1;
|
| XkLi |
0:c546b51ecf0b
|
274
|
|
| XkLi |
0:c546b51ecf0b
|
275
|
if (!gBitsLeft)
|
| XkLi |
0:c546b51ecf0b
|
276
|
{
|
| XkLi |
0:c546b51ecf0b
|
277
|
gBitBuf |= getOctet(1);
|
| XkLi |
0:c546b51ecf0b
|
278
|
|
| XkLi |
0:c546b51ecf0b
|
279
|
gBitsLeft += 8;
|
| XkLi |
0:c546b51ecf0b
|
280
|
}
|
| XkLi |
0:c546b51ecf0b
|
281
|
|
| XkLi |
0:c546b51ecf0b
|
282
|
gBitsLeft--;
|
| XkLi |
0:c546b51ecf0b
|
283
|
gBitBuf <<= 1;
|
| XkLi |
0:c546b51ecf0b
|
284
|
|
| XkLi |
0:c546b51ecf0b
|
285
|
return ret;
|
| XkLi |
0:c546b51ecf0b
|
286
|
}
|
| XkLi |
0:c546b51ecf0b
|
287
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
288
|
static uint16 getExtendTest(uint8 i)
|
| XkLi |
0:c546b51ecf0b
|
289
|
{
|
| XkLi |
0:c546b51ecf0b
|
290
|
switch (i)
|
| XkLi |
0:c546b51ecf0b
|
291
|
{
|
| XkLi |
0:c546b51ecf0b
|
292
|
case 0: return 0;
|
| XkLi |
0:c546b51ecf0b
|
293
|
case 1: return 0x0001;
|
| XkLi |
0:c546b51ecf0b
|
294
|
case 2: return 0x0002;
|
| XkLi |
0:c546b51ecf0b
|
295
|
case 3: return 0x0004;
|
| XkLi |
0:c546b51ecf0b
|
296
|
case 4: return 0x0008;
|
| XkLi |
0:c546b51ecf0b
|
297
|
case 5: return 0x0010;
|
| XkLi |
0:c546b51ecf0b
|
298
|
case 6: return 0x0020;
|
| XkLi |
0:c546b51ecf0b
|
299
|
case 7: return 0x0040;
|
| XkLi |
0:c546b51ecf0b
|
300
|
case 8: return 0x0080;
|
| XkLi |
0:c546b51ecf0b
|
301
|
case 9: return 0x0100;
|
| XkLi |
0:c546b51ecf0b
|
302
|
case 10: return 0x0200;
|
| XkLi |
0:c546b51ecf0b
|
303
|
case 11: return 0x0400;
|
| XkLi |
0:c546b51ecf0b
|
304
|
case 12: return 0x0800;
|
| XkLi |
0:c546b51ecf0b
|
305
|
case 13: return 0x1000;
|
| XkLi |
0:c546b51ecf0b
|
306
|
case 14: return 0x2000;
|
| XkLi |
0:c546b51ecf0b
|
307
|
case 15: return 0x4000;
|
| XkLi |
0:c546b51ecf0b
|
308
|
default: return 0;
|
| XkLi |
0:c546b51ecf0b
|
309
|
}
|
| XkLi |
0:c546b51ecf0b
|
310
|
}
|
| XkLi |
0:c546b51ecf0b
|
311
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
312
|
static int16 getExtendOffset(uint8 i)
|
| XkLi |
0:c546b51ecf0b
|
313
|
{
|
| XkLi |
0:c546b51ecf0b
|
314
|
switch (i)
|
| XkLi |
0:c546b51ecf0b
|
315
|
{
|
| XkLi |
0:c546b51ecf0b
|
316
|
case 0: return 0;
|
| XkLi |
0:c546b51ecf0b
|
317
|
case 1: return ((-1)<<1) + 1;
|
| XkLi |
0:c546b51ecf0b
|
318
|
case 2: return ((-1)<<2) + 1;
|
| XkLi |
0:c546b51ecf0b
|
319
|
case 3: return ((-1)<<3) + 1;
|
| XkLi |
0:c546b51ecf0b
|
320
|
case 4: return ((-1)<<4) + 1;
|
| XkLi |
0:c546b51ecf0b
|
321
|
case 5: return ((-1)<<5) + 1;
|
| XkLi |
0:c546b51ecf0b
|
322
|
case 6: return ((-1)<<6) + 1;
|
| XkLi |
0:c546b51ecf0b
|
323
|
case 7: return ((-1)<<7) + 1;
|
| XkLi |
0:c546b51ecf0b
|
324
|
case 8: return ((-1)<<8) + 1;
|
| XkLi |
0:c546b51ecf0b
|
325
|
case 9: return ((-1)<<9) + 1;
|
| XkLi |
0:c546b51ecf0b
|
326
|
case 10: return ((-1)<<10) + 1;
|
| XkLi |
0:c546b51ecf0b
|
327
|
case 11: return ((-1)<<11) + 1;
|
| XkLi |
0:c546b51ecf0b
|
328
|
case 12: return ((-1)<<12) + 1;
|
| XkLi |
0:c546b51ecf0b
|
329
|
case 13: return ((-1)<<13) + 1;
|
| XkLi |
0:c546b51ecf0b
|
330
|
case 14: return ((-1)<<14) + 1;
|
| XkLi |
0:c546b51ecf0b
|
331
|
case 15: return ((-1)<<15) + 1;
|
| XkLi |
0:c546b51ecf0b
|
332
|
default: return 0;
|
| XkLi |
0:c546b51ecf0b
|
333
|
}
|
| XkLi |
0:c546b51ecf0b
|
334
|
};
|
| XkLi |
0:c546b51ecf0b
|
335
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
336
|
static int16 huffExtend(uint16 x, uint8 s)
|
| XkLi |
0:c546b51ecf0b
|
337
|
{
|
| XkLi |
0:c546b51ecf0b
|
338
|
return ((x < getExtendTest(s)) ? ((int16)x + getExtendOffset(s)) : (int16)x);
|
| XkLi |
0:c546b51ecf0b
|
339
|
}
|
| XkLi |
0:c546b51ecf0b
|
340
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
341
|
static uint8 huffDecode(const HuffTable* pHuffTable, const uint8* pHuffVal)
|
| XkLi |
0:c546b51ecf0b
|
342
|
{
|
| XkLi |
0:c546b51ecf0b
|
343
|
uint8 i = 0;
|
| XkLi |
0:c546b51ecf0b
|
344
|
uint8 j;
|
| XkLi |
0:c546b51ecf0b
|
345
|
uint16 code = getBit();
|
| XkLi |
0:c546b51ecf0b
|
346
|
|
| XkLi |
0:c546b51ecf0b
|
347
|
for ( ; ; )
|
| XkLi |
0:c546b51ecf0b
|
348
|
{
|
| XkLi |
0:c546b51ecf0b
|
349
|
uint16 maxCode;
|
| XkLi |
0:c546b51ecf0b
|
350
|
|
| XkLi |
0:c546b51ecf0b
|
351
|
if (i == 16)
|
| XkLi |
0:c546b51ecf0b
|
352
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
353
|
|
| XkLi |
0:c546b51ecf0b
|
354
|
maxCode = pHuffTable->mMaxCode[i];
|
| XkLi |
0:c546b51ecf0b
|
355
|
if ((code <= maxCode) && (maxCode != 0xFFFF))
|
| XkLi |
0:c546b51ecf0b
|
356
|
break;
|
| XkLi |
0:c546b51ecf0b
|
357
|
|
| XkLi |
0:c546b51ecf0b
|
358
|
i++;
|
| XkLi |
0:c546b51ecf0b
|
359
|
code <<= 1;
|
| XkLi |
0:c546b51ecf0b
|
360
|
code |= getBit();
|
| XkLi |
0:c546b51ecf0b
|
361
|
}
|
| XkLi |
0:c546b51ecf0b
|
362
|
|
| XkLi |
0:c546b51ecf0b
|
363
|
j = pHuffTable->mValPtr[i];
|
| XkLi |
0:c546b51ecf0b
|
364
|
j = (uint8)(j + (code - pHuffTable->mMinCode[i]));
|
| XkLi |
0:c546b51ecf0b
|
365
|
|
| XkLi |
0:c546b51ecf0b
|
366
|
return pHuffVal[j];
|
| XkLi |
0:c546b51ecf0b
|
367
|
}
|
| XkLi |
0:c546b51ecf0b
|
368
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
369
|
static void huffCreate(const uint8* pBits, HuffTable* pHuffTable)
|
| XkLi |
0:c546b51ecf0b
|
370
|
{
|
| XkLi |
0:c546b51ecf0b
|
371
|
uint8 i = 0;
|
| XkLi |
0:c546b51ecf0b
|
372
|
uint8 j = 0;
|
| XkLi |
0:c546b51ecf0b
|
373
|
|
| XkLi |
0:c546b51ecf0b
|
374
|
uint16 code = 0;
|
| XkLi |
0:c546b51ecf0b
|
375
|
|
| XkLi |
0:c546b51ecf0b
|
376
|
for ( ; ; )
|
| XkLi |
0:c546b51ecf0b
|
377
|
{
|
| XkLi |
0:c546b51ecf0b
|
378
|
uint8 num = pBits[i];
|
| XkLi |
0:c546b51ecf0b
|
379
|
|
| XkLi |
0:c546b51ecf0b
|
380
|
if (!num)
|
| XkLi |
0:c546b51ecf0b
|
381
|
{
|
| XkLi |
0:c546b51ecf0b
|
382
|
pHuffTable->mMinCode[i] = 0x0000;
|
| XkLi |
0:c546b51ecf0b
|
383
|
pHuffTable->mMaxCode[i] = 0xFFFF;
|
| XkLi |
0:c546b51ecf0b
|
384
|
pHuffTable->mValPtr[i] = 0;
|
| XkLi |
0:c546b51ecf0b
|
385
|
}
|
| XkLi |
0:c546b51ecf0b
|
386
|
else
|
| XkLi |
0:c546b51ecf0b
|
387
|
{
|
| XkLi |
0:c546b51ecf0b
|
388
|
pHuffTable->mMinCode[i] = code;
|
| XkLi |
0:c546b51ecf0b
|
389
|
pHuffTable->mMaxCode[i] = code + num - 1;
|
| XkLi |
0:c546b51ecf0b
|
390
|
pHuffTable->mValPtr[i] = j;
|
| XkLi |
0:c546b51ecf0b
|
391
|
|
| XkLi |
0:c546b51ecf0b
|
392
|
j = (uint8)(j + num);
|
| XkLi |
0:c546b51ecf0b
|
393
|
|
| XkLi |
0:c546b51ecf0b
|
394
|
code = (uint16)(code + num);
|
| XkLi |
0:c546b51ecf0b
|
395
|
}
|
| XkLi |
0:c546b51ecf0b
|
396
|
|
| XkLi |
0:c546b51ecf0b
|
397
|
code <<= 1;
|
| XkLi |
0:c546b51ecf0b
|
398
|
|
| XkLi |
0:c546b51ecf0b
|
399
|
i++;
|
| XkLi |
0:c546b51ecf0b
|
400
|
if (i > 15)
|
| XkLi |
0:c546b51ecf0b
|
401
|
break;
|
| XkLi |
0:c546b51ecf0b
|
402
|
}
|
| XkLi |
0:c546b51ecf0b
|
403
|
}
|
| XkLi |
0:c546b51ecf0b
|
404
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
405
|
static HuffTable* getHuffTable(uint8 index)
|
| XkLi |
0:c546b51ecf0b
|
406
|
{
|
| XkLi |
0:c546b51ecf0b
|
407
|
// 0-1 = DC
|
| XkLi |
0:c546b51ecf0b
|
408
|
// 2-3 = AC
|
| XkLi |
0:c546b51ecf0b
|
409
|
switch (index)
|
| XkLi |
0:c546b51ecf0b
|
410
|
{
|
| XkLi |
0:c546b51ecf0b
|
411
|
case 0: return &gHuffTab0;
|
| XkLi |
0:c546b51ecf0b
|
412
|
case 1: return &gHuffTab1;
|
| XkLi |
0:c546b51ecf0b
|
413
|
case 2: return &gHuffTab2;
|
| XkLi |
0:c546b51ecf0b
|
414
|
case 3: return &gHuffTab3;
|
| XkLi |
0:c546b51ecf0b
|
415
|
default: return 0;
|
| XkLi |
0:c546b51ecf0b
|
416
|
}
|
| XkLi |
0:c546b51ecf0b
|
417
|
}
|
| XkLi |
0:c546b51ecf0b
|
418
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
419
|
static uint8* getHuffVal(uint8 index)
|
| XkLi |
0:c546b51ecf0b
|
420
|
{
|
| XkLi |
0:c546b51ecf0b
|
421
|
// 0-1 = DC
|
| XkLi |
0:c546b51ecf0b
|
422
|
// 2-3 = AC
|
| XkLi |
0:c546b51ecf0b
|
423
|
switch (index)
|
| XkLi |
0:c546b51ecf0b
|
424
|
{
|
| XkLi |
0:c546b51ecf0b
|
425
|
case 0: return gHuffVal0;
|
| XkLi |
0:c546b51ecf0b
|
426
|
case 1: return gHuffVal1;
|
| XkLi |
0:c546b51ecf0b
|
427
|
case 2: return gHuffVal2;
|
| XkLi |
0:c546b51ecf0b
|
428
|
case 3: return gHuffVal3;
|
| XkLi |
0:c546b51ecf0b
|
429
|
default: return 0;
|
| XkLi |
0:c546b51ecf0b
|
430
|
}
|
| XkLi |
0:c546b51ecf0b
|
431
|
}
|
| XkLi |
0:c546b51ecf0b
|
432
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
433
|
static uint16 getMaxHuffCodes(uint8 index)
|
| XkLi |
0:c546b51ecf0b
|
434
|
{
|
| XkLi |
0:c546b51ecf0b
|
435
|
return (index < 2) ? 12 : 255;
|
| XkLi |
0:c546b51ecf0b
|
436
|
}
|
| XkLi |
0:c546b51ecf0b
|
437
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
438
|
static uint8 readDHTMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
439
|
{
|
| XkLi |
0:c546b51ecf0b
|
440
|
uint8 bits[16];
|
| XkLi |
0:c546b51ecf0b
|
441
|
uint16 left = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
442
|
|
| XkLi |
0:c546b51ecf0b
|
443
|
if (left < 2)
|
| XkLi |
0:c546b51ecf0b
|
444
|
return PJPG_BAD_DHT_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
445
|
|
| XkLi |
0:c546b51ecf0b
|
446
|
left -= 2;
|
| XkLi |
0:c546b51ecf0b
|
447
|
|
| XkLi |
0:c546b51ecf0b
|
448
|
while (left)
|
| XkLi |
0:c546b51ecf0b
|
449
|
{
|
| XkLi |
0:c546b51ecf0b
|
450
|
uint8 i, tableIndex, index;
|
| XkLi |
0:c546b51ecf0b
|
451
|
uint8* pHuffVal;
|
| XkLi |
0:c546b51ecf0b
|
452
|
HuffTable* pHuffTable;
|
| XkLi |
0:c546b51ecf0b
|
453
|
uint16 count, totalRead;
|
| XkLi |
0:c546b51ecf0b
|
454
|
|
| XkLi |
0:c546b51ecf0b
|
455
|
index = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
456
|
|
| XkLi |
0:c546b51ecf0b
|
457
|
if ( ((index & 0xF) > 1) || ((index & 0xF0) > 0x10) )
|
| XkLi |
0:c546b51ecf0b
|
458
|
return PJPG_BAD_DHT_INDEX;
|
| XkLi |
0:c546b51ecf0b
|
459
|
|
| XkLi |
0:c546b51ecf0b
|
460
|
tableIndex = ((index >> 3) & 2) + (index & 1);
|
| XkLi |
0:c546b51ecf0b
|
461
|
|
| XkLi |
0:c546b51ecf0b
|
462
|
pHuffTable = getHuffTable(tableIndex);
|
| XkLi |
0:c546b51ecf0b
|
463
|
pHuffVal = getHuffVal(tableIndex);
|
| XkLi |
0:c546b51ecf0b
|
464
|
|
| XkLi |
0:c546b51ecf0b
|
465
|
gValidHuffTables |= (1 << tableIndex);
|
| XkLi |
0:c546b51ecf0b
|
466
|
|
| XkLi |
0:c546b51ecf0b
|
467
|
count = 0;
|
| XkLi |
0:c546b51ecf0b
|
468
|
for (i = 0; i <= 15; i++)
|
| XkLi |
0:c546b51ecf0b
|
469
|
{
|
| XkLi |
0:c546b51ecf0b
|
470
|
uint8 n = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
471
|
bits[i] = n;
|
| XkLi |
0:c546b51ecf0b
|
472
|
count = (uint16)(count + n);
|
| XkLi |
0:c546b51ecf0b
|
473
|
}
|
| XkLi |
0:c546b51ecf0b
|
474
|
|
| XkLi |
0:c546b51ecf0b
|
475
|
if (count > getMaxHuffCodes(tableIndex))
|
| XkLi |
0:c546b51ecf0b
|
476
|
return PJPG_BAD_DHT_COUNTS;
|
| XkLi |
0:c546b51ecf0b
|
477
|
|
| XkLi |
0:c546b51ecf0b
|
478
|
for (i = 0; i < count; i++)
|
| XkLi |
0:c546b51ecf0b
|
479
|
pHuffVal[i] = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
480
|
|
| XkLi |
0:c546b51ecf0b
|
481
|
totalRead = 1 + 16 + count;
|
| XkLi |
0:c546b51ecf0b
|
482
|
|
| XkLi |
0:c546b51ecf0b
|
483
|
if (left < totalRead)
|
| XkLi |
0:c546b51ecf0b
|
484
|
return PJPG_BAD_DHT_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
485
|
|
| XkLi |
0:c546b51ecf0b
|
486
|
left = (uint16)(left - totalRead);
|
| XkLi |
0:c546b51ecf0b
|
487
|
|
| XkLi |
0:c546b51ecf0b
|
488
|
huffCreate(bits, pHuffTable);
|
| XkLi |
0:c546b51ecf0b
|
489
|
}
|
| XkLi |
0:c546b51ecf0b
|
490
|
|
| XkLi |
0:c546b51ecf0b
|
491
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
492
|
}
|
| XkLi |
0:c546b51ecf0b
|
493
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
494
|
static void createWinogradQuant(int16* pQuant);
|
| XkLi |
0:c546b51ecf0b
|
495
|
|
| XkLi |
0:c546b51ecf0b
|
496
|
static uint8 readDQTMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
497
|
{
|
| XkLi |
0:c546b51ecf0b
|
498
|
uint16 left = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
499
|
|
| XkLi |
0:c546b51ecf0b
|
500
|
if (left < 2)
|
| XkLi |
0:c546b51ecf0b
|
501
|
return PJPG_BAD_DQT_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
502
|
|
| XkLi |
0:c546b51ecf0b
|
503
|
left -= 2;
|
| XkLi |
0:c546b51ecf0b
|
504
|
|
| XkLi |
0:c546b51ecf0b
|
505
|
while (left)
|
| XkLi |
0:c546b51ecf0b
|
506
|
{
|
| XkLi |
0:c546b51ecf0b
|
507
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
508
|
uint8 n = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
509
|
uint8 prec = n >> 4;
|
| XkLi |
0:c546b51ecf0b
|
510
|
uint16 totalRead;
|
| XkLi |
0:c546b51ecf0b
|
511
|
|
| XkLi |
0:c546b51ecf0b
|
512
|
n &= 0x0F;
|
| XkLi |
0:c546b51ecf0b
|
513
|
|
| XkLi |
0:c546b51ecf0b
|
514
|
if (n > 1)
|
| XkLi |
0:c546b51ecf0b
|
515
|
return PJPG_BAD_DQT_TABLE;
|
| XkLi |
0:c546b51ecf0b
|
516
|
|
| XkLi |
0:c546b51ecf0b
|
517
|
gValidQuantTables |= (n ? 2 : 1);
|
| XkLi |
0:c546b51ecf0b
|
518
|
|
| XkLi |
0:c546b51ecf0b
|
519
|
// read quantization entries, in zag order
|
| XkLi |
0:c546b51ecf0b
|
520
|
for (i = 0; i < 64; i++)
|
| XkLi |
0:c546b51ecf0b
|
521
|
{
|
| XkLi |
0:c546b51ecf0b
|
522
|
uint16 temp = getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
523
|
|
| XkLi |
0:c546b51ecf0b
|
524
|
if (prec)
|
| XkLi |
0:c546b51ecf0b
|
525
|
temp = (temp << 8) + getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
526
|
|
| XkLi |
0:c546b51ecf0b
|
527
|
if (n)
|
| XkLi |
0:c546b51ecf0b
|
528
|
gQuant1[i] = (int16)temp;
|
| XkLi |
0:c546b51ecf0b
|
529
|
else
|
| XkLi |
0:c546b51ecf0b
|
530
|
gQuant0[i] = (int16)temp;
|
| XkLi |
0:c546b51ecf0b
|
531
|
}
|
| XkLi |
0:c546b51ecf0b
|
532
|
|
| XkLi |
0:c546b51ecf0b
|
533
|
createWinogradQuant(n ? gQuant1 : gQuant0);
|
| XkLi |
0:c546b51ecf0b
|
534
|
|
| XkLi |
0:c546b51ecf0b
|
535
|
totalRead = 64 + 1;
|
| XkLi |
0:c546b51ecf0b
|
536
|
|
| XkLi |
0:c546b51ecf0b
|
537
|
if (prec)
|
| XkLi |
0:c546b51ecf0b
|
538
|
totalRead += 64;
|
| XkLi |
0:c546b51ecf0b
|
539
|
|
| XkLi |
0:c546b51ecf0b
|
540
|
if (left < totalRead)
|
| XkLi |
0:c546b51ecf0b
|
541
|
return PJPG_BAD_DQT_LENGTH;
|
| XkLi |
0:c546b51ecf0b
|
542
|
|
| XkLi |
0:c546b51ecf0b
|
543
|
left = (uint16)(left - totalRead);
|
| XkLi |
0:c546b51ecf0b
|
544
|
}
|
| XkLi |
0:c546b51ecf0b
|
545
|
|
| XkLi |
0:c546b51ecf0b
|
546
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
547
|
}
|
| XkLi |
0:c546b51ecf0b
|
548
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
549
|
static uint8 readSOFMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
550
|
{
|
| XkLi |
0:c546b51ecf0b
|
551
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
552
|
uint16 left = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
553
|
|
| XkLi |
0:c546b51ecf0b
|
554
|
if (getBits1(8) != 8)
|
| XkLi |
0:c546b51ecf0b
|
555
|
return PJPG_BAD_PRECISION;
|
| XkLi |
0:c546b51ecf0b
|
556
|
|
| XkLi |
0:c546b51ecf0b
|
557
|
gImageYSize = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
558
|
|
| XkLi |
0:c546b51ecf0b
|
559
|
if ((!gImageYSize) || (gImageYSize > PJPG_MAX_HEIGHT))
|
| XkLi |
0:c546b51ecf0b
|
560
|
return PJPG_BAD_HEIGHT;
|
| XkLi |
0:c546b51ecf0b
|
561
|
|
| XkLi |
0:c546b51ecf0b
|
562
|
gImageXSize = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
563
|
|
| XkLi |
0:c546b51ecf0b
|
564
|
if ((!gImageXSize) || (gImageXSize > PJPG_MAX_WIDTH))
|
| XkLi |
0:c546b51ecf0b
|
565
|
return PJPG_BAD_WIDTH;
|
| XkLi |
0:c546b51ecf0b
|
566
|
|
| XkLi |
0:c546b51ecf0b
|
567
|
gCompsInFrame = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
568
|
|
| XkLi |
0:c546b51ecf0b
|
569
|
if (gCompsInFrame > 3)
|
| XkLi |
0:c546b51ecf0b
|
570
|
return PJPG_TOO_MANY_COMPONENTS;
|
| XkLi |
0:c546b51ecf0b
|
571
|
|
| XkLi |
0:c546b51ecf0b
|
572
|
if (left != (gCompsInFrame + gCompsInFrame + gCompsInFrame + 8))
|
| XkLi |
0:c546b51ecf0b
|
573
|
return PJPG_BAD_SOF_LENGTH;
|
| XkLi |
0:c546b51ecf0b
|
574
|
|
| XkLi |
0:c546b51ecf0b
|
575
|
for (i = 0; i < gCompsInFrame; i++)
|
| XkLi |
0:c546b51ecf0b
|
576
|
{
|
| XkLi |
0:c546b51ecf0b
|
577
|
gCompIdent[i] = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
578
|
gCompHSamp[i] = (uint8)getBits1(4);
|
| XkLi |
0:c546b51ecf0b
|
579
|
gCompVSamp[i] = (uint8)getBits1(4);
|
| XkLi |
0:c546b51ecf0b
|
580
|
gCompQuant[i] = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
581
|
|
| XkLi |
0:c546b51ecf0b
|
582
|
if (gCompQuant[i] > 1)
|
| XkLi |
0:c546b51ecf0b
|
583
|
return PJPG_UNSUPPORTED_QUANT_TABLE;
|
| XkLi |
0:c546b51ecf0b
|
584
|
}
|
| XkLi |
0:c546b51ecf0b
|
585
|
|
| XkLi |
0:c546b51ecf0b
|
586
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
587
|
}
|
| XkLi |
0:c546b51ecf0b
|
588
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
589
|
// Used to skip unrecognized markers.
|
| XkLi |
0:c546b51ecf0b
|
590
|
static uint8 skipVariableMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
591
|
{
|
| XkLi |
0:c546b51ecf0b
|
592
|
uint16 left = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
593
|
|
| XkLi |
0:c546b51ecf0b
|
594
|
if (left < 2)
|
| XkLi |
0:c546b51ecf0b
|
595
|
return PJPG_BAD_VARIABLE_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
596
|
|
| XkLi |
0:c546b51ecf0b
|
597
|
left -= 2;
|
| XkLi |
0:c546b51ecf0b
|
598
|
|
| XkLi |
0:c546b51ecf0b
|
599
|
while (left)
|
| XkLi |
0:c546b51ecf0b
|
600
|
{
|
| XkLi |
0:c546b51ecf0b
|
601
|
getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
602
|
left--;
|
| XkLi |
0:c546b51ecf0b
|
603
|
}
|
| XkLi |
0:c546b51ecf0b
|
604
|
|
| XkLi |
0:c546b51ecf0b
|
605
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
606
|
}
|
| XkLi |
0:c546b51ecf0b
|
607
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
608
|
// Read a define restart interval (DRI) marker.
|
| XkLi |
0:c546b51ecf0b
|
609
|
static uint8 readDRIMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
610
|
{
|
| XkLi |
0:c546b51ecf0b
|
611
|
if (getBits1(16) != 4)
|
| XkLi |
0:c546b51ecf0b
|
612
|
return PJPG_BAD_DRI_LENGTH;
|
| XkLi |
0:c546b51ecf0b
|
613
|
|
| XkLi |
0:c546b51ecf0b
|
614
|
gRestartInterval = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
615
|
|
| XkLi |
0:c546b51ecf0b
|
616
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
617
|
}
|
| XkLi |
0:c546b51ecf0b
|
618
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
619
|
// Read a start of scan (SOS) marker.
|
| XkLi |
0:c546b51ecf0b
|
620
|
static uint8 readSOSMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
621
|
{
|
| XkLi |
0:c546b51ecf0b
|
622
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
623
|
uint16 left = getBits1(16);
|
| XkLi |
0:c546b51ecf0b
|
624
|
uint8 spectral_start, spectral_end, successive_high, successive_low;
|
| XkLi |
0:c546b51ecf0b
|
625
|
|
| XkLi |
0:c546b51ecf0b
|
626
|
gCompsInScan = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
627
|
|
| XkLi |
0:c546b51ecf0b
|
628
|
left -= 3;
|
| XkLi |
0:c546b51ecf0b
|
629
|
|
| XkLi |
0:c546b51ecf0b
|
630
|
if ( (left != (gCompsInScan + gCompsInScan + 3)) || (gCompsInScan < 1) || (gCompsInScan > PJPG_MAXCOMPSINSCAN) )
|
| XkLi |
0:c546b51ecf0b
|
631
|
return PJPG_BAD_SOS_LENGTH;
|
| XkLi |
0:c546b51ecf0b
|
632
|
|
| XkLi |
0:c546b51ecf0b
|
633
|
for (i = 0; i < gCompsInScan; i++)
|
| XkLi |
0:c546b51ecf0b
|
634
|
{
|
| XkLi |
0:c546b51ecf0b
|
635
|
uint8 cc = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
636
|
uint8 c = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
637
|
uint8 ci;
|
| XkLi |
0:c546b51ecf0b
|
638
|
|
| XkLi |
0:c546b51ecf0b
|
639
|
left -= 2;
|
| XkLi |
0:c546b51ecf0b
|
640
|
|
| XkLi |
0:c546b51ecf0b
|
641
|
for (ci = 0; ci < gCompsInFrame; ci++)
|
| XkLi |
0:c546b51ecf0b
|
642
|
if (cc == gCompIdent[ci])
|
| XkLi |
0:c546b51ecf0b
|
643
|
break;
|
| XkLi |
0:c546b51ecf0b
|
644
|
|
| XkLi |
0:c546b51ecf0b
|
645
|
if (ci >= gCompsInFrame)
|
| XkLi |
0:c546b51ecf0b
|
646
|
return PJPG_BAD_SOS_COMP_ID;
|
| XkLi |
0:c546b51ecf0b
|
647
|
|
| XkLi |
0:c546b51ecf0b
|
648
|
gCompList[i] = ci;
|
| XkLi |
0:c546b51ecf0b
|
649
|
gCompDCTab[ci] = (c >> 4) & 15;
|
| XkLi |
0:c546b51ecf0b
|
650
|
gCompACTab[ci] = (c & 15);
|
| XkLi |
0:c546b51ecf0b
|
651
|
}
|
| XkLi |
0:c546b51ecf0b
|
652
|
|
| XkLi |
0:c546b51ecf0b
|
653
|
spectral_start = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
654
|
spectral_end = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
655
|
successive_high = (uint8)getBits1(4);
|
| XkLi |
0:c546b51ecf0b
|
656
|
successive_low = (uint8)getBits1(4);
|
| XkLi |
0:c546b51ecf0b
|
657
|
|
| XkLi |
0:c546b51ecf0b
|
658
|
left -= 3;
|
| XkLi |
0:c546b51ecf0b
|
659
|
|
| XkLi |
0:c546b51ecf0b
|
660
|
while (left)
|
| XkLi |
0:c546b51ecf0b
|
661
|
{
|
| XkLi |
0:c546b51ecf0b
|
662
|
getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
663
|
left--;
|
| XkLi |
0:c546b51ecf0b
|
664
|
}
|
| XkLi |
0:c546b51ecf0b
|
665
|
|
| XkLi |
0:c546b51ecf0b
|
666
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
667
|
}
|
| XkLi |
0:c546b51ecf0b
|
668
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
669
|
static uint8 nextMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
670
|
{
|
| XkLi |
0:c546b51ecf0b
|
671
|
uint8 c;
|
| XkLi |
0:c546b51ecf0b
|
672
|
uint8 bytes = 0;
|
| XkLi |
0:c546b51ecf0b
|
673
|
|
| XkLi |
0:c546b51ecf0b
|
674
|
do
|
| XkLi |
0:c546b51ecf0b
|
675
|
{
|
| XkLi |
0:c546b51ecf0b
|
676
|
do
|
| XkLi |
0:c546b51ecf0b
|
677
|
{
|
| XkLi |
0:c546b51ecf0b
|
678
|
bytes++;
|
| XkLi |
0:c546b51ecf0b
|
679
|
|
| XkLi |
0:c546b51ecf0b
|
680
|
c = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
681
|
|
| XkLi |
0:c546b51ecf0b
|
682
|
} while (c != 0xFF);
|
| XkLi |
0:c546b51ecf0b
|
683
|
|
| XkLi |
0:c546b51ecf0b
|
684
|
do
|
| XkLi |
0:c546b51ecf0b
|
685
|
{
|
| XkLi |
0:c546b51ecf0b
|
686
|
c = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
687
|
|
| XkLi |
0:c546b51ecf0b
|
688
|
} while (c == 0xFF);
|
| XkLi |
0:c546b51ecf0b
|
689
|
|
| XkLi |
0:c546b51ecf0b
|
690
|
} while (c == 0);
|
| XkLi |
0:c546b51ecf0b
|
691
|
|
| XkLi |
0:c546b51ecf0b
|
692
|
// If bytes > 0 here, there where extra bytes before the marker (not good).
|
| XkLi |
0:c546b51ecf0b
|
693
|
|
| XkLi |
0:c546b51ecf0b
|
694
|
return c;
|
| XkLi |
0:c546b51ecf0b
|
695
|
}
|
| XkLi |
0:c546b51ecf0b
|
696
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
697
|
// Process markers. Returns when an SOFx, SOI, EOI, or SOS marker is
|
| XkLi |
0:c546b51ecf0b
|
698
|
// encountered.
|
| XkLi |
0:c546b51ecf0b
|
699
|
static uint8 processMarkers(uint8* pMarker)
|
| XkLi |
0:c546b51ecf0b
|
700
|
{
|
| XkLi |
0:c546b51ecf0b
|
701
|
for ( ; ; )
|
| XkLi |
0:c546b51ecf0b
|
702
|
{
|
| XkLi |
0:c546b51ecf0b
|
703
|
uint8 c = nextMarker();
|
| XkLi |
0:c546b51ecf0b
|
704
|
|
| XkLi |
0:c546b51ecf0b
|
705
|
switch (c)
|
| XkLi |
0:c546b51ecf0b
|
706
|
{
|
| XkLi |
0:c546b51ecf0b
|
707
|
case M_SOF0:
|
| XkLi |
0:c546b51ecf0b
|
708
|
case M_SOF1:
|
| XkLi |
0:c546b51ecf0b
|
709
|
case M_SOF2:
|
| XkLi |
0:c546b51ecf0b
|
710
|
case M_SOF3:
|
| XkLi |
0:c546b51ecf0b
|
711
|
case M_SOF5:
|
| XkLi |
0:c546b51ecf0b
|
712
|
case M_SOF6:
|
| XkLi |
0:c546b51ecf0b
|
713
|
case M_SOF7:
|
| XkLi |
0:c546b51ecf0b
|
714
|
// case M_JPG:
|
| XkLi |
0:c546b51ecf0b
|
715
|
case M_SOF9:
|
| XkLi |
0:c546b51ecf0b
|
716
|
case M_SOF10:
|
| XkLi |
0:c546b51ecf0b
|
717
|
case M_SOF11:
|
| XkLi |
0:c546b51ecf0b
|
718
|
case M_SOF13:
|
| XkLi |
0:c546b51ecf0b
|
719
|
case M_SOF14:
|
| XkLi |
0:c546b51ecf0b
|
720
|
case M_SOF15:
|
| XkLi |
0:c546b51ecf0b
|
721
|
case M_SOI:
|
| XkLi |
0:c546b51ecf0b
|
722
|
case M_EOI:
|
| XkLi |
0:c546b51ecf0b
|
723
|
case M_SOS:
|
| XkLi |
0:c546b51ecf0b
|
724
|
{
|
| XkLi |
0:c546b51ecf0b
|
725
|
*pMarker = c;
|
| XkLi |
0:c546b51ecf0b
|
726
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
727
|
}
|
| XkLi |
0:c546b51ecf0b
|
728
|
case M_DHT:
|
| XkLi |
0:c546b51ecf0b
|
729
|
{
|
| XkLi |
0:c546b51ecf0b
|
730
|
readDHTMarker();
|
| XkLi |
0:c546b51ecf0b
|
731
|
break;
|
| XkLi |
0:c546b51ecf0b
|
732
|
}
|
| XkLi |
0:c546b51ecf0b
|
733
|
// Sorry, no arithmitic support at this time. Dumb patents!
|
| XkLi |
0:c546b51ecf0b
|
734
|
case M_DAC:
|
| XkLi |
0:c546b51ecf0b
|
735
|
{
|
| XkLi |
0:c546b51ecf0b
|
736
|
return PJPG_NO_ARITHMITIC_SUPPORT;
|
| XkLi |
0:c546b51ecf0b
|
737
|
}
|
| XkLi |
0:c546b51ecf0b
|
738
|
case M_DQT:
|
| XkLi |
0:c546b51ecf0b
|
739
|
{
|
| XkLi |
0:c546b51ecf0b
|
740
|
readDQTMarker();
|
| XkLi |
0:c546b51ecf0b
|
741
|
break;
|
| XkLi |
0:c546b51ecf0b
|
742
|
}
|
| XkLi |
0:c546b51ecf0b
|
743
|
case M_DRI:
|
| XkLi |
0:c546b51ecf0b
|
744
|
{
|
| XkLi |
0:c546b51ecf0b
|
745
|
readDRIMarker();
|
| XkLi |
0:c546b51ecf0b
|
746
|
break;
|
| XkLi |
0:c546b51ecf0b
|
747
|
}
|
| XkLi |
0:c546b51ecf0b
|
748
|
//case M_APP0: /* no need to read the JFIF marker */
|
| XkLi |
0:c546b51ecf0b
|
749
|
|
| XkLi |
0:c546b51ecf0b
|
750
|
case M_JPG:
|
| XkLi |
0:c546b51ecf0b
|
751
|
case M_RST0: /* no parameters */
|
| XkLi |
0:c546b51ecf0b
|
752
|
case M_RST1:
|
| XkLi |
0:c546b51ecf0b
|
753
|
case M_RST2:
|
| XkLi |
0:c546b51ecf0b
|
754
|
case M_RST3:
|
| XkLi |
0:c546b51ecf0b
|
755
|
case M_RST4:
|
| XkLi |
0:c546b51ecf0b
|
756
|
case M_RST5:
|
| XkLi |
0:c546b51ecf0b
|
757
|
case M_RST6:
|
| XkLi |
0:c546b51ecf0b
|
758
|
case M_RST7:
|
| XkLi |
0:c546b51ecf0b
|
759
|
case M_TEM:
|
| XkLi |
0:c546b51ecf0b
|
760
|
{
|
| XkLi |
0:c546b51ecf0b
|
761
|
return PJPG_UNEXPECTED_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
762
|
}
|
| XkLi |
0:c546b51ecf0b
|
763
|
default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn or APP0 */
|
| XkLi |
0:c546b51ecf0b
|
764
|
{
|
| XkLi |
0:c546b51ecf0b
|
765
|
skipVariableMarker();
|
| XkLi |
0:c546b51ecf0b
|
766
|
break;
|
| XkLi |
0:c546b51ecf0b
|
767
|
}
|
| XkLi |
0:c546b51ecf0b
|
768
|
}
|
| XkLi |
0:c546b51ecf0b
|
769
|
}
|
| XkLi |
0:c546b51ecf0b
|
770
|
// return 0;
|
| XkLi |
0:c546b51ecf0b
|
771
|
}
|
| XkLi |
0:c546b51ecf0b
|
772
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
773
|
// Finds the start of image (SOI) marker.
|
| XkLi |
0:c546b51ecf0b
|
774
|
static uint8 locateSOIMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
775
|
{
|
| XkLi |
0:c546b51ecf0b
|
776
|
uint16 bytesleft;
|
| XkLi |
0:c546b51ecf0b
|
777
|
|
| XkLi |
0:c546b51ecf0b
|
778
|
uint8 lastchar = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
779
|
|
| XkLi |
0:c546b51ecf0b
|
780
|
uint8 thischar = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
781
|
|
| XkLi |
0:c546b51ecf0b
|
782
|
/* ok if it's a normal JPEG file without a special header */
|
| XkLi |
0:c546b51ecf0b
|
783
|
|
| XkLi |
0:c546b51ecf0b
|
784
|
if ((lastchar == 0xFF) && (thischar == M_SOI))
|
| XkLi |
0:c546b51ecf0b
|
785
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
786
|
|
| XkLi |
0:c546b51ecf0b
|
787
|
bytesleft = 4096; //512;
|
| XkLi |
0:c546b51ecf0b
|
788
|
|
| XkLi |
0:c546b51ecf0b
|
789
|
for ( ; ; )
|
| XkLi |
0:c546b51ecf0b
|
790
|
{
|
| XkLi |
0:c546b51ecf0b
|
791
|
if (--bytesleft == 0)
|
| XkLi |
0:c546b51ecf0b
|
792
|
return PJPG_NOT_JPEG;
|
| XkLi |
0:c546b51ecf0b
|
793
|
|
| XkLi |
0:c546b51ecf0b
|
794
|
lastchar = thischar;
|
| XkLi |
0:c546b51ecf0b
|
795
|
|
| XkLi |
0:c546b51ecf0b
|
796
|
thischar = (uint8)getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
797
|
|
| XkLi |
0:c546b51ecf0b
|
798
|
if (lastchar == 0xFF)
|
| XkLi |
0:c546b51ecf0b
|
799
|
{
|
| XkLi |
0:c546b51ecf0b
|
800
|
if (thischar == M_SOI)
|
| XkLi |
0:c546b51ecf0b
|
801
|
break;
|
| XkLi |
0:c546b51ecf0b
|
802
|
else if (thischar == M_EOI) //getBits1 will keep returning M_EOI if we read past the end
|
| XkLi |
0:c546b51ecf0b
|
803
|
return PJPG_NOT_JPEG;
|
| XkLi |
0:c546b51ecf0b
|
804
|
}
|
| XkLi |
0:c546b51ecf0b
|
805
|
}
|
| XkLi |
0:c546b51ecf0b
|
806
|
|
| XkLi |
0:c546b51ecf0b
|
807
|
/* Check the next character after marker: if it's not 0xFF, it can't
|
| XkLi |
0:c546b51ecf0b
|
808
|
be the start of the next marker, so the file is bad */
|
| XkLi |
0:c546b51ecf0b
|
809
|
|
| XkLi |
0:c546b51ecf0b
|
810
|
thischar = (uint8)((gBitBuf >> 8) & 0xFF);
|
| XkLi |
0:c546b51ecf0b
|
811
|
|
| XkLi |
0:c546b51ecf0b
|
812
|
if (thischar != 0xFF)
|
| XkLi |
0:c546b51ecf0b
|
813
|
return PJPG_NOT_JPEG;
|
| XkLi |
0:c546b51ecf0b
|
814
|
|
| XkLi |
0:c546b51ecf0b
|
815
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
816
|
}
|
| XkLi |
0:c546b51ecf0b
|
817
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
818
|
// Find a start of frame (SOF) marker.
|
| XkLi |
0:c546b51ecf0b
|
819
|
static uint8 locateSOFMarker(void)
|
| XkLi |
0:c546b51ecf0b
|
820
|
{
|
| XkLi |
0:c546b51ecf0b
|
821
|
uint8 c;
|
| XkLi |
0:c546b51ecf0b
|
822
|
|
| XkLi |
0:c546b51ecf0b
|
823
|
uint8 status = locateSOIMarker();
|
| XkLi |
0:c546b51ecf0b
|
824
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
825
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
826
|
|
| XkLi |
0:c546b51ecf0b
|
827
|
status = processMarkers(&c);
|
| XkLi |
0:c546b51ecf0b
|
828
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
829
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
830
|
|
| XkLi |
0:c546b51ecf0b
|
831
|
switch (c)
|
| XkLi |
0:c546b51ecf0b
|
832
|
{
|
| XkLi |
0:c546b51ecf0b
|
833
|
case M_SOF2:
|
| XkLi |
0:c546b51ecf0b
|
834
|
{
|
| XkLi |
0:c546b51ecf0b
|
835
|
return PJPG_UNSUPPORTED_MODE;
|
| XkLi |
0:c546b51ecf0b
|
836
|
}
|
| XkLi |
0:c546b51ecf0b
|
837
|
case M_SOF0: /* baseline DCT */
|
| XkLi |
0:c546b51ecf0b
|
838
|
{
|
| XkLi |
0:c546b51ecf0b
|
839
|
status = readSOFMarker();
|
| XkLi |
0:c546b51ecf0b
|
840
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
841
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
842
|
|
| XkLi |
0:c546b51ecf0b
|
843
|
break;
|
| XkLi |
0:c546b51ecf0b
|
844
|
}
|
| XkLi |
0:c546b51ecf0b
|
845
|
case M_SOF9:
|
| XkLi |
0:c546b51ecf0b
|
846
|
{
|
| XkLi |
0:c546b51ecf0b
|
847
|
return PJPG_NO_ARITHMITIC_SUPPORT;
|
| XkLi |
0:c546b51ecf0b
|
848
|
}
|
| XkLi |
0:c546b51ecf0b
|
849
|
case M_SOF1: /* extended sequential DCT */
|
| XkLi |
0:c546b51ecf0b
|
850
|
default:
|
| XkLi |
0:c546b51ecf0b
|
851
|
{
|
| XkLi |
0:c546b51ecf0b
|
852
|
return PJPG_UNSUPPORTED_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
853
|
}
|
| XkLi |
0:c546b51ecf0b
|
854
|
}
|
| XkLi |
0:c546b51ecf0b
|
855
|
|
| XkLi |
0:c546b51ecf0b
|
856
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
857
|
}
|
| XkLi |
0:c546b51ecf0b
|
858
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
859
|
// Find a start of scan (SOS) marker.
|
| XkLi |
0:c546b51ecf0b
|
860
|
static uint8 locateSOSMarker(uint8* pFoundEOI)
|
| XkLi |
0:c546b51ecf0b
|
861
|
{
|
| XkLi |
0:c546b51ecf0b
|
862
|
uint8 c;
|
| XkLi |
0:c546b51ecf0b
|
863
|
uint8 status;
|
| XkLi |
0:c546b51ecf0b
|
864
|
|
| XkLi |
0:c546b51ecf0b
|
865
|
*pFoundEOI = 0;
|
| XkLi |
0:c546b51ecf0b
|
866
|
|
| XkLi |
0:c546b51ecf0b
|
867
|
status = processMarkers(&c);
|
| XkLi |
0:c546b51ecf0b
|
868
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
869
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
870
|
|
| XkLi |
0:c546b51ecf0b
|
871
|
if (c == M_EOI)
|
| XkLi |
0:c546b51ecf0b
|
872
|
{
|
| XkLi |
0:c546b51ecf0b
|
873
|
*pFoundEOI = 1;
|
| XkLi |
0:c546b51ecf0b
|
874
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
875
|
}
|
| XkLi |
0:c546b51ecf0b
|
876
|
else if (c != M_SOS)
|
| XkLi |
0:c546b51ecf0b
|
877
|
return PJPG_UNEXPECTED_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
878
|
|
| XkLi |
0:c546b51ecf0b
|
879
|
return readSOSMarker();
|
| XkLi |
0:c546b51ecf0b
|
880
|
}
|
| XkLi |
0:c546b51ecf0b
|
881
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
882
|
static uint8 init(void)
|
| XkLi |
0:c546b51ecf0b
|
883
|
{
|
| XkLi |
0:c546b51ecf0b
|
884
|
gImageXSize = 0;
|
| XkLi |
0:c546b51ecf0b
|
885
|
gImageYSize = 0;
|
| XkLi |
0:c546b51ecf0b
|
886
|
gCompsInFrame = 0;
|
| XkLi |
0:c546b51ecf0b
|
887
|
gRestartInterval = 0;
|
| XkLi |
0:c546b51ecf0b
|
888
|
gCompsInScan = 0;
|
| XkLi |
0:c546b51ecf0b
|
889
|
gValidHuffTables = 0;
|
| XkLi |
0:c546b51ecf0b
|
890
|
gValidQuantTables = 0;
|
| XkLi |
0:c546b51ecf0b
|
891
|
gTemFlag = 0;
|
| XkLi |
0:c546b51ecf0b
|
892
|
gInBufOfs = 0;
|
| XkLi |
0:c546b51ecf0b
|
893
|
gInBufLeft = 0;
|
| XkLi |
0:c546b51ecf0b
|
894
|
gBitBuf = 0;
|
| XkLi |
0:c546b51ecf0b
|
895
|
gBitsLeft = 8;
|
| XkLi |
0:c546b51ecf0b
|
896
|
|
| XkLi |
0:c546b51ecf0b
|
897
|
getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
898
|
getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
899
|
|
| XkLi |
0:c546b51ecf0b
|
900
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
901
|
}
|
| XkLi |
0:c546b51ecf0b
|
902
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
903
|
// This method throws back into the stream any bytes that where read
|
| XkLi |
0:c546b51ecf0b
|
904
|
// into the bit buffer during initial marker scanning.
|
| XkLi |
0:c546b51ecf0b
|
905
|
static void fixInBuffer(void)
|
| XkLi |
0:c546b51ecf0b
|
906
|
{
|
| XkLi |
0:c546b51ecf0b
|
907
|
/* In case any 0xFF's where pulled into the buffer during marker scanning */
|
| XkLi |
0:c546b51ecf0b
|
908
|
|
| XkLi |
0:c546b51ecf0b
|
909
|
if (gBitsLeft > 0)
|
| XkLi |
0:c546b51ecf0b
|
910
|
stuffChar((uint8)gBitBuf);
|
| XkLi |
0:c546b51ecf0b
|
911
|
|
| XkLi |
0:c546b51ecf0b
|
912
|
stuffChar((uint8)(gBitBuf >> 8));
|
| XkLi |
0:c546b51ecf0b
|
913
|
|
| XkLi |
0:c546b51ecf0b
|
914
|
gBitsLeft = 8;
|
| XkLi |
0:c546b51ecf0b
|
915
|
getBits2(8);
|
| XkLi |
0:c546b51ecf0b
|
916
|
getBits2(8);
|
| XkLi |
0:c546b51ecf0b
|
917
|
}
|
| XkLi |
0:c546b51ecf0b
|
918
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
919
|
// Restart interval processing.
|
| XkLi |
0:c546b51ecf0b
|
920
|
static uint8 processRestart(void)
|
| XkLi |
0:c546b51ecf0b
|
921
|
{
|
| XkLi |
0:c546b51ecf0b
|
922
|
// Let's scan a little bit to find the marker, but not _too_ far.
|
| XkLi |
0:c546b51ecf0b
|
923
|
// 1536 is a "fudge factor" that determines how much to scan.
|
| XkLi |
0:c546b51ecf0b
|
924
|
uint16 i;
|
| XkLi |
0:c546b51ecf0b
|
925
|
uint8 c = 0;
|
| XkLi |
0:c546b51ecf0b
|
926
|
|
| XkLi |
0:c546b51ecf0b
|
927
|
for (i = 1536; i > 0; i--)
|
| XkLi |
0:c546b51ecf0b
|
928
|
if (getChar() == 0xFF)
|
| XkLi |
0:c546b51ecf0b
|
929
|
break;
|
| XkLi |
0:c546b51ecf0b
|
930
|
|
| XkLi |
0:c546b51ecf0b
|
931
|
if (i == 0)
|
| XkLi |
0:c546b51ecf0b
|
932
|
return PJPG_BAD_RESTART_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
933
|
|
| XkLi |
0:c546b51ecf0b
|
934
|
for ( ; i > 0; i--)
|
| XkLi |
0:c546b51ecf0b
|
935
|
if ((c = getChar()) != 0xFF)
|
| XkLi |
0:c546b51ecf0b
|
936
|
break;
|
| XkLi |
0:c546b51ecf0b
|
937
|
|
| XkLi |
0:c546b51ecf0b
|
938
|
if (i == 0)
|
| XkLi |
0:c546b51ecf0b
|
939
|
return PJPG_BAD_RESTART_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
940
|
|
| XkLi |
0:c546b51ecf0b
|
941
|
// Is it the expected marker? If not, something bad happened.
|
| XkLi |
0:c546b51ecf0b
|
942
|
if (c != (gNextRestartNum + M_RST0))
|
| XkLi |
0:c546b51ecf0b
|
943
|
return PJPG_BAD_RESTART_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
944
|
|
| XkLi |
0:c546b51ecf0b
|
945
|
// Reset each component's DC prediction values.
|
| XkLi |
0:c546b51ecf0b
|
946
|
gLastDC[0] = 0;
|
| XkLi |
0:c546b51ecf0b
|
947
|
gLastDC[1] = 0;
|
| XkLi |
0:c546b51ecf0b
|
948
|
gLastDC[2] = 0;
|
| XkLi |
0:c546b51ecf0b
|
949
|
|
| XkLi |
0:c546b51ecf0b
|
950
|
gRestartsLeft = gRestartInterval;
|
| XkLi |
0:c546b51ecf0b
|
951
|
|
| XkLi |
0:c546b51ecf0b
|
952
|
gNextRestartNum = (gNextRestartNum + 1) & 7;
|
| XkLi |
0:c546b51ecf0b
|
953
|
|
| XkLi |
0:c546b51ecf0b
|
954
|
// Get the bit buffer going again...
|
| XkLi |
0:c546b51ecf0b
|
955
|
|
| XkLi |
0:c546b51ecf0b
|
956
|
gBitsLeft = 8;
|
| XkLi |
0:c546b51ecf0b
|
957
|
getBits2(8);
|
| XkLi |
0:c546b51ecf0b
|
958
|
getBits2(8);
|
| XkLi |
0:c546b51ecf0b
|
959
|
|
| XkLi |
0:c546b51ecf0b
|
960
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
961
|
}
|
| XkLi |
0:c546b51ecf0b
|
962
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
963
|
static uint8 findEOI(void)
|
| XkLi |
0:c546b51ecf0b
|
964
|
{
|
| XkLi |
0:c546b51ecf0b
|
965
|
uint8 c;
|
| XkLi |
0:c546b51ecf0b
|
966
|
uint8 status;
|
| XkLi |
0:c546b51ecf0b
|
967
|
|
| XkLi |
0:c546b51ecf0b
|
968
|
// Prime the bit buffer
|
| XkLi |
0:c546b51ecf0b
|
969
|
gBitsLeft = 8;
|
| XkLi |
0:c546b51ecf0b
|
970
|
getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
971
|
getBits1(8);
|
| XkLi |
0:c546b51ecf0b
|
972
|
|
| XkLi |
0:c546b51ecf0b
|
973
|
// The next marker _should_ be EOI
|
| XkLi |
0:c546b51ecf0b
|
974
|
status = processMarkers(&c);
|
| XkLi |
0:c546b51ecf0b
|
975
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
976
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
977
|
|
| XkLi |
0:c546b51ecf0b
|
978
|
//gTotalBytesRead -= in_buf_left;
|
| XkLi |
0:c546b51ecf0b
|
979
|
if (c != M_EOI)
|
| XkLi |
0:c546b51ecf0b
|
980
|
return PJPG_UNEXPECTED_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
981
|
|
| XkLi |
0:c546b51ecf0b
|
982
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
983
|
}
|
| XkLi |
0:c546b51ecf0b
|
984
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
985
|
static uint8 checkHuffTables(void)
|
| XkLi |
0:c546b51ecf0b
|
986
|
{
|
| XkLi |
0:c546b51ecf0b
|
987
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
988
|
|
| XkLi |
0:c546b51ecf0b
|
989
|
for (i = 0; i < gCompsInScan; i++)
|
| XkLi |
0:c546b51ecf0b
|
990
|
{
|
| XkLi |
0:c546b51ecf0b
|
991
|
uint8 compDCTab = gCompDCTab[gCompList[i]];
|
| XkLi |
0:c546b51ecf0b
|
992
|
uint8 compACTab = gCompACTab[gCompList[i]] + 2;
|
| XkLi |
0:c546b51ecf0b
|
993
|
|
| XkLi |
0:c546b51ecf0b
|
994
|
if ( ((gValidHuffTables & (1 << compDCTab)) == 0) ||
|
| XkLi |
0:c546b51ecf0b
|
995
|
((gValidHuffTables & (1 << compACTab)) == 0) )
|
| XkLi |
0:c546b51ecf0b
|
996
|
return PJPG_UNDEFINED_HUFF_TABLE;
|
| XkLi |
0:c546b51ecf0b
|
997
|
}
|
| XkLi |
0:c546b51ecf0b
|
998
|
|
| XkLi |
0:c546b51ecf0b
|
999
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1000
|
}
|
| XkLi |
0:c546b51ecf0b
|
1001
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
1002
|
static uint8 checkQuantTables(void)
|
| XkLi |
0:c546b51ecf0b
|
1003
|
{
|
| XkLi |
0:c546b51ecf0b
|
1004
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1005
|
|
| XkLi |
0:c546b51ecf0b
|
1006
|
for (i = 0; i < gCompsInScan; i++)
|
| XkLi |
0:c546b51ecf0b
|
1007
|
{
|
| XkLi |
0:c546b51ecf0b
|
1008
|
uint8 compQuantMask = gCompQuant[gCompList[i]] ? 2 : 1;
|
| XkLi |
0:c546b51ecf0b
|
1009
|
|
| XkLi |
0:c546b51ecf0b
|
1010
|
if ((gValidQuantTables & compQuantMask) == 0)
|
| XkLi |
0:c546b51ecf0b
|
1011
|
return PJPG_UNDEFINED_QUANT_TABLE;
|
| XkLi |
0:c546b51ecf0b
|
1012
|
}
|
| XkLi |
0:c546b51ecf0b
|
1013
|
|
| XkLi |
0:c546b51ecf0b
|
1014
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1015
|
}
|
| XkLi |
0:c546b51ecf0b
|
1016
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
1017
|
static uint8 initScan(void)
|
| XkLi |
0:c546b51ecf0b
|
1018
|
{
|
| XkLi |
0:c546b51ecf0b
|
1019
|
uint8 foundEOI;
|
| XkLi |
0:c546b51ecf0b
|
1020
|
uint8 status = locateSOSMarker(&foundEOI);
|
| XkLi |
0:c546b51ecf0b
|
1021
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1022
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1023
|
if (foundEOI)
|
| XkLi |
0:c546b51ecf0b
|
1024
|
return PJPG_UNEXPECTED_MARKER;
|
| XkLi |
0:c546b51ecf0b
|
1025
|
|
| XkLi |
0:c546b51ecf0b
|
1026
|
status = checkHuffTables();
|
| XkLi |
0:c546b51ecf0b
|
1027
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1028
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1029
|
|
| XkLi |
0:c546b51ecf0b
|
1030
|
status = checkQuantTables();
|
| XkLi |
0:c546b51ecf0b
|
1031
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1032
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1033
|
|
| XkLi |
0:c546b51ecf0b
|
1034
|
gLastDC[0] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1035
|
gLastDC[1] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1036
|
gLastDC[2] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1037
|
|
| XkLi |
0:c546b51ecf0b
|
1038
|
if (gRestartInterval)
|
| XkLi |
0:c546b51ecf0b
|
1039
|
{
|
| XkLi |
0:c546b51ecf0b
|
1040
|
gRestartsLeft = gRestartInterval;
|
| XkLi |
0:c546b51ecf0b
|
1041
|
gNextRestartNum = 0;
|
| XkLi |
0:c546b51ecf0b
|
1042
|
}
|
| XkLi |
0:c546b51ecf0b
|
1043
|
|
| XkLi |
0:c546b51ecf0b
|
1044
|
fixInBuffer();
|
| XkLi |
0:c546b51ecf0b
|
1045
|
|
| XkLi |
0:c546b51ecf0b
|
1046
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1047
|
}
|
| XkLi |
0:c546b51ecf0b
|
1048
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
1049
|
static uint8 initFrame(void)
|
| XkLi |
0:c546b51ecf0b
|
1050
|
{
|
| XkLi |
0:c546b51ecf0b
|
1051
|
if (gCompsInFrame == 1)
|
| XkLi |
0:c546b51ecf0b
|
1052
|
{
|
| XkLi |
0:c546b51ecf0b
|
1053
|
if ((gCompHSamp[0] != 1) || (gCompVSamp[0] != 1))
|
| XkLi |
0:c546b51ecf0b
|
1054
|
return PJPG_UNSUPPORTED_SAMP_FACTORS;
|
| XkLi |
0:c546b51ecf0b
|
1055
|
|
| XkLi |
0:c546b51ecf0b
|
1056
|
gScanType = PJPG_GRAYSCALE;
|
| XkLi |
0:c546b51ecf0b
|
1057
|
|
| XkLi |
0:c546b51ecf0b
|
1058
|
gMaxBlocksPerMCU = 1;
|
| XkLi |
0:c546b51ecf0b
|
1059
|
gMCUOrg[0] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1060
|
|
| XkLi |
0:c546b51ecf0b
|
1061
|
gMaxMCUXSize = 8;
|
| XkLi |
0:c546b51ecf0b
|
1062
|
gMaxMCUYSize = 8;
|
| XkLi |
0:c546b51ecf0b
|
1063
|
}
|
| XkLi |
0:c546b51ecf0b
|
1064
|
else if (gCompsInFrame == 3)
|
| XkLi |
0:c546b51ecf0b
|
1065
|
{
|
| XkLi |
0:c546b51ecf0b
|
1066
|
if ( ((gCompHSamp[1] != 1) || (gCompVSamp[1] != 1)) ||
|
| XkLi |
0:c546b51ecf0b
|
1067
|
((gCompHSamp[2] != 1) || (gCompVSamp[2] != 1)) )
|
| XkLi |
0:c546b51ecf0b
|
1068
|
return PJPG_UNSUPPORTED_SAMP_FACTORS;
|
| XkLi |
0:c546b51ecf0b
|
1069
|
|
| XkLi |
0:c546b51ecf0b
|
1070
|
if ((gCompHSamp[0] == 1) && (gCompVSamp[0] == 1))
|
| XkLi |
0:c546b51ecf0b
|
1071
|
{
|
| XkLi |
0:c546b51ecf0b
|
1072
|
gScanType = PJPG_YH1V1;
|
| XkLi |
0:c546b51ecf0b
|
1073
|
|
| XkLi |
0:c546b51ecf0b
|
1074
|
gMaxBlocksPerMCU = 3;
|
| XkLi |
0:c546b51ecf0b
|
1075
|
gMCUOrg[0] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1076
|
gMCUOrg[1] = 1;
|
| XkLi |
0:c546b51ecf0b
|
1077
|
gMCUOrg[2] = 2;
|
| XkLi |
0:c546b51ecf0b
|
1078
|
|
| XkLi |
0:c546b51ecf0b
|
1079
|
gMaxMCUXSize = 8;
|
| XkLi |
0:c546b51ecf0b
|
1080
|
gMaxMCUYSize = 8;
|
| XkLi |
0:c546b51ecf0b
|
1081
|
}
|
| XkLi |
0:c546b51ecf0b
|
1082
|
else if ((gCompHSamp[0] == 2) && (gCompVSamp[0] == 2))
|
| XkLi |
0:c546b51ecf0b
|
1083
|
{
|
| XkLi |
0:c546b51ecf0b
|
1084
|
gScanType = PJPG_YH2V2;
|
| XkLi |
0:c546b51ecf0b
|
1085
|
|
| XkLi |
0:c546b51ecf0b
|
1086
|
gMaxBlocksPerMCU = 6;
|
| XkLi |
0:c546b51ecf0b
|
1087
|
gMCUOrg[0] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1088
|
gMCUOrg[1] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1089
|
gMCUOrg[2] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1090
|
gMCUOrg[3] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1091
|
gMCUOrg[4] = 1;
|
| XkLi |
0:c546b51ecf0b
|
1092
|
gMCUOrg[5] = 2;
|
| XkLi |
0:c546b51ecf0b
|
1093
|
|
| XkLi |
0:c546b51ecf0b
|
1094
|
gMaxMCUXSize = 16;
|
| XkLi |
0:c546b51ecf0b
|
1095
|
gMaxMCUYSize = 16;
|
| XkLi |
0:c546b51ecf0b
|
1096
|
}
|
| XkLi |
0:c546b51ecf0b
|
1097
|
else
|
| XkLi |
0:c546b51ecf0b
|
1098
|
return PJPG_UNSUPPORTED_SAMP_FACTORS;
|
| XkLi |
0:c546b51ecf0b
|
1099
|
}
|
| XkLi |
0:c546b51ecf0b
|
1100
|
else
|
| XkLi |
0:c546b51ecf0b
|
1101
|
return PJPG_UNSUPPORTED_COLORSPACE;
|
| XkLi |
0:c546b51ecf0b
|
1102
|
|
| XkLi |
0:c546b51ecf0b
|
1103
|
gMaxMCUSPerRow = (gImageXSize + (gMaxMCUXSize - 1)) >> ((gMaxMCUXSize == 8) ? 3 : 4);
|
| XkLi |
0:c546b51ecf0b
|
1104
|
gMaxMCUSPerCol = (gImageYSize + (gMaxMCUYSize - 1)) >> ((gMaxMCUYSize == 8) ? 3 : 4);
|
| XkLi |
0:c546b51ecf0b
|
1105
|
|
| XkLi |
0:c546b51ecf0b
|
1106
|
gNumMCUSRemaining = gMaxMCUSPerRow * gMaxMCUSPerCol;
|
| XkLi |
0:c546b51ecf0b
|
1107
|
|
| XkLi |
0:c546b51ecf0b
|
1108
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1109
|
}
|
| XkLi |
0:c546b51ecf0b
|
1110
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1111
|
#define DCT_SCALE_BITS 7
|
| XkLi |
0:c546b51ecf0b
|
1112
|
|
| XkLi |
0:c546b51ecf0b
|
1113
|
#define DCT_SCALE (1U << DCT_SCALE_BITS)
|
| XkLi |
0:c546b51ecf0b
|
1114
|
|
| XkLi |
0:c546b51ecf0b
|
1115
|
#define DESCALE(x) (((x) + (1U << (DCT_SCALE_BITS - 1))) >> DCT_SCALE_BITS)
|
| XkLi |
0:c546b51ecf0b
|
1116
|
|
| XkLi |
0:c546b51ecf0b
|
1117
|
#define WFIX(x) ((x) * DCT_SCALE + 0.5f)
|
| XkLi |
0:c546b51ecf0b
|
1118
|
|
| XkLi |
0:c546b51ecf0b
|
1119
|
#define WINOGRAD_QUANT_SCALE_BITS 10
|
| XkLi |
0:c546b51ecf0b
|
1120
|
|
| XkLi |
0:c546b51ecf0b
|
1121
|
const uint8 gWinogradQuant[] =
|
| XkLi |
0:c546b51ecf0b
|
1122
|
{
|
| XkLi |
0:c546b51ecf0b
|
1123
|
128, 178, 178, 167, 246, 167, 151, 232,
|
| XkLi |
0:c546b51ecf0b
|
1124
|
232, 151, 128, 209, 219, 209, 128, 101,
|
| XkLi |
0:c546b51ecf0b
|
1125
|
178, 197, 197, 178, 101, 69, 139, 167,
|
| XkLi |
0:c546b51ecf0b
|
1126
|
177, 167, 139, 69, 35, 96, 131, 151,
|
| XkLi |
0:c546b51ecf0b
|
1127
|
151, 131, 96, 35, 49, 91, 118, 128,
|
| XkLi |
0:c546b51ecf0b
|
1128
|
118, 91, 49, 46, 81, 101, 101, 81,
|
| XkLi |
0:c546b51ecf0b
|
1129
|
46, 42, 69, 79, 69, 42, 35, 54,
|
| XkLi |
0:c546b51ecf0b
|
1130
|
54, 35, 28, 37, 28, 19, 19, 10,
|
| XkLi |
0:c546b51ecf0b
|
1131
|
};
|
| XkLi |
0:c546b51ecf0b
|
1132
|
|
| XkLi |
0:c546b51ecf0b
|
1133
|
static void createWinogradQuant(int16* pQuant)
|
| XkLi |
0:c546b51ecf0b
|
1134
|
{
|
| XkLi |
0:c546b51ecf0b
|
1135
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1136
|
|
| XkLi |
0:c546b51ecf0b
|
1137
|
for (i = 0; i < 64; i++)
|
| XkLi |
0:c546b51ecf0b
|
1138
|
{
|
| XkLi |
0:c546b51ecf0b
|
1139
|
long x = pQuant[i];
|
| XkLi |
0:c546b51ecf0b
|
1140
|
x *= gWinogradQuant[i];
|
| XkLi |
0:c546b51ecf0b
|
1141
|
pQuant[i] = (int16)((x + (1 << (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS - 1))) >> (WINOGRAD_QUANT_SCALE_BITS - DCT_SCALE_BITS));
|
| XkLi |
0:c546b51ecf0b
|
1142
|
}
|
| XkLi |
0:c546b51ecf0b
|
1143
|
}
|
| XkLi |
0:c546b51ecf0b
|
1144
|
|
| XkLi |
0:c546b51ecf0b
|
1145
|
// 1/cos(4*pi/16)
|
| XkLi |
0:c546b51ecf0b
|
1146
|
// 362, 256+106
|
| XkLi |
0:c546b51ecf0b
|
1147
|
#define b1 362
|
| XkLi |
0:c546b51ecf0b
|
1148
|
|
| XkLi |
0:c546b51ecf0b
|
1149
|
// 1/cos(6*pi/16)
|
| XkLi |
0:c546b51ecf0b
|
1150
|
// 669, 256+256+157
|
| XkLi |
0:c546b51ecf0b
|
1151
|
#define b2 669
|
| XkLi |
0:c546b51ecf0b
|
1152
|
|
| XkLi |
0:c546b51ecf0b
|
1153
|
// 1/cos(4*pi/16)
|
| XkLi |
0:c546b51ecf0b
|
1154
|
// 362, 256+106
|
| XkLi |
0:c546b51ecf0b
|
1155
|
#define b3 362
|
| XkLi |
0:c546b51ecf0b
|
1156
|
|
| XkLi |
0:c546b51ecf0b
|
1157
|
// 1/cos(2*pi/16)
|
| XkLi |
0:c546b51ecf0b
|
1158
|
// 277, 256+21
|
| XkLi |
0:c546b51ecf0b
|
1159
|
#define b4 277
|
| XkLi |
0:c546b51ecf0b
|
1160
|
|
| XkLi |
0:c546b51ecf0b
|
1161
|
// 1/(cos(2*pi/16) + cos(6*pi/16))
|
| XkLi |
0:c546b51ecf0b
|
1162
|
// 196, 196
|
| XkLi |
0:c546b51ecf0b
|
1163
|
#define b5 196
|
| XkLi |
0:c546b51ecf0b
|
1164
|
|
| XkLi |
0:c546b51ecf0b
|
1165
|
static int16 imul_b1_b3(int16 w)
|
| XkLi |
0:c546b51ecf0b
|
1166
|
{
|
| XkLi |
0:c546b51ecf0b
|
1167
|
long x = (w * 362L);
|
| XkLi |
0:c546b51ecf0b
|
1168
|
x += 128L;
|
| XkLi |
0:c546b51ecf0b
|
1169
|
return (int16)(x >> 8);
|
| XkLi |
0:c546b51ecf0b
|
1170
|
}
|
| XkLi |
0:c546b51ecf0b
|
1171
|
|
| XkLi |
0:c546b51ecf0b
|
1172
|
static int16 imul_b2(int16 w)
|
| XkLi |
0:c546b51ecf0b
|
1173
|
{
|
| XkLi |
0:c546b51ecf0b
|
1174
|
long x = (w * 669L);
|
| XkLi |
0:c546b51ecf0b
|
1175
|
x += 128L;
|
| XkLi |
0:c546b51ecf0b
|
1176
|
return (int16)(x >> 8);
|
| XkLi |
0:c546b51ecf0b
|
1177
|
}
|
| XkLi |
0:c546b51ecf0b
|
1178
|
|
| XkLi |
0:c546b51ecf0b
|
1179
|
static int16 imul_b4(int16 w)
|
| XkLi |
0:c546b51ecf0b
|
1180
|
{
|
| XkLi |
0:c546b51ecf0b
|
1181
|
long x = (w * 277L);
|
| XkLi |
0:c546b51ecf0b
|
1182
|
x += 128L;
|
| XkLi |
0:c546b51ecf0b
|
1183
|
return (int16)(x >> 8);
|
| XkLi |
0:c546b51ecf0b
|
1184
|
}
|
| XkLi |
0:c546b51ecf0b
|
1185
|
|
| XkLi |
0:c546b51ecf0b
|
1186
|
static int16 imul_b5(int16 w)
|
| XkLi |
0:c546b51ecf0b
|
1187
|
{
|
| XkLi |
0:c546b51ecf0b
|
1188
|
long x = (w * 196L);
|
| XkLi |
0:c546b51ecf0b
|
1189
|
x += 128L;
|
| XkLi |
0:c546b51ecf0b
|
1190
|
return (int16)(x >> 8);
|
| XkLi |
0:c546b51ecf0b
|
1191
|
}
|
| XkLi |
0:c546b51ecf0b
|
1192
|
|
| XkLi |
0:c546b51ecf0b
|
1193
|
static uint8 clamp(int16 s)
|
| XkLi |
0:c546b51ecf0b
|
1194
|
{
|
| XkLi |
0:c546b51ecf0b
|
1195
|
if ((uint16)s > 255U)
|
| XkLi |
0:c546b51ecf0b
|
1196
|
{
|
| XkLi |
0:c546b51ecf0b
|
1197
|
if (s < 0)
|
| XkLi |
0:c546b51ecf0b
|
1198
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1199
|
else if (s > 255)
|
| XkLi |
0:c546b51ecf0b
|
1200
|
return 255;
|
| XkLi |
0:c546b51ecf0b
|
1201
|
}
|
| XkLi |
0:c546b51ecf0b
|
1202
|
|
| XkLi |
0:c546b51ecf0b
|
1203
|
return (uint8)s;
|
| XkLi |
0:c546b51ecf0b
|
1204
|
}
|
| XkLi |
0:c546b51ecf0b
|
1205
|
|
| XkLi |
0:c546b51ecf0b
|
1206
|
static void idctRows(void)
|
| XkLi |
0:c546b51ecf0b
|
1207
|
{
|
| XkLi |
0:c546b51ecf0b
|
1208
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1209
|
int16* pSrc = gCoeffBuf;
|
| XkLi |
0:c546b51ecf0b
|
1210
|
|
| XkLi |
0:c546b51ecf0b
|
1211
|
for (i = 0; i < 8; i++)
|
| XkLi |
0:c546b51ecf0b
|
1212
|
{
|
| XkLi |
0:c546b51ecf0b
|
1213
|
int16 src4 = *(pSrc+5);
|
| XkLi |
0:c546b51ecf0b
|
1214
|
int16 src7 = *(pSrc+3);
|
| XkLi |
0:c546b51ecf0b
|
1215
|
int16 x4 = src4 - src7;
|
| XkLi |
0:c546b51ecf0b
|
1216
|
int16 x7 = src4 + src7;
|
| XkLi |
0:c546b51ecf0b
|
1217
|
|
| XkLi |
0:c546b51ecf0b
|
1218
|
int16 src5 = *(pSrc+1);
|
| XkLi |
0:c546b51ecf0b
|
1219
|
int16 src6 = *(pSrc+7);
|
| XkLi |
0:c546b51ecf0b
|
1220
|
int16 x5 = src5 + src6;
|
| XkLi |
0:c546b51ecf0b
|
1221
|
int16 x6 = src5 - src6;
|
| XkLi |
0:c546b51ecf0b
|
1222
|
|
| XkLi |
0:c546b51ecf0b
|
1223
|
int16 tmp1 = imul_b5(x4 - x6);
|
| XkLi |
0:c546b51ecf0b
|
1224
|
int16 stg26 = imul_b4(x6) - tmp1;
|
| XkLi |
0:c546b51ecf0b
|
1225
|
|
| XkLi |
0:c546b51ecf0b
|
1226
|
int16 x24 = tmp1 - imul_b2(x4);
|
| XkLi |
0:c546b51ecf0b
|
1227
|
|
| XkLi |
0:c546b51ecf0b
|
1228
|
int16 x15 = x5 - x7;
|
| XkLi |
0:c546b51ecf0b
|
1229
|
int16 x17 = x5 + x7;
|
| XkLi |
0:c546b51ecf0b
|
1230
|
|
| XkLi |
0:c546b51ecf0b
|
1231
|
int16 tmp2 = stg26 - x17;
|
| XkLi |
0:c546b51ecf0b
|
1232
|
int16 tmp3 = imul_b1_b3(x15) - tmp2;
|
| XkLi |
0:c546b51ecf0b
|
1233
|
int16 x44 = tmp3 + x24;
|
| XkLi |
0:c546b51ecf0b
|
1234
|
|
| XkLi |
0:c546b51ecf0b
|
1235
|
int16 src0 = *(pSrc+0);
|
| XkLi |
0:c546b51ecf0b
|
1236
|
int16 src1 = *(pSrc+4);
|
| XkLi |
0:c546b51ecf0b
|
1237
|
int16 x30 = src0 + src1;
|
| XkLi |
0:c546b51ecf0b
|
1238
|
int16 x31 = src0 - src1;
|
| XkLi |
0:c546b51ecf0b
|
1239
|
|
| XkLi |
0:c546b51ecf0b
|
1240
|
int16 src2 = *(pSrc+2);
|
| XkLi |
0:c546b51ecf0b
|
1241
|
int16 src3 = *(pSrc+6);
|
| XkLi |
0:c546b51ecf0b
|
1242
|
int16 x12 = src2 - src3;
|
| XkLi |
0:c546b51ecf0b
|
1243
|
int16 x13 = src2 + src3;
|
| XkLi |
0:c546b51ecf0b
|
1244
|
|
| XkLi |
0:c546b51ecf0b
|
1245
|
int16 x32 = imul_b1_b3(x12) - x13;
|
| XkLi |
0:c546b51ecf0b
|
1246
|
|
| XkLi |
0:c546b51ecf0b
|
1247
|
int16 x40 = x30 + x13;
|
| XkLi |
0:c546b51ecf0b
|
1248
|
int16 x43 = x30 - x13;
|
| XkLi |
0:c546b51ecf0b
|
1249
|
int16 x41 = x31 + x32;
|
| XkLi |
0:c546b51ecf0b
|
1250
|
int16 x42 = x31 - x32;
|
| XkLi |
0:c546b51ecf0b
|
1251
|
|
| XkLi |
0:c546b51ecf0b
|
1252
|
*(pSrc+0) = x40 + x17;
|
| XkLi |
0:c546b51ecf0b
|
1253
|
*(pSrc+1) = x41 + tmp2;
|
| XkLi |
0:c546b51ecf0b
|
1254
|
*(pSrc+2) = x42 + tmp3;
|
| XkLi |
0:c546b51ecf0b
|
1255
|
*(pSrc+3) = x43 - x44;
|
| XkLi |
0:c546b51ecf0b
|
1256
|
*(pSrc+4) = x43 + x44;
|
| XkLi |
0:c546b51ecf0b
|
1257
|
*(pSrc+5) = x42 - tmp3;
|
| XkLi |
0:c546b51ecf0b
|
1258
|
*(pSrc+6) = x41 - tmp2;
|
| XkLi |
0:c546b51ecf0b
|
1259
|
*(pSrc+7) = x40 - x17;
|
| XkLi |
0:c546b51ecf0b
|
1260
|
|
| XkLi |
0:c546b51ecf0b
|
1261
|
pSrc += 8;
|
| XkLi |
0:c546b51ecf0b
|
1262
|
}
|
| XkLi |
0:c546b51ecf0b
|
1263
|
}
|
| XkLi |
0:c546b51ecf0b
|
1264
|
|
| XkLi |
0:c546b51ecf0b
|
1265
|
static void idctCols(void)
|
| XkLi |
0:c546b51ecf0b
|
1266
|
{
|
| XkLi |
0:c546b51ecf0b
|
1267
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1268
|
|
| XkLi |
0:c546b51ecf0b
|
1269
|
int16* pSrc = gCoeffBuf;
|
| XkLi |
0:c546b51ecf0b
|
1270
|
|
| XkLi |
0:c546b51ecf0b
|
1271
|
for (i = 0; i < 8; i++)
|
| XkLi |
0:c546b51ecf0b
|
1272
|
{
|
| XkLi |
0:c546b51ecf0b
|
1273
|
int16 src4 = *(pSrc+5*8);
|
| XkLi |
0:c546b51ecf0b
|
1274
|
int16 src7 = *(pSrc+3*8);
|
| XkLi |
0:c546b51ecf0b
|
1275
|
int16 x4 = src4 - src7;
|
| XkLi |
0:c546b51ecf0b
|
1276
|
int16 x7 = src4 + src7;
|
| XkLi |
0:c546b51ecf0b
|
1277
|
|
| XkLi |
0:c546b51ecf0b
|
1278
|
int16 src5 = *(pSrc+1*8);
|
| XkLi |
0:c546b51ecf0b
|
1279
|
int16 src6 = *(pSrc+7*8);
|
| XkLi |
0:c546b51ecf0b
|
1280
|
int16 x5 = src5 + src6;
|
| XkLi |
0:c546b51ecf0b
|
1281
|
int16 x6 = src5 - src6;
|
| XkLi |
0:c546b51ecf0b
|
1282
|
|
| XkLi |
0:c546b51ecf0b
|
1283
|
int16 tmp1 = imul_b5(x4 - x6);
|
| XkLi |
0:c546b51ecf0b
|
1284
|
int16 stg26 = imul_b4(x6) - tmp1;
|
| XkLi |
0:c546b51ecf0b
|
1285
|
|
| XkLi |
0:c546b51ecf0b
|
1286
|
int16 x24 = tmp1 - imul_b2(x4);
|
| XkLi |
0:c546b51ecf0b
|
1287
|
|
| XkLi |
0:c546b51ecf0b
|
1288
|
int16 x15 = x5 - x7;
|
| XkLi |
0:c546b51ecf0b
|
1289
|
int16 x17 = x5 + x7;
|
| XkLi |
0:c546b51ecf0b
|
1290
|
|
| XkLi |
0:c546b51ecf0b
|
1291
|
int16 tmp2 = stg26 - x17;
|
| XkLi |
0:c546b51ecf0b
|
1292
|
int16 tmp3 = imul_b1_b3(x15) - tmp2;
|
| XkLi |
0:c546b51ecf0b
|
1293
|
int16 x44 = tmp3 + x24;
|
| XkLi |
0:c546b51ecf0b
|
1294
|
|
| XkLi |
0:c546b51ecf0b
|
1295
|
int16 src0 = *(pSrc+0*8);
|
| XkLi |
0:c546b51ecf0b
|
1296
|
int16 src1 = *(pSrc+4*8);
|
| XkLi |
0:c546b51ecf0b
|
1297
|
int16 x30 = src0 + src1;
|
| XkLi |
0:c546b51ecf0b
|
1298
|
int16 x31 = src0 - src1;
|
| XkLi |
0:c546b51ecf0b
|
1299
|
|
| XkLi |
0:c546b51ecf0b
|
1300
|
int16 src2 = *(pSrc+2*8);
|
| XkLi |
0:c546b51ecf0b
|
1301
|
int16 src3 = *(pSrc+6*8);
|
| XkLi |
0:c546b51ecf0b
|
1302
|
int16 x12 = src2 - src3;
|
| XkLi |
0:c546b51ecf0b
|
1303
|
int16 x13 = src2 + src3;
|
| XkLi |
0:c546b51ecf0b
|
1304
|
|
| XkLi |
0:c546b51ecf0b
|
1305
|
int16 x32 = imul_b1_b3(x12) - x13;
|
| XkLi |
0:c546b51ecf0b
|
1306
|
|
| XkLi |
0:c546b51ecf0b
|
1307
|
int16 x40 = x30 + x13;
|
| XkLi |
0:c546b51ecf0b
|
1308
|
int16 x43 = x30 - x13;
|
| XkLi |
0:c546b51ecf0b
|
1309
|
int16 x41 = x31 + x32;
|
| XkLi |
0:c546b51ecf0b
|
1310
|
int16 x42 = x31 - x32;
|
| XkLi |
0:c546b51ecf0b
|
1311
|
|
| XkLi |
0:c546b51ecf0b
|
1312
|
*(pSrc+0*8) = clamp(DESCALE(x40 + x17) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1313
|
*(pSrc+1*8) = clamp(DESCALE(x41 + tmp2) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1314
|
*(pSrc+2*8) = clamp(DESCALE(x42 + tmp3) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1315
|
*(pSrc+3*8) = clamp(DESCALE(x43 - x44) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1316
|
*(pSrc+4*8) = clamp(DESCALE(x43 + x44) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1317
|
*(pSrc+5*8) = clamp(DESCALE(x42 - tmp3) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1318
|
*(pSrc+6*8) = clamp(DESCALE(x41 - tmp2) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1319
|
*(pSrc+7*8) = clamp(DESCALE(x40 - x17) + 128);
|
| XkLi |
0:c546b51ecf0b
|
1320
|
|
| XkLi |
0:c546b51ecf0b
|
1321
|
pSrc++;
|
| XkLi |
0:c546b51ecf0b
|
1322
|
}
|
| XkLi |
0:c546b51ecf0b
|
1323
|
}
|
| XkLi |
0:c546b51ecf0b
|
1324
|
|
| XkLi |
0:c546b51ecf0b
|
1325
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1326
|
static uint8 addAndClamp(uint8 a, int16 b)
|
| XkLi |
0:c546b51ecf0b
|
1327
|
{
|
| XkLi |
0:c546b51ecf0b
|
1328
|
b = a + b;
|
| XkLi |
0:c546b51ecf0b
|
1329
|
|
| XkLi |
0:c546b51ecf0b
|
1330
|
if ((uint16)b > 255U)
|
| XkLi |
0:c546b51ecf0b
|
1331
|
{
|
| XkLi |
0:c546b51ecf0b
|
1332
|
if (b < 0)
|
| XkLi |
0:c546b51ecf0b
|
1333
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1334
|
else if (b > 255)
|
| XkLi |
0:c546b51ecf0b
|
1335
|
return 255;
|
| XkLi |
0:c546b51ecf0b
|
1336
|
}
|
| XkLi |
0:c546b51ecf0b
|
1337
|
|
| XkLi |
0:c546b51ecf0b
|
1338
|
return (uint8)b;
|
| XkLi |
0:c546b51ecf0b
|
1339
|
}
|
| XkLi |
0:c546b51ecf0b
|
1340
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1341
|
static uint8 subAndClamp(uint8 a, int16 b)
|
| XkLi |
0:c546b51ecf0b
|
1342
|
{
|
| XkLi |
0:c546b51ecf0b
|
1343
|
b = a - b;
|
| XkLi |
0:c546b51ecf0b
|
1344
|
|
| XkLi |
0:c546b51ecf0b
|
1345
|
if ((uint16)b > 255U)
|
| XkLi |
0:c546b51ecf0b
|
1346
|
{
|
| XkLi |
0:c546b51ecf0b
|
1347
|
if (b < 0)
|
| XkLi |
0:c546b51ecf0b
|
1348
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1349
|
else if (b > 255)
|
| XkLi |
0:c546b51ecf0b
|
1350
|
return 255;
|
| XkLi |
0:c546b51ecf0b
|
1351
|
}
|
| XkLi |
0:c546b51ecf0b
|
1352
|
|
| XkLi |
0:c546b51ecf0b
|
1353
|
return (uint8)b;
|
| XkLi |
0:c546b51ecf0b
|
1354
|
}
|
| XkLi |
0:c546b51ecf0b
|
1355
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1356
|
// 103/256
|
| XkLi |
0:c546b51ecf0b
|
1357
|
//R = Y + 1.402 (Cr-128)
|
| XkLi |
0:c546b51ecf0b
|
1358
|
|
| XkLi |
0:c546b51ecf0b
|
1359
|
// 88/256, 183/256
|
| XkLi |
0:c546b51ecf0b
|
1360
|
//G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
|
| XkLi |
0:c546b51ecf0b
|
1361
|
|
| XkLi |
0:c546b51ecf0b
|
1362
|
// 198/256
|
| XkLi |
0:c546b51ecf0b
|
1363
|
//B = Y + 1.772 (Cb-128)
|
| XkLi |
0:c546b51ecf0b
|
1364
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1365
|
static void upsampleCb(uint8 srcOfs, uint8 dstOfs)
|
| XkLi |
0:c546b51ecf0b
|
1366
|
{
|
| XkLi |
0:c546b51ecf0b
|
1367
|
// Cb - affects G and B
|
| XkLi |
0:c546b51ecf0b
|
1368
|
uint8 x, y;
|
| XkLi |
0:c546b51ecf0b
|
1369
|
int16* pSrc = gCoeffBuf + srcOfs;
|
| XkLi |
0:c546b51ecf0b
|
1370
|
uint8* pDstG = gMCUBufG + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1371
|
uint8* pDstB = gMCUBufB + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1372
|
for (y = 0; y < 4; y++)
|
| XkLi |
0:c546b51ecf0b
|
1373
|
{
|
| XkLi |
0:c546b51ecf0b
|
1374
|
for (x = 0; x < 4; x++)
|
| XkLi |
0:c546b51ecf0b
|
1375
|
{
|
| XkLi |
0:c546b51ecf0b
|
1376
|
uint8 cb = (uint8)*pSrc++;
|
| XkLi |
0:c546b51ecf0b
|
1377
|
int16 cbG, cbB;
|
| XkLi |
0:c546b51ecf0b
|
1378
|
|
| XkLi |
0:c546b51ecf0b
|
1379
|
cbG = ((cb * 88U) >> 8U) - 44U;
|
| XkLi |
0:c546b51ecf0b
|
1380
|
pDstG[0] = subAndClamp(pDstG[0], cbG);
|
| XkLi |
0:c546b51ecf0b
|
1381
|
pDstG[1] = subAndClamp(pDstG[1], cbG);
|
| XkLi |
0:c546b51ecf0b
|
1382
|
pDstG[8] = subAndClamp(pDstG[8], cbG);
|
| XkLi |
0:c546b51ecf0b
|
1383
|
pDstG[9] = subAndClamp(pDstG[9], cbG);
|
| XkLi |
0:c546b51ecf0b
|
1384
|
|
| XkLi |
0:c546b51ecf0b
|
1385
|
cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
|
| XkLi |
0:c546b51ecf0b
|
1386
|
pDstB[0] = addAndClamp(pDstB[0], cbB);
|
| XkLi |
0:c546b51ecf0b
|
1387
|
pDstB[1] = addAndClamp(pDstB[1], cbB);
|
| XkLi |
0:c546b51ecf0b
|
1388
|
pDstB[8] = addAndClamp(pDstB[8], cbB);
|
| XkLi |
0:c546b51ecf0b
|
1389
|
pDstB[9] = addAndClamp(pDstB[9], cbB);
|
| XkLi |
0:c546b51ecf0b
|
1390
|
|
| XkLi |
0:c546b51ecf0b
|
1391
|
pDstG += 2;
|
| XkLi |
0:c546b51ecf0b
|
1392
|
pDstB += 2;
|
| XkLi |
0:c546b51ecf0b
|
1393
|
}
|
| XkLi |
0:c546b51ecf0b
|
1394
|
|
| XkLi |
0:c546b51ecf0b
|
1395
|
pSrc = pSrc - 4 + 8;
|
| XkLi |
0:c546b51ecf0b
|
1396
|
pDstG = pDstG - 8 + 16;
|
| XkLi |
0:c546b51ecf0b
|
1397
|
pDstB = pDstB - 8 + 16;
|
| XkLi |
0:c546b51ecf0b
|
1398
|
}
|
| XkLi |
0:c546b51ecf0b
|
1399
|
}
|
| XkLi |
0:c546b51ecf0b
|
1400
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1401
|
// 103/256
|
| XkLi |
0:c546b51ecf0b
|
1402
|
//R = Y + 1.402 (Cr-128)
|
| XkLi |
0:c546b51ecf0b
|
1403
|
|
| XkLi |
0:c546b51ecf0b
|
1404
|
// 88/256, 183/256
|
| XkLi |
0:c546b51ecf0b
|
1405
|
//G = Y - 0.34414 (Cb-128) - 0.71414 (Cr-128)
|
| XkLi |
0:c546b51ecf0b
|
1406
|
|
| XkLi |
0:c546b51ecf0b
|
1407
|
// 198/256
|
| XkLi |
0:c546b51ecf0b
|
1408
|
//B = Y + 1.772 (Cb-128)
|
| XkLi |
0:c546b51ecf0b
|
1409
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1410
|
static void upsampleCr(uint8 srcOfs, uint8 dstOfs)
|
| XkLi |
0:c546b51ecf0b
|
1411
|
{
|
| XkLi |
0:c546b51ecf0b
|
1412
|
// Cr - affects R and G
|
| XkLi |
0:c546b51ecf0b
|
1413
|
uint8 x, y;
|
| XkLi |
0:c546b51ecf0b
|
1414
|
int16* pSrc = gCoeffBuf + srcOfs;
|
| XkLi |
0:c546b51ecf0b
|
1415
|
uint8* pDstR = gMCUBufR + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1416
|
uint8* pDstG = gMCUBufG + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1417
|
for (y = 0; y < 4; y++)
|
| XkLi |
0:c546b51ecf0b
|
1418
|
{
|
| XkLi |
0:c546b51ecf0b
|
1419
|
for (x = 0; x < 4; x++)
|
| XkLi |
0:c546b51ecf0b
|
1420
|
{
|
| XkLi |
0:c546b51ecf0b
|
1421
|
uint8 cr = (uint8)*pSrc++;
|
| XkLi |
0:c546b51ecf0b
|
1422
|
int16 crR, crG;
|
| XkLi |
0:c546b51ecf0b
|
1423
|
|
| XkLi |
0:c546b51ecf0b
|
1424
|
crR = (cr + ((cr * 103U) >> 8U)) - 179;
|
| XkLi |
0:c546b51ecf0b
|
1425
|
pDstR[0] = addAndClamp(pDstR[0], crR);
|
| XkLi |
0:c546b51ecf0b
|
1426
|
pDstR[1] = addAndClamp(pDstR[1], crR);
|
| XkLi |
0:c546b51ecf0b
|
1427
|
pDstR[8] = addAndClamp(pDstR[8], crR);
|
| XkLi |
0:c546b51ecf0b
|
1428
|
pDstR[9] = addAndClamp(pDstR[9], crR);
|
| XkLi |
0:c546b51ecf0b
|
1429
|
|
| XkLi |
0:c546b51ecf0b
|
1430
|
crG = ((cr * 183U) >> 8U) - 91;
|
| XkLi |
0:c546b51ecf0b
|
1431
|
pDstG[0] = subAndClamp(pDstG[0], crG);
|
| XkLi |
0:c546b51ecf0b
|
1432
|
pDstG[1] = subAndClamp(pDstG[1], crG);
|
| XkLi |
0:c546b51ecf0b
|
1433
|
pDstG[8] = subAndClamp(pDstG[8], crG);
|
| XkLi |
0:c546b51ecf0b
|
1434
|
pDstG[9] = subAndClamp(pDstG[9], crG);
|
| XkLi |
0:c546b51ecf0b
|
1435
|
|
| XkLi |
0:c546b51ecf0b
|
1436
|
pDstR += 2;
|
| XkLi |
0:c546b51ecf0b
|
1437
|
pDstG += 2;
|
| XkLi |
0:c546b51ecf0b
|
1438
|
}
|
| XkLi |
0:c546b51ecf0b
|
1439
|
|
| XkLi |
0:c546b51ecf0b
|
1440
|
pSrc = pSrc - 4 + 8;
|
| XkLi |
0:c546b51ecf0b
|
1441
|
pDstR = pDstR - 8 + 16;
|
| XkLi |
0:c546b51ecf0b
|
1442
|
pDstG = pDstG - 8 + 16;
|
| XkLi |
0:c546b51ecf0b
|
1443
|
}
|
| XkLi |
0:c546b51ecf0b
|
1444
|
}
|
| XkLi |
0:c546b51ecf0b
|
1445
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1446
|
static void copyY(uint8 dstOfs)
|
| XkLi |
0:c546b51ecf0b
|
1447
|
{
|
| XkLi |
0:c546b51ecf0b
|
1448
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1449
|
uint8* pRDst = gMCUBufR + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1450
|
uint8* pGDst = gMCUBufG + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1451
|
uint8* pBDst = gMCUBufB + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1452
|
int16* pSrc = gCoeffBuf;
|
| XkLi |
0:c546b51ecf0b
|
1453
|
|
| XkLi |
0:c546b51ecf0b
|
1454
|
for (i = 64; i > 0; i--)
|
| XkLi |
0:c546b51ecf0b
|
1455
|
{
|
| XkLi |
0:c546b51ecf0b
|
1456
|
uint8 c = (uint8)*pSrc++;
|
| XkLi |
0:c546b51ecf0b
|
1457
|
|
| XkLi |
0:c546b51ecf0b
|
1458
|
*pRDst++ = c;
|
| XkLi |
0:c546b51ecf0b
|
1459
|
*pGDst++ = c;
|
| XkLi |
0:c546b51ecf0b
|
1460
|
*pBDst++ = c;
|
| XkLi |
0:c546b51ecf0b
|
1461
|
}
|
| XkLi |
0:c546b51ecf0b
|
1462
|
}
|
| XkLi |
0:c546b51ecf0b
|
1463
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1464
|
static void convertCb(uint8 dstOfs)
|
| XkLi |
0:c546b51ecf0b
|
1465
|
{
|
| XkLi |
0:c546b51ecf0b
|
1466
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1467
|
uint8* pDstG = gMCUBufG + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1468
|
uint8* pDstB = gMCUBufB + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1469
|
int16* pSrc = gCoeffBuf;
|
| XkLi |
0:c546b51ecf0b
|
1470
|
|
| XkLi |
0:c546b51ecf0b
|
1471
|
for (i = 64; i > 0; i--)
|
| XkLi |
0:c546b51ecf0b
|
1472
|
{
|
| XkLi |
0:c546b51ecf0b
|
1473
|
uint8 cb = (uint8)*pSrc++;
|
| XkLi |
0:c546b51ecf0b
|
1474
|
int16 cbG, cbB;
|
| XkLi |
0:c546b51ecf0b
|
1475
|
|
| XkLi |
0:c546b51ecf0b
|
1476
|
cbG = ((cb * 88U) >> 8U) - 44U;
|
| XkLi |
0:c546b51ecf0b
|
1477
|
*pDstG++ = subAndClamp(pDstG[0], cbG);
|
| XkLi |
0:c546b51ecf0b
|
1478
|
|
| XkLi |
0:c546b51ecf0b
|
1479
|
cbB = (cb + ((cb * 198U) >> 8U)) - 227U;
|
| XkLi |
0:c546b51ecf0b
|
1480
|
*pDstB++ = addAndClamp(pDstB[0], cbB);
|
| XkLi |
0:c546b51ecf0b
|
1481
|
}
|
| XkLi |
0:c546b51ecf0b
|
1482
|
}
|
| XkLi |
0:c546b51ecf0b
|
1483
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1484
|
static void convertCr(uint8 dstOfs)
|
| XkLi |
0:c546b51ecf0b
|
1485
|
{
|
| XkLi |
0:c546b51ecf0b
|
1486
|
uint8 i;
|
| XkLi |
0:c546b51ecf0b
|
1487
|
uint8* pDstR = gMCUBufR + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1488
|
uint8* pDstG = gMCUBufG + dstOfs;
|
| XkLi |
0:c546b51ecf0b
|
1489
|
int16* pSrc = gCoeffBuf;
|
| XkLi |
0:c546b51ecf0b
|
1490
|
|
| XkLi |
0:c546b51ecf0b
|
1491
|
for (i = 64; i > 0; i--)
|
| XkLi |
0:c546b51ecf0b
|
1492
|
{
|
| XkLi |
0:c546b51ecf0b
|
1493
|
uint8 cr = (uint8)*pSrc++;
|
| XkLi |
0:c546b51ecf0b
|
1494
|
int16 crR, crG;
|
| XkLi |
0:c546b51ecf0b
|
1495
|
|
| XkLi |
0:c546b51ecf0b
|
1496
|
crR = (cr + ((cr * 103U) >> 8U)) - 179;
|
| XkLi |
0:c546b51ecf0b
|
1497
|
*pDstR++ = addAndClamp(pDstR[0], crR);
|
| XkLi |
0:c546b51ecf0b
|
1498
|
|
| XkLi |
0:c546b51ecf0b
|
1499
|
crG = ((cr * 183U) >> 8U) - 91;
|
| XkLi |
0:c546b51ecf0b
|
1500
|
*pDstG++ = subAndClamp(pDstG[0], crG);
|
| XkLi |
0:c546b51ecf0b
|
1501
|
}
|
| XkLi |
0:c546b51ecf0b
|
1502
|
}
|
| XkLi |
0:c546b51ecf0b
|
1503
|
/*----------------------------------------------------------------------------*/
|
| XkLi |
0:c546b51ecf0b
|
1504
|
static void transformBlock(uint8 mcuBlock)
|
| XkLi |
0:c546b51ecf0b
|
1505
|
{
|
| XkLi |
0:c546b51ecf0b
|
1506
|
idctRows();
|
| XkLi |
0:c546b51ecf0b
|
1507
|
idctCols();
|
| XkLi |
0:c546b51ecf0b
|
1508
|
|
| XkLi |
0:c546b51ecf0b
|
1509
|
switch (gScanType)
|
| XkLi |
0:c546b51ecf0b
|
1510
|
{
|
| XkLi |
0:c546b51ecf0b
|
1511
|
case PJPG_GRAYSCALE:
|
| XkLi |
0:c546b51ecf0b
|
1512
|
{
|
| XkLi |
0:c546b51ecf0b
|
1513
|
copyY(0);
|
| XkLi |
0:c546b51ecf0b
|
1514
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1515
|
}
|
| XkLi |
0:c546b51ecf0b
|
1516
|
case PJPG_YH1V1:
|
| XkLi |
0:c546b51ecf0b
|
1517
|
{
|
| XkLi |
0:c546b51ecf0b
|
1518
|
switch (mcuBlock)
|
| XkLi |
0:c546b51ecf0b
|
1519
|
{
|
| XkLi |
0:c546b51ecf0b
|
1520
|
case 0:
|
| XkLi |
0:c546b51ecf0b
|
1521
|
{
|
| XkLi |
0:c546b51ecf0b
|
1522
|
copyY(0);
|
| XkLi |
0:c546b51ecf0b
|
1523
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1524
|
}
|
| XkLi |
0:c546b51ecf0b
|
1525
|
case 1:
|
| XkLi |
0:c546b51ecf0b
|
1526
|
{
|
| XkLi |
0:c546b51ecf0b
|
1527
|
convertCb(0);
|
| XkLi |
0:c546b51ecf0b
|
1528
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1529
|
}
|
| XkLi |
0:c546b51ecf0b
|
1530
|
case 2:
|
| XkLi |
0:c546b51ecf0b
|
1531
|
{
|
| XkLi |
0:c546b51ecf0b
|
1532
|
convertCr(0);
|
| XkLi |
0:c546b51ecf0b
|
1533
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1534
|
}
|
| XkLi |
0:c546b51ecf0b
|
1535
|
}
|
| XkLi |
0:c546b51ecf0b
|
1536
|
|
| XkLi |
0:c546b51ecf0b
|
1537
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1538
|
}
|
| XkLi |
0:c546b51ecf0b
|
1539
|
case PJPG_YH2V2:
|
| XkLi |
0:c546b51ecf0b
|
1540
|
{
|
| XkLi |
0:c546b51ecf0b
|
1541
|
switch (mcuBlock)
|
| XkLi |
0:c546b51ecf0b
|
1542
|
{
|
| XkLi |
0:c546b51ecf0b
|
1543
|
case 0:
|
| XkLi |
0:c546b51ecf0b
|
1544
|
{
|
| XkLi |
0:c546b51ecf0b
|
1545
|
copyY(0);
|
| XkLi |
0:c546b51ecf0b
|
1546
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1547
|
}
|
| XkLi |
0:c546b51ecf0b
|
1548
|
case 1:
|
| XkLi |
0:c546b51ecf0b
|
1549
|
{
|
| XkLi |
0:c546b51ecf0b
|
1550
|
copyY(64);
|
| XkLi |
0:c546b51ecf0b
|
1551
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1552
|
}
|
| XkLi |
0:c546b51ecf0b
|
1553
|
case 2:
|
| XkLi |
0:c546b51ecf0b
|
1554
|
{
|
| XkLi |
0:c546b51ecf0b
|
1555
|
copyY(128);
|
| XkLi |
0:c546b51ecf0b
|
1556
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1557
|
}
|
| XkLi |
0:c546b51ecf0b
|
1558
|
case 3:
|
| XkLi |
0:c546b51ecf0b
|
1559
|
{
|
| XkLi |
0:c546b51ecf0b
|
1560
|
copyY(192);
|
| XkLi |
0:c546b51ecf0b
|
1561
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1562
|
}
|
| XkLi |
0:c546b51ecf0b
|
1563
|
case 4:
|
| XkLi |
0:c546b51ecf0b
|
1564
|
{
|
| XkLi |
0:c546b51ecf0b
|
1565
|
upsampleCb(0, 0);
|
| XkLi |
0:c546b51ecf0b
|
1566
|
upsampleCb(4, 64);
|
| XkLi |
0:c546b51ecf0b
|
1567
|
upsampleCb(4*8, 128);
|
| XkLi |
0:c546b51ecf0b
|
1568
|
upsampleCb(4+4*8, 192);
|
| XkLi |
0:c546b51ecf0b
|
1569
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1570
|
}
|
| XkLi |
0:c546b51ecf0b
|
1571
|
case 5:
|
| XkLi |
0:c546b51ecf0b
|
1572
|
{
|
| XkLi |
0:c546b51ecf0b
|
1573
|
upsampleCr(0, 0);
|
| XkLi |
0:c546b51ecf0b
|
1574
|
upsampleCr(4, 64);
|
| XkLi |
0:c546b51ecf0b
|
1575
|
upsampleCr(4*8, 128);
|
| XkLi |
0:c546b51ecf0b
|
1576
|
upsampleCr(4+4*8, 192);
|
| XkLi |
0:c546b51ecf0b
|
1577
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1578
|
}
|
| XkLi |
0:c546b51ecf0b
|
1579
|
}
|
| XkLi |
0:c546b51ecf0b
|
1580
|
}
|
| XkLi |
0:c546b51ecf0b
|
1581
|
}
|
| XkLi |
0:c546b51ecf0b
|
1582
|
}
|
| XkLi |
0:c546b51ecf0b
|
1583
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
1584
|
static uint8 decodeNextMCU(void)
|
| XkLi |
0:c546b51ecf0b
|
1585
|
{
|
| XkLi |
0:c546b51ecf0b
|
1586
|
uint8 status;
|
| XkLi |
0:c546b51ecf0b
|
1587
|
uint8 mcuBlock;
|
| XkLi |
0:c546b51ecf0b
|
1588
|
|
| XkLi |
0:c546b51ecf0b
|
1589
|
if (gRestartInterval)
|
| XkLi |
0:c546b51ecf0b
|
1590
|
{
|
| XkLi |
0:c546b51ecf0b
|
1591
|
if (gRestartsLeft == 0)
|
| XkLi |
0:c546b51ecf0b
|
1592
|
{
|
| XkLi |
0:c546b51ecf0b
|
1593
|
status = processRestart();
|
| XkLi |
0:c546b51ecf0b
|
1594
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1595
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1596
|
}
|
| XkLi |
0:c546b51ecf0b
|
1597
|
gRestartsLeft--;
|
| XkLi |
0:c546b51ecf0b
|
1598
|
}
|
| XkLi |
0:c546b51ecf0b
|
1599
|
|
| XkLi |
0:c546b51ecf0b
|
1600
|
for (mcuBlock = 0; mcuBlock < gMaxBlocksPerMCU; mcuBlock++)
|
| XkLi |
0:c546b51ecf0b
|
1601
|
{
|
| XkLi |
0:c546b51ecf0b
|
1602
|
uint8 componentID = gMCUOrg[mcuBlock];
|
| XkLi |
0:c546b51ecf0b
|
1603
|
uint8 compQuant = gCompQuant[componentID];
|
| XkLi |
0:c546b51ecf0b
|
1604
|
uint8 compDCTab = gCompDCTab[componentID];
|
| XkLi |
0:c546b51ecf0b
|
1605
|
uint8 numExtraBits, compACTab, k;
|
| XkLi |
0:c546b51ecf0b
|
1606
|
const int16* pQ = compQuant ? gQuant1 : gQuant0;
|
| XkLi |
0:c546b51ecf0b
|
1607
|
uint16 r, dc;
|
| XkLi |
0:c546b51ecf0b
|
1608
|
|
| XkLi |
0:c546b51ecf0b
|
1609
|
uint8 s = huffDecode(compDCTab ? &gHuffTab1 : &gHuffTab0, compDCTab ? gHuffVal1 : gHuffVal0);
|
| XkLi |
0:c546b51ecf0b
|
1610
|
|
| XkLi |
0:c546b51ecf0b
|
1611
|
r = 0;
|
| XkLi |
0:c546b51ecf0b
|
1612
|
numExtraBits = s & 0xF;
|
| XkLi |
0:c546b51ecf0b
|
1613
|
if (numExtraBits)
|
| XkLi |
0:c546b51ecf0b
|
1614
|
r = getBits2(numExtraBits);
|
| XkLi |
0:c546b51ecf0b
|
1615
|
dc = huffExtend(r, s);
|
| XkLi |
0:c546b51ecf0b
|
1616
|
|
| XkLi |
0:c546b51ecf0b
|
1617
|
dc = dc + gLastDC[componentID];
|
| XkLi |
0:c546b51ecf0b
|
1618
|
gLastDC[componentID] = dc;
|
| XkLi |
0:c546b51ecf0b
|
1619
|
|
| XkLi |
0:c546b51ecf0b
|
1620
|
gCoeffBuf[0] = dc * pQ[0];
|
| XkLi |
0:c546b51ecf0b
|
1621
|
|
| XkLi |
0:c546b51ecf0b
|
1622
|
compACTab = gCompACTab[componentID];
|
| XkLi |
0:c546b51ecf0b
|
1623
|
|
| XkLi |
0:c546b51ecf0b
|
1624
|
for (k = 1; k < 64; k++)
|
| XkLi |
0:c546b51ecf0b
|
1625
|
{
|
| XkLi |
0:c546b51ecf0b
|
1626
|
uint16 extraBits;
|
| XkLi |
0:c546b51ecf0b
|
1627
|
|
| XkLi |
0:c546b51ecf0b
|
1628
|
s = huffDecode(compACTab ? &gHuffTab3 : &gHuffTab2, compACTab ? gHuffVal3 : gHuffVal2);
|
| XkLi |
0:c546b51ecf0b
|
1629
|
|
| XkLi |
0:c546b51ecf0b
|
1630
|
extraBits = 0;
|
| XkLi |
0:c546b51ecf0b
|
1631
|
numExtraBits = s & 0xF;
|
| XkLi |
0:c546b51ecf0b
|
1632
|
if (numExtraBits)
|
| XkLi |
0:c546b51ecf0b
|
1633
|
extraBits = getBits2(numExtraBits);
|
| XkLi |
0:c546b51ecf0b
|
1634
|
|
| XkLi |
0:c546b51ecf0b
|
1635
|
r = s >> 4;
|
| XkLi |
0:c546b51ecf0b
|
1636
|
s &= 15;
|
| XkLi |
0:c546b51ecf0b
|
1637
|
|
| XkLi |
0:c546b51ecf0b
|
1638
|
if (s)
|
| XkLi |
0:c546b51ecf0b
|
1639
|
{
|
| XkLi |
0:c546b51ecf0b
|
1640
|
int16 ac;
|
| XkLi |
0:c546b51ecf0b
|
1641
|
|
| XkLi |
0:c546b51ecf0b
|
1642
|
if (r)
|
| XkLi |
0:c546b51ecf0b
|
1643
|
{
|
| XkLi |
0:c546b51ecf0b
|
1644
|
if ((k + r) > 63)
|
| XkLi |
0:c546b51ecf0b
|
1645
|
return PJPG_DECODE_ERROR;
|
| XkLi |
0:c546b51ecf0b
|
1646
|
|
| XkLi |
0:c546b51ecf0b
|
1647
|
while (r)
|
| XkLi |
0:c546b51ecf0b
|
1648
|
{
|
| XkLi |
0:c546b51ecf0b
|
1649
|
gCoeffBuf[ZAG[k++]] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1650
|
r--;
|
| XkLi |
0:c546b51ecf0b
|
1651
|
}
|
| XkLi |
0:c546b51ecf0b
|
1652
|
}
|
| XkLi |
0:c546b51ecf0b
|
1653
|
|
| XkLi |
0:c546b51ecf0b
|
1654
|
ac = huffExtend(extraBits, s);
|
| XkLi |
0:c546b51ecf0b
|
1655
|
|
| XkLi |
0:c546b51ecf0b
|
1656
|
gCoeffBuf[ZAG[k]] = ac * pQ[k];
|
| XkLi |
0:c546b51ecf0b
|
1657
|
}
|
| XkLi |
0:c546b51ecf0b
|
1658
|
else
|
| XkLi |
0:c546b51ecf0b
|
1659
|
{
|
| XkLi |
0:c546b51ecf0b
|
1660
|
if (r == 15)
|
| XkLi |
0:c546b51ecf0b
|
1661
|
{
|
| XkLi |
0:c546b51ecf0b
|
1662
|
if ((k + 16) > 64)
|
| XkLi |
0:c546b51ecf0b
|
1663
|
return PJPG_DECODE_ERROR;
|
| XkLi |
0:c546b51ecf0b
|
1664
|
|
| XkLi |
0:c546b51ecf0b
|
1665
|
for (r = 16; r > 0; r--)
|
| XkLi |
0:c546b51ecf0b
|
1666
|
gCoeffBuf[ZAG[k++]] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1667
|
|
| XkLi |
0:c546b51ecf0b
|
1668
|
k--; // - 1 because the loop counter is k
|
| XkLi |
0:c546b51ecf0b
|
1669
|
}
|
| XkLi |
0:c546b51ecf0b
|
1670
|
else
|
| XkLi |
0:c546b51ecf0b
|
1671
|
break;
|
| XkLi |
0:c546b51ecf0b
|
1672
|
}
|
| XkLi |
0:c546b51ecf0b
|
1673
|
}
|
| XkLi |
0:c546b51ecf0b
|
1674
|
|
| XkLi |
0:c546b51ecf0b
|
1675
|
while (k < 64)
|
| XkLi |
0:c546b51ecf0b
|
1676
|
gCoeffBuf[ZAG[k++]] = 0;
|
| XkLi |
0:c546b51ecf0b
|
1677
|
|
| XkLi |
0:c546b51ecf0b
|
1678
|
transformBlock(mcuBlock);
|
| XkLi |
0:c546b51ecf0b
|
1679
|
}
|
| XkLi |
0:c546b51ecf0b
|
1680
|
|
| XkLi |
0:c546b51ecf0b
|
1681
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1682
|
}
|
| XkLi |
0:c546b51ecf0b
|
1683
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
1684
|
unsigned char pjpeg_decode_mcu(void)
|
| XkLi |
0:c546b51ecf0b
|
1685
|
{
|
| XkLi |
0:c546b51ecf0b
|
1686
|
uint8 status;
|
| XkLi |
0:c546b51ecf0b
|
1687
|
|
| XkLi |
0:c546b51ecf0b
|
1688
|
if (!gNumMCUSRemaining)
|
| XkLi |
0:c546b51ecf0b
|
1689
|
return PJPG_NO_MORE_BLOCKS;
|
| XkLi |
0:c546b51ecf0b
|
1690
|
|
| XkLi |
0:c546b51ecf0b
|
1691
|
status = decodeNextMCU();
|
| XkLi |
0:c546b51ecf0b
|
1692
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1693
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1694
|
|
| XkLi |
0:c546b51ecf0b
|
1695
|
gNumMCUSRemaining--;
|
| XkLi |
0:c546b51ecf0b
|
1696
|
|
| XkLi |
0:c546b51ecf0b
|
1697
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1698
|
}
|
| XkLi |
0:c546b51ecf0b
|
1699
|
//------------------------------------------------------------------------------
|
| XkLi |
0:c546b51ecf0b
|
1700
|
unsigned char pjpeg_decode_init(pjpeg_image_info_t *pInfo, pjpeg_need_bytes_callback_t pNeed_bytes_callback, void *pCallback_data)
|
| XkLi |
0:c546b51ecf0b
|
1701
|
{
|
| XkLi |
0:c546b51ecf0b
|
1702
|
uint8 status;
|
| XkLi |
0:c546b51ecf0b
|
1703
|
|
| XkLi |
0:c546b51ecf0b
|
1704
|
g_pNeedBytesCallback = pNeed_bytes_callback;
|
| XkLi |
0:c546b51ecf0b
|
1705
|
g_pCallback_data = pCallback_data;
|
| XkLi |
0:c546b51ecf0b
|
1706
|
|
| XkLi |
0:c546b51ecf0b
|
1707
|
status = init();
|
| XkLi |
0:c546b51ecf0b
|
1708
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1709
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1710
|
|
| XkLi |
0:c546b51ecf0b
|
1711
|
status = locateSOFMarker();
|
| XkLi |
0:c546b51ecf0b
|
1712
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1713
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1714
|
|
| XkLi |
0:c546b51ecf0b
|
1715
|
status = initFrame();
|
| XkLi |
0:c546b51ecf0b
|
1716
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1717
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1718
|
|
| XkLi |
0:c546b51ecf0b
|
1719
|
status = initScan();
|
| XkLi |
0:c546b51ecf0b
|
1720
|
if (status)
|
| XkLi |
0:c546b51ecf0b
|
1721
|
return status;
|
| XkLi |
0:c546b51ecf0b
|
1722
|
|
| XkLi |
0:c546b51ecf0b
|
1723
|
pInfo->m_width = gImageXSize;
|
| XkLi |
0:c546b51ecf0b
|
1724
|
pInfo->m_height = gImageYSize;
|
| XkLi |
0:c546b51ecf0b
|
1725
|
pInfo->m_comps = gCompsInFrame;
|
| XkLi |
0:c546b51ecf0b
|
1726
|
pInfo->m_scanType = gScanType;
|
| XkLi |
0:c546b51ecf0b
|
1727
|
pInfo->m_MCUSPerRow = gMaxMCUSPerRow;
|
| XkLi |
0:c546b51ecf0b
|
1728
|
pInfo->m_MCUSPerCol = gMaxMCUSPerCol;
|
| XkLi |
0:c546b51ecf0b
|
1729
|
pInfo->m_MCUWidth = gMaxMCUXSize;
|
| XkLi |
0:c546b51ecf0b
|
1730
|
pInfo->m_MCUHeight = gMaxMCUYSize;
|
| XkLi |
0:c546b51ecf0b
|
1731
|
pInfo->m_pMCUBufR = gMCUBufR;
|
| XkLi |
0:c546b51ecf0b
|
1732
|
pInfo->m_pMCUBufG = gMCUBufG;
|
| XkLi |
0:c546b51ecf0b
|
1733
|
pInfo->m_pMCUBufB = gMCUBufB;
|
| XkLi |
0:c546b51ecf0b
|
1734
|
|
| XkLi |
0:c546b51ecf0b
|
1735
|
return 0;
|
| XkLi |
0:c546b51ecf0b
|
1736
|
}
|