root/dwt/internal/image/PngEncoder.d

Revision 246:fd9c62a2998e, 9.3 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, 2007 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.PngEncoder;
14
15 import dwt.internal.image.LEDataOutputStream;
16 import dwt.internal.image.PngDeflater;
17 import dwt.dwthelper.ByteArrayOutputStream;
18 import dwt.dwthelper.OutputStream;
19 import dwt.DWT;
20 import dwt.graphics.ImageData;
21 import dwt.graphics.ImageLoader;
22 import dwt.graphics.RGB;
23 import dwt.internal.Compatibility;
24 import dwt.internal.image.PngChunk;
25
26 import tango.core.Exception;
27
28 final class PngEncoder {
29
30     static const byte SIGNATURE[] = [cast(byte) '\211', cast(byte) 'P', cast(byte) 'N', cast(byte) 'G', cast(byte) '\r', cast(byte) '\n', cast(byte) '\032', cast(byte) '\n'];
31     static const byte TAG_IHDR[] = [cast(byte) 'I', cast(byte) 'H', cast(byte) 'D', cast(byte) 'R'];
32     static const byte TAG_PLTE[] = [cast(byte) 'P', cast(byte) 'L', cast(byte) 'T', cast(byte) 'E'];
33     static const byte TAG_TRNS[] = [cast(byte) 't', cast(byte) 'R', cast(byte) 'N', cast(byte) 'S'];
34     static const byte TAG_IDAT[] = [cast(byte) 'I', cast(byte) 'D', cast(byte) 'A', cast(byte) 'T'];
35     static const byte TAG_IEND[] = [cast(byte) 'I', cast(byte) 'E', cast(byte) 'N', cast(byte) 'D'];
36
37     ByteArrayOutputStream bytes;
38     PngChunk chunk;
39
40     ImageLoader loader;
41     ImageData data;
42     int transparencyType;
43
44     int width, height, bitDepth, colorType;
45
46     int compressionMethod = 0;
47     int filterMethod = 0;
48     int interlaceMethod = 0;
49
50 public this(ImageLoader loader) {
51     this.bytes = new ByteArrayOutputStream(1024);
52     this.loader = loader;
53     this.data = loader.data[0];
54     this.transparencyType = data.getTransparencyType();
55
56     this.width = data.width;
57     this.height = data.height;
58
59     this.bitDepth = 8;
60
61     this.colorType = 2;
62
63     if (data.palette.isDirect) {
64         if (transparencyType is DWT.TRANSPARENCY_ALPHA) {
65             this.colorType = 6;
66         }
67     }
68     else {
69         this.colorType = 3;
70     }
71
72     if (!(colorType is 2 || colorType is 3 || colorType is 6)) DWT.error(DWT.ERROR_INVALID_IMAGE);
73
74 }
75
76 void writeShort(ByteArrayOutputStream baos, int theShort) {
77
78     byte byte1 = cast(byte) ((theShort >> 8) & 0xff);
79     byte byte2 = cast(byte) (theShort & 0xff);
80     byte[] temp = [byte1, byte2];
81     baos.write(temp, 0, 2);
82
83 }
84
85 void writeInt(ByteArrayOutputStream baos, int theInt) {
86
87     byte byte1 = cast(byte) ((theInt >> 24) & 0xff);
88     byte byte2 = cast(byte) ((theInt >> 16) & 0xff);
89     byte byte3 = cast(byte) ((theInt >> 8) & 0xff);
90     byte byte4 = cast(byte) (theInt & 0xff);
91     byte[] temp = [byte1, byte2, byte3, byte4];
92     baos.write(temp, 0, 4);
93
94 }
95
96 void writeChunk(byte[] tag, byte[] buffer) {
97
98     int bufferLength = (buffer !is null) ? buffer.length : 0;
99
100     chunk = new PngChunk(bufferLength);
101
102     writeInt(bytes, bufferLength);
103     bytes.write(tag, 0, 4);
104     chunk.setType(tag);
105     if (bufferLength !is 0) {
106         bytes.write(buffer, 0, bufferLength);
107         chunk.setData(buffer);
108     }
109     else {
110         chunk.setCRC(chunk.computeCRC());
111     }
112     writeInt(bytes, chunk.getCRC());
113
114 }
115
116 void writeSignature() {
117
118     bytes.write(SIGNATURE, 0, 8);
119
120 }
121
122 void writeHeader() {
123
124     ByteArrayOutputStream baos = new ByteArrayOutputStream(13);
125
126     writeInt(baos, width);
127     writeInt(baos, height);
128     baos.write(bitDepth);
129     baos.write(colorType);
130     baos.write(compressionMethod);
131     baos.write(filterMethod);
132     baos.write(interlaceMethod);
133
134     writeChunk(TAG_IHDR, baos.toByteArray());
135
136 }
137
138 void writePalette() {
139
140     RGB[] RGBs = data.palette.getRGBs();
141
142     if (RGBs.length > 256) DWT.error(DWT.ERROR_INVALID_IMAGE);
143
144     ByteArrayOutputStream baos = new ByteArrayOutputStream(RGBs.length);
145
146     for (int i = 0; i < RGBs.length; i++) {
147
148         baos.write(cast(byte) RGBs[i].red);
149         baos.write(cast(byte) RGBs[i].green);
150         baos.write(cast(byte) RGBs[i].blue);
151
152     }
153
154     writeChunk(TAG_PLTE, baos.toByteArray());
155
156 }
157
158 void writeTransparency() {
159
160     ByteArrayOutputStream baos = new ByteArrayOutputStream();
161
162     switch (transparencyType) {
163
164         case DWT.TRANSPARENCY_ALPHA:
165
166             int pixelValue, alphaValue;
167
168             byte[] alphas = new byte[data.palette.getRGBs().length];
169
170             for (int y = 0; y < height; y++) {
171
172                 for (int x = 0; x < width; x++) {
173
174                     pixelValue = data.getPixel(x, y);
175                     alphaValue = data.getAlpha(x, y);
176
177                     alphas[pixelValue] = cast(byte) alphaValue;
178
179                 }
180
181             }
182
183             baos.write(alphas, 0, alphas.length);
184
185             break;
186
187         case DWT.TRANSPARENCY_PIXEL:
188
189             int pixel = data.transparentPixel;
190
191             if (colorType is 2) {
192
193                 int redMask = data.palette.redMask;
194                 int redShift = data.palette.redShift;
195                 int greenMask = data.palette.greenMask;
196                 int greenShift = data.palette.greenShift;
197                 int blueShift = data.palette.blueShift;
198                 int blueMask = data.palette.blueMask;
199
200                 int r = pixel & redMask;
201                 r = (redShift < 0) ? r >>> -redShift : r << redShift;
202                 int g = pixel & greenMask;
203                 g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
204                 int b = pixel & blueMask;
205                 b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
206
207                 writeShort(baos, r);
208                 writeShort(baos, g);
209                 writeShort(baos, b);
210
211             }
212
213             if (colorType is 3) {
214
215                 byte[] padding = new byte[pixel + 1];
216
217                 for (int i = 0; i < pixel; i++) {
218
219                     padding[i] = cast(byte) 255;
220
221                 }
222
223                 padding[pixel] = cast(byte) 0;
224
225                 baos.write(padding, 0, padding.length);
226
227             }
228
229             break;
230         default:
231
232     }
233
234     writeChunk(TAG_TRNS, baos.toByteArray());
235
236 }
237
238 void writeImageData() {
239
240     ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
241     OutputStream os = Compatibility.newDeflaterOutputStream(baos);
242     if (os is null) os = baos;
243
244     if (colorType is 3) {
245
246         byte[] lineData = new byte[width];
247
248         for (int y = 0; y < height; y++) {
249
250             int filter = 0;
251             os.write(filter);
252
253             data.getPixels(0, y, width, lineData, 0);
254
255             for (int x = 0; x < lineData.length; x++) {
256
257                 os.write(lineData[x]);
258
259             }
260
261         }
262
263     }
264
265     else {
266
267         int[] lineData = new int[width];
268         byte[] alphaData = null;
269         if (colorType is 6) {
270             alphaData = new byte[width];
271         }
272
273         int redMask = data.palette.redMask;
274         int redShift = data.palette.redShift;
275         int greenMask = data.palette.greenMask;
276         int greenShift = data.palette.greenShift;
277         int blueShift = data.palette.blueShift;
278         int blueMask = data.palette.blueMask;
279
280         for (int y = 0; y < height; y++) {
281
282             int filter = 0;
283             os.write(filter);
284
285             data.getPixels(0, y, width, lineData, 0);
286
287             if (colorType is 6) {
288                 data.getAlphas(0, y, width, alphaData, 0);
289             }
290
291             for (int x = 0; x < lineData.length; x++) {
292
293                 int pixel = lineData[x];
294
295                 int r = pixel & redMask;
296                 r = (redShift < 0) ? r >>> -redShift : r << redShift;
297                 int g = pixel & greenMask;
298                 g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
299                 int b = pixel & blueMask;
300                 b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
301
302                 os.write(r);
303                 os.write(g);
304                 os.write(b);
305
306                 if (colorType is 6) {
307                     os.write(alphaData[x]);
308                 }
309
310             }
311
312         }
313
314     }
315
316     os.flush();
317     os.close();
318
319     byte[] compressed = baos.toByteArray();
320     if (os is baos) {
321         PngDeflater deflater = new PngDeflater();
322         compressed = deflater.deflate(compressed);
323     }
324
325     writeChunk(TAG_IDAT, compressed);
326
327 }
328
329 void writeEnd() {
330
331     writeChunk(TAG_IEND, null);
332
333 }
334
335 public void encode(LEDataOutputStream outputStream) {
336
337     try {
338
339         writeSignature();
340         writeHeader();
341
342         if (colorType is 3) {
343             writePalette();
344         }
345
346         bool transparencyAlpha = (transparencyType is DWT.TRANSPARENCY_ALPHA);
347         bool transparencyPixel = (transparencyType is DWT.TRANSPARENCY_PIXEL);
348         bool type2Transparency = (colorType is 2 && transparencyPixel);
349         bool type3Transparency = (colorType is 3 && (transparencyAlpha || transparencyPixel));
350
351         if (type2Transparency || type3Transparency) {
352             writeTransparency();
353         }
354
355         writeImageData();
356         writeEnd();
357
358         outputStream.write(bytes.toByteArray());
359
360     }
361
362     catch (IOException e) {
363
364         DWT.error(DWT.ERROR_IO, e);
365
366     }
367
368 }
369
370 }
Note: See TracBrowser for help on using the browser.