root/dwt/internal/image/PngIhdrChunk.d

Revision 213:36f5cb12e1a2, 10.8 kB (checked in by Frank Benoit <benoit@tionex.de>, 8 months ago)

Update to SWT 3.4M7

Line 
1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module dwt.internal.image.PngIhdrChunk;
14
15 import dwt.dwthelper.utils;
16
17
18 import dwt.DWT;
19 import dwt.graphics.PaletteData;
20 import dwt.graphics.RGB;
21 import dwt.internal.image.PngFileReadState;
22 import dwt.internal.image.PngIhdrChunk;
23 import dwt.internal.image.PngChunk;
24 import tango.text.convert.Format;
25
26 class PngIhdrChunk : PngChunk {
27     static const int IHDR_DATA_LENGTH = 13;
28
29     static const int WIDTH_DATA_OFFSET = DATA_OFFSET + 0;
30     static const int HEIGHT_DATA_OFFSET = DATA_OFFSET + 4;
31     static const int BIT_DEPTH_OFFSET = DATA_OFFSET + 8;
32     static const int COLOR_TYPE_OFFSET = DATA_OFFSET + 9;
33     static const int COMPRESSION_METHOD_OFFSET = DATA_OFFSET + 10;
34     static const int FILTER_METHOD_OFFSET = DATA_OFFSET + 11;
35     static const int INTERLACE_METHOD_OFFSET = DATA_OFFSET + 12;
36
37     static const byte COLOR_TYPE_GRAYSCALE = 0;
38     static const byte COLOR_TYPE_RGB = 2;
39     static const byte COLOR_TYPE_PALETTE = 3;
40     static const byte COLOR_TYPE_GRAYSCALE_WITH_ALPHA = 4;
41     static const byte COLOR_TYPE_RGB_WITH_ALPHA = 6;
42
43     static const int INTERLACE_METHOD_NONE = 0;
44     static const int INTERLACE_METHOD_ADAM7 = 1;
45
46     static const int FILTER_NONE = 0;
47     static const int FILTER_SUB = 1;
48     static const int FILTER_UP = 2;
49     static const int FILTER_AVERAGE = 3;
50     static const int FILTER_PAETH = 4;
51
52     static const byte[] ValidBitDepths = [ cast(byte)1, 2, 4, 8, 16];
53     static const byte[] ValidColorTypes = [ cast(byte)0, 2, 3, 4, 6];
54
55     int width, height;
56     byte bitDepth, colorType, compressionMethod, filterMethod, interlaceMethod;
57
58 this(int width, int height, byte bitDepth, byte colorType, byte compressionMethod, byte filterMethod, byte interlaceMethod) {
59     super(IHDR_DATA_LENGTH);
60     setType(TYPE_IHDR);
61     setWidth(width);
62     setHeight(height);
63     setBitDepth(bitDepth);
64     setColorType(colorType);
65     setCompressionMethod(compressionMethod);
66     setFilterMethod(filterMethod);
67     setInterlaceMethod(interlaceMethod);
68     setCRC(computeCRC());
69 }
70
71 /**
72  * Construct a PNGChunk using the reference bytes
73  * given.
74  */
75 this(byte[] reference) {
76     super(reference);
77     if (reference.length <= IHDR_DATA_LENGTH) DWT.error(DWT.ERROR_INVALID_IMAGE);
78     width = getInt32(WIDTH_DATA_OFFSET);
79     height = getInt32(HEIGHT_DATA_OFFSET);
80     bitDepth = reference[BIT_DEPTH_OFFSET];
81     colorType = reference[COLOR_TYPE_OFFSET];
82     compressionMethod = reference[COMPRESSION_METHOD_OFFSET];
83     filterMethod = reference[FILTER_METHOD_OFFSET];
84     interlaceMethod = reference[INTERLACE_METHOD_OFFSET];
85 }
86
87 override int getChunkType() {
88     return CHUNK_IHDR;
89 }
90
91 /**
92  * Get the image's width in pixels.
93  */
94 int getWidth() {
95     return width;
96 }
97
98 /**
99  * Set the image's width in pixels.
100  */
101 void setWidth(int value) {
102     setInt32(WIDTH_DATA_OFFSET, value);
103     width = value;
104 }
105
106 /**
107  * Get the image's height in pixels.
108  */
109 int getHeight() {
110     return height;
111 }
112
113 /**
114  * Set the image's height in pixels.
115  */
116 void setHeight(int value) {
117     setInt32(HEIGHT_DATA_OFFSET, value);
118     height = value;
119 }
120
121 /**
122  * Get the image's bit depth.
123  * This is limited to the values 1, 2, 4, 8, or 16.
124  */
125 byte getBitDepth() {
126     return bitDepth;
127 }
128
129 /**
130  * Set the image's bit depth.
131  * This is limited to the values 1, 2, 4, 8, or 16.
132  */
133 void setBitDepth(byte value) {
134     reference[BIT_DEPTH_OFFSET] = value;
135     bitDepth = value;
136 }
137
138 /**
139  * Get the image's color type.
140  * This is limited to the values:
141  * 0 - Grayscale image.
142  * 2 - RGB triple.
143  * 3 - Palette.
144  * 4 - Grayscale with Alpha channel.
145  * 6 - RGB with Alpha channel.
146  */
147 byte getColorType() {
148     return colorType;
149 }
150
151 /**
152  * Set the image's color type.
153  * This is limited to the values:
154  * 0 - Grayscale image.
155  * 2 - RGB triple.
156  * 3 - Palette.
157  * 4 - Grayscale with Alpha channel.
158  * 6 - RGB with Alpha channel.
159  */
160 void setColorType(byte value) {
161     reference[COLOR_TYPE_OFFSET] = value;
162     colorType = value;
163 }
164
165 /**
166  * Get the image's compression method.
167  * This value must be 0.
168  */
169 byte getCompressionMethod() {
170     return compressionMethod;
171 }
172
173 /**
174  * Set the image's compression method.
175  * This value must be 0.
176  */
177 void setCompressionMethod(byte value) {
178     reference[COMPRESSION_METHOD_OFFSET] = value;
179     compressionMethod = value;
180 }
181
182 /**
183  * Get the image's filter method.
184  * This value must be 0.
185  */
186 byte getFilterMethod() {
187     return filterMethod;
188 }
189
190 /**
191  * Set the image's filter method.
192  * This value must be 0.
193  */
194 void setFilterMethod(byte value) {
195     reference[FILTER_METHOD_OFFSET] = value;
196     filterMethod = value;
197 }
198
199 /**
200  * Get the image's interlace method.
201  * This value is limited to:
202  * 0 - No interlacing used.
203  * 1 - Adam7 interlacing used.
204  */
205 byte getInterlaceMethod() {
206     return interlaceMethod;
207 }
208
209 /**
210  * Set the image's interlace method.
211  * This value is limited to:
212  * 0 - No interlacing used.
213  * 1 - Adam7 interlacing used.
214  */
215 void setInterlaceMethod(byte value) {
216     reference[INTERLACE_METHOD_OFFSET] = value;
217     interlaceMethod = value;
218 }
219
220 /**
221  * Answer whether the chunk is a valid IHDR chunk.
222  */
223 override void validate(PngFileReadState readState, PngIhdrChunk headerChunk) {
224     // An IHDR chunk is invalid if any other chunk has
225     // been read.
226     if (readState.readIHDR
227         || readState.readPLTE
228         || readState.readIDAT
229         || readState.readIEND)
230     {
231         DWT.error(DWT.ERROR_INVALID_IMAGE);
232     } else {
233         readState.readIHDR = true;
234     }
235
236     super.validate(readState, headerChunk);
237
238     if (length !is IHDR_DATA_LENGTH) DWT.error(DWT.ERROR_INVALID_IMAGE);
239     if (compressionMethod !is 0) DWT.error(DWT.ERROR_INVALID_IMAGE);
240     if (interlaceMethod !is INTERLACE_METHOD_NONE &&
241         interlaceMethod !is INTERLACE_METHOD_ADAM7) {
242             DWT.error(DWT.ERROR_INVALID_IMAGE);
243     }
244
245     bool colorTypeIsValid = false;
246     for (int i = 0; i < ValidColorTypes.length; i++) {
247         if (ValidColorTypes[i] is colorType) {
248             colorTypeIsValid = true;
249             break;
250         }
251     }
252     if (!colorTypeIsValid) DWT.error(DWT.ERROR_INVALID_IMAGE);
253
254     bool bitDepthIsValid = false;
255     for (int i = 0; i < ValidBitDepths.length; i++) {
256         if (ValidBitDepths[i] is bitDepth) {
257             bitDepthIsValid = true;
258             break;
259         }
260     }
261     if (!bitDepthIsValid) DWT.error(DWT.ERROR_INVALID_IMAGE);
262
263     if ((colorType is COLOR_TYPE_RGB
264         || colorType is COLOR_TYPE_RGB_WITH_ALPHA
265         || colorType is COLOR_TYPE_GRAYSCALE_WITH_ALPHA)
266         && bitDepth < 8)
267     {
268             DWT.error(DWT.ERROR_INVALID_IMAGE);
269     }
270
271     if (colorType is COLOR_TYPE_PALETTE && bitDepth > 8) {
272         DWT.error(DWT.ERROR_INVALID_IMAGE);
273     }
274 }
275
276 String getColorTypeString() {
277     switch (colorType) {
278         case COLOR_TYPE_GRAYSCALE:              return "Grayscale";
279         case COLOR_TYPE_RGB:                    return "RGB";
280         case COLOR_TYPE_PALETTE:                return "Palette";
281         case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:   return "Grayscale with Alpha";
282         case COLOR_TYPE_RGB_WITH_ALPHA:         return "RGB with Alpha";
283         default:                                return "Unknown - " ~ cast(char)colorType;
284     }
285 }
286
287 String getFilterMethodString() {
288     switch (filterMethod) {
289         case FILTER_NONE:       return "None";
290         case FILTER_SUB:        return "Sub";
291         case FILTER_UP:         return "Up";
292         case FILTER_AVERAGE:    return "Average";
293         case FILTER_PAETH:      return "Paeth";
294         default:                return "Unknown";
295     }
296 }
297
298 String getInterlaceMethodString() {
299     switch (interlaceMethod) {
300         case INTERLACE_METHOD_NONE:     return "Not Interlaced";
301         case INTERLACE_METHOD_ADAM7:    return "Interlaced - ADAM7";
302         default:                return "Unknown";
303     }
304 }
305
306 override String contributeToString() {
307     return Format( "\n\tWidth: {}\n\tHeight: {}\n\tBit Depth: {}\n\tColor Type: {}\n\tCompression Method: {}\n\tFilter Method: {}\n\tInterlace Method: {}",
308         width, height, bitDepth, getColorTypeString(), compressionMethod, getFilterMethodString(), getInterlaceMethodString() );
309 }
310
311 bool getMustHavePalette() {
312     return colorType is COLOR_TYPE_PALETTE;
313 }
314
315 bool getCanHavePalette() {
316     return colorType !is COLOR_TYPE_GRAYSCALE &&
317         colorType !is COLOR_TYPE_GRAYSCALE_WITH_ALPHA;
318 }
319
320 /**
321  * Answer the pixel size in bits based on the color type
322  * and bit depth.
323  */
324 int getBitsPerPixel() {
325     switch (colorType) {
326         case COLOR_TYPE_RGB_WITH_ALPHA:
327             return 4 * bitDepth;
328         case COLOR_TYPE_RGB:
329             return 3 * bitDepth;
330         case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
331             return 2 * bitDepth;
332         case COLOR_TYPE_GRAYSCALE:
333         case COLOR_TYPE_PALETTE:
334             return bitDepth;
335         default:
336             DWT.error(DWT.ERROR_INVALID_IMAGE);
337             return 0;
338     }
339 }
340
341 /**
342  * Answer the pixel size in bits based on the color type
343  * and bit depth.
344  */
345 int getSwtBitsPerPixel() {
346     switch (colorType) {
347         case COLOR_TYPE_RGB_WITH_ALPHA:
348         case COLOR_TYPE_RGB:
349         case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
350             return 24;
351         case COLOR_TYPE_GRAYSCALE:
352         case COLOR_TYPE_PALETTE:
353             return Math.min(bitDepth, 8);
354         default:
355             DWT.error(DWT.ERROR_INVALID_IMAGE);
356             return 0;
357     }
358 }
359
360 int getFilterByteOffset() {
361     if (bitDepth < 8) return 1;
362     return getBitsPerPixel() / 8;
363 }
364
365 bool usesDirectColor() {
366     switch (colorType) {
367         case COLOR_TYPE_GRAYSCALE:
368         case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
369         case COLOR_TYPE_RGB:
370         case COLOR_TYPE_RGB_WITH_ALPHA:
371             return true;
372         default:
373             return false;
374     }
375 }
376
377 PaletteData createGrayscalePalette() {
378     int depth = Math.min(bitDepth, 8);
379     int max = (1 << depth) - 1;
380     int delta = 255 / max;
381     int gray = 0;
382     RGB[] rgbs = new RGB[max + 1];
383     for (int i = 0; i <= max; i++) {
384         rgbs[i] = new RGB(gray, gray, gray);
385         gray += delta;
386     }
387     return new PaletteData(rgbs);
388 }
389
390 PaletteData getPaletteData() {
391     switch (colorType) {
392         case COLOR_TYPE_GRAYSCALE:
393             return createGrayscalePalette();
394         case COLOR_TYPE_GRAYSCALE_WITH_ALPHA:
395         case COLOR_TYPE_RGB:
396         case COLOR_TYPE_RGB_WITH_ALPHA:
397             return new PaletteData(0xFF0000, 0xFF00, 0xFF);
398         default:
399             return null;
400     }
401 }
402
403
404
405 }
Note: See TracBrowser for help on using the browser.