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