Mercurial > projects > dwt-mac
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 } |