Lines 1-1468
Link Here
|
1 |
--- ipelib/ipedct.cpp.orig |
|
|
2 |
+++ ipelib/ipedct.cpp |
3 |
@@ -0,0 +1,1465 @@ |
4 |
+//------------------------------------------------------------------------ |
5 |
+// Decoding a DCT stream (JPEG image) |
6 |
+// This code has been taken from Xpdf, |
7 |
+// Copyright 1996-2002 Glyph & Cog, LLC |
8 |
+//------------------------------------------------------------------------ |
9 |
+/* |
10 |
+ |
11 |
+ This file is part of the extensible drawing editor Ipe. |
12 |
+ Copyright (C) 1993-2013 Otfried Cheong |
13 |
+ |
14 |
+ Ipe is free software; you can redistribute it and/or modify it |
15 |
+ under the terms of the GNU General Public License as published by |
16 |
+ the Free Software Foundation; either version 3 of the License, or |
17 |
+ (at your option) any later version. |
18 |
+ |
19 |
+ As a special exception, you have permission to link Ipe with the |
20 |
+ CGAL library and distribute executables, as long as you follow the |
21 |
+ requirements of the Gnu General Public License in regard to all of |
22 |
+ the software in the executable aside from CGAL. |
23 |
+ |
24 |
+ Ipe is distributed in the hope that it will be useful, but WITHOUT |
25 |
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
26 |
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
27 |
+ License for more details. |
28 |
+ |
29 |
+ You should have received a copy of the GNU General Public License |
30 |
+ along with Ipe; if not, you can find it at |
31 |
+ "http://www.gnu.org/copyleft/gpl.html", or write to the Free |
32 |
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
33 |
+ |
34 |
+*/ |
35 |
+ |
36 |
+#include "ipebase.h" |
37 |
+ |
38 |
+using namespace ipe; |
39 |
+ |
40 |
+// -------------------------------------------------------------------- |
41 |
+ |
42 |
+// DCT component info |
43 |
+struct DCTCompInfo { |
44 |
+ int id; // component ID |
45 |
+ int hSample, vSample; // horiz/vert sampling resolutions |
46 |
+ int quantTable; // quantization table number |
47 |
+ int prevDC; // DC coefficient accumulator |
48 |
+}; |
49 |
+ |
50 |
+struct DCTScanInfo { |
51 |
+ bool comp[4]; // comp[i] is set if component i is |
52 |
+ // included in this scan |
53 |
+ int numComps; // number of components in the scan |
54 |
+ int dcHuffTable[4]; // DC Huffman table numbers |
55 |
+ int acHuffTable[4]; // AC Huffman table numbers |
56 |
+ int firstCoeff, lastCoeff; // first and last DCT coefficient |
57 |
+ int ah, al; // successive approximation parameters |
58 |
+}; |
59 |
+ |
60 |
+// DCT Huffman decoding table |
61 |
+struct DCTHuffTable { |
62 |
+ uchar firstSym[17]; // first symbol for this bit length |
63 |
+ ushort firstCode[17]; // first code for this bit length |
64 |
+ ushort numCodes[17]; // number of codes of this bit length |
65 |
+ uchar sym[256]; // symbols |
66 |
+}; |
67 |
+ |
68 |
+// -------------------------------------------------------------------- |
69 |
+ |
70 |
+class DCTStream { |
71 |
+public: |
72 |
+ |
73 |
+ DCTStream(DataSource &source); |
74 |
+ ~DCTStream(); |
75 |
+ void reset(); |
76 |
+ int getChar(); |
77 |
+ |
78 |
+private: |
79 |
+ DataSource &iSource; |
80 |
+ |
81 |
+ bool progressive; // set if in progressive mode |
82 |
+ bool interleaved; // set if in interleaved mode |
83 |
+ int width, height; // image size |
84 |
+ int mcuWidth, mcuHeight; // size of min coding unit, in data units |
85 |
+ int bufWidth, bufHeight; // frameBuf size |
86 |
+ DCTCompInfo compInfo[4]; // info for each component |
87 |
+ DCTScanInfo scanInfo; // info for the current scan |
88 |
+ int numComps; // number of components in image |
89 |
+ int colorXform; // need YCbCr-to-RGB transform? |
90 |
+ bool gotAdobeMarker; // set if APP14 Adobe marker was present |
91 |
+ int restartInterval; // restart interval, in MCUs |
92 |
+ uchar quantTables[4][64]; // quantization tables |
93 |
+ int numQuantTables; // number of quantization tables |
94 |
+ DCTHuffTable dcHuffTables[4]; // DC Huffman tables |
95 |
+ DCTHuffTable acHuffTables[4]; // AC Huffman tables |
96 |
+ int numDCHuffTables; // number of DC Huffman tables |
97 |
+ int numACHuffTables; // number of AC Huffman tables |
98 |
+ uchar *rowBuf[4][32]; // buffer for one MCU (non-progressive mode) |
99 |
+ int *frameBuf[4]; // buffer for frame (progressive mode) |
100 |
+ int comp, x, y, dy; // current position within image/MCU |
101 |
+ int restartCtr; // MCUs left until restart |
102 |
+ int restartMarker; // next restart marker |
103 |
+ int eobRun; // number of EOBs left in the current run |
104 |
+ int inputBuf; // input buffer for variable length codes |
105 |
+ int inputBits; // number of valid bits in input buffer |
106 |
+ |
107 |
+ void restart(); |
108 |
+ bool readMCURow(); |
109 |
+ void readScan(); |
110 |
+ bool readDataUnit(DCTHuffTable *dcHuffTable, |
111 |
+ DCTHuffTable *acHuffTable, |
112 |
+ int *prevDC, int data[64]); |
113 |
+ bool readProgressiveDataUnit(DCTHuffTable *dcHuffTable, |
114 |
+ DCTHuffTable *acHuffTable, |
115 |
+ int *prevDC, int data[64]); |
116 |
+ void decodeImage(); |
117 |
+ void transformDataUnit(uchar *quantTable, |
118 |
+ int dataIn[64], uchar dataOut[64]); |
119 |
+ int readHuffSym(DCTHuffTable *table); |
120 |
+ int readAmp(int size); |
121 |
+ int readBit(); |
122 |
+ bool readHeader(); |
123 |
+ bool readBaselineSOF(); |
124 |
+ bool readProgressiveSOF(); |
125 |
+ bool readScanInfo(); |
126 |
+ bool readQuantTables(); |
127 |
+ bool readHuffmanTables(); |
128 |
+ bool readRestartInterval(); |
129 |
+ bool readAdobeMarker(); |
130 |
+ bool readTrailer(); |
131 |
+ int readMarker(); |
132 |
+ int read16(); |
133 |
+}; |
134 |
+ |
135 |
+// -------------------------------------------------------------------- |
136 |
+ |
137 |
+// IDCT constants (20.12 fixed point format) |
138 |
+#define dctCos1 4017 // cos(pi/16) |
139 |
+#define dctSin1 799 // sin(pi/16) |
140 |
+#define dctCos3 3406 // cos(3*pi/16) |
141 |
+#define dctSin3 2276 // sin(3*pi/16) |
142 |
+#define dctCos6 1567 // cos(6*pi/16) |
143 |
+#define dctSin6 3784 // sin(6*pi/16) |
144 |
+#define dctSqrt2 5793 // sqrt(2) |
145 |
+#define dctSqrt1d2 2896 // sqrt(2) / 2 |
146 |
+ |
147 |
+// color conversion parameters (16.16 fixed point format) |
148 |
+#define dctCrToR 91881 // 1.4020 |
149 |
+#define dctCbToG -22553 // -0.3441363 |
150 |
+#define dctCrToG -46802 // -0.71413636 |
151 |
+#define dctCbToB 116130 // 1.772 |
152 |
+ |
153 |
+// clip [-256,511] --> [0,255] |
154 |
+#define dctClipOffset 256 |
155 |
+static uchar dctClip[768]; |
156 |
+static int dctClipInit = 0; |
157 |
+ |
158 |
+// zig zag decode map |
159 |
+static int dctZigZag[64] = { |
160 |
+ 0, |
161 |
+ 1, 8, |
162 |
+ 16, 9, 2, |
163 |
+ 3, 10, 17, 24, |
164 |
+ 32, 25, 18, 11, 4, |
165 |
+ 5, 12, 19, 26, 33, 40, |
166 |
+ 48, 41, 34, 27, 20, 13, 6, |
167 |
+ 7, 14, 21, 28, 35, 42, 49, 56, |
168 |
+ 57, 50, 43, 36, 29, 22, 15, |
169 |
+ 23, 30, 37, 44, 51, 58, |
170 |
+ 59, 52, 45, 38, 31, |
171 |
+ 39, 46, 53, 60, |
172 |
+ 61, 54, 47, |
173 |
+ 55, 62, |
174 |
+ 63 |
175 |
+}; |
176 |
+ |
177 |
+// -------------------------------------------------------------------- |
178 |
+ |
179 |
+DCTStream::DCTStream(DataSource &source) |
180 |
+ : iSource(source) |
181 |
+{ |
182 |
+ int i, j; |
183 |
+ |
184 |
+ progressive = interleaved = false; |
185 |
+ width = height = 0; |
186 |
+ mcuWidth = mcuHeight = 0; |
187 |
+ numComps = 0; |
188 |
+ comp = 0; |
189 |
+ x = y = dy = 0; |
190 |
+ for (i = 0; i < 4; ++i) { |
191 |
+ for (j = 0; j < 32; ++j) { |
192 |
+ rowBuf[i][j] = 0; |
193 |
+ } |
194 |
+ frameBuf[i] = 0; |
195 |
+ } |
196 |
+ |
197 |
+ if (!dctClipInit) { |
198 |
+ for (i = -256; i < 0; ++i) |
199 |
+ dctClip[dctClipOffset + i] = 0; |
200 |
+ for (i = 0; i < 256; ++i) |
201 |
+ dctClip[dctClipOffset + i] = uchar(i); |
202 |
+ for (i = 256; i < 512; ++i) |
203 |
+ dctClip[dctClipOffset + i] = 255; |
204 |
+ dctClipInit = 1; |
205 |
+ } |
206 |
+} |
207 |
+ |
208 |
+DCTStream::~DCTStream() |
209 |
+{ |
210 |
+ int i, j; |
211 |
+ if (progressive || !interleaved) { |
212 |
+ for (i = 0; i < numComps; ++i) { |
213 |
+ delete [] frameBuf[i]; |
214 |
+ } |
215 |
+ } else { |
216 |
+ for (i = 0; i < numComps; ++i) { |
217 |
+ for (j = 0; j < mcuHeight; ++j) { |
218 |
+ delete [] rowBuf[i][j]; |
219 |
+ } |
220 |
+ } |
221 |
+ } |
222 |
+} |
223 |
+ |
224 |
+void DCTStream::reset() |
225 |
+{ |
226 |
+ int minHSample, minVSample; |
227 |
+ int i, j; |
228 |
+ |
229 |
+ progressive = interleaved = false; |
230 |
+ width = height = 0; |
231 |
+ numComps = 0; |
232 |
+ numQuantTables = 0; |
233 |
+ numDCHuffTables = 0; |
234 |
+ numACHuffTables = 0; |
235 |
+ colorXform = 0; |
236 |
+ gotAdobeMarker = false; |
237 |
+ restartInterval = 0; |
238 |
+ |
239 |
+ if (!readHeader()) { |
240 |
+ y = height; |
241 |
+ return; |
242 |
+ } |
243 |
+ |
244 |
+ // compute MCU size |
245 |
+ mcuWidth = minHSample = compInfo[0].hSample; |
246 |
+ mcuHeight = minVSample = compInfo[0].vSample; |
247 |
+ for (i = 1; i < numComps; ++i) { |
248 |
+ if (compInfo[i].hSample < minHSample) |
249 |
+ minHSample = compInfo[i].hSample; |
250 |
+ if (compInfo[i].vSample < minVSample) |
251 |
+ minVSample = compInfo[i].vSample; |
252 |
+ if (compInfo[i].hSample > mcuWidth) |
253 |
+ mcuWidth = compInfo[i].hSample; |
254 |
+ if (compInfo[i].vSample > mcuHeight) |
255 |
+ mcuHeight = compInfo[i].vSample; |
256 |
+ } |
257 |
+ for (i = 0; i < numComps; ++i) { |
258 |
+ compInfo[i].hSample /= minHSample; |
259 |
+ compInfo[i].vSample /= minVSample; |
260 |
+ } |
261 |
+ mcuWidth = (mcuWidth / minHSample) * 8; |
262 |
+ mcuHeight = (mcuHeight / minVSample) * 8; |
263 |
+ |
264 |
+ // figure out color transform |
265 |
+ if (!gotAdobeMarker && numComps == 3) { |
266 |
+ if (compInfo[0].id == 1 && compInfo[1].id == 2 && compInfo[2].id == 3) { |
267 |
+ colorXform = 1; |
268 |
+ } |
269 |
+ } |
270 |
+ |
271 |
+ if (progressive || !interleaved) { |
272 |
+ |
273 |
+ // allocate a buffer for the whole image |
274 |
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; |
275 |
+ bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; |
276 |
+ for (i = 0; i < numComps; ++i) { |
277 |
+ frameBuf[i] = new int[bufWidth * bufHeight]; |
278 |
+ memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); |
279 |
+ } |
280 |
+ |
281 |
+ // read the image data |
282 |
+ do { |
283 |
+ restartMarker = 0xd0; |
284 |
+ restart(); |
285 |
+ readScan(); |
286 |
+ } while (readHeader()); |
287 |
+ |
288 |
+ // decode |
289 |
+ decodeImage(); |
290 |
+ |
291 |
+ // initialize counters |
292 |
+ comp = 0; |
293 |
+ x = 0; |
294 |
+ y = 0; |
295 |
+ |
296 |
+ } else { |
297 |
+ |
298 |
+ // allocate a buffer for one row of MCUs |
299 |
+ bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; |
300 |
+ for (i = 0; i < numComps; ++i) { |
301 |
+ for (j = 0; j < mcuHeight; ++j) { |
302 |
+ rowBuf[i][j] = new uchar[bufWidth]; |
303 |
+ } |
304 |
+ } |
305 |
+ |
306 |
+ // initialize counters |
307 |
+ comp = 0; |
308 |
+ x = 0; |
309 |
+ y = 0; |
310 |
+ dy = mcuHeight; |
311 |
+ |
312 |
+ restartMarker = 0xd0; |
313 |
+ restart(); |
314 |
+ } |
315 |
+} |
316 |
+ |
317 |
+int DCTStream::getChar() |
318 |
+{ |
319 |
+ int c; |
320 |
+ |
321 |
+ if (y >= height) { |
322 |
+ return EOF; |
323 |
+ } |
324 |
+ if (progressive || !interleaved) { |
325 |
+ c = frameBuf[comp][y * bufWidth + x]; |
326 |
+ if (++comp == numComps) { |
327 |
+ comp = 0; |
328 |
+ if (++x == width) { |
329 |
+ x = 0; |
330 |
+ ++y; |
331 |
+ } |
332 |
+ } |
333 |
+ } else { |
334 |
+ if (dy >= mcuHeight) { |
335 |
+ if (!readMCURow()) { |
336 |
+ y = height; |
337 |
+ return EOF; |
338 |
+ } |
339 |
+ comp = 0; |
340 |
+ x = 0; |
341 |
+ dy = 0; |
342 |
+ } |
343 |
+ c = rowBuf[comp][dy][x]; |
344 |
+ if (++comp == numComps) { |
345 |
+ comp = 0; |
346 |
+ if (++x == width) { |
347 |
+ x = 0; |
348 |
+ ++y; |
349 |
+ ++dy; |
350 |
+ if (y == height) { |
351 |
+ readTrailer(); |
352 |
+ } |
353 |
+ } |
354 |
+ } |
355 |
+ } |
356 |
+ return c; |
357 |
+} |
358 |
+ |
359 |
+void DCTStream::restart() |
360 |
+{ |
361 |
+ int i; |
362 |
+ |
363 |
+ inputBits = 0; |
364 |
+ restartCtr = restartInterval; |
365 |
+ for (i = 0; i < numComps; ++i) { |
366 |
+ compInfo[i].prevDC = 0; |
367 |
+ } |
368 |
+ eobRun = 0; |
369 |
+} |
370 |
+ |
371 |
+// Read one row of MCUs from a sequential JPEG stream. |
372 |
+bool DCTStream::readMCURow() |
373 |
+{ |
374 |
+ int data1[64]; |
375 |
+ uchar data2[64]; |
376 |
+ uchar *p1, *p2; |
377 |
+ int pY, pCb, pCr, pR, pG, pB; |
378 |
+ int h, v, horiz, vert, hSub, vSub; |
379 |
+ int x1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; |
380 |
+ int c; |
381 |
+ |
382 |
+ for (x1 = 0; x1 < width; x1 += mcuWidth) { |
383 |
+ |
384 |
+ // deal with restart marker |
385 |
+ if (restartInterval > 0 && restartCtr == 0) { |
386 |
+ c = readMarker(); |
387 |
+ if (c != restartMarker) { |
388 |
+ ipeDebug("Bad DCT data: incorrect restart marker"); |
389 |
+ return false; |
390 |
+ } |
391 |
+ if (++restartMarker == 0xd8) |
392 |
+ restartMarker = 0xd0; |
393 |
+ restart(); |
394 |
+ } |
395 |
+ |
396 |
+ // read one MCU |
397 |
+ for (cc = 0; cc < numComps; ++cc) { |
398 |
+ h = compInfo[cc].hSample; |
399 |
+ v = compInfo[cc].vSample; |
400 |
+ horiz = mcuWidth / h; |
401 |
+ vert = mcuHeight / v; |
402 |
+ hSub = horiz / 8; |
403 |
+ vSub = vert / 8; |
404 |
+ for (y2 = 0; y2 < mcuHeight; y2 += vert) { |
405 |
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) { |
406 |
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], |
407 |
+ &acHuffTables[scanInfo.acHuffTable[cc]], |
408 |
+ &compInfo[cc].prevDC, |
409 |
+ data1)) { |
410 |
+ return false; |
411 |
+ } |
412 |
+ transformDataUnit(quantTables[compInfo[cc].quantTable], |
413 |
+ data1, data2); |
414 |
+ if (hSub == 1 && vSub == 1) { |
415 |
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { |
416 |
+ p1 = &rowBuf[cc][y2+y3][x1+x2]; |
417 |
+ p1[0] = data2[i]; |
418 |
+ p1[1] = data2[i+1]; |
419 |
+ p1[2] = data2[i+2]; |
420 |
+ p1[3] = data2[i+3]; |
421 |
+ p1[4] = data2[i+4]; |
422 |
+ p1[5] = data2[i+5]; |
423 |
+ p1[6] = data2[i+6]; |
424 |
+ p1[7] = data2[i+7]; |
425 |
+ } |
426 |
+ } else if (hSub == 2 && vSub == 2) { |
427 |
+ for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { |
428 |
+ p1 = &rowBuf[cc][y2+y3][x1+x2]; |
429 |
+ p2 = &rowBuf[cc][y2+y3+1][x1+x2]; |
430 |
+ p1[0] = p1[1] = p2[0] = p2[1] = data2[i]; |
431 |
+ p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1]; |
432 |
+ p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2]; |
433 |
+ p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3]; |
434 |
+ p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4]; |
435 |
+ p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5]; |
436 |
+ p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6]; |
437 |
+ p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7]; |
438 |
+ } |
439 |
+ } else { |
440 |
+ i = 0; |
441 |
+ for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { |
442 |
+ for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { |
443 |
+ for (y5 = 0; y5 < vSub; ++y5) |
444 |
+ for (x5 = 0; x5 < hSub; ++x5) |
445 |
+ rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i]; |
446 |
+ ++i; |
447 |
+ } |
448 |
+ } |
449 |
+ } |
450 |
+ } |
451 |
+ } |
452 |
+ } |
453 |
+ --restartCtr; |
454 |
+ |
455 |
+ // color space conversion |
456 |
+ if (colorXform) { |
457 |
+ // convert YCbCr to RGB |
458 |
+ if (numComps == 3) { |
459 |
+ for (y2 = 0; y2 < mcuHeight; ++y2) { |
460 |
+ for (x2 = 0; x2 < mcuWidth; ++x2) { |
461 |
+ pY = rowBuf[0][y2][x1+x2]; |
462 |
+ pCb = rowBuf[1][y2][x1+x2] - 128; |
463 |
+ pCr = rowBuf[2][y2][x1+x2] - 128; |
464 |
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; |
465 |
+ rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR]; |
466 |
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; |
467 |
+ rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG]; |
468 |
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; |
469 |
+ rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB]; |
470 |
+ } |
471 |
+ } |
472 |
+ // convert YCbCrK to CMYK (K is passed through unchanged) |
473 |
+ } else if (numComps == 4) { |
474 |
+ for (y2 = 0; y2 < mcuHeight; ++y2) { |
475 |
+ for (x2 = 0; x2 < mcuWidth; ++x2) { |
476 |
+ pY = rowBuf[0][y2][x1+x2]; |
477 |
+ pCb = rowBuf[1][y2][x1+x2] - 128; |
478 |
+ pCr = rowBuf[2][y2][x1+x2] - 128; |
479 |
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; |
480 |
+ rowBuf[0][y2][x1+x2] = uchar(255 - dctClip[dctClipOffset + pR]); |
481 |
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; |
482 |
+ rowBuf[1][y2][x1+x2] = uchar(255 - dctClip[dctClipOffset + pG]); |
483 |
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; |
484 |
+ rowBuf[2][y2][x1+x2] = uchar(255 - dctClip[dctClipOffset + pB]); |
485 |
+ } |
486 |
+ } |
487 |
+ } |
488 |
+ } |
489 |
+ } |
490 |
+ return true; |
491 |
+} |
492 |
+ |
493 |
+// Read one scan from a progressive or non-interleaved JPEG stream. |
494 |
+void DCTStream::readScan() |
495 |
+{ |
496 |
+ int data[64]; |
497 |
+ int x1, y1, dy1, x2, y2, y3, cc, i; |
498 |
+ int h, v, horiz, vert, vSub; |
499 |
+ int *p1; |
500 |
+ int c; |
501 |
+ |
502 |
+ if (scanInfo.numComps == 1) { |
503 |
+ for (cc = 0; cc < numComps; ++cc) { |
504 |
+ if (scanInfo.comp[cc]) { |
505 |
+ break; |
506 |
+ } |
507 |
+ } |
508 |
+ dy1 = mcuHeight / compInfo[cc].vSample; |
509 |
+ } else { |
510 |
+ dy1 = mcuHeight; |
511 |
+ } |
512 |
+ |
513 |
+ for (y1 = 0; y1 < bufHeight; y1 += dy1) { |
514 |
+ for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) { |
515 |
+ |
516 |
+ // deal with restart marker |
517 |
+ if (restartInterval > 0 && restartCtr == 0) { |
518 |
+ c = readMarker(); |
519 |
+ if (c != restartMarker) { |
520 |
+ ipeDebug("Bad DCT data: incorrect restart marker"); |
521 |
+ return; |
522 |
+ } |
523 |
+ if (++restartMarker == 0xd8) { |
524 |
+ restartMarker = 0xd0; |
525 |
+ } |
526 |
+ restart(); |
527 |
+ } |
528 |
+ |
529 |
+ // read one MCU |
530 |
+ for (cc = 0; cc < numComps; ++cc) { |
531 |
+ if (!scanInfo.comp[cc]) { |
532 |
+ continue; |
533 |
+ } |
534 |
+ |
535 |
+ h = compInfo[cc].hSample; |
536 |
+ v = compInfo[cc].vSample; |
537 |
+ horiz = mcuWidth / h; |
538 |
+ vert = mcuHeight / v; |
539 |
+ // hSub = horiz / 8; |
540 |
+ vSub = vert / 8; |
541 |
+ for (y2 = 0; y2 < dy1; y2 += vert) { |
542 |
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) { |
543 |
+ |
544 |
+ // pull out the current values |
545 |
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; |
546 |
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { |
547 |
+ data[i] = p1[0]; |
548 |
+ data[i+1] = p1[1]; |
549 |
+ data[i+2] = p1[2]; |
550 |
+ data[i+3] = p1[3]; |
551 |
+ data[i+4] = p1[4]; |
552 |
+ data[i+5] = p1[5]; |
553 |
+ data[i+6] = p1[6]; |
554 |
+ data[i+7] = p1[7]; |
555 |
+ p1 += bufWidth * vSub; |
556 |
+ } |
557 |
+ |
558 |
+ // read one data unit |
559 |
+ if (progressive) { |
560 |
+ if (!readProgressiveDataUnit( |
561 |
+ &dcHuffTables[scanInfo.dcHuffTable[cc]], |
562 |
+ &acHuffTables[scanInfo.acHuffTable[cc]], |
563 |
+ &compInfo[cc].prevDC, |
564 |
+ data)) { |
565 |
+ return; |
566 |
+ } |
567 |
+ } else { |
568 |
+ if (!readDataUnit(&dcHuffTables[scanInfo.dcHuffTable[cc]], |
569 |
+ &acHuffTables[scanInfo.acHuffTable[cc]], |
570 |
+ &compInfo[cc].prevDC, |
571 |
+ data)) { |
572 |
+ return; |
573 |
+ } |
574 |
+ } |
575 |
+ |
576 |
+ // add the data unit into frameBuf |
577 |
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; |
578 |
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { |
579 |
+ p1[0] = data[i]; |
580 |
+ p1[1] = data[i+1]; |
581 |
+ p1[2] = data[i+2]; |
582 |
+ p1[3] = data[i+3]; |
583 |
+ p1[4] = data[i+4]; |
584 |
+ p1[5] = data[i+5]; |
585 |
+ p1[6] = data[i+6]; |
586 |
+ p1[7] = data[i+7]; |
587 |
+ p1 += bufWidth * vSub; |
588 |
+ } |
589 |
+ } |
590 |
+ } |
591 |
+ } |
592 |
+ --restartCtr; |
593 |
+ } |
594 |
+ } |
595 |
+} |
596 |
+ |
597 |
+// Read one data unit from a sequential JPEG stream. |
598 |
+bool DCTStream::readDataUnit(DCTHuffTable *dcHuffTable, |
599 |
+ DCTHuffTable *acHuffTable, |
600 |
+ int *prevDC, int data[64]) |
601 |
+{ |
602 |
+ int run, size, amp; |
603 |
+ int c; |
604 |
+ int i, j; |
605 |
+ |
606 |
+ if ((size = readHuffSym(dcHuffTable)) == 9999) { |
607 |
+ return false; |
608 |
+ } |
609 |
+ if (size > 0) { |
610 |
+ if ((amp = readAmp(size)) == 9999) { |
611 |
+ return false; |
612 |
+ } |
613 |
+ } else { |
614 |
+ amp = 0; |
615 |
+ } |
616 |
+ data[0] = *prevDC += amp; |
617 |
+ for (i = 1; i < 64; ++i) { |
618 |
+ data[i] = 0; |
619 |
+ } |
620 |
+ i = 1; |
621 |
+ while (i < 64) { |
622 |
+ run = 0; |
623 |
+ while ((c = readHuffSym(acHuffTable)) == 0xf0 && run < 0x30) { |
624 |
+ run += 0x10; |
625 |
+ } |
626 |
+ if (c == 9999) { |
627 |
+ return false; |
628 |
+ } |
629 |
+ if (c == 0x00) { |
630 |
+ break; |
631 |
+ } else { |
632 |
+ run += (c >> 4) & 0x0f; |
633 |
+ size = c & 0x0f; |
634 |
+ amp = readAmp(size); |
635 |
+ if (amp == 9999) { |
636 |
+ return false; |
637 |
+ } |
638 |
+ i += run; |
639 |
+ j = dctZigZag[i++]; |
640 |
+ data[j] = amp; |
641 |
+ } |
642 |
+ } |
643 |
+ return true; |
644 |
+} |
645 |
+ |
646 |
+// Read one data unit from a sequential JPEG stream. |
647 |
+bool DCTStream::readProgressiveDataUnit(DCTHuffTable *dcHuffTable, |
648 |
+ DCTHuffTable *acHuffTable, |
649 |
+ int *prevDC, int data[64]) |
650 |
+{ |
651 |
+ int run, size, amp, bit, c; |
652 |
+ int i, j, k; |
653 |
+ |
654 |
+ // get the DC coefficient |
655 |
+ i = scanInfo.firstCoeff; |
656 |
+ if (i == 0) { |
657 |
+ if (scanInfo.ah == 0) { |
658 |
+ if ((size = readHuffSym(dcHuffTable)) == 9999) { |
659 |
+ return false; |
660 |
+ } |
661 |
+ if (size > 0) { |
662 |
+ if ((amp = readAmp(size)) == 9999) { |
663 |
+ return false; |
664 |
+ } |
665 |
+ } else { |
666 |
+ amp = 0; |
667 |
+ } |
668 |
+ data[0] += (*prevDC += amp) << scanInfo.al; |
669 |
+ } else { |
670 |
+ if ((bit = readBit()) == 9999) { |
671 |
+ return false; |
672 |
+ } |
673 |
+ data[0] += bit << scanInfo.al; |
674 |
+ } |
675 |
+ ++i; |
676 |
+ } |
677 |
+ if (scanInfo.lastCoeff == 0) { |
678 |
+ return true; |
679 |
+ } |
680 |
+ |
681 |
+ // check for an EOB run |
682 |
+ if (eobRun > 0) { |
683 |
+ while (i <= scanInfo.lastCoeff) { |
684 |
+ j = dctZigZag[i++]; |
685 |
+ if (data[j] != 0) { |
686 |
+ if ((bit = readBit()) == EOF) { |
687 |
+ return false; |
688 |
+ } |
689 |
+ if (bit) { |
690 |
+ data[j] += 1 << scanInfo.al; |
691 |
+ } |
692 |
+ } |
693 |
+ } |
694 |
+ --eobRun; |
695 |
+ return true; |
696 |
+ } |
697 |
+ |
698 |
+ // read the AC coefficients |
699 |
+ while (i <= scanInfo.lastCoeff) { |
700 |
+ if ((c = readHuffSym(acHuffTable)) == 9999) { |
701 |
+ return false; |
702 |
+ } |
703 |
+ |
704 |
+ // ZRL |
705 |
+ if (c == 0xf0) { |
706 |
+ k = 0; |
707 |
+ while (k < 16) { |
708 |
+ j = dctZigZag[i++]; |
709 |
+ if (data[j] == 0) { |
710 |
+ ++k; |
711 |
+ } else { |
712 |
+ if ((bit = readBit()) == EOF) { |
713 |
+ return false; |
714 |
+ } |
715 |
+ if (bit) { |
716 |
+ data[j] += 1 << scanInfo.al; |
717 |
+ } |
718 |
+ } |
719 |
+ } |
720 |
+ |
721 |
+ // EOB run |
722 |
+ } else if ((c & 0x0f) == 0x00) { |
723 |
+ j = c >> 4; |
724 |
+ eobRun = 0; |
725 |
+ for (k = 0; k < j; ++k) { |
726 |
+ if ((bit = readBit()) == EOF) { |
727 |
+ return 9999; |
728 |
+ } |
729 |
+ eobRun = (eobRun << 1) | bit; |
730 |
+ } |
731 |
+ eobRun += 1 << j; |
732 |
+ while (i <= scanInfo.lastCoeff) { |
733 |
+ j = dctZigZag[i++]; |
734 |
+ if (data[j] != 0) { |
735 |
+ if ((bit = readBit()) == EOF) { |
736 |
+ return false; |
737 |
+ } |
738 |
+ if (bit) { |
739 |
+ data[j] += 1 << scanInfo.al; |
740 |
+ } |
741 |
+ } |
742 |
+ } |
743 |
+ --eobRun; |
744 |
+ break; |
745 |
+ |
746 |
+ // zero run and one AC coefficient |
747 |
+ } else { |
748 |
+ run = (c >> 4) & 0x0f; |
749 |
+ size = c & 0x0f; |
750 |
+ if ((amp = readAmp(size)) == 9999) { |
751 |
+ return false; |
752 |
+ } |
753 |
+ k = 0; |
754 |
+ do { |
755 |
+ j = dctZigZag[i++]; |
756 |
+ while (data[j] != 0) { |
757 |
+ if ((bit = readBit()) == EOF) { |
758 |
+ return false; |
759 |
+ } |
760 |
+ if (bit) { |
761 |
+ data[j] += 1 << scanInfo.al; |
762 |
+ } |
763 |
+ j = dctZigZag[i++]; |
764 |
+ } |
765 |
+ ++k; |
766 |
+ } while (k <= run); |
767 |
+ data[j] = amp << scanInfo.al; |
768 |
+ } |
769 |
+ } |
770 |
+ |
771 |
+ return true; |
772 |
+} |
773 |
+ |
774 |
+// Decode a progressive JPEG image. |
775 |
+void DCTStream::decodeImage() |
776 |
+{ |
777 |
+ int dataIn[64]; |
778 |
+ uchar dataOut[64]; |
779 |
+ uchar *quantTable; |
780 |
+ int pY, pCb, pCr, pR, pG, pB; |
781 |
+ int x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, cc, i; |
782 |
+ int h, v, horiz, vert, hSub, vSub; |
783 |
+ int *p0, *p1, *p2; |
784 |
+ |
785 |
+ for (y1 = 0; y1 < bufHeight; y1 += mcuHeight) { |
786 |
+ for (x1 = 0; x1 < bufWidth; x1 += mcuWidth) { |
787 |
+ for (cc = 0; cc < numComps; ++cc) { |
788 |
+ quantTable = quantTables[compInfo[cc].quantTable]; |
789 |
+ h = compInfo[cc].hSample; |
790 |
+ v = compInfo[cc].vSample; |
791 |
+ horiz = mcuWidth / h; |
792 |
+ vert = mcuHeight / v; |
793 |
+ hSub = horiz / 8; |
794 |
+ vSub = vert / 8; |
795 |
+ for (y2 = 0; y2 < mcuHeight; y2 += vert) { |
796 |
+ for (x2 = 0; x2 < mcuWidth; x2 += horiz) { |
797 |
+ |
798 |
+ // pull out the coded data unit |
799 |
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; |
800 |
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { |
801 |
+ dataIn[i] = p1[0]; |
802 |
+ dataIn[i+1] = p1[1]; |
803 |
+ dataIn[i+2] = p1[2]; |
804 |
+ dataIn[i+3] = p1[3]; |
805 |
+ dataIn[i+4] = p1[4]; |
806 |
+ dataIn[i+5] = p1[5]; |
807 |
+ dataIn[i+6] = p1[6]; |
808 |
+ dataIn[i+7] = p1[7]; |
809 |
+ p1 += bufWidth * vSub; |
810 |
+ } |
811 |
+ |
812 |
+ // transform |
813 |
+ transformDataUnit(quantTable, dataIn, dataOut); |
814 |
+ |
815 |
+ // store back into frameBuf, doing replication for |
816 |
+ // subsampled components |
817 |
+ p1 = &frameBuf[cc][(y1+y2) * bufWidth + (x1+x2)]; |
818 |
+ if (hSub == 1 && vSub == 1) { |
819 |
+ for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { |
820 |
+ p1[0] = dataOut[i] & 0xff; |
821 |
+ p1[1] = dataOut[i+1] & 0xff; |
822 |
+ p1[2] = dataOut[i+2] & 0xff; |
823 |
+ p1[3] = dataOut[i+3] & 0xff; |
824 |
+ p1[4] = dataOut[i+4] & 0xff; |
825 |
+ p1[5] = dataOut[i+5] & 0xff; |
826 |
+ p1[6] = dataOut[i+6] & 0xff; |
827 |
+ p1[7] = dataOut[i+7] & 0xff; |
828 |
+ p1 += bufWidth; |
829 |
+ } |
830 |
+ } else if (hSub == 2 && vSub == 2) { |
831 |
+ p2 = p1 + bufWidth; |
832 |
+ for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { |
833 |
+ p1[0] = p1[1] = p2[0] = p2[1] = dataOut[i] & 0xff; |
834 |
+ p1[2] = p1[3] = p2[2] = p2[3] = dataOut[i+1] & 0xff; |
835 |
+ p1[4] = p1[5] = p2[4] = p2[5] = dataOut[i+2] & 0xff; |
836 |
+ p1[6] = p1[7] = p2[6] = p2[7] = dataOut[i+3] & 0xff; |
837 |
+ p1[8] = p1[9] = p2[8] = p2[9] = dataOut[i+4] & 0xff; |
838 |
+ p1[10] = p1[11] = p2[10] = p2[11] = dataOut[i+5] & 0xff; |
839 |
+ p1[12] = p1[13] = p2[12] = p2[13] = dataOut[i+6] & 0xff; |
840 |
+ p1[14] = p1[15] = p2[14] = p2[15] = dataOut[i+7] & 0xff; |
841 |
+ p1 += bufWidth * 2; |
842 |
+ p2 += bufWidth * 2; |
843 |
+ } |
844 |
+ } else { |
845 |
+ i = 0; |
846 |
+ for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { |
847 |
+ for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { |
848 |
+ p2 = p1 + x4; |
849 |
+ for (y5 = 0; y5 < vSub; ++y5) { |
850 |
+ for (x5 = 0; x5 < hSub; ++x5) { |
851 |
+ p2[x5] = dataOut[i] & 0xff; |
852 |
+ } |
853 |
+ p2 += bufWidth; |
854 |
+ } |
855 |
+ ++i; |
856 |
+ } |
857 |
+ p1 += bufWidth * vSub; |
858 |
+ } |
859 |
+ } |
860 |
+ } |
861 |
+ } |
862 |
+ } |
863 |
+ |
864 |
+ // color space conversion |
865 |
+ if (colorXform) { |
866 |
+ // convert YCbCr to RGB |
867 |
+ if (numComps == 3) { |
868 |
+ for (y2 = 0; y2 < mcuHeight; ++y2) { |
869 |
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; |
870 |
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; |
871 |
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; |
872 |
+ for (x2 = 0; x2 < mcuWidth; ++x2) { |
873 |
+ pY = *p0; |
874 |
+ pCb = *p1 - 128; |
875 |
+ pCr = *p2 - 128; |
876 |
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; |
877 |
+ *p0++ = dctClip[dctClipOffset + pR]; |
878 |
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + |
879 |
+ 32768) >> 16; |
880 |
+ *p1++ = dctClip[dctClipOffset + pG]; |
881 |
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; |
882 |
+ *p2++ = dctClip[dctClipOffset + pB]; |
883 |
+ } |
884 |
+ } |
885 |
+ // convert YCbCrK to CMYK (K is passed through unchanged) |
886 |
+ } else if (numComps == 4) { |
887 |
+ for (y2 = 0; y2 < mcuHeight; ++y2) { |
888 |
+ p0 = &frameBuf[0][(y1+y2) * bufWidth + x1]; |
889 |
+ p1 = &frameBuf[1][(y1+y2) * bufWidth + x1]; |
890 |
+ p2 = &frameBuf[2][(y1+y2) * bufWidth + x1]; |
891 |
+ for (x2 = 0; x2 < mcuWidth; ++x2) { |
892 |
+ pY = *p0; |
893 |
+ pCb = *p1 - 128; |
894 |
+ pCr = *p2 - 128; |
895 |
+ pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; |
896 |
+ *p0++ = 255 - dctClip[dctClipOffset + pR]; |
897 |
+ pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + |
898 |
+ 32768) >> 16; |
899 |
+ *p1++ = 255 - dctClip[dctClipOffset + pG]; |
900 |
+ pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; |
901 |
+ *p2++ = 255 - dctClip[dctClipOffset + pB]; |
902 |
+ } |
903 |
+ } |
904 |
+ } |
905 |
+ } |
906 |
+ } |
907 |
+ } |
908 |
+} |
909 |
+ |
910 |
+// Transform one data unit -- this performs the dequantization and |
911 |
+// IDCT steps. This IDCT algorithm is taken from: |
912 |
+// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, |
913 |
+// "Practical Fast 1-D DCT Algorithms with 11 Multiplications", |
914 |
+// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, |
915 |
+// 988-991. |
916 |
+// The stage numbers mentioned in the comments refer to Figure 1 in this |
917 |
+// paper. |
918 |
+void DCTStream::transformDataUnit(uchar *quantTable, |
919 |
+ int dataIn[64], uchar dataOut[64]) |
920 |
+{ |
921 |
+ int v0, v1, v2, v3, v4, v5, v6, v7, t; |
922 |
+ int *p; |
923 |
+ int i; |
924 |
+ |
925 |
+ // dequant |
926 |
+ for (i = 0; i < 64; ++i) { |
927 |
+ dataIn[i] *= quantTable[i]; |
928 |
+ } |
929 |
+ |
930 |
+ // inverse DCT on rows |
931 |
+ for (i = 0; i < 64; i += 8) { |
932 |
+ p = dataIn + i; |
933 |
+ |
934 |
+ // check for all-zero AC coefficients |
935 |
+ if (p[1] == 0 && p[2] == 0 && p[3] == 0 && |
936 |
+ p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) { |
937 |
+ t = (dctSqrt2 * p[0] + 512) >> 10; |
938 |
+ p[0] = t; |
939 |
+ p[1] = t; |
940 |
+ p[2] = t; |
941 |
+ p[3] = t; |
942 |
+ p[4] = t; |
943 |
+ p[5] = t; |
944 |
+ p[6] = t; |
945 |
+ p[7] = t; |
946 |
+ continue; |
947 |
+ } |
948 |
+ |
949 |
+ // stage 4 |
950 |
+ v0 = (dctSqrt2 * p[0] + 128) >> 8; |
951 |
+ v1 = (dctSqrt2 * p[4] + 128) >> 8; |
952 |
+ v2 = p[2]; |
953 |
+ v3 = p[6]; |
954 |
+ v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8; |
955 |
+ v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8; |
956 |
+ v5 = p[3] << 4; |
957 |
+ v6 = p[5] << 4; |
958 |
+ |
959 |
+ // stage 3 |
960 |
+ t = (v0 - v1+ 1) >> 1; |
961 |
+ v0 = (v0 + v1 + 1) >> 1; |
962 |
+ v1 = t; |
963 |
+ t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; |
964 |
+ v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; |
965 |
+ v3 = t; |
966 |
+ t = (v4 - v6 + 1) >> 1; |
967 |
+ v4 = (v4 + v6 + 1) >> 1; |
968 |
+ v6 = t; |
969 |
+ t = (v7 + v5 + 1) >> 1; |
970 |
+ v5 = (v7 - v5 + 1) >> 1; |
971 |
+ v7 = t; |
972 |
+ |
973 |
+ // stage 2 |
974 |
+ t = (v0 - v3 + 1) >> 1; |
975 |
+ v0 = (v0 + v3 + 1) >> 1; |
976 |
+ v3 = t; |
977 |
+ t = (v1 - v2 + 1) >> 1; |
978 |
+ v1 = (v1 + v2 + 1) >> 1; |
979 |
+ v2 = t; |
980 |
+ t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; |
981 |
+ v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; |
982 |
+ v7 = t; |
983 |
+ t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; |
984 |
+ v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; |
985 |
+ v6 = t; |
986 |
+ |
987 |
+ // stage 1 |
988 |
+ p[0] = v0 + v7; |
989 |
+ p[7] = v0 - v7; |
990 |
+ p[1] = v1 + v6; |
991 |
+ p[6] = v1 - v6; |
992 |
+ p[2] = v2 + v5; |
993 |
+ p[5] = v2 - v5; |
994 |
+ p[3] = v3 + v4; |
995 |
+ p[4] = v3 - v4; |
996 |
+ } |
997 |
+ |
998 |
+ // inverse DCT on columns |
999 |
+ for (i = 0; i < 8; ++i) { |
1000 |
+ p = dataIn + i; |
1001 |
+ |
1002 |
+ // check for all-zero AC coefficients |
1003 |
+ if (p[1*8] == 0 && p[2*8] == 0 && p[3*8] == 0 && |
1004 |
+ p[4*8] == 0 && p[5*8] == 0 && p[6*8] == 0 && p[7*8] == 0) { |
1005 |
+ t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; |
1006 |
+ p[0*8] = t; |
1007 |
+ p[1*8] = t; |
1008 |
+ p[2*8] = t; |
1009 |
+ p[3*8] = t; |
1010 |
+ p[4*8] = t; |
1011 |
+ p[5*8] = t; |
1012 |
+ p[6*8] = t; |
1013 |
+ p[7*8] = t; |
1014 |
+ continue; |
1015 |
+ } |
1016 |
+ |
1017 |
+ // stage 4 |
1018 |
+ v0 = (dctSqrt2 * p[0*8] + 2048) >> 12; |
1019 |
+ v1 = (dctSqrt2 * p[4*8] + 2048) >> 12; |
1020 |
+ v2 = p[2*8]; |
1021 |
+ v3 = p[6*8]; |
1022 |
+ v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12; |
1023 |
+ v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12; |
1024 |
+ v5 = p[3*8]; |
1025 |
+ v6 = p[5*8]; |
1026 |
+ |
1027 |
+ // stage 3 |
1028 |
+ t = (v0 - v1 + 1) >> 1; |
1029 |
+ v0 = (v0 + v1 + 1) >> 1; |
1030 |
+ v1 = t; |
1031 |
+ t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; |
1032 |
+ v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; |
1033 |
+ v3 = t; |
1034 |
+ t = (v4 - v6 + 1) >> 1; |
1035 |
+ v4 = (v4 + v6 + 1) >> 1; |
1036 |
+ v6 = t; |
1037 |
+ t = (v7 + v5 + 1) >> 1; |
1038 |
+ v5 = (v7 - v5 + 1) >> 1; |
1039 |
+ v7 = t; |
1040 |
+ |
1041 |
+ // stage 2 |
1042 |
+ t = (v0 - v3 + 1) >> 1; |
1043 |
+ v0 = (v0 + v3 + 1) >> 1; |
1044 |
+ v3 = t; |
1045 |
+ t = (v1 - v2 + 1) >> 1; |
1046 |
+ v1 = (v1 + v2 + 1) >> 1; |
1047 |
+ v2 = t; |
1048 |
+ t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; |
1049 |
+ v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; |
1050 |
+ v7 = t; |
1051 |
+ t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; |
1052 |
+ v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; |
1053 |
+ v6 = t; |
1054 |
+ |
1055 |
+ // stage 1 |
1056 |
+ p[0*8] = v0 + v7; |
1057 |
+ p[7*8] = v0 - v7; |
1058 |
+ p[1*8] = v1 + v6; |
1059 |
+ p[6*8] = v1 - v6; |
1060 |
+ p[2*8] = v2 + v5; |
1061 |
+ p[5*8] = v2 - v5; |
1062 |
+ p[3*8] = v3 + v4; |
1063 |
+ p[4*8] = v3 - v4; |
1064 |
+ } |
1065 |
+ |
1066 |
+ // convert to 8-bit integers |
1067 |
+ for (i = 0; i < 64; ++i) { |
1068 |
+ dataOut[i] = dctClip[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)]; |
1069 |
+ } |
1070 |
+} |
1071 |
+ |
1072 |
+int DCTStream::readHuffSym(DCTHuffTable *table) |
1073 |
+{ |
1074 |
+ ushort code; |
1075 |
+ int bit; |
1076 |
+ int codeBits; |
1077 |
+ |
1078 |
+ code = 0; |
1079 |
+ codeBits = 0; |
1080 |
+ do { |
1081 |
+ // add a bit to the code |
1082 |
+ if ((bit = readBit()) == EOF) |
1083 |
+ return 9999; |
1084 |
+ code = ushort((code << 1) + bit); |
1085 |
+ ++codeBits; |
1086 |
+ |
1087 |
+ // look up code |
1088 |
+ if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) { |
1089 |
+ code -= table->firstCode[codeBits]; |
1090 |
+ return table->sym[table->firstSym[codeBits] + code]; |
1091 |
+ } |
1092 |
+ } while (codeBits < 16); |
1093 |
+ |
1094 |
+ ipeDebug("Bad Huffman code in DCT stream"); |
1095 |
+ return 9999; |
1096 |
+} |
1097 |
+ |
1098 |
+int DCTStream::readAmp(int size) |
1099 |
+{ |
1100 |
+ int amp, bit; |
1101 |
+ int bits; |
1102 |
+ |
1103 |
+ amp = 0; |
1104 |
+ for (bits = 0; bits < size; ++bits) { |
1105 |
+ if ((bit = readBit()) == EOF) |
1106 |
+ return 9999; |
1107 |
+ amp = (amp << 1) + bit; |
1108 |
+ } |
1109 |
+ if (amp < (1 << (size - 1))) |
1110 |
+ amp -= (1 << size) - 1; |
1111 |
+ return amp; |
1112 |
+} |
1113 |
+ |
1114 |
+int DCTStream::readBit() |
1115 |
+{ |
1116 |
+ int bit; |
1117 |
+ int c, c2; |
1118 |
+ |
1119 |
+ if (inputBits == 0) { |
1120 |
+ if ((c = iSource.getChar()) == EOF) |
1121 |
+ return EOF; |
1122 |
+ if (c == 0xff) { |
1123 |
+ do { |
1124 |
+ c2 = iSource.getChar(); |
1125 |
+ } while (c2 == 0xff); |
1126 |
+ if (c2 != 0x00) { |
1127 |
+ ipeDebug("Bad DCT data: missing 00 after ff"); |
1128 |
+ return EOF; |
1129 |
+ } |
1130 |
+ } |
1131 |
+ inputBuf = c; |
1132 |
+ inputBits = 8; |
1133 |
+ } |
1134 |
+ bit = (inputBuf >> (inputBits - 1)) & 1; |
1135 |
+ --inputBits; |
1136 |
+ return bit; |
1137 |
+} |
1138 |
+ |
1139 |
+bool DCTStream::readHeader() |
1140 |
+{ |
1141 |
+ bool doScan; |
1142 |
+ int n; |
1143 |
+ int c; |
1144 |
+ int i; |
1145 |
+ |
1146 |
+ // read headers |
1147 |
+ doScan = false; |
1148 |
+ while (!doScan) { |
1149 |
+ c = readMarker(); |
1150 |
+ switch (c) { |
1151 |
+ case 0xc0: // SOF0 |
1152 |
+ if (!readBaselineSOF()) { |
1153 |
+ return false; |
1154 |
+ } |
1155 |
+ break; |
1156 |
+ case 0xc2: // SOF2 |
1157 |
+ if (!readProgressiveSOF()) { |
1158 |
+ return false; |
1159 |
+ } |
1160 |
+ break; |
1161 |
+ case 0xc4: // DHT |
1162 |
+ if (!readHuffmanTables()) { |
1163 |
+ return false; |
1164 |
+ } |
1165 |
+ break; |
1166 |
+ case 0xd8: // SOI |
1167 |
+ break; |
1168 |
+ case 0xd9: // EOI |
1169 |
+ return false; |
1170 |
+ case 0xda: // SOS |
1171 |
+ if (!readScanInfo()) { |
1172 |
+ return false; |
1173 |
+ } |
1174 |
+ doScan = true; |
1175 |
+ break; |
1176 |
+ case 0xdb: // DQT |
1177 |
+ if (!readQuantTables()) { |
1178 |
+ return false; |
1179 |
+ } |
1180 |
+ break; |
1181 |
+ case 0xdd: // DRI |
1182 |
+ if (!readRestartInterval()) { |
1183 |
+ return false; |
1184 |
+ } |
1185 |
+ break; |
1186 |
+ case 0xee: // APP14 |
1187 |
+ if (!readAdobeMarker()) { |
1188 |
+ return false; |
1189 |
+ } |
1190 |
+ break; |
1191 |
+ case EOF: |
1192 |
+ ipeDebug("Bad DCT header"); |
1193 |
+ return false; |
1194 |
+ default: |
1195 |
+ // skip APPn / COM / etc. |
1196 |
+ if (c >= 0xe0) { |
1197 |
+ n = read16() - 2; |
1198 |
+ for (i = 0; i < n; ++i) { |
1199 |
+ iSource.getChar(); |
1200 |
+ } |
1201 |
+ } else { |
1202 |
+ ipeDebug("Unknown DCT marker <%02x>", c); |
1203 |
+ return false; |
1204 |
+ } |
1205 |
+ break; |
1206 |
+ } |
1207 |
+ } |
1208 |
+ |
1209 |
+ return true; |
1210 |
+} |
1211 |
+ |
1212 |
+bool DCTStream::readBaselineSOF() |
1213 |
+{ |
1214 |
+ (void) read16(); // length |
1215 |
+ int prec = iSource.getChar(); |
1216 |
+ height = read16(); |
1217 |
+ width = read16(); |
1218 |
+ numComps = iSource.getChar(); |
1219 |
+ if (prec != 8) { |
1220 |
+ ipeDebug("Bad DCT precision %d", prec); |
1221 |
+ return false; |
1222 |
+ } |
1223 |
+ for (int i = 0; i < numComps; ++i) { |
1224 |
+ compInfo[i].id = iSource.getChar(); |
1225 |
+ int c = iSource.getChar(); |
1226 |
+ compInfo[i].hSample = (c >> 4) & 0x0f; |
1227 |
+ compInfo[i].vSample = c & 0x0f; |
1228 |
+ compInfo[i].quantTable = iSource.getChar(); |
1229 |
+ } |
1230 |
+ progressive = false; |
1231 |
+ return true; |
1232 |
+} |
1233 |
+ |
1234 |
+bool DCTStream::readProgressiveSOF() |
1235 |
+{ |
1236 |
+ (void) read16(); // length |
1237 |
+ int prec = iSource.getChar(); |
1238 |
+ height = read16(); |
1239 |
+ width = read16(); |
1240 |
+ numComps = iSource.getChar(); |
1241 |
+ if (prec != 8) { |
1242 |
+ ipeDebug("Bad DCT precision %d", prec); |
1243 |
+ return false; |
1244 |
+ } |
1245 |
+ for (int i = 0; i < numComps; ++i) { |
1246 |
+ compInfo[i].id = iSource.getChar(); |
1247 |
+ int c = iSource.getChar(); |
1248 |
+ compInfo[i].hSample = (c >> 4) & 0x0f; |
1249 |
+ compInfo[i].vSample = c & 0x0f; |
1250 |
+ compInfo[i].quantTable = iSource.getChar(); |
1251 |
+ } |
1252 |
+ progressive = true; |
1253 |
+ return true; |
1254 |
+} |
1255 |
+ |
1256 |
+bool DCTStream::readScanInfo() |
1257 |
+{ |
1258 |
+ int length; |
1259 |
+ int id, c; |
1260 |
+ int i, j; |
1261 |
+ |
1262 |
+ length = read16() - 2; |
1263 |
+ scanInfo.numComps = iSource.getChar(); |
1264 |
+ --length; |
1265 |
+ if (length != 2 * scanInfo.numComps + 3) { |
1266 |
+ ipeDebug("Bad DCT scan info block"); |
1267 |
+ return false; |
1268 |
+ } |
1269 |
+ interleaved = scanInfo.numComps == numComps; |
1270 |
+ for (j = 0; j < numComps; ++j) { |
1271 |
+ scanInfo.comp[j] = false; |
1272 |
+ } |
1273 |
+ for (i = 0; i < scanInfo.numComps; ++i) { |
1274 |
+ id = iSource.getChar(); |
1275 |
+ for (j = 0; j < numComps; ++j) { |
1276 |
+ if (id == compInfo[j].id) { |
1277 |
+ break; |
1278 |
+ } |
1279 |
+ } |
1280 |
+ if (j == numComps) { |
1281 |
+ ipeDebug("Bad DCT component ID in scan info block"); |
1282 |
+ return false; |
1283 |
+ } |
1284 |
+ scanInfo.comp[j] = true; |
1285 |
+ c = iSource.getChar(); |
1286 |
+ scanInfo.dcHuffTable[j] = (c >> 4) & 0x0f; |
1287 |
+ scanInfo.acHuffTable[j] = c & 0x0f; |
1288 |
+ } |
1289 |
+ scanInfo.firstCoeff = iSource.getChar(); |
1290 |
+ scanInfo.lastCoeff = iSource.getChar(); |
1291 |
+ c = iSource.getChar(); |
1292 |
+ scanInfo.ah = (c >> 4) & 0x0f; |
1293 |
+ scanInfo.al = c & 0x0f; |
1294 |
+ return true; |
1295 |
+} |
1296 |
+ |
1297 |
+bool DCTStream::readQuantTables() |
1298 |
+{ |
1299 |
+ int length; |
1300 |
+ int i; |
1301 |
+ int index; |
1302 |
+ |
1303 |
+ length = read16() - 2; |
1304 |
+ while (length > 0) { |
1305 |
+ index = iSource.getChar(); |
1306 |
+ if ((index & 0xf0) || index >= 4) { |
1307 |
+ ipeDebug("Bad DCT quantization table"); |
1308 |
+ return false; |
1309 |
+ } |
1310 |
+ if (index == numQuantTables) |
1311 |
+ numQuantTables = index + 1; |
1312 |
+ for (i = 0; i < 64; ++i) |
1313 |
+ quantTables[index][dctZigZag[i]] = uchar(iSource.getChar()); |
1314 |
+ length -= 65; |
1315 |
+ } |
1316 |
+ return true; |
1317 |
+} |
1318 |
+ |
1319 |
+bool DCTStream::readHuffmanTables() |
1320 |
+{ |
1321 |
+ DCTHuffTable *tbl; |
1322 |
+ int length; |
1323 |
+ int index; |
1324 |
+ ushort code; |
1325 |
+ uchar sym; |
1326 |
+ int i; |
1327 |
+ int c; |
1328 |
+ |
1329 |
+ length = read16() - 2; |
1330 |
+ while (length > 0) { |
1331 |
+ index = iSource.getChar(); |
1332 |
+ --length; |
1333 |
+ if ((index & 0x0f) >= 4) { |
1334 |
+ ipeDebug("Bad DCT Huffman table"); |
1335 |
+ return false; |
1336 |
+ } |
1337 |
+ if (index & 0x10) { |
1338 |
+ index &= 0x0f; |
1339 |
+ if (index >= numACHuffTables) |
1340 |
+ numACHuffTables = index+1; |
1341 |
+ tbl = &acHuffTables[index]; |
1342 |
+ } else { |
1343 |
+ if (index >= numDCHuffTables) |
1344 |
+ numDCHuffTables = index+1; |
1345 |
+ tbl = &dcHuffTables[index]; |
1346 |
+ } |
1347 |
+ sym = 0; |
1348 |
+ code = 0; |
1349 |
+ for (i = 1; i <= 16; ++i) { |
1350 |
+ c = iSource.getChar(); |
1351 |
+ tbl->firstSym[i] = sym; |
1352 |
+ tbl->firstCode[i] = code; |
1353 |
+ tbl->numCodes[i] = ushort(c); |
1354 |
+ sym += uchar(c); |
1355 |
+ code = ushort((code + c) << 1); |
1356 |
+ } |
1357 |
+ length -= 16; |
1358 |
+ for (i = 0; i < sym; ++i) |
1359 |
+ tbl->sym[i] = uchar(iSource.getChar()); |
1360 |
+ length -= sym; |
1361 |
+ } |
1362 |
+ return true; |
1363 |
+} |
1364 |
+ |
1365 |
+bool DCTStream::readRestartInterval() |
1366 |
+{ |
1367 |
+ int length; |
1368 |
+ |
1369 |
+ length = read16(); |
1370 |
+ if (length != 4) { |
1371 |
+ ipeDebug("Bad DCT restart interval"); |
1372 |
+ return false; |
1373 |
+ } |
1374 |
+ restartInterval = read16(); |
1375 |
+ return true; |
1376 |
+} |
1377 |
+ |
1378 |
+bool DCTStream::readAdobeMarker() |
1379 |
+{ |
1380 |
+ int length, i; |
1381 |
+ char buf[12]; |
1382 |
+ int c; |
1383 |
+ |
1384 |
+ length = read16(); |
1385 |
+ if (length < 14) { |
1386 |
+ goto err; |
1387 |
+ } |
1388 |
+ for (i = 0; i < 12; ++i) { |
1389 |
+ if ((c = iSource.getChar()) == EOF) { |
1390 |
+ goto err; |
1391 |
+ } |
1392 |
+ buf[i] = char(c); |
1393 |
+ } |
1394 |
+ if (::strncmp(buf, "Adobe", 5)) { |
1395 |
+ goto err; |
1396 |
+ } |
1397 |
+ colorXform = buf[11]; |
1398 |
+ gotAdobeMarker = true; |
1399 |
+ for (i = 14; i < length; ++i) { |
1400 |
+ if (iSource.getChar() == EOF) { |
1401 |
+ goto err; |
1402 |
+ } |
1403 |
+ } |
1404 |
+ return true; |
1405 |
+ |
1406 |
+ err: |
1407 |
+ ipeDebug("Bad DCT Adobe APP14 marker"); |
1408 |
+ return false; |
1409 |
+} |
1410 |
+ |
1411 |
+bool DCTStream::readTrailer() |
1412 |
+{ |
1413 |
+ int c; |
1414 |
+ |
1415 |
+ c = readMarker(); |
1416 |
+ if (c != 0xd9) { // EOI |
1417 |
+ ipeDebug("Bad DCT trailer"); |
1418 |
+ return false; |
1419 |
+ } |
1420 |
+ return true; |
1421 |
+} |
1422 |
+ |
1423 |
+int DCTStream::readMarker() |
1424 |
+{ |
1425 |
+ int c; |
1426 |
+ |
1427 |
+ do { |
1428 |
+ do { |
1429 |
+ c = iSource.getChar(); |
1430 |
+ } while (c != 0xff); |
1431 |
+ do { |
1432 |
+ c = iSource.getChar(); |
1433 |
+ } while (c == 0xff); |
1434 |
+ } while (c == 0x00); |
1435 |
+ return c; |
1436 |
+} |
1437 |
+ |
1438 |
+int DCTStream::read16() |
1439 |
+{ |
1440 |
+ int c1, c2; |
1441 |
+ |
1442 |
+ if ((c1 = iSource.getChar()) == EOF) |
1443 |
+ return EOF; |
1444 |
+ if ((c2 = iSource.getChar()) == EOF) |
1445 |
+ return EOF; |
1446 |
+ return (c1 << 8) + c2; |
1447 |
+} |
1448 |
+ |
1449 |
+// -------------------------------------------------------------------- |
1450 |
+ |
1451 |
+bool dctDecode(Buffer dctData, Buffer pixelData) |
1452 |
+{ |
1453 |
+ // ipeDebug("dctDecode %d, %d", dctData.size(), pixelData.size()); |
1454 |
+ BufferSource source(dctData); |
1455 |
+ DCTStream dct(source); |
1456 |
+ dct.reset(); |
1457 |
+ char *p = pixelData.data(); |
1458 |
+ int n = pixelData.size(); |
1459 |
+ while (n--) { |
1460 |
+ int c = dct.getChar(); |
1461 |
+ if (c == EOF) |
1462 |
+ return false; |
1463 |
+ *p++ = char(c); |
1464 |
+ } |
1465 |
+ return true; |
1466 |
+} |
1467 |
+ |
1468 |
+// -------------------------------------------------------------------- |