Source Code Cross Referenced for PNGFileFormat.java in  » IDE-Eclipse » swt » org » eclipse » swt » internal » image » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » swt » org.eclipse.swt.internal.image 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*******************************************************************************
002:         * Copyright (c) 2000, 2006 IBM Corporation and others.
003:         * All rights reserved. This program and the accompanying materials
004:         * are made available under the terms of the Eclipse Public License v1.0
005:         * which accompanies this distribution, and is available at
006:         * http://www.eclipse.org/legal/epl-v10.html
007:         *
008:         * Contributors:
009:         *     IBM Corporation - initial API and implementation
010:         *******************************************************************************/package org.eclipse.swt.internal.image;
011:
012:        import java.io.*;
013:        import org.eclipse.swt.*;
014:        import org.eclipse.swt.graphics.*;
015:        import org.eclipse.swt.internal.*;
016:
017:        final class PNGFileFormat extends FileFormat {
018:            static final int SIGNATURE_LENGTH = 8;
019:            static final int PRIME = 65521;
020:            PngIhdrChunk headerChunk;
021:            PngPlteChunk paletteChunk;
022:            ImageData imageData;
023:            byte[] data;
024:            byte[] alphaPalette;
025:            byte headerByte1;
026:            byte headerByte2;
027:            int adler;
028:
029:            /**
030:             * Skip over signature data. This has already been
031:             * verified in isFileFormat(). 
032:             */
033:            void readSignature() throws IOException {
034:                byte[] signature = new byte[SIGNATURE_LENGTH];
035:                inputStream.read(signature);
036:            }
037:
038:            /**
039:             * Load the PNG image from the byte stream.
040:             */
041:            ImageData[] loadFromByteStream() {
042:                try {
043:                    readSignature();
044:                    PngChunkReader chunkReader = new PngChunkReader(inputStream);
045:                    headerChunk = chunkReader.getIhdrChunk();
046:                    int width = headerChunk.getWidth(), height = headerChunk
047:                            .getHeight();
048:                    if (width <= 0 || height <= 0)
049:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
050:                    int imageSize = getAlignedBytesPerRow() * height;
051:                    data = new byte[imageSize];
052:                    imageData = ImageData.internal_new(width, height,
053:                            headerChunk.getSwtBitsPerPixel(), new PaletteData(
054:                                    0, 0, 0), 4, data, 0, null, null, -1, -1,
055:                            SWT.IMAGE_PNG, 0, 0, 0, 0);
056:
057:                    if (headerChunk.usesDirectColor()) {
058:                        imageData.palette = headerChunk.getPaletteData();
059:                    }
060:
061:                    // Read and process chunks until the IEND chunk is encountered.
062:                    while (chunkReader.hasMoreChunks()) {
063:                        readNextChunk(chunkReader);
064:                    }
065:
066:                    return new ImageData[] { imageData };
067:                } catch (IOException e) {
068:                    SWT.error(SWT.ERROR_INVALID_IMAGE);
069:                    return null;
070:                }
071:            }
072:
073:            /**
074:             * Read and handle the next chunk of data from the 
075:             * PNG file.
076:             */
077:            void readNextChunk(PngChunkReader chunkReader) throws IOException {
078:                PngChunk chunk = chunkReader.readNextChunk();
079:                switch (chunk.getChunkType()) {
080:                case PngChunk.CHUNK_IEND:
081:                    break;
082:                case PngChunk.CHUNK_PLTE:
083:                    if (!headerChunk.usesDirectColor()) {
084:                        paletteChunk = (PngPlteChunk) chunk;
085:                        imageData.palette = paletteChunk.getPaletteData();
086:                    }
087:                    break;
088:                case PngChunk.CHUNK_tRNS:
089:                    PngTrnsChunk trnsChunk = (PngTrnsChunk) chunk;
090:                    if (trnsChunk.getTransparencyType(headerChunk) == PngTrnsChunk.TRANSPARENCY_TYPE_PIXEL) {
091:                        imageData.transparentPixel = trnsChunk
092:                                .getSwtTransparentPixel(headerChunk);
093:                    } else {
094:                        alphaPalette = trnsChunk.getAlphaValues(headerChunk,
095:                                paletteChunk);
096:                        int transparentCount = 0, transparentPixel = -1;
097:                        for (int i = 0; i < alphaPalette.length; i++) {
098:                            if ((alphaPalette[i] & 0xFF) != 255) {
099:                                transparentCount++;
100:                                transparentPixel = i;
101:                            }
102:                        }
103:                        if (transparentCount == 0) {
104:                            alphaPalette = null;
105:                        } else if (transparentCount == 1
106:                                && alphaPalette[transparentPixel] == 0) {
107:                            alphaPalette = null;
108:                            imageData.transparentPixel = transparentPixel;
109:                        }
110:                    }
111:                    break;
112:                case PngChunk.CHUNK_IDAT:
113:                    if (chunkReader.readPixelData()) {
114:                        // All IDAT chunks in an image file must be
115:                        // sequential. If the pixel data has already
116:                        // been read and another IDAT block is encountered,
117:                        // then this is an invalid image.
118:                        SWT.error(SWT.ERROR_INVALID_IMAGE);
119:                    } else {
120:                        // Read in the pixel data for the image. This should
121:                        // go through all the image's IDAT chunks. 	
122:                        PngIdatChunk dataChunk = (PngIdatChunk) chunk;
123:                        readPixelData(dataChunk, chunkReader);
124:                    }
125:                    break;
126:                default:
127:                    if (chunk.isCritical()) {
128:                        // All critical chunks must be supported.
129:                        SWT.error(SWT.ERROR_NOT_IMPLEMENTED);
130:                    }
131:                }
132:            }
133:
134:            void unloadIntoByteStream(ImageLoader loader) {
135:                PngEncoder encoder = new PngEncoder(loader);
136:                encoder.encode(outputStream);
137:            }
138:
139:            boolean isFileFormat(LEDataInputStream stream) {
140:                try {
141:                    byte[] signature = new byte[SIGNATURE_LENGTH];
142:                    stream.read(signature);
143:                    stream.unread(signature);
144:                    if ((signature[0] & 0xFF) != 137)
145:                        return false; //137
146:                    if ((signature[1] & 0xFF) != 80)
147:                        return false; //P
148:                    if ((signature[2] & 0xFF) != 78)
149:                        return false; //N
150:                    if ((signature[3] & 0xFF) != 71)
151:                        return false; //G
152:                    if ((signature[4] & 0xFF) != 13)
153:                        return false; //<RETURN>
154:                    if ((signature[5] & 0xFF) != 10)
155:                        return false; //<LINEFEED>
156:                    if ((signature[6] & 0xFF) != 26)
157:                        return false; //<CTRL/Z>
158:                    if ((signature[7] & 0xFF) != 10)
159:                        return false; //<LINEFEED>		
160:                    return true;
161:                } catch (Exception e) {
162:                    return false;
163:                }
164:            }
165:
166:            /**
167:             * SWT does not support 16-bit depths. If this image uses
168:             * 16-bit depths, convert the data to an 8-bit depth.
169:             */
170:            byte[] validateBitDepth(byte[] data) {
171:                if (headerChunk.getBitDepth() > 8) {
172:                    byte[] result = new byte[data.length / 2];
173:                    compress16BitDepthTo8BitDepth(data, 0, result, 0,
174:                            result.length);
175:                    return result;
176:                } else {
177:                    return data;
178:                }
179:            }
180:
181:            /**
182:             * SWT does not support greyscale as a color type. For
183:             * plain grayscale, we create a palette. For Grayscale
184:             * with Alpha, however, we need to convert the pixels
185:             * to use RGB values.
186:             * Note: This method assumes that the bit depth of the
187:             * data has already been restricted to 8 or less.
188:             */
189:            void setPixelData(byte[] data, ImageData imageData) {
190:                switch (headerChunk.getColorType()) {
191:                case PngIhdrChunk.COLOR_TYPE_GRAYSCALE_WITH_ALPHA: {
192:                    int width = imageData.width;
193:                    int height = imageData.height;
194:                    int destBytesPerLine = imageData.bytesPerLine;
195:                    /*
196:                     * If the image uses 16-bit depth, it is converted
197:                     * to an 8-bit depth image.
198:                     */
199:                    int srcBytesPerLine = getAlignedBytesPerRow();
200:                    if (headerChunk.getBitDepth() > 8)
201:                        srcBytesPerLine /= 2;
202:
203:                    byte[] rgbData = new byte[destBytesPerLine * height];
204:                    byte[] alphaData = new byte[width * height];
205:                    for (int y = 0; y < height; y++) {
206:                        int srcIndex = srcBytesPerLine * y;
207:                        int destIndex = destBytesPerLine * y;
208:                        int destAlphaIndex = width * y;
209:                        for (int x = 0; x < width; x++) {
210:                            byte grey = data[srcIndex];
211:                            byte alpha = data[srcIndex + 1];
212:                            rgbData[destIndex + 0] = grey;
213:                            rgbData[destIndex + 1] = grey;
214:                            rgbData[destIndex + 2] = grey;
215:                            alphaData[destAlphaIndex] = alpha;
216:                            srcIndex += 2;
217:                            destIndex += 3;
218:                            destAlphaIndex++;
219:                        }
220:                    }
221:                    imageData.data = rgbData;
222:                    imageData.alphaData = alphaData;
223:                    break;
224:                }
225:                case PngIhdrChunk.COLOR_TYPE_RGB_WITH_ALPHA: {
226:                    int width = imageData.width;
227:                    int height = imageData.height;
228:                    int destBytesPerLine = imageData.bytesPerLine;
229:                    int srcBytesPerLine = getAlignedBytesPerRow();
230:                    /*
231:                     * If the image uses 16-bit depth, it is converted
232:                     * to an 8-bit depth image.
233:                     */
234:                    if (headerChunk.getBitDepth() > 8)
235:                        srcBytesPerLine /= 2;
236:
237:                    byte[] rgbData = new byte[destBytesPerLine * height];
238:                    byte[] alphaData = new byte[width * height];
239:                    for (int y = 0; y < height; y++) {
240:                        int srcIndex = srcBytesPerLine * y;
241:                        int destIndex = destBytesPerLine * y;
242:                        int destAlphaIndex = width * y;
243:                        for (int x = 0; x < width; x++) {
244:                            rgbData[destIndex + 0] = data[srcIndex + 0];
245:                            rgbData[destIndex + 1] = data[srcIndex + 1];
246:                            rgbData[destIndex + 2] = data[srcIndex + 2];
247:                            alphaData[destAlphaIndex] = data[srcIndex + 3];
248:                            srcIndex += 4;
249:                            destIndex += 3;
250:                            destAlphaIndex++;
251:                        }
252:                    }
253:                    imageData.data = rgbData;
254:                    imageData.alphaData = alphaData;
255:                    break;
256:                }
257:                case PngIhdrChunk.COLOR_TYPE_RGB:
258:                    imageData.data = data;
259:                    break;
260:                case PngIhdrChunk.COLOR_TYPE_PALETTE:
261:                    imageData.data = data;
262:                    if (alphaPalette != null) {
263:                        int size = imageData.width * imageData.height;
264:                        byte[] alphaData = new byte[size];
265:                        byte[] pixelData = new byte[size];
266:                        imageData.getPixels(0, 0, size, pixelData, 0);
267:                        for (int i = 0; i < pixelData.length; i++) {
268:                            alphaData[i] = alphaPalette[pixelData[i] & 0xFF];
269:                        }
270:                        imageData.alphaData = alphaData;
271:                    }
272:                    break;
273:                default:
274:                    imageData.data = data;
275:                    break;
276:                }
277:            }
278:
279:            /**
280:             * PNG supports some color types and bit depths that are 
281:             * unsupported by SWT. If the image uses an unsupported
282:             * color type (either of the gray scale types) or bit
283:             * depth (16), convert the data to an SWT-supported
284:             * format. Then assign the data into the ImageData given.
285:             */
286:            void setImageDataValues(byte[] data, ImageData imageData) {
287:                byte[] result = validateBitDepth(data);
288:                setPixelData(result, imageData);
289:            }
290:
291:            /**
292:             * Read the image data from the data stream. This must handle
293:             * decoding the data, filtering, and interlacing.
294:             */
295:            void readPixelData(PngIdatChunk chunk, PngChunkReader chunkReader)
296:                    throws IOException {
297:                InputStream stream = new PngInputStream(chunk, chunkReader);
298:                //TEMPORARY CODE
299:                boolean use3_2 = System
300:                        .getProperty("org.eclipse.swt.internal.image.PNGFileFormat_3.2") != null;
301:                InputStream inflaterStream = use3_2 ? null : Compatibility
302:                        .newInflaterInputStream(stream);
303:                if (inflaterStream != null) {
304:                    stream = new BufferedInputStream(inflaterStream);
305:                } else {
306:                    stream = new PngDecodingDataStream(stream);
307:                }
308:                int interlaceMethod = headerChunk.getInterlaceMethod();
309:                if (interlaceMethod == PngIhdrChunk.INTERLACE_METHOD_NONE) {
310:                    readNonInterlacedImage(stream);
311:                } else {
312:                    readInterlacedImage(stream);
313:                }
314:                /*
315:                 * InflaterInputStream does not consume all bytes in the stream
316:                 * when it is closed. This may leave unread IDAT chunks. The fix
317:                 * is to read all available bytes before closing it.
318:                 */
319:                while (stream.available() > 0)
320:                    stream.read();
321:                stream.close();
322:            }
323:
324:            /**
325:             * Answer the number of bytes in a word-aligned row of pixel data.
326:             */
327:            int getAlignedBytesPerRow() {
328:                return ((getBytesPerRow(headerChunk.getWidth()) + 3) / 4) * 4;
329:            }
330:
331:            /**
332:             * Answer the number of bytes in each row of the image
333:             * data. Each PNG row is byte-aligned, so images with bit
334:             * depths less than a byte may have unused bits at the
335:             * end of each row. The value of these bits is undefined.
336:             */
337:            int getBytesPerRow() {
338:                return getBytesPerRow(headerChunk.getWidth());
339:            }
340:
341:            /**
342:             * Answer the number of bytes needed to represent a pixel.
343:             * This value depends on the image's color type and bit
344:             * depth. 
345:             * Note that this method rounds up if an image's pixel size
346:             * isn't byte-aligned.
347:             */
348:            int getBytesPerPixel() {
349:                int bitsPerPixel = headerChunk.getBitsPerPixel();
350:                return (bitsPerPixel + 7) / 8;
351:            }
352:
353:            /**
354:             * Answer the number of bytes in a row of the given pixel
355:             * width. Each row is byte-aligned, so images with bit
356:             * depths less than a byte may have unused bits at the
357:             * end of each row. The value of these bits is undefined.
358:             */
359:            int getBytesPerRow(int rowWidthInPixels) {
360:                int bitsPerPixel = headerChunk.getBitsPerPixel();
361:                int bitsPerRow = bitsPerPixel * rowWidthInPixels;
362:                int bitsPerByte = 8;
363:                return (bitsPerRow + (bitsPerByte - 1)) / bitsPerByte;
364:            }
365:
366:            /**
367:             * 1. Read one of the seven frames of interlaced data.
368:             * 2. Update the imageData.
369:             * 3. Notify the image loader's listeners of the frame load.
370:             */
371:            void readInterlaceFrame(InputStream inputStream, int rowInterval,
372:                    int columnInterval, int startRow, int startColumn,
373:                    int frameCount) throws IOException {
374:                int width = headerChunk.getWidth();
375:                int alignedBytesPerRow = getAlignedBytesPerRow();
376:                int height = headerChunk.getHeight();
377:                if (startRow >= height || startColumn >= width)
378:                    return;
379:
380:                int pixelsPerRow = (width - startColumn + columnInterval - 1)
381:                        / columnInterval;
382:                int bytesPerRow = getBytesPerRow(pixelsPerRow);
383:                byte[] row1 = new byte[bytesPerRow];
384:                byte[] row2 = new byte[bytesPerRow];
385:                byte[] currentRow = row1;
386:                byte[] lastRow = row2;
387:                for (int row = startRow; row < height; row += rowInterval) {
388:                    byte filterType = (byte) inputStream.read();
389:                    int read = 0;
390:                    while (read != bytesPerRow) {
391:                        read += inputStream.read(currentRow, read, bytesPerRow
392:                                - read);
393:                    }
394:                    filterRow(currentRow, lastRow, filterType);
395:                    if (headerChunk.getBitDepth() >= 8) {
396:                        int bytesPerPixel = getBytesPerPixel();
397:                        int dataOffset = (row * alignedBytesPerRow)
398:                                + (startColumn * bytesPerPixel);
399:                        for (int rowOffset = 0; rowOffset < currentRow.length; rowOffset += bytesPerPixel) {
400:                            for (int byteOffset = 0; byteOffset < bytesPerPixel; byteOffset++) {
401:                                data[dataOffset + byteOffset] = currentRow[rowOffset
402:                                        + byteOffset];
403:                            }
404:                            dataOffset += (columnInterval * bytesPerPixel);
405:                        }
406:                    } else {
407:                        int bitsPerPixel = headerChunk.getBitDepth();
408:                        int pixelsPerByte = 8 / bitsPerPixel;
409:                        int column = startColumn;
410:                        int rowBase = row * alignedBytesPerRow;
411:                        int valueMask = 0;
412:                        for (int i = 0; i < bitsPerPixel; i++) {
413:                            valueMask <<= 1;
414:                            valueMask |= 1;
415:                        }
416:                        int maxShift = 8 - bitsPerPixel;
417:                        for (int byteOffset = 0; byteOffset < currentRow.length; byteOffset++) {
418:                            for (int bitOffset = maxShift; bitOffset >= 0; bitOffset -= bitsPerPixel) {
419:                                if (column < width) {
420:                                    int dataOffset = rowBase
421:                                            + (column * bitsPerPixel / 8);
422:                                    int value = (currentRow[byteOffset] >> bitOffset)
423:                                            & valueMask;
424:                                    int dataShift = maxShift
425:                                            - (bitsPerPixel * (column % pixelsPerByte));
426:                                    data[dataOffset] |= value << dataShift;
427:                                }
428:                                column += columnInterval;
429:                            }
430:                        }
431:                    }
432:                    currentRow = (currentRow == row1) ? row2 : row1;
433:                    lastRow = (lastRow == row1) ? row2 : row1;
434:                }
435:                setImageDataValues(data, imageData);
436:                fireInterlacedFrameEvent(frameCount);
437:            }
438:
439:            /**
440:             * Read the pixel data for an interlaced image from the
441:             * data stream.
442:             */
443:            void readInterlacedImage(InputStream inputStream)
444:                    throws IOException {
445:                readInterlaceFrame(inputStream, 8, 8, 0, 0, 0);
446:                readInterlaceFrame(inputStream, 8, 8, 0, 4, 1);
447:                readInterlaceFrame(inputStream, 8, 4, 4, 0, 2);
448:                readInterlaceFrame(inputStream, 4, 4, 0, 2, 3);
449:                readInterlaceFrame(inputStream, 4, 2, 2, 0, 4);
450:                readInterlaceFrame(inputStream, 2, 2, 0, 1, 5);
451:                readInterlaceFrame(inputStream, 2, 1, 1, 0, 6);
452:            }
453:
454:            /**
455:             * Fire an event to let listeners know that an interlaced
456:             * frame has been loaded.
457:             * finalFrame should be true if the image has finished
458:             * loading, false if there are more frames to come.
459:             */
460:            void fireInterlacedFrameEvent(int frameCount) {
461:                if (loader.hasListeners()) {
462:                    ImageData image = (ImageData) imageData.clone();
463:                    boolean finalFrame = frameCount == 6;
464:                    loader.notifyListeners(new ImageLoaderEvent(loader, image,
465:                            frameCount, finalFrame));
466:                }
467:            }
468:
469:            /**
470:             * Read the pixel data for a non-interlaced image from the
471:             * data stream.
472:             * Update the imageData to reflect the new data.
473:             */
474:            void readNonInterlacedImage(InputStream inputStream)
475:                    throws IOException {
476:                int dataOffset = 0;
477:                int alignedBytesPerRow = getAlignedBytesPerRow();
478:                int bytesPerRow = getBytesPerRow();
479:                byte[] row1 = new byte[bytesPerRow];
480:                byte[] row2 = new byte[bytesPerRow];
481:                byte[] currentRow = row1;
482:                byte[] lastRow = row2;
483:                int height = headerChunk.getHeight();
484:                for (int row = 0; row < height; row++) {
485:                    byte filterType = (byte) inputStream.read();
486:                    int read = 0;
487:                    while (read != bytesPerRow) {
488:                        read += inputStream.read(currentRow, read, bytesPerRow
489:                                - read);
490:                    }
491:                    filterRow(currentRow, lastRow, filterType);
492:                    System.arraycopy(currentRow, 0, data, dataOffset,
493:                            bytesPerRow);
494:                    dataOffset += alignedBytesPerRow;
495:                    currentRow = (currentRow == row1) ? row2 : row1;
496:                    lastRow = (lastRow == row1) ? row2 : row1;
497:                }
498:                setImageDataValues(data, imageData);
499:            }
500:
501:            /**
502:             * SWT does not support 16-bit depth color formats.
503:             * Convert the 16-bit data to 8-bit data.
504:             * The correct way to do this is to multiply each
505:             * 16 bit value by the value:
506:             * (2^8 - 1) / (2^16 - 1).
507:             * The fast way to do this is just to drop the low
508:             * byte of the 16-bit value.
509:             */
510:            static void compress16BitDepthTo8BitDepth(byte[] source,
511:                    int sourceOffset, byte[] destination,
512:                    int destinationOffset, int numberOfValues) {
513:                //double multiplier = (Compatibility.pow2(8) - 1) / (Compatibility.pow2(16) - 1);
514:                for (int i = 0; i < numberOfValues; i++) {
515:                    int sourceIndex = sourceOffset + (2 * i);
516:                    int destinationIndex = destinationOffset + i;
517:                    //int value = (source[sourceIndex] << 8) | source[sourceIndex + 1];
518:                    //byte compressedValue = (byte)(value * multiplier);
519:                    byte compressedValue = source[sourceIndex];
520:                    destination[destinationIndex] = compressedValue;
521:                }
522:            }
523:
524:            /**
525:             * SWT does not support 16-bit depth color formats.
526:             * Convert the 16-bit data to 8-bit data.
527:             * The correct way to do this is to multiply each
528:             * 16 bit value by the value:
529:             * (2^8 - 1) / (2^16 - 1).
530:             * The fast way to do this is just to drop the low
531:             * byte of the 16-bit value.
532:             */
533:            static int compress16BitDepthTo8BitDepth(int value) {
534:                //double multiplier = (Compatibility.pow2(8) - 1) / (Compatibility.pow2(16) - 1);
535:                //byte compressedValue = (byte)(value * multiplier);
536:                return value >> 8;
537:            }
538:
539:            /**
540:             * PNG supports four filtering types. These types are applied
541:             * per row of image data. This method unfilters the given row
542:             * based on the filterType.
543:             */
544:            void filterRow(byte[] row, byte[] previousRow, int filterType) {
545:                int byteOffset = headerChunk.getFilterByteOffset();
546:                switch (filterType) {
547:                case PngIhdrChunk.FILTER_NONE:
548:                    break;
549:                case PngIhdrChunk.FILTER_SUB:
550:                    for (int i = byteOffset; i < row.length; i++) {
551:                        int current = row[i] & 0xFF;
552:                        int left = row[i - byteOffset] & 0xFF;
553:                        row[i] = (byte) ((current + left) & 0xFF);
554:                    }
555:                    break;
556:                case PngIhdrChunk.FILTER_UP:
557:                    for (int i = 0; i < row.length; i++) {
558:                        int current = row[i] & 0xFF;
559:                        int above = previousRow[i] & 0xFF;
560:                        row[i] = (byte) ((current + above) & 0xFF);
561:                    }
562:                    break;
563:                case PngIhdrChunk.FILTER_AVERAGE:
564:                    for (int i = 0; i < row.length; i++) {
565:                        int left = (i < byteOffset) ? 0
566:                                : row[i - byteOffset] & 0xFF;
567:                        int above = previousRow[i] & 0xFF;
568:                        int current = row[i] & 0xFF;
569:                        row[i] = (byte) ((current + ((left + above) / 2)) & 0xFF);
570:                    }
571:                    break;
572:                case PngIhdrChunk.FILTER_PAETH:
573:                    for (int i = 0; i < row.length; i++) {
574:                        int left = (i < byteOffset) ? 0
575:                                : row[i - byteOffset] & 0xFF;
576:                        int aboveLeft = (i < byteOffset) ? 0 : previousRow[i
577:                                - byteOffset] & 0xFF;
578:                        int above = previousRow[i] & 0xFF;
579:
580:                        int a = Math.abs(above - aboveLeft);
581:                        int b = Math.abs(left - aboveLeft);
582:                        int c = Math.abs(left - aboveLeft + above - aboveLeft);
583:
584:                        int preductor = 0;
585:                        if (a <= b && a <= c) {
586:                            preductor = left;
587:                        } else if (b <= c) {
588:                            preductor = above;
589:                        } else {
590:                            preductor = aboveLeft;
591:                        }
592:
593:                        int currentValue = row[i] & 0xFF;
594:                        row[i] = (byte) ((currentValue + preductor) & 0xFF);
595:                    }
596:                    break;
597:                }
598:            }
599:
600:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.