comparison dwt/internal/image/JPEGFileFormat.d @ 13:3d9bbe0a83a0

FileFormats
author Frank Benoit <benoit@tionex.de>
date Sun, 06 Jan 2008 22:54:14 +0100
parents
children fc2b263b8a3f
comparison
equal deleted inserted replaced
12:0c78fa47d476 13:3d9bbe0a83a0
1 /*******************************************************************************
2 * Copyright (c) 2000, 2006 IBM Corporation and others.
3 * All rights reserved. This source file is made available under the terms contained in the README file
4 * accompanying this program. The README file should be located in the about_files directory of the
5 * plug-in that contains this source file.
6 *
7 * Contributors:
8 * IBM Corporation - initial API and implementation
9 *******************************************************************************/
10 module dwt.internal.image.JPEGFileFormat;
11
12 import dwt.SWT;
13 import dwt.internal.image.JPEGFrameHeader;
14 import dwt.internal.image.JPEGScanHeader;
15 import dwt.internal.image.JPEGHuffmanTable;
16 import dwt.internal.image.JPEGAppn;
17 import dwt.internal.image.JPEGSegment;
18 import dwt.internal.image.FileFormat;
19 import dwt.internal.image.JPEGComment;
20 import dwt.internal.image.JPEGArithmeticConditioningTable;
21 import dwt.internal.image.JPEGRestartInterval;
22 import dwt.internal.image.JPEGQuantizationTable;
23 import dwt.internal.image.JPEGStartOfImage;
24 import dwt.internal.image.JPEGDecoder;
25 import dwt.internal.image.JPEGEndOfImage;
26
27 import dwt.graphics.RGB;
28 import dwt.graphics.PaletteData;
29
30 import tango.core.Exception;
31
32 final class JPEGFileFormat : FileFormat {
33 int restartInterval;
34 JPEGFrameHeader frameHeader;
35 int imageWidth, imageHeight;
36 int interleavedMcuCols, interleavedMcuRows;
37 int maxV, maxH;
38 bool progressive;
39 int samplePrecision;
40 int nComponents;
41 int[][] frameComponents;
42 int[] componentIds;
43 byte[][] imageComponents;
44 int[] dataUnit;
45 int[][][] dataUnits;
46 int[] precedingDCs;
47 JPEGScanHeader scanHeader;
48 byte[] dataBuffer;
49 int currentBitCount;
50 int bufferCurrentPosition;
51 int restartsToGo;
52 int nextRestartNumber;
53 JPEGHuffmanTable[] acHuffmanTables;
54 JPEGHuffmanTable[] dcHuffmanTables;
55 int[][] quantizationTables;
56 int currentByte;
57 int encoderQFactor = 75;
58 int eobrun = 0;
59 /* JPEGConstants */
60 public static const int DCTSIZE = 8;
61 public static const int DCTSIZESQR = 64;
62 /* JPEGFixedPointConstants */
63 public static const int FIX_0_899976223 = 7373;
64 public static const int FIX_1_961570560 = 16069;
65 public static const int FIX_2_053119869 = 16819;
66 public static const int FIX_0_298631336 = 2446;
67 public static const int FIX_1_847759065 = 15137;
68 public static const int FIX_1_175875602 = 9633;
69 public static const int FIX_3_072711026 = 25172;
70 public static const int FIX_0_765366865 = 6270;
71 public static const int FIX_2_562915447 = 20995;
72 public static const int FIX_0_541196100 = 4433;
73 public static const int FIX_0_390180644 = 3196;
74 public static const int FIX_1_501321110 = 12299;
75 /* JPEGMarkerCodes */
76 public static const int APP0 = 0xFFE0;
77 public static const int APP15 = 0xFFEF;
78 public static const int COM = 0xFFFE;
79 public static const int DAC = 0xFFCC;
80 public static const int DHP = 0xFFDE;
81 public static const int DHT = 0xFFC4;
82 public static const int DNL = 0xFFDC;
83 public static const int DRI = 0xFFDD;
84 public static const int DQT = 0xFFDB;
85 public static const int EOI = 0xFFD9;
86 public static const int EXP = 0xFFDF;
87 public static const int JPG = 0xFFC8;
88 public static const int JPG0 = 0xFFF0;
89 public static const int JPG13 = 0xFFFD;
90 public static const int RST0 = 0xFFD0;
91 public static const int RST1 = 0xFFD1;
92 public static const int RST2 = 0xFFD2;
93 public static const int RST3 = 0xFFD3;
94 public static const int RST4 = 0xFFD4;
95 public static const int RST5 = 0xFFD5;
96 public static const int RST6 = 0xFFD6;
97 public static const int RST7 = 0xFFD7;
98 public static const int SOF0 = 0xFFC0;
99 public static const int SOF1 = 0xFFC1;
100 public static const int SOF2 = 0xFFC2;
101 public static const int SOF3 = 0xFFC3;
102 public static const int SOF5 = 0xFFC5;
103 public static const int SOF6 = 0xFFC6;
104 public static const int SOF7 = 0xFFC7;
105 public static const int SOF9 = 0xFFC9;
106 public static const int SOF10 = 0xFFCA;
107 public static const int SOF11 = 0xFFCB;
108 public static const int SOF13 = 0xFFCD;
109 public static const int SOF14 = 0xFFCE;
110 public static const int SOF15 = 0xFFCF;
111 public static const int SOI = 0xFFD8;
112 public static const int SOS = 0xFFDA;
113 public static const int TEM = 0xFF01;
114 /* JPEGFrameComponentParameterConstants */
115 public static const int TQI = 0;
116 public static const int HI = 1;
117 public static const int VI = 2;
118 public static const int CW = 3;
119 public static const int CH = 4;
120 /* JPEGScanComponentParameterConstants */
121 public static const int DC = 0;
122 public static const int AC = 1;
123 /* JFIF Component Constants */
124 public static const int ID_Y = 1 - 1;
125 public static const int ID_CB = 2 - 1;
126 public static const int ID_CR = 3 - 1;
127 public static const RGB[] RGB16;
128 public static const int[] ExtendTest = [
129 0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
130 4096, 8192, 16384, 32768, 65536, 131072, 262144
131 ];
132 public static const int[] ExtendOffset = [
133 0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047,
134 -4095, -8191, -16383, -32767, -65535, -131071, -262143
135 ];
136 public static const int[] ZigZag8x8 = [
137 0, 1, 8, 16, 9, 2, 3, 10,
138 17, 24, 32, 25, 18, 11, 4, 5,
139 12, 19, 26, 33, 40, 48, 41, 34,
140 27, 20, 13, 6, 7, 14, 21, 28,
141 35, 42, 49, 56, 57, 50, 43, 36,
142 29, 22, 15, 23, 30, 37, 44, 51,
143 58, 59, 52, 45, 38, 31, 39, 46,
144 53, 60, 61, 54, 47, 55, 62, 63
145 ];
146
147 public static int[] CrRTable, CbBTable, CrGTable, CbGTable;
148 public static int[] RYTable, GYTable, BYTable,
149 RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable;
150 static this(){
151 initialize();
152 RGB16 = [
153 new RGB(0,0,0),
154 new RGB(0x80,0,0),
155 new RGB(0,0x80,0),
156 new RGB(0x80,0x80,0),
157 new RGB(0,0,0x80),
158 new RGB(0x80,0,0x80),
159 new RGB(0,0x80,0x80),
160 new RGB(0xC0,0xC0,0xC0),
161 new RGB(0x80,0x80,0x80),
162 new RGB(0xFF,0,0),
163 new RGB(0,0xFF,0),
164 new RGB(0xFF,0xFF,0),
165 new RGB(0,0,0xFF),
166 new RGB(0xFF,0,0xFF),
167 new RGB(0,0xFF,0xFF),
168 new RGB(0xFF,0xFF,0xFF)
169 ];
170 }
171 void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) {
172 int srcWidth = image.width;
173 int srcHeight = image.height;
174 int vhFactor = maxV * maxH;
175 int[] frameComponent;
176 imageComponents = new byte[][](nComponents);
177 for (int i = 0; i < nComponents; i++) {
178 frameComponent = frameComponents[componentIds[i]];
179 imageComponents[i] = new byte[frameComponent[CW] * frameComponent[CH]];
180 }
181 frameComponent = frameComponents[componentIds[ID_Y]];
182 for (int yPos = 0; yPos < srcHeight; yPos++) {
183 int srcOfs = yPos * srcWidth;
184 int dstOfs = yPos * frameComponent[CW];
185 imageComponents[ID_Y][ dstOfs .. dstOfs+srcWidth] = dataYComp[ srcOfs .. srcOfs+srcWidth ];
186 }
187 frameComponent = frameComponents[componentIds[ID_CB]];
188 for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
189 int destRowIndex = yPos * frameComponent[CW];
190 for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
191 int sum = 0;
192 for (int iv = 0; iv < maxV; iv++) {
193 int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
194 for (int ih = 0; ih < maxH; ih++) {
195 sum += dataCbComp[srcIndex + ih] & 0xFF;
196 }
197 }
198 imageComponents[ID_CB][destRowIndex + xPos] = cast(byte)(sum / vhFactor);
199 }
200 }
201 frameComponent = frameComponents[componentIds[ID_CR]];
202 for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
203 int destRowIndex = yPos * frameComponent[CW];
204 for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
205 int sum = 0;
206 for (int iv = 0; iv < maxV; iv++) {
207 int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
208 for (int ih = 0; ih < maxH; ih++) {
209 sum += dataCrComp[srcIndex + ih] & 0xFF;
210 }
211 }
212 imageComponents[ID_CR][destRowIndex + xPos] = cast(byte)(sum / vhFactor);
213 }
214 }
215 for (int iComp = 0; iComp < nComponents; iComp++) {
216 byte[] imageComponent = imageComponents[iComp];
217 frameComponent = frameComponents[componentIds[iComp]];
218 int hFactor = frameComponent[HI];
219 int vFactor = frameComponent[VI];
220 int componentWidth = frameComponent[CW];
221 int componentHeight = frameComponent[CH];
222 int compressedWidth = srcWidth / (maxH / hFactor);
223 int compressedHeight = srcHeight / (maxV / vFactor);
224 if (compressedWidth < componentWidth) {
225 int delta = componentWidth - compressedWidth;
226 for (int yPos = 0; yPos < compressedHeight; yPos++) {
227 int dstOfs = ((yPos + 1) * componentWidth - delta);
228 int dataValue = imageComponent[dstOfs - 1] & 0xFF;
229 for (int i = 0; i < delta; i++) {
230 imageComponent[dstOfs + i] = cast(byte)dataValue;
231 }
232 }
233 }
234 if (compressedHeight < componentHeight) {
235 int srcOfs = (compressedHeight - 1) * componentWidth;
236 for (int yPos = compressedHeight; yPos <= componentHeight; yPos++) {
237 int dstOfs = (yPos - 1) * componentWidth;
238 imageComponent[dstOfs .. dstOfs+componentWidth] = imageComponent[srcOfs .. srcOfs+componentWidth];
239 }
240 }
241 }
242 }
243 void convert4BitRGBToYCbCr(ImageData image) {
244 RGB[] rgbs = image.getRGBs();
245 int paletteSize = rgbs.length;
246 byte[] yComp = new byte[paletteSize];
247 byte[] cbComp = new byte[paletteSize];
248 byte[] crComp = new byte[paletteSize];
249 int srcWidth = image.width;
250 int srcHeight = image.height;
251 for (int i = 0; i < paletteSize; i++) {
252 RGB color = rgbs[i];
253 int r = color.red;
254 int g = color.green;
255 int b = color.blue;
256 int n = RYTable[r] + GYTable[g] + BYTable[b];
257 yComp[i] = cast(byte)(n >> 16);
258 if ((n < 0) && ((n & 0xFFFF) != 0)) yComp[i]--;
259 n = RCbTable[r] + GCbTable[g] + BCbTable[b];
260 cbComp[i] = cast(byte)(n >> 16);
261 if ((n < 0) && ((n & 0xFFFF) != 0)) cbComp[i]--;
262 n = RCrTable[r] + GCrTable[g] + BCrTable[b];
263 crComp[i] = cast(byte)(n >> 16);
264 if ((n < 0) && ((n & 0xFFFF) != 0)) crComp[i]--;
265 }
266 int bSize = srcWidth * srcHeight;
267 byte[] dataYComp = new byte[bSize];
268 byte[] dataCbComp = new byte[bSize];
269 byte[] dataCrComp = new byte[bSize];
270 byte[] origData = image.data;
271 int bytesPerLine = image.bytesPerLine;
272 int maxScanlineByte = srcWidth >> 1;
273 for (int yPos = 0; yPos < srcHeight; yPos++) {
274 for (int xPos = 0; xPos < maxScanlineByte; xPos++) {
275 int srcIndex = yPos * bytesPerLine + xPos;
276 int dstIndex = yPos * srcWidth + (xPos * 2);
277 int value2 = origData[srcIndex] & 0xFF;
278 int value1 = value2 >> 4;
279 value2 &= 0x0F;
280 dataYComp[dstIndex] = yComp[value1];
281 dataCbComp[dstIndex] = cbComp[value1];
282 dataCrComp[dstIndex] = crComp[value1];
283 dataYComp[dstIndex + 1] = yComp[value2];
284 dataCbComp[dstIndex + 1] = cbComp[value2];
285 dataCrComp[dstIndex + 1] = crComp[value2];
286 }
287 }
288 compress(image, dataYComp, dataCbComp, dataCrComp);
289 }
290 void convert8BitRGBToYCbCr(ImageData image) {
291 RGB[] rgbs = image.getRGBs();
292 int paletteSize = rgbs.length;
293 byte[] yComp = new byte[paletteSize];
294 byte[] cbComp = new byte[paletteSize];
295 byte[] crComp = new byte[paletteSize];
296 int srcWidth = image.width;
297 int srcHeight = image.height;
298 for (int i = 0; i < paletteSize; i++) {
299 RGB color = rgbs[i];
300 int r = color.red;
301 int g = color.green;
302 int b = color.blue;
303 int n = RYTable[r] + GYTable[g] + BYTable[b];
304 yComp[i] = cast(byte)(n >> 16);
305 if ((n < 0) && ((n & 0xFFFF) != 0)) yComp[i]--;
306 n = RCbTable[r] + GCbTable[g] + BCbTable[b];
307 cbComp[i] = cast(byte)(n >> 16);
308 if ((n < 0) && ((n & 0xFFFF) != 0)) cbComp[i]--;
309 n = RCrTable[r] + GCrTable[g] + BCrTable[b];
310 crComp[i] = cast(byte)(n >> 16);
311 if ((n < 0) && ((n & 0xFFFF) != 0)) crComp[i]--;
312 }
313 int dstWidth = image.width;
314 int dstHeight = srcHeight;
315 int stride = ((srcWidth + 3) >> 2) << 2;
316 int bSize = dstWidth * dstHeight;
317 byte[] dataYComp = new byte[bSize];
318 byte[] dataCbComp = new byte[bSize];
319 byte[] dataCrComp = new byte[bSize];
320 byte[] origData = image.data;
321 for (int yPos = 0; yPos < srcHeight; yPos++) {
322 int srcRowIndex = yPos * stride;
323 int dstRowIndex = yPos * dstWidth;
324 for (int xPos = 0; xPos < srcWidth; xPos++) {
325 int value = origData[srcRowIndex + xPos] & 0xFF;
326 int dstIndex = dstRowIndex + xPos;
327 dataYComp[dstIndex] = yComp[value];
328 dataCbComp[dstIndex] = cbComp[value];
329 dataCrComp[dstIndex] = crComp[value];
330 }
331 }
332 compress(image, dataYComp, dataCbComp, dataCrComp);
333 }
334 byte[] convertCMYKToRGB() {
335 /* Unsupported CMYK format. Answer an empty byte array. */
336 return new byte[0];
337 }
338 void convertImageToYCbCr(ImageData image) {
339 switch (image.depth) {
340 case 4:
341 convert4BitRGBToYCbCr(image);
342 return;
343 case 8:
344 convert8BitRGBToYCbCr(image);
345 return;
346 case 16:
347 case 24:
348 case 32:
349 convertMultiRGBToYCbCr(image);
350 return;
351 default:
352 SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
353 }
354 return;
355 }
356 void convertMultiRGBToYCbCr(ImageData image) {
357 int srcWidth = image.width;
358 int srcHeight = image.height;
359 int bSize = srcWidth * srcHeight;
360 byte[] dataYComp = new byte[bSize];
361 byte[] dataCbComp = new byte[bSize];
362 byte[] dataCrComp = new byte[bSize];
363 PaletteData palette = image.palette;
364 int[] buffer = new int[srcWidth];
365 if (palette.isDirect) {
366 int redMask = palette.redMask;
367 int greenMask = palette.greenMask;
368 int blueMask = palette.blueMask;
369 int redShift = palette.redShift;
370 int greenShift = palette.greenShift;
371 int blueShift = palette.blueShift;
372 for (int yPos = 0; yPos < srcHeight; yPos++) {
373 image.getPixels(0, yPos, srcWidth, buffer, 0);
374 int dstRowIndex = yPos * srcWidth;
375 for (int xPos = 0; xPos < srcWidth; xPos++) {
376 int pixel = buffer[xPos];
377 int dstDataIndex = dstRowIndex + xPos;
378 int r = pixel & redMask;
379 r = (redShift < 0) ? r >>> -redShift : r << redShift;
380 int g = pixel & greenMask;
381 g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
382 int b = pixel & blueMask;
383 b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
384 dataYComp[dstDataIndex] = cast(byte)((RYTable[r] + GYTable[g] + BYTable[b]) >> 16);
385 dataCbComp[dstDataIndex] = cast(byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) >> 16);
386 dataCrComp[dstDataIndex] = cast(byte)((RCrTable[r] + GCrTable[g] + BCrTable[b]) >> 16);
387 }
388 }
389 } else {
390 for (int yPos = 0; yPos < srcHeight; yPos++) {
391 image.getPixels(0, yPos, srcWidth, buffer, 0);
392 int dstRowIndex = yPos * srcWidth;
393 for (int xPos = 0; xPos < srcWidth; xPos++) {
394 int pixel = buffer[xPos];
395 int dstDataIndex = dstRowIndex + xPos;
396 RGB rgb = palette.getRGB(pixel);
397 int r = rgb.red;
398 int g = rgb.green;
399 int b = rgb.blue;
400 dataYComp[dstDataIndex] = cast(byte)((RYTable[r] + GYTable[g] + BYTable[b]) >> 16);
401 dataCbComp[dstDataIndex] = cast(byte)((RCbTable[r] + GCbTable[g] + BCbTable[b]) >> 16);
402 dataCrComp[dstDataIndex] = cast(byte)((RCrTable[r] + GCrTable[g] + BCrTable[b]) >> 16);
403 }
404 }
405 }
406 compress(image, dataYComp, dataCbComp, dataCrComp);
407 }
408 byte[] convertYToRGB() {
409 int compWidth = frameComponents[componentIds[ID_Y]][CW];
410 int bytesPerLine = (((imageWidth * 8 + 7) / 8) + 3) / 4 * 4;
411 byte[] data = new byte[bytesPerLine * imageHeight];
412 byte[] yComp = imageComponents[ID_Y];
413 int destIndex = 0;
414 for (int i = 0; i < imageHeight; i++) {
415 int srcIndex = i * compWidth;
416 for (int j = 0; j < bytesPerLine; j++) {
417 int y = yComp[srcIndex] & 0xFF;
418 if (y < 0) {
419 y = 0;
420 } else {
421 if (y > 255) y = 255;
422 }
423 if (j >= imageWidth) {
424 y = 0;
425 }
426 data[destIndex] = cast(byte)y;
427 srcIndex++;
428 destIndex++;
429 }
430 }
431 return data;
432 }
433 byte[] convertYCbCrToRGB() {
434 /**
435 * Convert existing image components into an RGB format.
436 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
437 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
438 * The conversion equations to be implemented are therefore
439 * R = Y + 1.40200 * Cr
440 * G = Y - 0.34414 * Cb - 0.71414 * Cr
441 * B = Y + 1.77200 * Cb
442 * where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
443 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
444 *
445 * To avoid floating-point arithmetic, we represent the fractional constants
446 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
447 * the products by 2^16, with appropriate rounding, to get the correct answer.
448 * Notice that Y, being an integral input, does not contribute any fraction
449 * so it need not participate in the rounding.
450 *
451 * For even more speed, we avoid doing any multiplications in the inner loop
452 * by precalculating the constants times Cb and Cr for all possible values.
453 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
454 * for 12-bit samples it is still acceptable. It's not very reasonable for
455 * 16-bit samples, but if you want lossless storage you shouldn't be changing
456 * colorspace anyway.
457 * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
458 * values for the G calculation are left scaled up, since we must add them
459 * together before rounding.
460 */
461 int bSize = imageWidth * imageHeight * nComponents;
462 byte[] rgbData = new byte[bSize];
463 int destIndex = 0;
464 expandImageComponents();
465 byte[] yComp = imageComponents[ID_Y];
466 byte[] cbComp = imageComponents[ID_CB];
467 byte[] crComp = imageComponents[ID_CR];
468 int compWidth = frameComponents[componentIds[ID_Y]][CW];
469 for (int v = 0; v < imageHeight; v++) {
470 int srcIndex = v * compWidth;
471 for (int i = 0; i < imageWidth; i++) {
472 int y = yComp[srcIndex] & 0xFF;
473 int cb = cbComp[srcIndex] & 0xFF;
474 int cr = crComp[srcIndex] & 0xFF;
475 int r = y + CrRTable[cr];
476 int g = y + ((CbGTable[cb] + CrGTable[cr]) >> 16);
477 int b = y + CbBTable[cb];
478 if (r < 0) {
479 r = 0;
480 } else {
481 if (r > 255) r = 255;
482 }
483 if (g < 0) {
484 g = 0;
485 } else {
486 if (g > 255) g = 255;
487 }
488 if (b < 0) {
489 b = 0;
490 } else {
491 if (b > 255) b = 255;
492 }
493 rgbData[destIndex] = cast(byte)b;
494 rgbData[destIndex + 1] = cast(byte)g;
495 rgbData[destIndex + 2] = cast(byte)r;
496 destIndex += 3;
497 srcIndex++;
498 }
499 }
500 return rgbData;
501 }
502 void decodeACCoefficients(int[] dataUnit, int iComp) {
503 int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
504 JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
505 int k = 1;
506 while (k < 64) {
507 int rs = decodeUsingTable(acTable);
508 int r = rs >> 4;
509 int s = rs & 0xF;
510 if (s == 0) {
511 if (r == 15) {
512 k += 16;
513 } else {
514 break;
515 }
516 } else {
517 k += r;
518 int bits = receive(s);
519 dataUnit[ZigZag8x8[k]] = extendBy(bits, s);
520 k++;
521 }
522 }
523 }
524 void decodeACFirstCoefficients(int[] dataUnit, int iComp, int start, int end, int approxBit) {
525 if (eobrun > 0) {
526 eobrun--;
527 return;
528 }
529 int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
530 JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
531 int k = start;
532 while (k <= end) {
533 int rs = decodeUsingTable(acTable);
534 int r = rs >> 4;
535 int s = rs & 0xF;
536 if (s == 0) {
537 if (r == 15) {
538 k += 16;
539 } else {
540 eobrun = (1 << r) + receive(r) - 1;
541 break;
542 }
543 } else {
544 k += r;
545 int bits = receive(s);
546 dataUnit[ZigZag8x8[k]] = extendBy(bits, s) << approxBit;
547 k++;
548 }
549 }
550 }
551 void decodeACRefineCoefficients(int[] dataUnit, int iComp, int start, int end, int approxBit) {
552 int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
553 JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
554 int k = start;
555 while (k <= end) {
556 if (eobrun > 0) {
557 while (k <= end) {
558 int zzIndex = ZigZag8x8[k];
559 if (dataUnit[zzIndex] != 0) {
560 dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
561 }
562 k++;
563 }
564 eobrun--;
565 } else {
566 int rs = decodeUsingTable(acTable);
567 int r = rs >> 4;
568 int s = rs & 0xF;
569 if (s == 0) {
570 if (r == 15) {
571 int zeros = 0;
572 while (zeros < 16 && k <= end) {
573 int zzIndex = ZigZag8x8[k];
574 if (dataUnit[zzIndex] != 0) {
575 dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
576 } else {
577 zeros++;
578 }
579 k++;
580 }
581 } else {
582 eobrun = (1 << r) + receive(r);
583 }
584 } else {
585 int bit = receive(s);
586 int zeros = 0;
587 int zzIndex = ZigZag8x8[k];
588 while ((zeros < r || dataUnit[zzIndex] != 0) && k <= end) {
589 if (dataUnit[zzIndex] != 0) {
590 dataUnit[zzIndex] = refineAC(dataUnit[zzIndex], approxBit);
591 } else {
592 zeros++;
593 }
594 k++;
595 zzIndex = ZigZag8x8[k];
596 }
597 if (bit != 0) {
598 dataUnit[zzIndex] = 1 << approxBit;
599 } else {
600 dataUnit[zzIndex] = -1 << approxBit;
601 }
602 k++;
603 }
604 }
605 }
606 }
607 int refineAC(int ac, int approxBit) {
608 if (ac > 0) {
609 int bit = nextBit();
610 if (bit != 0) {
611 ac += 1 << approxBit;
612 }
613 } else if (ac < 0) {
614 int bit = nextBit();
615 if (bit != 0) {
616 ac += -1 << approxBit;
617 }
618 }
619 return ac;
620 }
621 void decodeDCCoefficient(int[] dataUnit, int iComp, bool first, int approxBit) {
622 int[] sParams = scanHeader.componentParameters[componentIds[iComp]];
623 JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
624 int lastDC = 0;
625 if (progressive && !first) {
626 int bit = nextBit();
627 lastDC = dataUnit[0] + (bit << approxBit);
628 } else {
629 lastDC = precedingDCs[iComp];
630 int nBits = decodeUsingTable(dcTable);
631 if (nBits != 0) {
632 int bits = receive(nBits);
633 int diff = extendBy(bits, nBits);
634 lastDC += diff;
635 precedingDCs[iComp] = lastDC;
636 }
637 if (progressive) {
638 lastDC = lastDC << approxBit;
639 }
640 }
641 dataUnit[0] = lastDC;
642 }
643 void dequantize(int[] dataUnit, int iComp) {
644 int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
645 for (int i = 0; i < dataUnit.length; i++) {
646 int zzIndex = ZigZag8x8[i];
647 dataUnit[zzIndex] = dataUnit[zzIndex] * qTable[i];
648 }
649 }
650 byte[] decodeImageComponents() {
651 if (nComponents == 3) { // compIds 1, 2, 3
652 return convertYCbCrToRGB();
653 }
654 // if (nComponents == 3) { // compIds 1, 4, 5
655 // Unsupported CMYK format.
656 // return convertYIQToRGB();
657 // }
658 if (nComponents == 4) {
659 return convertCMYKToRGB();
660 }
661 return convertYToRGB();
662 }
663 void decodeMCUAtXAndY(int xmcu, int ymcu, int nComponentsInScan, bool first, int start, int end, int approxBit) {
664 for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
665 int scanComponent = iComp;
666 while (scanHeader.componentParameters[componentIds[scanComponent]] == null) {
667 scanComponent++;
668 }
669 int[] frameComponent = frameComponents[componentIds[scanComponent]];
670 int hi = frameComponent[HI];
671 int vi = frameComponent[VI];
672 if (nComponentsInScan == 1) {
673 hi = 1;
674 vi = 1;
675 }
676 int compWidth = frameComponent[CW];
677 for (int ivi = 0; ivi < vi; ivi++) {
678 for (int ihi = 0; ihi < hi; ihi++) {
679 if (progressive) {
680 // Progressive: First scan - create a new data unit.
681 // Subsequent scans - refine the existing data unit.
682 int index = (ymcu * vi + ivi) * compWidth + xmcu * hi + ihi;
683 dataUnit = dataUnits[scanComponent][index];
684 if (dataUnit == null) {
685 dataUnit = new int[64];
686 dataUnits[scanComponent][index] = dataUnit;
687 }
688 } else {
689 // Sequential: Clear and reuse the data unit buffer.
690 for (int i = 0; i < dataUnit.length; i++) {
691 dataUnit[i] = 0;
692 }
693 }
694 if (!progressive || scanHeader.isDCProgressiveScan()) {
695 decodeDCCoefficient(dataUnit, scanComponent, first, approxBit);
696 }
697 if (!progressive) {
698 decodeACCoefficients(dataUnit, scanComponent);
699 } else {
700 if (scanHeader.isACProgressiveScan()) {
701 if (first) {
702 decodeACFirstCoefficients(dataUnit, scanComponent, start, end, approxBit);
703 } else {
704 decodeACRefineCoefficients(dataUnit, scanComponent, start, end, approxBit);
705 }
706 }
707 if (loader.hasListeners()) {
708 // Dequantization, IDCT, up-sampling and color conversion
709 // are done on a copy of the coefficient data in order to
710 // display the image incrementally.
711 dataUnit.length = 64;
712 }
713 }
714 if (!progressive || (progressive && loader.hasListeners())) {
715 dequantize(dataUnit, scanComponent);
716 inverseDCT(dataUnit);
717 storeData(dataUnit, scanComponent, xmcu, ymcu, hi, ihi, vi, ivi);
718 }
719 }
720 }
721 }
722 }
723 void decodeScan() {
724 if (progressive && !scanHeader.verifyProgressiveScan()) {
725 SWT.error(SWT.ERROR_INVALID_IMAGE);
726 }
727 int nComponentsInScan = scanHeader.getNumberOfImageComponents();
728 int mcuRowsInScan = interleavedMcuRows;
729 int mcusPerRow = interleavedMcuCols;
730 if (nComponentsInScan == 1) {
731 // Non-interleaved.
732 int scanComponent = 0;
733 while (scanHeader.componentParameters[componentIds[scanComponent]] == null) {
734 scanComponent++;
735 }
736 int[] frameComponent = frameComponents[componentIds[scanComponent]];
737 int hi = frameComponent[HI];
738 int vi = frameComponent[VI];
739 int mcuWidth = DCTSIZE * maxH / hi;
740 int mcuHeight = DCTSIZE * maxV / vi;
741 mcusPerRow = (imageWidth + mcuWidth - 1) / mcuWidth;
742 mcuRowsInScan = (imageHeight + mcuHeight - 1) / mcuHeight;
743 }
744 bool first = scanHeader.isFirstScan();
745 int start = scanHeader.getStartOfSpectralSelection();
746 int end = scanHeader.getEndOfSpectralSelection();
747 int approxBit = scanHeader.getApproxBitPositionLow();
748 restartsToGo = restartInterval;
749 nextRestartNumber = 0;
750 for (int ymcu = 0; ymcu < mcuRowsInScan; ymcu++) {
751 for (int xmcu = 0; xmcu < mcusPerRow; xmcu++) {
752 if (restartInterval != 0) {
753 if (restartsToGo == 0) processRestartInterval();
754 restartsToGo--;
755 }
756 decodeMCUAtXAndY(xmcu, ymcu, nComponentsInScan, first, start, end, approxBit);
757 }
758 }
759 }
760 int decodeUsingTable(JPEGHuffmanTable huffmanTable) {
761 int i = 0;
762 int[] maxCodes = huffmanTable.getDhMaxCodes();
763 int[] minCodes = huffmanTable.getDhMinCodes();
764 int[] valPtrs = huffmanTable.getDhValPtrs();
765 int[] huffVals = huffmanTable.getDhValues();
766 int code = nextBit();
767 while (code > maxCodes[i]) {
768 code = code * 2 + nextBit();
769 i++;
770 }
771 int j = valPtrs[i] + code - minCodes[i];
772 return huffVals[j];
773 }
774 void emit(int huffCode, int nBits) {
775 if (nBits == 0) {
776 SWT.error(SWT.ERROR_INVALID_IMAGE);
777 }
778 int[] power2m1 = [
779 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
780 16383, 32767, 65535, 131125
781 ];
782 int code = (huffCode & power2m1[nBits - 1]) << (24 - nBits - currentBitCount);
783 byte[] codeBuffer = new byte[4];
784 codeBuffer[0] = cast(byte)(code & 0xFF);
785 codeBuffer[1] = cast(byte)((code >> 8) & 0xFF);
786 codeBuffer[2] = cast(byte)((code >> 16) & 0xFF);
787 codeBuffer[3] = cast(byte)((code >> 24) & 0xFF);
788 int abs = nBits - (8 - currentBitCount);
789 if (abs < 0) abs = -abs;
790 if ((abs >> 3) > 0) {
791 currentByte += codeBuffer[2];
792 emitByte(cast(byte)currentByte);
793 emitByte(codeBuffer[1]);
794 currentByte = codeBuffer[0];
795 currentBitCount += nBits - 16;
796 } else {
797 currentBitCount += nBits;
798 if (currentBitCount >= 8) {
799 currentByte += codeBuffer[2];
800 emitByte(cast(byte)currentByte);
801 currentByte = codeBuffer[1];
802 currentBitCount -= 8;
803 } else {
804 currentByte += codeBuffer[2];
805 }
806 }
807 }
808 void emitByte(byte byteValue) {
809 if (bufferCurrentPosition >= 512) {
810 resetOutputBuffer();
811 }
812 dataBuffer[bufferCurrentPosition] = byteValue;
813 bufferCurrentPosition++;
814 if (byteValue == -1) {
815 emitByte(cast(byte)0);
816 }
817 }
818 void encodeACCoefficients(int[] dataUnit, int iComp) {
819 int[] sParams = scanHeader.componentParameters[iComp];
820 JPEGHuffmanTable acTable = acHuffmanTables[sParams[AC]];
821 int[] ehCodes = acTable.ehCodes;
822 byte[] ehSizes = acTable.ehCodeLengths;
823 int r = 0;
824 int k = 1;
825 while (k < 64) {
826 k++;
827 int acValue = dataUnit[ZigZag8x8[k - 1]];
828 if (acValue == 0) {
829 if (k == 64) {
830 emit(ehCodes[0], ehSizes[0] & 0xFF);
831 } else {
832 r++;
833 }
834 } else {
835 while (r > 15) {
836 emit(ehCodes[0xF0], ehSizes[0xF0] & 0xFF);
837 r -= 16;
838 }
839 if (acValue < 0) {
840 int absACValue = acValue;
841 if (absACValue < 0) absACValue = -absACValue;
842 int nBits = NBitsTable[absACValue];
843 int rs = r * 16 + nBits;
844 emit(ehCodes[rs], ehSizes[rs] & 0xFF);
845 emit(0xFFFFFF - absACValue, nBits);
846 } else {
847 int nBits = NBitsTable[acValue];
848 int rs = r * 16 + nBits;
849 emit(ehCodes[rs], ehSizes[rs] & 0xFF);
850 emit(acValue, nBits);
851 }
852 r = 0;
853 }
854 }
855 }
856 void encodeDCCoefficients(int[] dataUnit, int iComp) {
857 int[] sParams = scanHeader.componentParameters[iComp];
858 JPEGHuffmanTable dcTable = dcHuffmanTables[sParams[DC]];
859 int lastDC = precedingDCs[iComp];
860 int dcValue = dataUnit[0];
861 int diff = dcValue - lastDC;
862 precedingDCs[iComp] = dcValue;
863 if (diff < 0) {
864 int absDiff = 0 - diff;
865 int nBits = NBitsTable[absDiff];
866 emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
867 emit(0xFFFFFF - absDiff, nBits);
868 } else {
869 int nBits = NBitsTable[diff];
870 emit(dcTable.ehCodes[nBits], dcTable.ehCodeLengths[nBits]);
871 if (nBits != 0) {
872 emit(diff, nBits);
873 }
874 }
875 }
876 void encodeMCUAtXAndY(int xmcu, int ymcu) {
877 int nComponentsInScan = scanHeader.getNumberOfImageComponents();
878 dataUnit = new int[64];
879 for (int iComp = 0; iComp < nComponentsInScan; iComp++) {
880 int[] frameComponent = frameComponents[componentIds[iComp]];
881 int hi = frameComponent[HI];
882 int vi = frameComponent[VI];
883 for (int ivi = 0; ivi < vi; ivi++) {
884 for (int ihi = 0; ihi < hi; ihi++) {
885 extractData(dataUnit, iComp, xmcu, ymcu, ihi, ivi);
886 forwardDCT(dataUnit);
887 quantizeData(dataUnit, iComp);
888 encodeDCCoefficients(dataUnit, iComp);
889 encodeACCoefficients(dataUnit, iComp);
890 }
891 }
892 }
893 }
894 void encodeScan() {
895 for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
896 for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
897 encodeMCUAtXAndY(xmcu, ymcu);
898 }
899 }
900 if (currentBitCount != 0) {
901 emitByte(cast(byte)currentByte);
902 }
903 resetOutputBuffer();
904 }
905 void expandImageComponents() {
906 for (int iComp = 0; iComp < nComponents; iComp++) {
907 int[] frameComponent = frameComponents[componentIds[iComp]];
908 int hi = frameComponent[HI];
909 int vi = frameComponent[VI];
910 int upH = maxH / hi;
911 int upV = maxV / vi;
912 if ((upH * upV) > 1) {
913 byte[] component = imageComponents[iComp];
914 int compWidth = frameComponent[CW];
915 int compHeight = frameComponent[CH];
916 int upCompWidth = compWidth * upH;
917 int upCompHeight = compHeight * upV;
918 ImageData src = new ImageData(compWidth, compHeight, 8, new PaletteData(RGB16), 4, component);
919 ImageData dest = src.scaledTo(upCompWidth, upCompHeight);
920 imageComponents[iComp] = dest.data;
921 }
922 }
923 }
924 int extendBy(int diff, int t) {
925 if (diff < ExtendTest[t]) {
926 return diff + ExtendOffset[t];
927 } else {
928 return diff;
929 }
930 }
931 void extractData(int[] dataUnit, int iComp, int xmcu, int ymcu, int ihi, int ivi) {
932 byte[] compImage = imageComponents[iComp];
933 int[] frameComponent = frameComponents[componentIds[iComp]];
934 int hi = frameComponent[HI];
935 int vi = frameComponent[VI];
936 int compWidth = frameComponent[CW];
937 int srcIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE) + ((xmcu * hi + ihi) * DCTSIZE);
938 int destIndex = 0;
939 for (int i = 0; i < DCTSIZE; i++) {
940 for (int col = 0; col < DCTSIZE; col++) {
941 dataUnit[destIndex] = (compImage[srcIndex + col] & 0xFF) - 128;
942 destIndex++;
943 }
944 srcIndex += compWidth;
945 }
946 }
947 void forwardDCT(int[] dataUnit) {
948 for (int row = 0; row < 8; row++) {
949 int rIndex = row * DCTSIZE;
950 int tmp0 = dataUnit[rIndex] + dataUnit[rIndex + 7];
951 int tmp7 = dataUnit[rIndex] - dataUnit[rIndex + 7];
952 int tmp1 = dataUnit[rIndex + 1] + dataUnit[rIndex + 6];
953 int tmp6 = dataUnit[rIndex + 1] - dataUnit[rIndex + 6];
954 int tmp2 = dataUnit[rIndex + 2] + dataUnit[rIndex + 5];
955 int tmp5 = dataUnit[rIndex + 2] - dataUnit[rIndex + 5];
956 int tmp3 = dataUnit[rIndex + 3] + dataUnit[rIndex + 4];
957 int tmp4 = dataUnit[rIndex + 3] - dataUnit[rIndex + 4];
958
959 /**
960 * Even part per LL&M figure 1 --- note that published figure
961 * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
962 */
963 int tmp10 = tmp0 + tmp3;
964 int tmp13 = tmp0 - tmp3;
965 int tmp11 = tmp1 + tmp2;
966 int tmp12 = tmp1 - tmp2;
967
968 dataUnit[rIndex] = (tmp10 + tmp11) * 4;
969 dataUnit[rIndex + 4] = (tmp10 - tmp11) * 4;
970
971 int z1 = (tmp12 + tmp13) * FIX_0_541196100;
972 int n = z1 + (tmp13 * FIX_0_765366865) + 1024;
973 dataUnit[rIndex + 2] = n >> 11;
974 if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 2]--;
975 n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 1024;
976 dataUnit[rIndex + 6] = n >> 11;
977 if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 6]--;
978
979 /**
980 * Odd part per figure 8 --- note paper omits factor of sqrt(2).
981 * cK represents cos(K*pi/16).
982 * i0..i3 in the paper are tmp4..tmp7 here.
983 */
984 z1 = tmp4 + tmp7;
985 int z2 = tmp5 + tmp6;
986 int z3 = tmp4 + tmp6;
987 int z4 = tmp5 + tmp7;
988 int z5 = (z3 + z4) * FIX_1_175875602; // sqrt(2) * c3
989
990 tmp4 *= FIX_0_298631336; // sqrt(2) * (-c1+c3+c5-c7)
991 tmp5 *= FIX_2_053119869; // sqrt(2) * ( c1+c3-c5+c7)
992 tmp6 *= FIX_3_072711026; // sqrt(2) * ( c1+c3+c5-c7)
993 tmp7 *= FIX_1_501321110; // sqrt(2) * ( c1+c3-c5-c7)
994 z1 *= 0 - FIX_0_899976223; // sqrt(2) * (c7-c3)
995 z2 *= 0 - FIX_2_562915447; // sqrt(2) * (-c1-c3)
996 z3 *= 0 - FIX_1_961570560; // sqrt(2) * (-c3-c5)
997 z4 *= 0 - FIX_0_390180644; // sqrt(2) * (c5-c3)
998
999 z3 += z5;
1000 z4 += z5;
1001
1002 n = tmp4 + z1 + z3 + 1024;
1003 dataUnit[rIndex + 7] = n >> 11;
1004 if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 7]--;
1005 n = tmp5 + z2 + z4 + 1024;
1006 dataUnit[rIndex + 5] = n >> 11;
1007 if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 5]--;
1008 n = tmp6 + z2 + z3 + 1024;
1009 dataUnit[rIndex + 3] = n >> 11;
1010 if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 3]--;
1011 n = tmp7 + z1 + z4 + 1024;
1012 dataUnit[rIndex + 1] = n >> 11;
1013 if ((n < 0) && ((n & 0x07FF) != 0)) dataUnit[rIndex + 1]--;
1014 }
1015
1016 /**
1017 * Pass 2: process columns.
1018 * Note that we must descale the results by a factor of 8 == 2**3,
1019 * and also undo the PASS1_BITS scaling.
1020 */
1021 for (int col = 0; col < 8; col++) {
1022 int c0 = col;
1023 int c1 = col + 8;
1024 int c2 = col + 16;
1025 int c3 = col + 24;
1026 int c4 = col + 32;
1027 int c5 = col + 40;
1028 int c6 = col + 48;
1029 int c7 = col + 56;
1030 int tmp0 = dataUnit[c0] + dataUnit[c7];
1031 int tmp7 = dataUnit[c0] - dataUnit[c7];
1032 int tmp1 = dataUnit[c1] + dataUnit[c6];
1033 int tmp6 = dataUnit[c1] - dataUnit[c6];
1034 int tmp2 = dataUnit[c2] + dataUnit[c5];
1035 int tmp5 = dataUnit[c2] - dataUnit[c5];
1036 int tmp3 = dataUnit[c3] + dataUnit[c4];
1037 int tmp4 = dataUnit[c3] - dataUnit[c4];
1038
1039 /**
1040 * Even part per LL&M figure 1 --- note that published figure
1041 * is faulty; rotator 'sqrt(2)*c1' should be 'sqrt(2)*c6'.
1042 */
1043 int tmp10 = tmp0 + tmp3;
1044 int tmp13 = tmp0 - tmp3;
1045 int tmp11 = tmp1 + tmp2;
1046 int tmp12 = tmp1 - tmp2;
1047
1048 int n = tmp10 + tmp11 + 16;
1049 dataUnit[c0] = n >> 5;
1050 if ((n < 0) && ((n & 0x1F) != 0)) dataUnit[c0]--;
1051 n = tmp10 - tmp11 + 16;
1052 dataUnit[c4] = n >> 5;
1053 if ((n < 0) && ((n & 0x1F) != 0)) dataUnit[c4]--;
1054
1055 int z1 = (tmp12 + tmp13) * FIX_0_541196100;
1056 n = z1 + (tmp13 * FIX_0_765366865) + 131072;
1057 dataUnit[c2] = n >> 18;
1058 if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c2]--;
1059 n = z1 + (tmp12 * (0 - FIX_1_847759065)) + 131072;
1060 dataUnit[c6] = n >> 18;
1061 if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c6]--;
1062
1063 /**
1064 * Odd part per figure 8 --- note paper omits factor of sqrt(2).
1065 * cK represents cos(K*pi/16).
1066 * i0..i3 in the paper are tmp4..tmp7 here.
1067 */
1068 z1 = tmp4 + tmp7;
1069 int z2 = tmp5 + tmp6;
1070 int z3 = tmp4 + tmp6;
1071 int z4 = tmp5 + tmp7;
1072 int z5 = (z3 + z4) * FIX_1_175875602; // sqrt(2) * c3
1073
1074 tmp4 *= FIX_0_298631336; // sqrt(2) * (-c1+c3+c5-c7)
1075 tmp5 *= FIX_2_053119869; // sqrt(2) * ( c1+c3-c5+c7)
1076 tmp6 *= FIX_3_072711026; // sqrt(2) * ( c1+c3+c5-c7)
1077 tmp7 *= FIX_1_501321110; // sqrt(2) * ( c1+c3-c5-c7)
1078 z1 *= 0 - FIX_0_899976223; // sqrt(2) * (c7-c3)
1079 z2 *= 0 - FIX_2_562915447; // sqrt(2) * (-c1-c3)
1080 z3 *= 0 - FIX_1_961570560; // sqrt(2) * (-c3-c5)
1081 z4 *= 0 - FIX_0_390180644; // sqrt(2) * (c5-c3)
1082
1083 z3 += z5;
1084 z4 += z5;
1085
1086 n = tmp4 + z1 + z3 + 131072;
1087 dataUnit[c7] = n >> 18;
1088 if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c7]--;
1089 n = tmp5 + z2 + z4 + 131072;
1090 dataUnit[c5] = n >> 18;
1091 if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c5]--;
1092 n = tmp6 + z2 + z3 + 131072;
1093 dataUnit[c3] = n >> 18;
1094 if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c3]--;
1095 n = tmp7 + z1 + z4 + 131072;
1096 dataUnit[c1] = n >> 18;
1097 if ((n < 0) && ((n & 0x3FFFF) != 0)) dataUnit[c1]--;
1098 }
1099 }
1100 void getAPP0() {
1101 JPEGAppn appn = new JPEGAppn(inputStream);
1102 if (!appn.verify()) {
1103 SWT.error(SWT.ERROR_INVALID_IMAGE);
1104 }
1105 }
1106 void getCOM() {
1107 new JPEGComment(inputStream);
1108 }
1109 void getDAC() {
1110 new JPEGArithmeticConditioningTable(inputStream);
1111 }
1112 void getDHT() {
1113 JPEGHuffmanTable dht = new JPEGHuffmanTable(inputStream);
1114 if (!dht.verify()) {
1115 SWT.error(SWT.ERROR_INVALID_IMAGE);
1116 }
1117 if (acHuffmanTables == null) {
1118 acHuffmanTables = new JPEGHuffmanTable[4];
1119 }
1120 if (dcHuffmanTables == null) {
1121 dcHuffmanTables = new JPEGHuffmanTable[4];
1122 }
1123 JPEGHuffmanTable[] dhtTables = dht.getAllTables();
1124 for (int i = 0; i < dhtTables.length; i++) {
1125 JPEGHuffmanTable dhtTable = dhtTables[i];
1126 if (dhtTable.getTableClass() == 0) {
1127 dcHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
1128 } else {
1129 acHuffmanTables[dhtTable.getTableIdentifier()] = dhtTable;
1130 }
1131 }
1132 }
1133 void getDNL() {
1134 new JPEGRestartInterval(inputStream);
1135 }
1136 void getDQT() {
1137 JPEGQuantizationTable dqt = new JPEGQuantizationTable(inputStream);
1138 int[][] currentTables = quantizationTables;
1139 if (currentTables == null) {
1140 currentTables = new int[][](4);
1141 }
1142 int[] dqtTablesKeys = dqt.getQuantizationTablesKeys();
1143 int[][] dqtTablesValues = dqt.getQuantizationTablesValues();
1144 for (int i = 0; i < dqtTablesKeys.length; i++) {
1145 int index = dqtTablesKeys[i];
1146 currentTables[index] = dqtTablesValues[i];
1147 }
1148 quantizationTables = currentTables;
1149 }
1150 void getDRI() {
1151 JPEGRestartInterval dri = new JPEGRestartInterval(inputStream);
1152 if (!dri.verify()) {
1153 SWT.error(SWT.ERROR_INVALID_IMAGE);
1154 }
1155 restartInterval = dri.getRestartInterval();
1156 }
1157 static void initialize() {
1158 initializeRGBYCbCrTables();
1159 initializeYCbCrRGBTables();
1160 initializeBitCountTable();
1161 }
1162 static void initializeBitCountTable() {
1163 int nBits = 1;
1164 int power2 = 2;
1165 NBitsTable = new int[2048];
1166 NBitsTable[0] = 0;
1167 for (int i = 1; i < NBitsTable.length; i++) {
1168 if (!(i < power2)) {
1169 nBits++;
1170 power2 *= 2;
1171 }
1172 NBitsTable[i] = nBits;
1173 }
1174 }
1175 static void initializeRGBYCbCrTables() {
1176 RYTable = new int[256];
1177 GYTable = new int[256];
1178 BYTable = new int[256];
1179 RCbTable = new int[256];
1180 GCbTable = new int[256];
1181 BCbTable = new int[256];
1182 RCrTable = BCbTable;
1183 GCrTable = new int[256];
1184 BCrTable = new int[256];
1185 for (int i = 0; i < 256; i++) {
1186 RYTable[i] = i * 19595;
1187 GYTable[i] = i * 38470;
1188 BYTable[i] = i * 7471 + 32768;
1189 RCbTable[i] = i * -11059;
1190 GCbTable[i] = i * -21709;
1191 BCbTable[i] = i * 32768 + 8388608;
1192 GCrTable[i] = i * -27439;
1193 BCrTable[i] = i * -5329;
1194 }
1195 }
1196 static void initializeYCbCrRGBTables() {
1197 CrRTable = new int[256];
1198 CbBTable = new int[256];
1199 CrGTable = new int[256];
1200 CbGTable = new int[256];
1201 for (int i = 0; i < 256; i++) {
1202 int x2 = 2 * i - 255;
1203 CrRTable[i] = (45941 * x2 + 32768) >> 16;
1204 CbBTable[i] = (58065 * x2 + 32768) >> 16;
1205 CrGTable[i] = -23401 * x2;
1206 CbGTable[i] = -11277 * x2 + 32768;
1207 }
1208 }
1209 void inverseDCT(int[] dataUnit) {
1210 for (int row = 0; row < 8; row++) {
1211 int rIndex = row * DCTSIZE;
1212 /**
1213 * Due to quantization, we will usually find that many of the input
1214 * coefficients are zero, especially the AC terms. We can exploit this
1215 * by short-circuiting the IDCT calculation for any row in which all
1216 * the AC terms are zero. In that case each output is equal to the
1217 * DC coefficient (with scale factor as needed).
1218 * With typical images and quantization tables, half or more of the
1219 * row DCT calculations can be simplified this way.
1220 */
1221 if (isZeroInRow(dataUnit, rIndex)) {
1222 int dcVal = dataUnit[rIndex] << 2;
1223 for (int i = rIndex + 7; i >= rIndex; i--) {
1224 dataUnit[i] = dcVal;
1225 }
1226 } else {
1227 /**
1228 * Even part: reverse the even part of the forward DCT.
1229 * The rotator is sqrt(2)*c(-6).
1230 */
1231 int z2 = dataUnit[rIndex + 2];
1232 int z3 = dataUnit[rIndex + 6];
1233 int z1 = (z2 + z3) * FIX_0_541196100;
1234 int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
1235 int tmp3 = z1 + (z2 * FIX_0_765366865);
1236 int tmp0 = (dataUnit[rIndex] + dataUnit[rIndex + 4]) << 13;
1237 int tmp1 = (dataUnit[rIndex] - dataUnit[rIndex + 4]) << 13;
1238 int tmp10 = tmp0 + tmp3;
1239 int tmp13 = tmp0 - tmp3;
1240 int tmp11 = tmp1 + tmp2;
1241 int tmp12 = tmp1 - tmp2;
1242 /**
1243 * Odd part per figure 8; the matrix is unitary and hence its
1244 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
1245 */
1246 tmp0 = dataUnit[rIndex + 7];
1247 tmp1 = dataUnit[rIndex + 5];
1248 tmp2 = dataUnit[rIndex + 3];
1249 tmp3 = dataUnit[rIndex + 1];
1250 z1 = tmp0 + tmp3;
1251 z2 = tmp1 + tmp2;
1252 z3 = tmp0 + tmp2;
1253 int z4 = tmp1 + tmp3;
1254 int z5 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */
1255
1256 tmp0 *= FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
1257 tmp1 *= FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
1258 tmp2 *= FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
1259 tmp3 *= FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
1260 z1 *= 0 - FIX_0_899976223; /* sqrt(2) * (c7-c3) */
1261 z2 *= 0 - FIX_2_562915447; /* sqrt(2) * (-c1-c3) */
1262 z3 *= 0 - FIX_1_961570560; /* sqrt(2) * (-c3-c5) */
1263 z4 *= 0 - FIX_0_390180644; /* sqrt(2) * (c5-c3) */
1264
1265 z3 += z5;
1266 z4 += z5;
1267 tmp0 += z1 + z3;
1268 tmp1 += z2 + z4;
1269 tmp2 += z2 + z3;
1270 tmp3 += z1 + z4;
1271
1272 dataUnit[rIndex] = (tmp10 + tmp3 + 1024) >> 11;
1273 dataUnit[rIndex + 7] = (tmp10 - tmp3 + 1024) >> 11;
1274 dataUnit[rIndex + 1] = (tmp11 + tmp2 + 1024) >> 11;
1275 dataUnit[rIndex + 6] = (tmp11 - tmp2 + 1024) >> 11;
1276 dataUnit[rIndex + 2] = (tmp12 + tmp1 + 1024) >> 11;
1277 dataUnit[rIndex + 5] = (tmp12 - tmp1 + 1024) >> 11;
1278 dataUnit[rIndex + 3] = (tmp13 + tmp0 + 1024) >> 11;
1279 dataUnit[rIndex + 4] = (tmp13 - tmp0 + 1024) >> 11;
1280 }
1281 }
1282 /**
1283 * Pass 2: process columns.
1284 * Note that we must descale the results by a factor of 8 == 2**3,
1285 * and also undo the PASS1_BITS scaling.
1286 */
1287 for (int col = 0; col < 8; col++) {
1288 int c0 = col;
1289 int c1 = col + 8;
1290 int c2 = col + 16;
1291 int c3 = col + 24;
1292 int c4 = col + 32;
1293 int c5 = col + 40;
1294 int c6 = col + 48;
1295 int c7 = col + 56;
1296 if (isZeroInColumn(dataUnit, col)) {
1297 int dcVal = (dataUnit[c0] + 16) >> 5;
1298 dataUnit[c0] = dcVal;
1299 dataUnit[c1] = dcVal;
1300 dataUnit[c2] = dcVal;
1301 dataUnit[c3] = dcVal;
1302 dataUnit[c4] = dcVal;
1303 dataUnit[c5] = dcVal;
1304 dataUnit[c6] = dcVal;
1305 dataUnit[c7] = dcVal;
1306 } else {
1307 /**
1308 * Even part: reverse the even part of the forward DCT.
1309 * The rotator is sqrt(2)*c(-6).
1310 */
1311 int z0 = dataUnit[c0];
1312 int z2 = dataUnit[c2];
1313 int z3 = dataUnit[c6];
1314 int z4 = dataUnit[c4];
1315 int z1 = (z2 + z3) * FIX_0_541196100;
1316 int tmp2 = z1 + (z3 * (0 - FIX_1_847759065));
1317 int tmp3 = z1 + (z2 * FIX_0_765366865);
1318 int tmp0 = (z0 + z4) << 13;
1319 int tmp1 = (z0 - z4) << 13;
1320 int tmp10 = tmp0 + tmp3;
1321 int tmp13 = tmp0 - tmp3;
1322 int tmp11 = tmp1 + tmp2;
1323 int tmp12 = tmp1 - tmp2;
1324 /**
1325 * Odd part per figure 8; the matrix is unitary and hence its
1326 * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
1327 */
1328 tmp0 = dataUnit[c7];
1329 tmp1 = dataUnit[c5];
1330 tmp2 = dataUnit[c3];
1331 tmp3 = dataUnit[c1];
1332 z1 = tmp0 + tmp3;
1333 z2 = tmp1 + tmp2;
1334 z3 = tmp0 + tmp2;
1335 z4 = tmp1 + tmp3;
1336 z0 = (z3 + z4) * FIX_1_175875602; /* sqrt(2) * c3 */
1337
1338 tmp0 *= FIX_0_298631336; /* sqrt(2) * (-c1+c3+c5-c7) */
1339 tmp1 *= FIX_2_053119869; /* sqrt(2) * ( c1+c3-c5+c7) */
1340 tmp2 *= FIX_3_072711026; /* sqrt(2) * ( c1+c3+c5-c7) */
1341 tmp3 *= FIX_1_501321110; /* sqrt(2) * ( c1+c3-c5-c7) */
1342 z1 *= 0 - FIX_0_899976223; /* sqrt(2) * (c7-c3) */
1343 z2 *= 0 - FIX_2_562915447; /* sqrt(2) * (-c1-c3) */
1344 z3 *= 0 - FIX_1_961570560; /* sqrt(2) * (-c3-c5) */
1345 z4 *= 0 - FIX_0_390180644; /* sqrt(2) * (c5-c3) */
1346
1347 z3 += z0;
1348 z4 += z0;
1349
1350 tmp0 += z1 + z3;
1351 tmp1 += z2 + z4;
1352 tmp2 += z2 + z3;
1353 tmp3 += z1 + z4;
1354
1355 /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
1356 dataUnit[c0] = (tmp10 + tmp3 + 131072) >> 18;
1357 dataUnit[c7] = (tmp10 - tmp3 + 131072) >> 18;
1358 dataUnit[c1] = (tmp11 + tmp2 + 131072) >> 18;
1359 dataUnit[c6] = (tmp11 - tmp2 + 131072) >> 18;
1360 dataUnit[c2] = (tmp12 + tmp1 + 131072) >> 18;
1361 dataUnit[c5] = (tmp12 - tmp1 + 131072) >> 18;
1362 dataUnit[c3] = (tmp13 + tmp0 + 131072) >> 18;
1363 dataUnit[c4] = (tmp13 - tmp0 + 131072) >> 18;
1364 }
1365 }
1366 }
1367 bool isFileFormat(LEDataInputStream stream) {
1368 try {
1369 JPEGStartOfImage soi = new JPEGStartOfImage(stream);
1370 stream.unread(soi.reference);
1371 return soi.verify(); // we no longer check for appN
1372 } catch (TracedException e) {
1373 return false;
1374 }
1375 }
1376 bool isZeroInColumn(int[] dataUnit, int col) {
1377 return dataUnit[col + 8] == 0 && dataUnit[col + 16] == 0
1378 && dataUnit[col + 24] == 0 && dataUnit[col + 32] == 0
1379 && dataUnit[col + 40] == 0 && dataUnit[col + 48] == 0
1380 && dataUnit[col + 56] == 0;
1381 }
1382 bool isZeroInRow(int[] dataUnit, int rIndex) {
1383 return dataUnit[rIndex + 1] == 0 && dataUnit[rIndex + 2] == 0
1384 && dataUnit[rIndex + 3] == 0 && dataUnit[rIndex + 4] == 0
1385 && dataUnit[rIndex + 5] == 0 && dataUnit[rIndex + 6] == 0
1386 && dataUnit[rIndex + 7] == 0;
1387 }
1388 ImageData[] loadFromByteStream() {
1389 //TEMPORARY CODE
1390 //PORTING_FIXME
1391 if (/+System.getProperty("dwt.internal.image.JPEGFileFormat_3.2") == null+/ true ) {
1392 return JPEGDecoder.loadFromByteStream(inputStream, loader);
1393 }
1394 JPEGStartOfImage soi = new JPEGStartOfImage(inputStream);
1395 if (!soi.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
1396 restartInterval = 0;
1397
1398 /* Process the tables preceding the frame header. */
1399 processTables();
1400
1401 /* Start of Frame. */
1402 frameHeader = new JPEGFrameHeader(inputStream);
1403 if (!frameHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
1404 imageWidth = frameHeader.getSamplesPerLine();
1405 imageHeight = frameHeader.getNumberOfLines();
1406 maxH = frameHeader.getMaxHFactor();
1407 maxV = frameHeader.getMaxVFactor();
1408 int mcuWidth = maxH * DCTSIZE;
1409 int mcuHeight = maxV * DCTSIZE;
1410 interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
1411 interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
1412 progressive = frameHeader.isProgressive();
1413 samplePrecision = frameHeader.getSamplePrecision();
1414 nComponents = frameHeader.getNumberOfImageComponents();
1415 frameComponents = frameHeader.componentParameters;
1416 componentIds = frameHeader.componentIdentifiers;
1417 imageComponents = new byte[][](nComponents);
1418 if (progressive) {
1419 // Progressive jpeg: need to keep all of the data units.
1420 dataUnits = new int[][][](nComponents);
1421 } else {
1422 // Sequential jpeg: only need one data unit.
1423 dataUnit = new int[8 * 8];
1424 }
1425 for (int i = 0; i < nComponents; i++) {
1426 int[] frameComponent = frameComponents[componentIds[i]];
1427 int bufferSize = frameComponent[CW] * frameComponent[CH];
1428 imageComponents[i] = new byte[bufferSize];
1429 if (progressive) {
1430 dataUnits[i] = new int[][](bufferSize);
1431 }
1432 }
1433
1434 /* Process the tables preceding the scan header. */
1435 processTables();
1436
1437 /* Start of Scan. */
1438 scanHeader = new JPEGScanHeader(inputStream);
1439 if (!scanHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
1440
1441 /* Process scan(s) and further tables until EOI. */
1442 int progressiveScanCount = 0;
1443 bool done = false;
1444 while(!done) {
1445 resetInputBuffer();
1446 precedingDCs = new int[4];
1447 decodeScan();
1448 if (progressive && loader.hasListeners()) {
1449 ImageData imageData = createImageData();
1450 loader.notifyListeners(new ImageLoaderEvent(loader, imageData, progressiveScanCount, false));
1451 progressiveScanCount++;
1452 }
1453
1454 /* Unread any buffered data before looking for tables again. */
1455 int delta = 512 - bufferCurrentPosition - 1;
1456 if (delta > 0) {
1457 byte[] unreadBuffer = new byte[delta];
1458 unreadBuffer[ 0 .. delta ] = dataBuffer[ bufferCurrentPosition+1 .. bufferCurrentPosition+1+delta ];
1459 try {
1460 inputStream.unread(unreadBuffer);
1461 } catch (IOException e) {
1462 SWT.error(SWT.ERROR_IO, e);
1463 }
1464 }
1465
1466 /* Process the tables preceding the next scan header. */
1467 JPEGSegment jpegSegment = processTables();
1468 if (jpegSegment == null || jpegSegment.getSegmentMarker() == EOI) {
1469 done = true;
1470 } else {
1471 scanHeader = new JPEGScanHeader(inputStream);
1472 if (!scanHeader.verify()) SWT.error(SWT.ERROR_INVALID_IMAGE);
1473 }
1474 }
1475
1476 if (progressive) {
1477 for (int ymcu = 0; ymcu < interleavedMcuRows; ymcu++) {
1478 for (int xmcu = 0; xmcu < interleavedMcuCols; xmcu++) {
1479 for (int iComp = 0; iComp < nComponents; iComp++) {
1480 int[] frameComponent = frameComponents[componentIds[iComp]];
1481 int hi = frameComponent[HI];
1482 int vi = frameComponent[VI];
1483 int compWidth = frameComponent[CW];
1484 for (int ivi = 0; ivi < vi; ivi++) {
1485 for (int ihi = 0; ihi < hi; ihi++) {
1486 int index = (ymcu * vi + ivi) * compWidth + xmcu * hi + ihi;
1487 dataUnit = dataUnits[iComp][index];
1488 dequantize(dataUnit, iComp);
1489 inverseDCT(dataUnit);
1490 storeData(dataUnit, iComp, xmcu, ymcu, hi, ihi, vi, ivi);
1491 }
1492 }
1493 }
1494 }
1495 }
1496 dataUnits = null; // release memory
1497 }
1498 ImageData imageData = createImageData();
1499 if (progressive && loader.hasListeners()) {
1500 loader.notifyListeners(new ImageLoaderEvent(loader, imageData, progressiveScanCount, true));
1501 }
1502 return [imageData];
1503 }
1504 ImageData createImageData() {
1505 return ImageData.internal_new(
1506 imageWidth,
1507 imageHeight,
1508 nComponents * samplePrecision,
1509 setUpPalette(),
1510 nComponents == 1 ? 4 : 1,
1511 decodeImageComponents(),
1512 0,
1513 null,
1514 null,
1515 -1,
1516 -1,
1517 SWT.IMAGE_JPEG,
1518 0,
1519 0,
1520 0,
1521 0);
1522 }
1523 int nextBit() {
1524 if (currentBitCount != 0) {
1525 currentBitCount--;
1526 currentByte *= 2;
1527 if (currentByte > 255) {
1528 currentByte -= 256;
1529 return 1;
1530 } else {
1531 return 0;
1532 }
1533 }
1534 bufferCurrentPosition++;
1535 if (bufferCurrentPosition >= 512) {
1536 resetInputBuffer();
1537 bufferCurrentPosition = 0;
1538 }
1539 currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1540 currentBitCount = 8;
1541 byte nextByte;
1542 if (bufferCurrentPosition == 511) {
1543 resetInputBuffer();
1544 currentBitCount = 8;
1545 nextByte = dataBuffer[0];
1546 } else {
1547 nextByte = dataBuffer[bufferCurrentPosition + 1];
1548 }
1549 if (currentByte == 0xFF) {
1550 if (nextByte == 0) {
1551 bufferCurrentPosition ++;
1552 currentBitCount--;
1553 currentByte *= 2;
1554 if (currentByte > 255) {
1555 currentByte -= 256;
1556 return 1;
1557 } else {
1558 return 0;
1559 }
1560 } else {
1561 if ((nextByte & 0xFF) + 0xFF00 == DNL) {
1562 getDNL();
1563 return 0;
1564 } else {
1565 SWT.error(SWT.ERROR_INVALID_IMAGE);
1566 return 0;
1567 }
1568 }
1569 } else {
1570 currentBitCount--;
1571 currentByte *= 2;
1572 if (currentByte > 255) {
1573 currentByte -= 256;
1574 return 1;
1575 } else {
1576 return 0;
1577 }
1578 }
1579 }
1580 void processRestartInterval() {
1581 do {
1582 bufferCurrentPosition++;
1583 if (bufferCurrentPosition > 511) {
1584 resetInputBuffer();
1585 bufferCurrentPosition = 0;
1586 }
1587 currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1588 } while (currentByte != 0xFF);
1589 while (currentByte == 0xFF) {
1590 bufferCurrentPosition++;
1591 if (bufferCurrentPosition > 511) {
1592 resetInputBuffer();
1593 bufferCurrentPosition = 0;
1594 }
1595 currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1596 }
1597 if (currentByte != ((RST0 + nextRestartNumber) & 0xFF)) {
1598 SWT.error(SWT.ERROR_INVALID_IMAGE);
1599 }
1600 bufferCurrentPosition++;
1601 if (bufferCurrentPosition > 511) {
1602 resetInputBuffer();
1603 bufferCurrentPosition = 0;
1604 }
1605 currentByte = dataBuffer[bufferCurrentPosition] & 0xFF;
1606 currentBitCount = 8;
1607 restartsToGo = restartInterval;
1608 nextRestartNumber = (nextRestartNumber + 1) & 0x7;
1609 precedingDCs = new int[4];
1610 eobrun = 0;
1611 }
1612 /* Process all markers until a frame header, scan header, or EOI is found. */
1613 JPEGSegment processTables() {
1614 while (true) {
1615 JPEGSegment jpegSegment = seekUnspecifiedMarker(inputStream);
1616 if (jpegSegment == null) return null;
1617 JPEGFrameHeader sof = new JPEGFrameHeader(jpegSegment.reference);
1618 if (sof.verify()) {
1619 return jpegSegment;
1620 }
1621 int marker = jpegSegment.getSegmentMarker();
1622 switch (marker) {
1623 case SOI: // there should only be one SOI per file
1624 SWT.error(SWT.ERROR_INVALID_IMAGE);
1625 case EOI:
1626 case SOS:
1627 return jpegSegment;
1628 case DQT:
1629 getDQT();
1630 break;
1631 case DHT:
1632 getDHT();
1633 break;
1634 case DAC:
1635 getDAC();
1636 break;
1637 case DRI:
1638 getDRI();
1639 break;
1640 case APP0:
1641 getAPP0();
1642 break;
1643 case COM:
1644 getCOM();
1645 break;
1646 default:
1647 skipSegmentFrom(inputStream);
1648
1649 }
1650 }
1651 }
1652 void quantizeData(int[] dataUnit, int iComp) {
1653 int[] qTable = quantizationTables[frameComponents[componentIds[iComp]][TQI]];
1654 for (int i = 0; i < dataUnit.length; i++) {
1655 int zzIndex = ZigZag8x8[i];
1656 int data = dataUnit[zzIndex];
1657 int absData = data < 0 ? 0 - data : data;
1658 int qValue = qTable[i];
1659 int q2 = qValue >> 1;
1660 absData += q2;
1661 if (absData < qValue) {
1662 dataUnit[zzIndex] = 0;
1663 } else {
1664 absData /= qValue;
1665 if (data >= 0) {
1666 dataUnit[zzIndex] = absData;
1667 } else {
1668 dataUnit[zzIndex] = 0 - absData;
1669 }
1670 }
1671 }
1672 }
1673 int receive(int nBits) {
1674 int v = 0;
1675 for (int i = 0; i < nBits; i++) {
1676 v = v * 2 + nextBit();
1677 }
1678 return v;
1679 }
1680 void resetInputBuffer() {
1681 if (dataBuffer == null) {
1682 dataBuffer = new byte[512];
1683 }
1684 try {
1685 inputStream.read(dataBuffer);
1686 } catch (IOException e) {
1687 SWT.error(SWT.ERROR_IO, e);
1688 }
1689 currentBitCount = 0;
1690 bufferCurrentPosition = -1;
1691 }
1692 void resetOutputBuffer() {
1693 if (dataBuffer == null) {
1694 dataBuffer = new byte[512];
1695 } else {
1696 try {
1697 outputStream.write(dataBuffer, 0, bufferCurrentPosition);
1698 } catch (IOException e) {
1699 SWT.error(SWT.ERROR_IO, e);
1700 }
1701 }
1702 bufferCurrentPosition = 0;
1703 }
1704 static JPEGSegment seekUnspecifiedMarker(LEDataInputStream byteStream) {
1705 byte[] byteArray = new byte[2];
1706 try {
1707 while (true) {
1708 if (byteStream.read(byteArray, 0, 1) != 1) return null;
1709 if (byteArray[0] == cast(byte) 0xFF) {
1710 if (byteStream.read(byteArray, 1, 1) != 1) return null;
1711 if (byteArray[1] != cast(byte) 0xFF && byteArray[1] != 0) {
1712 byteStream.unread(byteArray);
1713 return new JPEGSegment(byteArray);
1714 }
1715 }
1716 }
1717 } catch (IOException e) {
1718 SWT.error(SWT.ERROR_IO, e);
1719 }
1720 return null;
1721 }
1722 PaletteData setUpPalette() {
1723 if (nComponents == 1) {
1724 RGB[] entries = new RGB[256];
1725 for (int i = 0; i < 256; i++) {
1726 entries[i] = new RGB(i, i, i);
1727 }
1728 return new PaletteData(entries);
1729 }
1730 return new PaletteData(0xFF, 0xFF00, 0xFF0000);
1731 }
1732 static void skipSegmentFrom(LEDataInputStream byteStream) {
1733 try {
1734 byte[] byteArray = new byte[4];
1735 JPEGSegment jpegSegment = new JPEGSegment(byteArray);
1736
1737 if (byteStream.read(byteArray) != byteArray.length) {
1738 SWT.error(SWT.ERROR_INVALID_IMAGE);
1739 }
1740 if (!(byteArray[0] == -1 && byteArray[1] != 0 && byteArray[1] != -1)) {
1741 SWT.error(SWT.ERROR_INVALID_IMAGE);
1742 }
1743 int delta = jpegSegment.getSegmentLength() - 2;
1744 byteStream.skip(delta);
1745 } catch (TracedException e) {
1746 SWT.error(SWT.ERROR_IO, e);
1747 }
1748 }
1749 void storeData(int[] dataUnit, int iComp, int xmcu, int ymcu, int hi, int ihi, int vi, int ivi) {
1750 byte[] compImage = imageComponents[iComp];
1751 int[] frameComponent = frameComponents[componentIds[iComp]];
1752 int compWidth = frameComponent[CW];
1753 int destIndex = ((ymcu * vi + ivi) * compWidth * DCTSIZE) + ((xmcu * hi + ihi) * DCTSIZE);
1754 int srcIndex = 0;
1755 for (int i = 0; i < DCTSIZE; i++) {
1756 for (int col = 0; col < DCTSIZE; col++) {
1757 int x = dataUnit[srcIndex] + 128;
1758 if (x < 0) {
1759 x = 0;
1760 } else {
1761 if (x > 255) x = 255;
1762 }
1763 compImage[destIndex + col] = cast(byte)x;
1764 srcIndex++;
1765 }
1766 destIndex += compWidth;
1767 }
1768 }
1769 void unloadIntoByteStream(ImageLoader loader) {
1770 ImageData image = loader.data[0];
1771 if (!(new JPEGStartOfImage()).writeToStream(outputStream)) {
1772 SWT.error(SWT.ERROR_IO);
1773 }
1774 JPEGAppn appn = new JPEGAppn([cast(byte)0xFF, cast(byte)0xE0, 0, 0x10, 0x4A, 0x46, 0x49, 0x46, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0]);
1775 if (!appn.writeToStream(outputStream)) {
1776 SWT.error(SWT.ERROR_IO);
1777 }
1778 quantizationTables = new int[][](4);
1779 JPEGQuantizationTable chromDQT = JPEGQuantizationTable.defaultChrominanceTable();
1780 chromDQT.scaleBy(encoderQFactor);
1781 int[] jpegDQTKeys = chromDQT.getQuantizationTablesKeys();
1782 int[][] jpegDQTValues = chromDQT.getQuantizationTablesValues();
1783 for (int i = 0; i < jpegDQTKeys.length; i++) {
1784 quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
1785 }
1786 JPEGQuantizationTable lumDQT = JPEGQuantizationTable.defaultLuminanceTable();
1787 lumDQT.scaleBy(encoderQFactor);
1788 jpegDQTKeys = lumDQT.getQuantizationTablesKeys();
1789 jpegDQTValues = lumDQT.getQuantizationTablesValues();
1790 for (int i = 0; i < jpegDQTKeys.length; i++) {
1791 quantizationTables[jpegDQTKeys[i]] = jpegDQTValues[i];
1792 }
1793 if (!lumDQT.writeToStream(outputStream)) {
1794 SWT.error(SWT.ERROR_IO);
1795 }
1796 if (!chromDQT.writeToStream(outputStream)) {
1797 SWT.error(SWT.ERROR_IO);
1798 }
1799 int frameLength, scanLength, precision;
1800 int[][] frameParams, scanParams;
1801 if (image.depth == 1) {
1802 frameLength = 11;
1803 frameParams = new int[][](1);
1804 frameParams[0] = [1, 1, 1, 0, 0];
1805 scanParams = new int[][](1);
1806 scanParams[0] = [0, 0];
1807 scanLength = 8;
1808 nComponents = 1;
1809 precision = 1;
1810 } else {
1811 frameLength = 17;
1812 frameParams = new int[][](3);
1813 frameParams[0] = [0, 2, 2, 0, 0];
1814 frameParams[1] = [1, 1, 1, 0, 0];
1815 frameParams[2] = [1, 1, 1, 0, 0];
1816 scanParams = new int[][](3);
1817 scanParams[0] = [0, 0];
1818 scanParams[1] = [1, 1];
1819 scanParams[2] = [1, 1];
1820 scanLength = 12;
1821 nComponents = 3;
1822 precision = 8;
1823 }
1824 imageWidth = image.width;
1825 imageHeight = image.height;
1826 frameHeader = new JPEGFrameHeader(new byte[19]);
1827 frameHeader.setSegmentMarker(SOF0);
1828 frameHeader.setSegmentLength(frameLength);
1829 frameHeader.setSamplePrecision(precision);
1830 frameHeader.setSamplesPerLine(imageWidth);
1831 frameHeader.setNumberOfLines(imageHeight);
1832 frameHeader.setNumberOfImageComponents(nComponents);
1833 frameHeader.componentParameters = frameParams;
1834 frameHeader.componentIdentifiers = [0, 1, 2];
1835 frameHeader.initializeContents();
1836 if (!frameHeader.writeToStream(outputStream)) {
1837 SWT.error(SWT.ERROR_IO);
1838 }
1839 frameComponents = frameParams;
1840 componentIds = frameHeader.componentIdentifiers;
1841 maxH = frameHeader.getMaxHFactor();
1842 maxV = frameHeader.getMaxVFactor();
1843 int mcuWidth = maxH * DCTSIZE;
1844 int mcuHeight = maxV * DCTSIZE;
1845 interleavedMcuCols = (imageWidth + mcuWidth - 1) / mcuWidth;
1846 interleavedMcuRows = (imageHeight + mcuHeight - 1) / mcuHeight;
1847 acHuffmanTables = new JPEGHuffmanTable[4];
1848 dcHuffmanTables = new JPEGHuffmanTable[4];
1849 JPEGHuffmanTable[] dhtTables = [
1850 JPEGHuffmanTable.getDefaultDCLuminanceTable(),
1851 JPEGHuffmanTable.getDefaultDCChrominanceTable(),
1852 JPEGHuffmanTable.getDefaultACLuminanceTable(),
1853 JPEGHuffmanTable.getDefaultACChrominanceTable()
1854 ];
1855 for (int i = 0; i < dhtTables.length; i++) {
1856 JPEGHuffmanTable dhtTable = dhtTables[i];
1857 if (!dhtTable.writeToStream(outputStream)) {
1858 SWT.error(SWT.ERROR_IO);
1859 }
1860 JPEGHuffmanTable[] allTables = dhtTable.getAllTables();
1861 for (int j = 0; j < allTables.length; j++) {
1862 JPEGHuffmanTable huffmanTable = allTables[j];
1863 if (huffmanTable.getTableClass() == 0) {
1864 dcHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
1865 } else {
1866 acHuffmanTables[huffmanTable.getTableIdentifier()] = huffmanTable;
1867 }
1868 }
1869 }
1870 precedingDCs = new int[4];
1871 scanHeader = new JPEGScanHeader(new byte[14]);
1872 scanHeader.setSegmentMarker(SOS);
1873 scanHeader.setSegmentLength(scanLength);
1874 scanHeader.setNumberOfImageComponents(nComponents);
1875 scanHeader.setStartOfSpectralSelection(0);
1876 scanHeader.setEndOfSpectralSelection(63);
1877 scanHeader.componentParameters = scanParams;
1878 scanHeader.initializeContents();
1879 if (!scanHeader.writeToStream(outputStream)) {
1880 SWT.error(SWT.ERROR_IO);
1881 }
1882 convertImageToYCbCr(image);
1883 resetOutputBuffer();
1884 currentByte = 0;
1885 currentBitCount = 0;
1886 encodeScan();
1887 if (!(new JPEGEndOfImage()).writeToStream(outputStream)) {
1888 SWT.error(SWT.ERROR_IO);
1889 }
1890 }
1891 }