root/dwt/internal/image/JPEGFileFormat.d

Revision 246:fd9c62a2998e, 69.4 kB (checked in by Frank Benoit <benoit@tionex.de>, 6 months ago)

Updater SWT 3.4M7 to 3.4

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved.  This source file is made available under the terms contained in the README file
4  * accompanying this program.  The README file should be located in the about_files directory of the
5  * plug-in that contains this source file.
6  *
7  * Contributors:
8  *     IBM Corporation - initial API and implementation
9  * Port to the D programming language:
10  *     Frank Benoit <benoit@tionex.de>
11  *******************************************************************************/
12 module dwt.internal.image.JPEGFileFormat;
13
14 import dwt.DWT;
15 import dwt.internal.image.JPEGFrameHeader;
16 import dwt.internal.image.JPEGScanHeader;
17 import dwt.internal.image.JPEGHuffmanTable;
18 import dwt.internal.image.JPEGAppn;
19 import dwt.internal.image.JPEGSegment;
20 import dwt.internal.image.FileFormat;
21 import dwt.internal.image.JPEGComment;
22 import dwt.internal.image.JPEGArithmeticConditioningTable;
23 import dwt.internal.image.JPEGRestartInterval;
24 import dwt.internal.image.JPEGQuantizationTable;
25 import dwt.internal.image.JPEGStartOfImage;
26 import dwt.internal.image.JPEGDecoder;
27 import dwt.internal.image.JPEGEndOfImage;
28 import dwt.dwthelper.utils;
29
30 import dwt.graphics.RGB;
31 import dwt.graphics.PaletteData;
32
33 import tango.core.Exception;
34
35 final class JPEGFileFormat : FileFormat {
36     int restartInterval;
37     JPEGFrameHeader frameHeader;
38     int imageWidth, imageHeight;
39     int interleavedMcuCols, interleavedMcuRows;
40     int maxV, maxH;
41     bool progressive;
42     int samplePrecision;
43     int nComponents;
44     int[][] frameComponents;
45     int[] componentIds;
46     byte[][] imageComponents;
47     int[] dataUnit;
48     int[][][] dataUnits;
49     int[] precedingDCs;
50     JPEGScanHeader scanHeader;
51     byte[] dataBuffer;
52     int currentBitCount;
53     int bufferCurrentPosition;
54     int restartsToGo;
55     int nextRestartNumber;
56     JPEGHuffmanTable[] acHuffmanTables;
57     JPEGHuffmanTable[] dcHuffmanTables;
58     int[][] quantizationTables;
59     int currentByte;
60     int encoderQFactor = 75;
61     int eobrun = 0;
62     /* JPEGConstants */
63     public static const int DCTSIZE = 8;
64     public static const int DCTSIZESQR = 64;
65     /* JPEGFixedPointConstants */
66     public static const int FIX_0_899976223 = 7373;
67     public static const int FIX_1_961570560 = 16069;
68     public static const int FIX_2_053119869 = 16819;
69     public static const int FIX_0_298631336 = 2446;
70     public static const int FIX_1_847759065 = 15137;
71     public static const int FIX_1_175875602 = 9633;
72     public static const int FIX_3_072711026 = 25172;
73     public static const int FIX_0_765366865 = 6270;
74     public static const int FIX_2_562915447 = 20995;
75     public static const int FIX_0_541196100 = 4433;
76     public static const int FIX_0_390180644 = 3196;
77     public static const int FIX_1_501321110 = 12299;
78     /* JPEGMarkerCodes */
79     public static const int APP0  = 0xFFE0;
80     public static const int APP15 = 0xFFEF;
81     public static const int COM   = 0xFFFE;
82     public static const int DAC   = 0xFFCC;
83     public static const int DHP   = 0xFFDE;
84     public static const int DHT   = 0xFFC4;
85     public static const int DNL   = 0xFFDC;
86     public static const int DRI   = 0xFFDD;
87     public static const int DQT   = 0xFFDB;
88     public static const int EOI   = 0xFFD9;
89     public static const int EXP   = 0xFFDF;
90     public static const int JPG   = 0xFFC8;
91     public static const int JPG0  = 0xFFF0;
92     public static const int JPG13 = 0xFFFD;
93     public static const int RST0  = 0xFFD0;
94     public static const int RST1  = 0xFFD1;
95     public static const int RST2  = 0xFFD2;
96     public static const int RST3  = 0xFFD3;
97     public static const int RST4  = 0xFFD4;
98     public static const int RST5  = 0xFFD5;
99     public static const int RST6  = 0xFFD6;
100     public static const int RST7  = 0xFFD7;
101     public static const int SOF0  = 0xFFC0;
102     public static const int SOF1  = 0xFFC1;
103     public static const int SOF2  = 0xFFC2;
104     public static const int SOF3  = 0xFFC3;
105     public static const int SOF5  = 0xFFC5;
106     public static const int SOF6  = 0xFFC6;
107     public static const int SOF7  = 0xFFC7;
108     public static const int SOF9  = 0xFFC9;
109     public static const int SOF10 = 0xFFCA;
110     public static const int SOF11 = 0xFFCB;
111     public static const int SOF13 = 0xFFCD;
112     public static const int SOF14 = 0xFFCE;
113     public static const int SOF15 = 0xFFCF;
114     public static const int SOI   = 0xFFD8;
115     public static const int SOS   = 0xFFDA;
116     public static const int TEM   = 0xFF01;
117     /* JPEGFrameComponentParameterConstants */
118     public static const int TQI = 0;
119     public static const int HI  = 1;
120     public static const int VI  = 2;
121     public static const int CW  = 3;
122     public static const int CH  = 4;
123     /* JPEGScanComponentParameterConstants */
124     public static const int DC  = 0;
125     public static const int AC  = 1;
126     /* JFIF Component Constants */
127     public static const int ID_Y        = 1 - 1;
128     public static const int ID_CB   = 2 - 1;
129     public static const int ID_CR   = 3 - 1;
130     public static /*const*/ RGB[] RGB16;
131     public static const int[] ExtendTest = [
132         0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
133         4096, 8192, 16384, 32768, 65536, 131072, 262144
134     ];
135     public static const int[] ExtendOffset = [
136         0, -1, -3, -7, -15, -31, -63, -127, -255, -511, -1023, -2047,
137         -4095, -8191, -16383, -32767, -65535, -131071, -262143
138     ];
139     public static const int[] ZigZag8x8 = [
140         0, 1, 8, 16, 9, 2, 3, 10,
141         17, 24, 32, 25, 18, 11, 4, 5,
142         12, 19, 26, 33, 40, 48, 41, 34,
143         27, 20, 13, 6, 7, 14, 21, 28,
144         35, 42, 49, 56, 57, 50, 43, 36,
145         29, 22, 15, 23, 30, 37, 44, 51,
146         58, 59, 52, 45, 38, 31, 39, 46,
147         53, 60, 61, 54, 47, 55, 62, 63
148     ];
149
150     public static int[] CrRTable, CbBTable, CrGTable, CbGTable;
151     public static int[] RYTable, GYTable, BYTable,
152         RCbTable, GCbTable, BCbTable, RCrTable, GCrTable, BCrTable, NBitsTable;
153     //public static void static_this() {
154     static this() {
155
156         RGB16 = [
157             new RGB(0,0,0),
158             new RGB(0x80,0,0),
159             new RGB(0,0x80,0),
160             new RGB(0x80,0x80,0),
161             new RGB(0,0,0x80),
162             new RGB(0x80,0,0x80),
163             new RGB(0,0x80,0x80),
164             new RGB(0xC0,0xC0,0xC0),
165             new RGB(0x80,0x80,0x80),
166             new RGB(0xFF,0,0),
167             new RGB(0,0xFF,0),
168             new RGB(0xFF,0xFF,0),
169             new RGB(0,0,0xFF),
170             new RGB(0xFF,0,0xFF),
171             new RGB(0,0xFF,0xFF),
172             new RGB(0xFF,0xFF,0xFF)
173         ];
174         int [] rYTable = new int[256];
175         int [] gYTable = new int[256];
176         int [] bYTable = new int[256];
177         int [] rCbTable = new int[256];
178         int [] gCbTable = new int[256];
179         int [] bCbTable = new int[256];
180         int [] rCrTable = new int[256];
181         int [] gCrTable = new int[256];
182         int [] bCrTable = new int[256];
183         for (int i = 0; i < 256; i++) {
184             rYTable[i] = i * 19595;
185             gYTable[i] = i * 38470;
186             bYTable[i] = i * 7471 + 32768;
187             rCbTable[i] = i * -11059;
188             gCbTable[i] = i * -21709;
189             bCbTable[i] = i * 32768 + 8388608;
190             gCrTable[i] = i * -27439;
191             bCrTable[i] = i * -5329;
192         }
193         RYTable = rYTable;
194         GYTable = gYTable;
195         BYTable = bYTable;
196         RCbTable = rCbTable;
197         GCbTable = gCbTable;
198         BCbTable = bCbTable;
199         RCrTable = bCbTable;
200         GCrTable = gCrTable;
201         BCrTable = bCrTable;
202
203         /* Initialize YCbCr-RGB Tables */
204         int [] crRTable = new int[256];
205         int [] cbBTable = new int[256];
206         int [] crGTable = new int[256];
207         int [] cbGTable = new int[256];
208         for (int i = 0; i < 256; i++) {
209             int x2 = 2 * i - 255;
210             crRTable[i] = (45941 * x2 + 32768) >> 16;
211             cbBTable[i] = (58065 * x2 + 32768) >> 16;
212             crGTable[i] = -23401 * x2;
213             cbGTable[i] = -11277 * x2 + 32768;
214         }
215         CrRTable = crRTable;
216         CbBTable = cbBTable;
217         CrGTable = crGTable;
218         CbGTable = cbGTable;
219
220         /* Initialize BitCount Table */
221         int nBits = 1;
222         int power2 = 2;
223         int [] nBitsTable = new int[2048];
224         nBitsTable[0] = 0;
225         for (int i = 1; i < nBitsTable.length; i++) {
226             if (!(i < power2)) {
227                 nBits++;
228                 power2 *= 2;
229             }
230             nBitsTable[i] = nBits;
231         }
232         NBitsTable = nBitsTable;
233     }
234 void compress(ImageData image, byte[] dataYComp, byte[] dataCbComp, byte[] dataCrComp) {
235     int srcWidth = image.width;
236     int srcHeight = image.height;
237     int vhFactor = maxV * maxH;
238     int[] frameComponent;
239     imageComponents = new byte[][](nComponents);
240     for (int i = 0; i < nComponents; i++) {
241         frameComponent = frameComponents[componentIds[i]];
242         imageComponents[i] = new byte[frameComponent[CW] * frameComponent[CH]];
243     }
244     frameComponent = frameComponents[componentIds[ID_Y]];
245     for (int yPos = 0; yPos < srcHeight; yPos++) {
246         int srcOfs = yPos * srcWidth;
247         int dstOfs = yPos * frameComponent[CW];
248         System.arraycopy(dataYComp, srcOfs, imageComponents[ID_Y], dstOfs, srcWidth);
249     }
250     frameComponent = frameComponents[componentIds[ID_CB]];
251     for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
252         int destRowIndex = yPos * frameComponent[CW];
253         for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
254             int sum = 0;
255             for (int iv = 0; iv < maxV; iv++) {
256                 int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
257                 for (int ih = 0; ih < maxH; ih++) {
258                     sum += dataCbComp[srcIndex + ih] & 0xFF;
259                 }
260             }
261             imageComponents[ID_CB][destRowIndex + xPos] = cast(byte)(sum / vhFactor);
262         }
263     }
264     frameComponent = frameComponents[componentIds[ID_CR]];
265     for (int yPos = 0; yPos < srcHeight / maxV; yPos++) {
266         int destRowIndex = yPos * frameComponent[CW];
267         for (int xPos = 0; xPos < srcWidth / maxH; xPos++) {
268             int sum = 0;
269             for (int iv = 0; iv < maxV; iv++) {
270                 int srcIndex = (yPos * maxV + iv) * srcWidth + (xPos * maxH);
271                 for (int ih = 0; ih < maxH; ih++) {
272                     sum += dataCrComp[srcIndex + ih] & 0xFF;
273                 }
274             }
275             imageComponents[ID_CR][destRowIndex + xPos] = cast(byte)(sum / vhFactor);
276         }
277     }
278     for (int iComp = 0; iComp < nComponents; iComp++) {
279         byte[] imageComponent = imageComponents[iComp];
280         frameComponent = frameComponents[componentIds[iComp]];
281         int hFactor = frameComponent[HI];
282         int vFactor = frameComponent[VI];
283         int componentWidth = frameComponent[CW];
284         int componentHeight = frameComponent[CH];
285         int compressedWidth = srcWidth / (maxH / hFactor);
286         int compressedHeight = srcHeight / (maxV / vFactor);
287         if (compressedWidth < componentWidth) {
288             int delta = componentWidth - compressedWidth;
289             for (int yPos = 0; yPos < compressedHeight; yPos++) {
290                 int dstOfs = ((yPos + 1) * componentWidth - delta);
291                 int dataValue = imageComponent[(dstOfs > 0) ? dstOfs - 1 : 0] & 0xFF;
292                 for (int i = 0; i < delta; i++) {
293                     imageComponent[dstOfs + i] = cast(byte)dataValue;
294                 }
295             }
296         }
297         if (compressedHeight < componentHeight) {
298             int srcOfs = (compressedHeight > 0) ? (compressedHeight - 1) * componentWidth : 1;
299             for (int yPos = (compressedHeight > 0) ? compressedHeight : 1; yPos <= componentHeight; yPos++) {
300                 int dstOfs = (yPos - 1) * componentWidth;
301                 System.arraycopy(imageComponent, srcOfs, imageComponent, dstOfs, componentWidth);
302             }
303         }
304     }
305 }
306 void convert4BitRGBToYCbCr(ImageData image) {
307     RGB[] rgbs = image.getRGBs();
308     int paletteSize = rgbs.length;
309     byte[] yComp = new byte[paletteSize];
310     byte[] cbComp = new byte[paletteSize];
311     byte[] crComp = new byte[paletteSize];
312     int srcWidth = image.width;
313     int srcHeight = image.height;
314     for (int i = 0; i < paletteSize; i++) {
315         RGB color = rgbs[i];
316         int r = color.red;
317         int g = color.green;
318         int b = color.blue;
319         int n = RYTable[r] + GYTable[g] + BYTable[b];
320         yComp[i] = cast(byte)(n >> 16);
321         if ((n < 0) && ((n & 0xFFFF) !is 0)) yComp[i]--;
322         n = RCbTable[r] + GCbTable[g] + BCbTable[b];
323         cbComp[i] = cast(byte)(n >> 16);
324         if ((n < 0) && ((n & 0xFFFF) !is 0)) cbComp[i]--;
325         n = RCrTable[r] + GCrTable[g] + BCrTable[b];
326         crComp[i] = cast(byte)(n >> 16);
327         if ((n < 0) && ((n & 0xFFFF) !is 0)) crComp[i]--;
328     }
329     int bSize = srcWidth * srcHeight;
330     byte[] dataYComp = new byte[bSize];
331     byte[] dataCbComp = new byte[bSize];
332     byte[] dataCrComp = new byte[bSize];
333     byte[] origData = image.data;
334     int bytesPerLine = image.bytesPerLine;
335     int maxScanlineByte = srcWidth >> 1;
336     for (int yPos = 0; yPos < srcHeight; yPos++) {
337         for (int xPos = 0; xPos < maxScanlineByte; xPos++) {
338             int srcIndex = yPos * bytesPerLine + xPos;
339             int dstIndex = yPos * srcWidth + (xPos * 2);
340             int value2 = origData[srcIndex] & 0xFF;
341             int value1 = value2 >> 4;
342             value2 &= 0x0F;
343             dataYComp[dstIndex] = yComp[value1];
344             dataCbComp[dstIndex] = cbComp[value1];
345             dataCrComp[dstIndex] = crComp[value1];
346             dataYComp[dstIndex + 1] = yComp[value2];
347             dataCbComp[dstIndex + 1] = cbComp[value2];
348             dataCrComp[dstIndex + 1] = crComp[value2];
349         }
350     }
351     compress(image, dataYComp, dataCbComp, dataCrComp);
352 }
353 void convert8BitRGBToYCbCr(ImageData image) {
354     RGB[] rgbs = image.getRGBs();
355     int paletteSize = rgbs.length;
356     byte[] yComp = new byte[paletteSize];
357     byte[] cbComp = new byte[paletteSize];
358     byte[] crComp = new byte[paletteSize];
359     int srcWidth = image.width;
360     int srcHeight = image.height;
361     for (int i = 0; i < paletteSize; i++) {
362         RGB color = rgbs[i];
363         int r = color.red;
364         int g = color.green;
365         int b = color.blue;
366         int n = RYTable[r] + GYTable[g] + BYTable[b];
367         yComp[i] = cast(byte)(n >> 16);
368         if ((n < 0) && ((n & 0xFFFF) !is 0)) yComp[i]--;
369         n = RCbTable[r] + GCbTable[g] + BCbTable[b];
370         cbComp[i] = cast(byte)(n >> 16);
371         if ((n < 0) && ((n & 0xFFFF) !is 0)) cbComp[i]--;
372         n = RCrTable[r] + GCrTable[g] + BCrTable[b];
373         crComp[i] = cast(byte)(n >> 16);
374         if ((n < 0) && ((n & 0xFFFF) !is 0)) crComp[i]--;
375     }
376     int dstWidth = image.width;
377     int dstHeight = srcHeight;
378     int stride = ((srcWidth + 3) >> 2) << 2;
379     int bSize = dstWidth * dstHeight;
380     byte[] dataYComp = new byte[bSize];
381     byte[] dataCbComp = new byte[bSize];
382     byte[] dataCrComp = new byte[bSize];
383     byte[] origData = image.data;
384     for (int yPos = 0; yPos < srcHeight; yPos++) {
385         int srcRowIndex = yPos * stride;
386         int dstRowIndex = yPos * dstWidth;
387         for (int xPos = 0; xPos < srcWidth; xPos++) {
388             int value = origData[srcRowIndex + xPos] & 0xFF;
389             int dstIndex = dstRowIndex + xPos;
390             dataYComp[dstIndex] = yComp[value];
391             dataCbComp[dstIndex] = cbComp[value];
392             dataCrComp[dstIndex] = crComp[value];
393         }
394     }
395     compress(image, dataYComp, dataCbComp, dataCrComp);
396 }
397 byte[] convertCMYKToRGB() {
398     /* Unsupported CMYK format. Answer an empty byte array. */
399     return new byte[0];
400 }
401 void convertImageToYCbCr(ImageData image) {
402     switch (image.depth) {
403         case 4:
404             convert4BitRGBToYCbCr(image);
405             return;
406         case 8:
407             convert8BitRGBToYCbCr(image);
408             return;
409         case 16:
410         case 24:
411         case 32:
412             convertMultiRGBToYCbCr(image);
413             return;
414         default:
415             DWT.error(DWT.ERROR_UNSUPPORTED_DEPTH);
416     }
417     return;
418 }
419 void convertMultiRGBToYCbCr(ImageData image) {
420     int srcWidth = image.width;
421     int srcHeight = image.height;
422     int