comparison dwt/internal/image/PngEncoder.d @ 0:380af2bdd8e5

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