Source Code Cross Referenced for PNGHelper.java in  » Ajax » Laszlo-4.0.10 » org » openlaszlo » iv » flash » util » 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 » Ajax » Laszlo 4.0.10 » org.openlaszlo.iv.flash.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: PNGHelper.java,v 1.3 2002/06/27 21:49:17 awason Exp $
0003:         *
0004:         * ===========================================================================
0005:         *
0006:         * The JGenerator Software License, Version 1.0
0007:         *
0008:         * Copyright (c) 2000 Dmitry Skavish (skavish@usa.net). All rights reserved.
0009:         *
0010:         * Redistribution and use in source and binary forms, with or without
0011:         * modification, are permitted provided that the following conditions are met:
0012:         *
0013:         * 1. Redistributions of source code must retain the above copyright
0014:         *    notice, this list of conditions and the following disclaimer.
0015:         *
0016:         * 2. Redistributions in binary form must reproduce the above copyright
0017:         *    notice, this list of conditions and the following disclaimer in
0018:         *    the documentation and/or other materials provided with the
0019:         *    distribution.
0020:         *
0021:         * 3. The end-user documentation included with the redistribution, if
0022:         *    any, must include the following acknowlegement:
0023:         *    "This product includes software developed by Dmitry Skavish
0024:         *     (skavish@usa.net, http://www.flashgap.com/)."
0025:         *    Alternately, this acknowlegement may appear in the software itself,
0026:         *    if and wherever such third-party acknowlegements normally appear.
0027:         *
0028:         * 4. The name "The JGenerator" must not be used to endorse or promote
0029:         *    products derived from this software without prior written permission.
0030:         *    For written permission, please contact skavish@usa.net.
0031:         *
0032:         * 5. Products derived from this software may not be called "The JGenerator"
0033:         *    nor may "The JGenerator" appear in their names without prior written
0034:         *    permission of Dmitry Skavish.
0035:         *
0036:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0037:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0038:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0039:         * DISCLAIMED.  IN NO EVENT SHALL DMITRY SKAVISH OR THE OTHER
0040:         * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0041:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0042:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0043:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0044:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0045:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0046:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0047:         * SUCH DAMAGE.
0048:         *
0049:         */
0050:
0051:        package org.openlaszlo.iv.flash.util;
0052:
0053:        import java.io.EOFException;
0054:        import java.io.IOException;
0055:        import java.io.InputStream;
0056:        import java.io.DataInputStream;
0057:        import java.io.BufferedInputStream;
0058:        import java.io.ByteArrayInputStream;
0059:        import java.util.zip.InflaterInputStream;
0060:        import java.util.zip.Deflater;
0061:        import java.util.zip.CRC32;
0062:        import java.util.Hashtable;
0063:        import org.openlaszlo.iv.flash.parser.DataMarker;
0064:
0065:        /**
0066:         * Helper class to decode PNG images.
0067:         * Does read but not support gAMA chunk (yet :-)
0068:         * @author Patrick Talbot
0069:         */
0070:        public class PNGHelper {
0071:            /** header chunk */
0072:            private static final int CHUNK_IHDR = 0x49484452;
0073:            /** palette chunk */
0074:            private static final int CHUNK_PLTE = 0x504c5445;
0075:            /** data chunk */
0076:            private static final int CHUNK_IDAT = 0x49444154;
0077:            /** end of file chunk */
0078:            private static final int CHUNK_IEND = 0x49454e44;
0079:            /** transparency chunk */
0080:            private static final int CHUNK_tRNS = 0x74524e53;
0081:
0082:            /** background (ignored) chunk */
0083:            private static final int CHUNK_bKGD = 0x624b4744;
0084:            /** chromaticities (ignored) chunk */
0085:            private static final int CHUNK_cHRM = 0x6348524d;
0086:            /** fractal image parameters (ignored) chunk */
0087:            private static final int CHUNK_fRAc = 0x66524163;
0088:            /** gamma (ignored) chunk */
0089:            private static final int CHUNK_gAMA = 0x67414d41;
0090:            /** GIF graphic control (ignored) chunk */
0091:            private static final int CHUNK_gIFg = 0x67494667;
0092:            /** GIF plain text (ignored) chunk */
0093:            private static final int CHUNK_gIFt = 0x67494674;
0094:            /** GIF application (ignored) chunk */
0095:            private static final int CHUNK_gIFx = 0x67494678;
0096:            /** histogram (ignored) chunk */
0097:            private static final int CHUNK_hIST = 0x68495354;
0098:            /** embedded ICC profile (ignored) chunk */
0099:            private static final int CHUNK_iCCP = 0x69434350;
0100:            /** unicode UTF-8 text (ignored) chunk */
0101:            private static final int CHUNK_iTXt = 0x69545874;
0102:            /** image offset (ignored) chunk */
0103:            private static final int CHUNK_oFFs = 0x6f464673;
0104:            /** calibration (ignored) chunk */
0105:            private static final int CHUNK_pCAL = 0x7043414c;
0106:            /** physical pixel dimension (ignored) chunk */
0107:            private static final int CHUNK_pHYs = 0x70485973;
0108:            /** significant bits (ignored) chunk */
0109:            private static final int CHUNK_sBIT = 0x73424954;
0110:            /** physical scale (ignored) chunk */
0111:            private static final int CHUNK_sCAL = 0x7343414c;
0112:            /** suggested palette (ignored) chunk */
0113:            private static final int CHUNK_sPLT = 0x73504c54;
0114:            /** standard RGB colour space (ignored) chunk */
0115:            private static final int CHUNK_sRGB = 0x73524742;
0116:            /** normal text (ignored) chunk */
0117:            private static final int CHUNK_tEXt = 0x74455874;
0118:            /** time stamp (ignored) chunk */
0119:            private static final int CHUNK_tIME = 0x74494d45;
0120:            /** compressed text (ignored) chunk */
0121:            private static final int CHUNK_zTXt = 0x7a545874;
0122:
0123:            /** PNG Signature */
0124:            private static final int[] PNG_SIGN = { 0x89, 0x50, 0x4e, 0x47,
0125:                    0x0d, 0x0a, 0x1a, 0x0a };
0126:
0127:            /** a flag to test if the header chunk has been encountered */
0128:            private boolean flagIHDR = false;
0129:            /** a flag to test if data chunks have been encountered */
0130:            private boolean flagIDAT = false;
0131:            /** a flag to test if the palette chunk has been encountered */
0132:            private boolean flagPLTE = false;
0133:
0134:            /** flag used to indicate that further computing is need to manage transparency */
0135:            private boolean tRNSPassRequired = false;
0136:            /** transparency color for colorType 0 and 2 */
0137:            private RGB tRNSKeyColor = null;
0138:            /** used to determine if transparency chunk exists */
0139:            private boolean flagtRNS = false;
0140:
0141:            /** number of bytes used per pixel */
0142:            private int colorType_components = -1;
0143:
0144:            /** compression method should always be 0 = deflate/inflate, */
0145:            private int compressionMethod = -1;
0146:            /** filter method can be
0147:             * 0 = none
0148:             * 1 = sub
0149:             * 2 = up
0150:             * 3 = average
0151:             * 4 = paeth
0152:             */
0153:            private int filterMethod = -1;
0154:            /** interlace method can be
0155:             * 0 = not interlace
0156:             * 1 = Adam7 interlacing
0157:             */
0158:            private int interlaceMethod = -1;
0159:
0160:            /** width of image*/
0161:            private int width = -1;
0162:            /** height of image */
0163:            private int height = -1;
0164:            /** pixels bit depth can be 1,2,4,8,16 */
0165:            private int bitDepth = -1;
0166:
0167:            /** gamma value of image, set to default value */
0168:            private long gamma = 45455;
0169:
0170:            /** color type can be
0171:             * 0 = gray
0172:             * 2 = RGB
0173:             * 3 = paletted
0174:             * 4 = gray + alpha
0175:             * 6 = RGB + alpha
0176:             */
0177:            private int colorType = -1;
0178:
0179:            /** flag set if palette is used */
0180:            private boolean colorType_hasPalette = false;
0181:            /** flag set if alpha channel exists for colorType = 4 or 6 */
0182:            private boolean colorType_hasAlpha = false;
0183:            /** flag set if not gray */
0184:            private boolean colorType_hasColor = false;
0185:
0186:            /** RGB Palette */
0187:            private RGB[] palette;
0188:
0189:            /** size of the palette */
0190:            private int colorsUsed = 0;
0191:
0192:            /** main IDAT buffer */
0193:            private byte[] buffer;
0194:
0195:            /** main filters per row buffer */
0196:            //private int[] filters;
0197:            /** Stream to read data from */
0198:            private CRCInputStream source;
0199:
0200:            /**
0201:             * A private input stream class used to read multi-byte integer values
0202:             * while maintaining CRC code for read bytes.
0203:             * Provides utility methods to read multi-byte integer values
0204:             * in both little- and bit-endian orders.
0205:             */
0206:            //private
0207:            public class CRCInputStream extends DataInputStream {
0208:                /** crc checker */
0209:                private CRC32 crc = new CRC32();
0210:
0211:                /**
0212:                 * Constructor
0213:                 * @param inputStream java.io.InputStream
0214:                 */
0215:                public CRCInputStream(InputStream inputStream) {
0216:                    super (inputStream);
0217:                }
0218:
0219:                /**
0220:                 * Return the crc value
0221:                 * @return long
0222:                 */
0223:                public long getCRC() {
0224:                    return crc.getValue();
0225:                }
0226:
0227:                /**
0228:                 * Reset the crc checker
0229:                 */
0230:                public void reset() {
0231:                    crc.reset();
0232:                }
0233:
0234:                /**
0235:                 * Read one int and ensure the crc is updated
0236:                 * @return int
0237:                 */
0238:                public int read() throws IOException {
0239:                    int x = super .read();
0240:                    crc.update(x);
0241:                    return x;
0242:                }
0243:
0244:                /**
0245:                 * Read two ints
0246:                 * @return int
0247:                 */
0248:                public int read2() throws IOException, EOFException {
0249:                    int a = read();
0250:                    int b = read();
0251:                    return a | b << 8;
0252:                }
0253:
0254:                /**
0255:                 * Read two ints in reverse order
0256:                 * @return int
0257:                 */
0258:                public int read2n() throws IOException, EOFException {
0259:                    int b = read();
0260:                    int a = read();
0261:                    return a | b << 8;
0262:                }
0263:
0264:                /**
0265:                 * Read a long in reverse order
0266:                 * @return long
0267:                 */
0268:                public long read4n() throws IOException, EOFException {
0269:                    long b = (long) read2n();
0270:                    long a = (long) read2n();
0271:                    return a | b << 16;
0272:                }
0273:            }
0274:
0275:            /**
0276:             * Private wrapper class for colors in RGBA float format
0277:             * Provides utilities to set Color from different input format
0278:             * And utilities to retrive them accordingly
0279:             */
0280:            //private
0281:            public class RGB {
0282:                /** represents 15 bits format */
0283:                private static final int FORMAT_RGB5 = 0x8050;
0284:                /** represents 24 bits format */
0285:                private static final int FORMAT_RGB8 = 0x8051;
0286:                /** represents 16 bits format */
0287:                private static final int FORMAT_RGB5_A1 = 0x8057;
0288:                /** represents 32 bits format */
0289:                private static final int FORMAT_RGBA8 = 0x8058;
0290:
0291:                /** used to define color without alpha information */
0292:                private static final int NO_ALPHA = -1;
0293:
0294:                /** default alpha value */
0295:                private static final float DEFAULT_ALPHA = 1.0f;
0296:                /** used to define color with default format */
0297:                private static final float DEFAULT_FORMAT = 255.0f;
0298:
0299:                /** red value */
0300:                private float red;
0301:                /** green value */
0302:                private float green;
0303:                /** blue value */
0304:                private float blue;
0305:                /** alpha value */
0306:                private float alpha;
0307:
0308:                /**
0309:                 * float gray constructor
0310:                 * @param gray float
0311:                 */
0312:                public RGB(float gray) {
0313:                    set(gray, gray, gray, DEFAULT_ALPHA);
0314:                }
0315:
0316:                /**
0317:                 * int gray constructor
0318:                 * @param gray int
0319:                 */
0320:                public RGB(int gray) {
0321:                    set(gray, gray, gray, NO_ALPHA, NO_ALPHA);
0322:                }
0323:
0324:                /**
0325:                 * int gray + alpha constructor
0326:                 * @param gray int
0327:                 * @param a int
0328:                 */
0329:                public RGB(int gray, int a) {
0330:                    set(gray, gray, gray, a, DEFAULT_FORMAT);
0331:                }
0332:
0333:                /**
0334:                 * float gray + alpha constructor
0335:                 * @param gray float
0336:                 * @param a float
0337:                 */
0338:                public RGB(float gray, float a) {
0339:                    set(gray, gray, gray, a);
0340:                }
0341:
0342:                /**
0343:                 * float r,g,b constructor
0344:                 * @param r float
0345:                 * @param g float
0346:                 * @param b float
0347:                 */
0348:                public RGB(float r, float g, float b) {
0349:                    set(r, g, b, DEFAULT_ALPHA);
0350:                }
0351:
0352:                /**
0353:                 * int r,g,b constructor
0354:                 * @param r int
0355:                 * @param g int
0356:                 * @param b int
0357:                 */
0358:                public RGB(int r, int g, int b) {
0359:                    set(r, g, b, NO_ALPHA, NO_ALPHA);
0360:                }
0361:
0362:                /**
0363:                 * int r,g,b + alpha constructor
0364:                 * @param r int
0365:                 * @param g int
0366:                 * @param b int
0367:                 * @param a int
0368:                 */
0369:                public RGB(int r, int g, int b, int a) {
0370:                    set((float) r / DEFAULT_FORMAT, (float) g / DEFAULT_FORMAT,
0371:                            (float) b / DEFAULT_FORMAT, (float) a
0372:                                    / DEFAULT_FORMAT);
0373:                }
0374:
0375:                /**
0376:                 * float r,g,b + alpha constructor
0377:                 * @param r float
0378:                 * @param g float
0379:                 * @param b float
0380:                 * @param a float
0381:                 */
0382:                public RGB(float r, float g, float b, float a) {
0383:                    set(r, g, b, a);
0384:                }
0385:
0386:                /**
0387:                 * general float r,g,b + alpha setter
0388:                 * @param r float
0389:                 * @param g float
0390:                 * @param b float
0391:                 * @param a float
0392:                 */
0393:                public void set(float r, float g, float b, float a) {
0394:                    red = r > 1.0f ? 1.0f : (r < 0.0f ? 0.0f : r);
0395:                    green = g > 1.0f ? 1.0f : (g < 0.0f ? 0.0f : g);
0396:                    blue = b > 1.0f ? 1.0f : (b < 0.0f ? 0.0f : b);
0397:                    alpha = a > 1.0f ? 1.0f : (a < 0.0f ? 0.0f : a);
0398:                }
0399:
0400:                /**
0401:                 * general int r,g,b + alpha setter
0402:                 * @param r int
0403:                 * @param g int
0404:                 * @param b int
0405:                 * @param a int
0406:                 * @param format float
0407:                 */
0408:                public void set(int r, int g, int b, int a, float format) {
0409:                    set((float) r / DEFAULT_FORMAT, (float) g / DEFAULT_FORMAT,
0410:                            (float) b / DEFAULT_FORMAT,
0411:                            format == NO_ALPHA ? DEFAULT_ALPHA : (float) a
0412:                                    / format);
0413:                }
0414:
0415:                /**
0416:                 * Return an int array of color packed in the requested format
0417:                 * @param format int
0418:                 * @return int[]
0419:                 */
0420:                public int[] getPacked(int format) {
0421:                    int r;
0422:                    int g;
0423:                    int b;
0424:                    switch (format) {
0425:                    case FORMAT_RGB5:
0426:                        r = (int) (red * 32.0f);
0427:                        g = (int) (green * 32.0f);
0428:                        b = (int) (blue * 32.0f);
0429:                        return new int[] { r + (g & 0x07) << 5,
0430:                                (g & 0x18) >> 3 + (b & 0x1f) << 2 };
0431:                    case FORMAT_RGB8:
0432:                        return new int[] { (int) (red * 255.0f),
0433:                                (int) (green * 255.0f), (int) (blue * 255.0f) };
0434:                    case FORMAT_RGB5_A1:
0435:                        r = (int) (red * 32.0f);
0436:                        g = (int) (green * 32.0f);
0437:                        b = (int) (blue * 32.0f);
0438:                        return new int[] {
0439:                                r + (g & 0x07) << 5,
0440:                                (g & 0x18) >> 3 + (b & 0x1f) << 2 + (alpha > 0.5f ? 128
0441:                                        : 0) };
0442:                    case FORMAT_RGBA8:
0443:                        return new int[] { (int) (red * 255.0f),
0444:                                (int) (green * 255.0f), (int) (blue * 255.0f),
0445:                                (int) (alpha * 255.0f) };
0446:                    default:
0447:                        throw new IllegalArgumentException(
0448:                                "Unknown color format " + format);
0449:                    }
0450:                }
0451:
0452:                /*
0453:                 * get the red value as a float
0454:                 * @return float
0455:                 */
0456:                public float getRed() {
0457:                    return red;
0458:                }
0459:
0460:                /*
0461:                 * get the green value as a float
0462:                 * @return float
0463:                 */
0464:                public float getGreen() {
0465:                    return green;
0466:                }
0467:
0468:                /*
0469:                 * get the blue value as a float
0470:                 * @return float
0471:                 */
0472:                public float getBlue() {
0473:                    return blue;
0474:                }
0475:
0476:                /*
0477:                 * get the alpha value as a float
0478:                 * @return float
0479:                 */
0480:                public float getAlpha() {
0481:                    return alpha;
0482:                }
0483:
0484:                /**
0485:                 * Set the alpha value as a float
0486:                 * @param alpha float
0487:                 */
0488:                public void setAlpha(float alpha) {
0489:                    this .alpha = alpha;
0490:                }
0491:
0492:                /*
0493:                 * Compare to RGB colors (with or without alpha)
0494:                 * @param rgb RGB the color to compare to
0495:                 * @param compareAlpha boolean (use or not alpha in the comparison)
0496:                 * @return boolean
0497:                 */
0498:                public boolean compareTo(RGB rgb, boolean compareAlpha) {
0499:                    if (rgb.getRed() == red && rgb.getGreen() == green
0500:                            && rgb.getBlue() == blue)
0501:                        if (!compareAlpha
0502:                                || (compareAlpha && rgb.getAlpha() == alpha))
0503:                            return true;
0504:                    return false;
0505:                }
0506:            }
0507:
0508:            /*
0509:             * Default constructor does nothing
0510:             * You need to use the setInputStream method to set the input
0511:             * before attempting to get the zlib buffer and info
0512:             */
0513:            public PNGHelper() {
0514:            }
0515:
0516:            /*
0517:             * Constructor. Allocates a Buffered Input Stream to optimises reading
0518:             * @param inputBuffer byte[]
0519:             */
0520:            public PNGHelper(byte[] inputBuffer) {
0521:                setInputBuffer(inputBuffer);
0522:            }
0523:
0524:            /**
0525:             * Set the main inputStream and construct the CRCInputStream to read to
0526:             *
0527:             * @param inputBuffer buffer to read from
0528:             */
0529:            public void setInputBuffer(byte[] inputBuffer) {
0530:                source = new CRCInputStream(new ByteArrayInputStream(
0531:                        inputBuffer));
0532:            }
0533:
0534:            /**
0535:             * Set the main inputStream and construct the CRCInputStream to read to
0536:             *
0537:             * @param fob    buffer to read from
0538:             */
0539:            public void setInputBuffer(FlashBuffer fob) {
0540:                //source = new CRCInputStream(new ByteArrayInputStream(fob.getBuf(),0,fob.getSize()));
0541:                source = new CRCInputStream(fob.getInputStream());
0542:            }
0543:
0544:            /**
0545:             * Return the width of the image
0546:             * @return width of the image
0547:             */
0548:            public int getWidth() {
0549:                return width;
0550:            }
0551:
0552:            /**
0553:             * Return the height of the image
0554:             *
0555:             * @return height of the image
0556:             */
0557:            public int getHeight() {
0558:                return height;
0559:            }
0560:
0561:            /*
0562:             * Return the palette size (= -1 if none)
0563:             * @return int
0564:             */
0565:            public int getColorTableSize() {
0566:                return (colorsUsed - 1);
0567:            }
0568:
0569:            /*
0570:             * Return transparency
0571:             * if colorType = 4 or 6, the image uses Alpha Channel
0572:             * Otherwise if a tRNS chunk has been seen
0573:             * @return boolean
0574:             */
0575:            public boolean hasTransparency() {
0576:                return (colorType > 3 || flagtRNS);
0577:            }
0578:
0579:            /*
0580:             * Return a color format compatible with Flash expectancy
0581:             * 3 = 8 bits; 4 = 16 bits; 5 = 32 bits
0582:             * Based on the colorType_components value
0583:             * And the bitDepth of image
0584:             * @return int
0585:             */
0586:            public int getFormat() {
0587:                int format;
0588:                switch (colorType_components) {
0589:                case 1:
0590:                    format = 3; // 8 bits
0591:                    if (colorType == 0)
0592:                        format = 5;
0593:                    if (bitDepth == 16)
0594:                        format = 5;
0595:                    break;
0596:                //case 2:
0597:                //format = 4; // 16 bits : forget about it
0598:                //break;
0599:                default:
0600:                    format = 5; // 32 bits
0601:                    break;
0602:                }
0603:                return format;
0604:            }
0605:
0606:            /*
0607:             * Return the zLib compressed Image data.
0608:             * We should be able to send back the IDAT buffer... unfortunately,
0609:             * its format is not recognised as such by Flash Player !
0610:             * So basically we need to compute our own zLib compression
0611:             * on data compatible with Flash
0612:             * This can be time consuming !
0613:             * @return DataMarker the zlibDatas
0614:             * @exception java.io.IOException
0615:             * @exception java.io.EOFException
0616:             */
0617:            public DataMarker getZlibData() throws IOException, EOFException,
0618:                    IVException {
0619:                RGB[][] rgb = read();
0620:                boolean transparency = hasTransparency();
0621:                int format = getFormat();
0622:                int mult = 1;
0623:                switch (format) {
0624:                case 4:
0625:                    mult = 2;
0626:                    break;
0627:                case 5:
0628:                    mult = 4;
0629:                }
0630:                byte[] tempData;
0631:                int plus = 3;
0632:                int[] pixel;
0633:                int idx = 0;
0634:                int falsewidth = width;
0635:                int added = 0;
0636:                int maxpixels = width * height;
0637:                // calculate padding (if needed)
0638:                if ((mult == 1) && (width % 4 > 0)) {
0639:                    while (falsewidth % 4 > 0) {
0640:                        falsewidth++;
0641:                        added++;
0642:                    }
0643:                    maxpixels = falsewidth * height;
0644:                }
0645:
0646:                if (colorType_hasPalette) {
0647:                    if (transparency) // Use RGBA palette
0648:                        plus++;
0649:
0650:                    tempData = new byte[(maxpixels) + (colorsUsed * plus)]; // Index + Palette RGB(A)
0651:                    for (int i = 0; i < colorsUsed; i++) {
0652:                        if (transparency)
0653:                            pixel = palette[i].getPacked(RGB.FORMAT_RGBA8);
0654:                        else
0655:                            pixel = palette[i].getPacked(RGB.FORMAT_RGB8);
0656:
0657:                        if (transparency && pixel[3] == 0x00) // the color itself should be 0
0658:                        {
0659:                            tempData[idx++] = 0;
0660:                            tempData[idx++] = 0;
0661:                            tempData[idx++] = 0;
0662:                        } else {
0663:                            tempData[idx++] = (byte) ((pixel[0]));
0664:                            tempData[idx++] = (byte) ((pixel[1]));
0665:                            tempData[idx++] = (byte) ((pixel[2]));
0666:                        }
0667:                        if (transparency)
0668:                            tempData[idx++] = (byte) ((pixel[3]));
0669:                    }
0670:                } else {
0671:                    if (transparency)
0672:                        mult = 4;
0673:                    tempData = new byte[(maxpixels * mult)]; // RGB (+ Alpha)
0674:                }
0675:
0676:                for (int y = 0; y < height; y++) {
0677:                    for (int x = 0; x < width; x++) {
0678:                        if (colorType_hasPalette) {
0679:                            if (transparency)
0680:                                pixel = rgb[y][x].getPacked(RGB.FORMAT_RGBA8);
0681:                            else
0682:                                pixel = rgb[y][x].getPacked(RGB.FORMAT_RGB8);
0683:                            int b = 0;
0684:                            for (int i = 0; i < palette.length; i++) {
0685:                                if (palette[i].compareTo(rgb[y][x], false)) {
0686:                                    b = i;
0687:                                    break;
0688:                                }
0689:                            }
0690:                            tempData[idx++] = (byte) b;
0691:                        } else {
0692:                            if (mult == 4)
0693:                                pixel = rgb[y][x].getPacked(RGB.FORMAT_RGBA8);
0694:                            else if (mult == 2)
0695:                                pixel = rgb[y][x].getPacked(RGB.FORMAT_RGB5_A1);
0696:                            else
0697:                                pixel = rgb[y][x].getPacked(RGB.FORMAT_RGB8);
0698:
0699:                            if (pixel != null) {
0700:                                if (mult == 4)
0701:                                    tempData[idx++] = (byte) ((pixel[3]));
0702:                                tempData[idx++] = (byte) ((pixel[0]));
0703:                                if (mult > 1)
0704:                                    tempData[idx++] = (byte) ((pixel[1]));
0705:                                if (mult == 4)
0706:                                    tempData[idx++] = (byte) ((pixel[2]));
0707:                            }
0708:                        }
0709:                    }
0710:                    if (added > 0) // 32 bits padding for 8 bits image
0711:                    {
0712:                        for (int i = 0; i < added; i++) {
0713:                            tempData[idx++] = 0x00;
0714:                        }
0715:                    }
0716:                }
0717:                Deflater deflater = new Deflater(9); // MAXIMUM Compression
0718:                deflater.setInput(tempData);
0719:                byte[] data = new byte[(maxpixels * mult) + (colorsUsed * plus)];
0720:                deflater.finish();
0721:                int defsize = deflater.deflate(data);
0722:                byte[] buff = new byte[defsize];
0723:                System.arraycopy(data, 0, buff, 0, defsize);
0724:                DataMarker zlibDatas = new DataMarker(buff, 0, defsize);
0725:                return zlibDatas;
0726:            }
0727:
0728:            /***********************************************************************************
0729:             **                              PRIVATE IMPLEMENTATION                            **
0730:             ***********************************************************************************/
0731:
0732:            /*
0733:             * Reads the actual datas, return a multiDimentionnal RGB array : the pixels
0734:             * @return RGB[][]
0735:             * @exception java.io.IOException
0736:             * @exception java.io.EOFException
0737:             */
0738:            private RGB[][] read() throws IOException, EOFException,
0739:                    IVException {
0740:                if (source == null)
0741:                    throw new IOException("Null input stream");
0742:                source.mark(Integer.MAX_VALUE);
0743:                buffer = new byte[0];
0744:                try {
0745:                    for (int i = 0; i < 8; i++)
0746:                        if (source.read() != PNG_SIGN[i])
0747:                            throw new IOException("Not a valid PNG file");
0748:
0749:                    int length;
0750:                    int id;
0751:                    while (true) {
0752:                        length = (int) source.read4n();
0753:                        source.reset();
0754:                        id = (int) source.read4n();
0755:                        switch (id) {
0756:                        // Critical chunks
0757:                        case CHUNK_IHDR:
0758:                            readChunk_IHDR(length);
0759:                            break;
0760:                        case CHUNK_PLTE:
0761:                            readChunk_PLTE(length);
0762:                            break;
0763:                        case CHUNK_tRNS:
0764:                            readChunk_tRNS(length);
0765:                            break;
0766:                        case CHUNK_IDAT:
0767:                            readChunk_IDAT(length);
0768:                            break;
0769:                        case CHUNK_IEND:
0770:                            if (!flagIHDR || !flagIDAT)
0771:                                throw new IOException(
0772:                                        "No header or data chunk found");
0773:                            return decode(buffer);
0774:
0775:                            // known, ignored chunks
0776:                        case CHUNK_gAMA:
0777:                            readChunk_gAMA(length);
0778:                            break; // read only for now
0779:                        case CHUNK_bKGD:
0780:                        case CHUNK_cHRM: // we might need this one later for advanced color handling
0781:                        case CHUNK_fRAc:
0782:                        case CHUNK_gIFg:
0783:                        case CHUNK_gIFt:
0784:                        case CHUNK_gIFx:
0785:                        case CHUNK_hIST:
0786:                        case CHUNK_iCCP: // we might need this one later for advanced color handling
0787:                        case CHUNK_iTXt:
0788:                        case CHUNK_oFFs:
0789:                        case CHUNK_pCAL:
0790:                        case CHUNK_pHYs:
0791:                        case CHUNK_sBIT:
0792:                        case CHUNK_sCAL:
0793:                        case CHUNK_sPLT: // we might need this one later for advanced color handling
0794:                        case CHUNK_sRGB: // we might need this one later for advanced color handling
0795:                        case CHUNK_tEXt:
0796:                        case CHUNK_tIME:
0797:                        case CHUNK_zTXt:
0798:                            source.skipBytes(length + 4); // skip it and its CRC code
0799:                            break;
0800:                        default:
0801:                            // unknown chunk...
0802:                            if ((id & 0x20000000) == 0)
0803:                                // if critical we throw...
0804:                                throw new IOException("Unknown critical chunk "
0805:                                        + (char) ((id >> 24) & 0xff)
0806:                                        + (char) ((id >> 16) & 0xff)
0807:                                        + (char) ((id >> 8) & 0xff)
0808:                                        + (char) (id & 0xff));
0809:                            // otherwise, skip that chunk and its CRC code
0810:                            source.skipBytes(length + 4);
0811:                        }
0812:                    }
0813:                } catch (EOFException eofe) {
0814:                    throw new EOFException("Reached unexpected EOF");
0815:                } catch (IOException ioe) {
0816:                    throw new IOException("Error while reading file");
0817:                }
0818:            }
0819:
0820:            /**
0821:             * Deal with the gamma chunk
0822:             * @param length int the length of the chunk to read
0823:             * @exception java.io.IOException
0824:             */
0825:            private void readChunk_gAMA(int length) throws IOException {
0826:                if (flagIDAT || flagPLTE)
0827:                    throw new IOException(
0828:                            "gAMA chunk must precede IDAT and PLTE chunks");
0829:
0830:                if (length != 4)
0831:                    throw new IOException("Invalid length " + length
0832:                            + " for gAMA chunk");
0833:
0834:                gamma = source.read4n(); // the float value will be : (val / 100000)
0835:
0836:                long okCRC = source.getCRC();
0837:                if (source.read4n() != okCRC)
0838:                    throw new IOException("Invalid CRC for gAMA chunk "
0839:                            + length);
0840:            }
0841:
0842:            /**
0843:             * Deal with the transparency chunk
0844:             * @param length int the length of the chunk to read
0845:             * @exception java.io.IOException
0846:             */
0847:            private void readChunk_tRNS(int length) throws IOException {
0848:                if (!flagIHDR || flagIDAT)
0849:                    throw new IOException("Misplaced transparency chunk");
0850:
0851:                switch (colorType) {
0852:                case 0: // grayscale
0853:                    int tmp1 = source.read();
0854:                    int tmp2 = source.read();
0855:
0856:                    if (bitDepth < 16) {
0857:                        int max = 1;
0858:                        switch (bitDepth) {
0859:                        case 1:
0860:                            max = 256;
0861:                            break;
0862:                        case 2:
0863:                            max = 256 / 4;
0864:                            break;
0865:                        case 4:
0866:                            max = 256 / 16;
0867:                            break;
0868:                        }
0869:                        if (bitDepth == 1) // (0x00 or 0xff)
0870:                            tRNSKeyColor = new RGB(tmp2 * max);
0871:                        else {
0872:                            tmp1 = ((tmp2 + 1) * max) - 1;
0873:                            tmp1 = (tmp1 < 0) ? 0 : tmp1;
0874:                            tRNSKeyColor = new RGB(tmp1);
0875:                        }
0876:                    } else
0877:                        tRNSKeyColor = new RGB(
0878:                                (float) (tmp1 << 8 | tmp2) / 65535.0f);
0879:
0880:                    tRNSKeyColor.setAlpha(0.0f);
0881:                    tRNSPassRequired = true;
0882:                    break;
0883:                case 2: // RGB
0884:                    int tmp;
0885:                    int cr1 = source.read();
0886:                    int cr2 = source.read();
0887:                    int cg1 = source.read();
0888:                    int cg2 = source.read();
0889:                    int cb1 = source.read();
0890:                    int cb2 = source.read();
0891:                    if (bitDepth < 16) {
0892:                        tRNSKeyColor = new RGB(cr2, cg2, cb2);
0893:                    } else
0894:                        tRNSKeyColor = new RGB(
0895:                                (float) (cr1 << 8 | cr2) / 65535.0f,
0896:                                (float) (cg1 << 8 | cg2) / 65535.0f,
0897:                                (float) (cb1 << 8 | cb2) / 65535.0f);
0898:                    tRNSKeyColor.setAlpha(0.0f);
0899:                    tRNSPassRequired = true;
0900:                    break;
0901:                case 3: // paletted
0902:                    // update palette entries with alpha information
0903:                    for (int i = 0; i < length; i++)
0904:                        palette[i].setAlpha((float) source.read() / 255.0f);
0905:                    break;
0906:                default: // 4 and 6 colorType should not have tranparency chunk, they have Alpha channel instead
0907:                    throw new IOException("Unexpected transparency chunk");
0908:                }
0909:                flagtRNS = true;
0910:
0911:                long okCRC = source.getCRC();
0912:                if (source.read4n() != okCRC)
0913:                    throw new IOException("Invalid CRC for tRNS chunk "
0914:                            + length);
0915:            }
0916:
0917:            /**
0918:             * Deal with the palette chunk
0919:             * @param length int the length of the chunk to read
0920:             * @exception java.io.IOException
0921:             */
0922:            private void readChunk_PLTE(int length) throws IOException {
0923:                if (!flagIHDR || flagIDAT)
0924:                    throw new IOException("Misplaced palette chunk");
0925:
0926:                if (length % 3 != 0)
0927:                    throw new IOException("Invalid palette size: " + length
0928:                            + " bytes");
0929:                if (colorType != 3) {
0930:                    // throw new IOException("Palette must not appear in grayscale or RGB images");
0931:                    // eat the entries
0932:                    int tmp;
0933:                    for (int i = 0; i < length; i++)
0934:                        tmp = source.read();
0935:                } else {
0936:                    flagPLTE = true;
0937:                    int entries = length / 3;
0938:                    colorsUsed = entries;
0939:                    palette = new RGB[entries];
0940:                    for (int i = 0; i < entries; i++)
0941:                        palette[i] = new RGB(source.read(), source.read(),
0942:                                source.read());
0943:                }
0944:                long okCRC = source.getCRC();
0945:                if (source.read4n() != okCRC)
0946:                    throw new IOException("Invalid CRC for PLTE chunk");
0947:            }
0948:
0949:            /**
0950:             * Deal with the header chunk
0951:             * @param length int the length of the chunk to read
0952:             * @exception java.io.IOException
0953:             */
0954:            private void readChunk_IHDR(int length) throws IOException {
0955:                if (flagIHDR)
0956:                    throw new IOException("Duplicate header chunks");
0957:                flagIHDR = true;
0958:
0959:                width = (int) source.read4n();
0960:                height = (int) source.read4n();
0961:                bitDepth = source.read();
0962:                colorType = source.read();
0963:                compressionMethod = source.read();
0964:                filterMethod = source.read();
0965:                interlaceMethod = source.read();
0966:
0967:                if ((width == 0) || (height == 0))
0968:                    throw new IOException("Invalid image size: " + width + "x"
0969:                            + height);
0970:                switch (colorType) {
0971:                case 0: // grayscale: 1, 2, 4, 8, 16
0972:                    if ((bitDepth != 1) && (bitDepth != 2) && (bitDepth != 4)
0973:                            && (bitDepth != 8) && (bitDepth != 16))
0974:                        throw new IOException("Invalid bit depth: " + bitDepth
0975:                                + " for color type: grayscale");
0976:                    colorType_components = 1;
0977:                    //colorType_hasPalette = false;
0978:                    //colorType_hasColor = false;
0979:                    //colorType_hasAlpha = false;
0980:                    break;
0981:                case 3: // paletted: 1, 2, 4, 8
0982:                    if ((bitDepth != 1) && (bitDepth != 2) && (bitDepth != 4)
0983:                            && (bitDepth != 8))
0984:                        throw new IOException("Invalid bit depth: " + bitDepth
0985:                                + " for color type: paletted");
0986:                    colorType_components = 1;
0987:                    colorType_hasPalette = true;
0988:                    colorType_hasColor = true;
0989:                    //colorType_hasAlpha = false;
0990:                    break;
0991:                case 2: // RGB: 8, 16
0992:                    if ((bitDepth != 8) && (bitDepth != 16))
0993:                        throw new IOException("Invalid bit depth: " + bitDepth
0994:                                + " for color type: RGB");
0995:                    colorType_components = 3;
0996:                    //colorType_hasPalette = false;
0997:                    colorType_hasColor = true;
0998:                    //colorType_hasAlpha = false;
0999:                    break;
1000:                case 4: // gray + alpha: 8, 16
1001:                    if ((bitDepth != 8) && (bitDepth != 16))
1002:                        throw new IOException("Invalid bit depth: " + bitDepth
1003:                                + " for color type: gray + alpha");
1004:                    colorType_components = 2;
1005:                    //colorType_hasPalette = false;
1006:                    //colorType_hasColor = false;
1007:                    colorType_hasAlpha = true;
1008:                    break;
1009:                case 6: // RGB + alpha: 8, 16
1010:                    if ((bitDepth != 8) && (bitDepth != 16))
1011:                        throw new IOException("Invalid bit depth: " + bitDepth
1012:                                + " for color type: RGB + alpha");
1013:                    colorType_components = 4;
1014:                    //colorType_hasPalette = false;
1015:                    colorType_hasColor = true;
1016:                    colorType_hasAlpha = true;
1017:                    break;
1018:                default:
1019:                    throw new IOException("Invalid color type: " + colorType);
1020:                }
1021:                if (compressionMethod != 0)
1022:                    throw new IOException("Unsupported compression method: "
1023:                            + compressionMethod);
1024:                if (filterMethod != 0)
1025:                    throw new IOException("Unsupported filter method: "
1026:                            + compressionMethod);
1027:                if ((interlaceMethod != 0) && (interlaceMethod != 1))
1028:                    throw new IOException("Unsupported interlace method: "
1029:                            + interlaceMethod);
1030:
1031:                long okCRC = source.getCRC();
1032:                if (source.read4n() != okCRC)
1033:                    throw new IOException("Invalid CRC for IHDR chunk");
1034:            }
1035:
1036:            /**
1037:             * Deal with data chunks
1038:             * @param length int the length of the chunk to read
1039:             * @exception java.io.IOException
1040:             */
1041:            private void readChunk_IDAT(int length) throws IOException {
1042:                if (!flagIHDR)
1043:                    throw new IOException("Data chunks before header");
1044:                if ((colorType == 3) && (!flagPLTE))
1045:                    throw new IOException("Missing palette");
1046:                flagIDAT = true;
1047:
1048:                int oldLength = buffer.length;
1049:                int newLength = oldLength + length;
1050:                byte[] zlibNew = new byte[newLength];
1051:                System.arraycopy(buffer, 0, zlibNew, 0, oldLength);
1052:
1053:                for (int i = oldLength; i < newLength; i++)
1054:                    zlibNew[i] = (byte) source.read();
1055:
1056:                buffer = zlibNew;
1057:
1058:                long okCRC = source.getCRC();
1059:                if (source.read4n() != okCRC)
1060:                    throw new IOException("Invalid CRC for IDAT chunk");
1061:            }
1062:
1063:            /*
1064:             * Decodes the zLib buffer according to compression/filtering
1065:             * and return an array of pixel computed based on the colorType/bitDepth
1066:             * need to take interlaced method (Adam7) into account
1067:             * @param zlibStream byte[]
1068:             * @return RGB[][]
1069:             * @exception java.io.IOException
1070:             */
1071:            private RGB[][] decode(byte[] zlibStream) throws IOException {
1072:                InflaterInputStream inflater = new InflaterInputStream(
1073:                        new java.io.ByteArrayInputStream(zlibStream));
1074:
1075:                int bytesPerScanline = (int) ((float) width * (float) bitDepth
1076:                        * (float) colorType_components / 8.0f);
1077:
1078:                // add 1 byte of padding for paletted colors of less than 8 bit depth
1079:                if (colorType == 3) {
1080:                    // width/bitdepth
1081:                    switch (bitDepth) {
1082:                    case 1:
1083:                        if ((width % 8) > 0)
1084:                            bytesPerScanline++;
1085:                        break;
1086:                    case 2:
1087:                        if ((width % 4) > 0)
1088:                            bytesPerScanline++;
1089:                        break;
1090:                    case 4:
1091:                        if ((width % 2) > 0)
1092:                            bytesPerScanline++;
1093:                        break;
1094:                    }
1095:                }
1096:
1097:                RGB[][] rgb = new RGB[height][width];
1098:
1099:                // decompressing // deinterlacing (if needed) and process color (if needed)
1100:                if (interlaceMethod == 1 && bitDepth < 8) {
1101:                    // special case with padding involved, colors will already be decoded
1102:                    rgb = deCompressSpecial(rgb, inflater);
1103:                } else {
1104:                    int bytesPerPixel = bitDepth * colorType_components / 8;
1105:                    bytesPerPixel = (bytesPerPixel == 0) ? 1 : bytesPerPixel;
1106:
1107:                    int[][] scanlines = new int[height][bytesPerScanline];
1108:                    scanlines = deCompress(scanlines, inflater, bytesPerPixel);
1109:
1110:                    // decoding byte values to pixel values
1111:                    int b, bb; // temp
1112:                    int cr, cg, cb, ca;
1113:                    switch (colorType) {
1114:
1115:                    case 0: // grayscale: 1, 2, 4, 8, 16
1116:                        switch (bitDepth) {
1117:                        case 1:
1118:                            for (int y = 0; y < height; y++) {
1119:                                int scanX = 0;
1120:                                for (int x = 0; x < width;) {
1121:                                    b = scanlines[y][scanX++];
1122:                                    for (int z = 7; ((x < width) && (z > -1)); z--) {
1123:                                        bb = ((b >> z) & 0x01) * 256;
1124:                                        RGB color = new RGB(bb, bb, bb);
1125:                                        if (tRNSPassRequired) // Apply transparency
1126:                                        {
1127:                                            if (color.compareTo(tRNSKeyColor,
1128:                                                    false)) // on the right color
1129:                                            {
1130:                                                color = new RGB(0);
1131:                                                color.setAlpha(0.0f);
1132:                                            }
1133:                                        }
1134:                                        rgb[y][x++] = color;
1135:                                    }
1136:                                }
1137:                            }
1138:                            break;
1139:                        case 2:
1140:                            for (int y = 0; y < height; y++) {
1141:                                int scanX = 0;
1142:                                for (int x = 0; x < width;) {
1143:                                    b = scanlines[y][scanX++];
1144:                                    for (int z = 6; ((x < width) && (z > -1)); z -= 2) {
1145:                                        bb = ((((b >> z) & 0x03) + 1) * 64) - 1;
1146:                                        bb = (bb < 0) ? 0 : bb;
1147:                                        RGB color = new RGB(bb, bb, bb);
1148:                                        if (tRNSPassRequired) // Apply transparency
1149:                                        {
1150:                                            if (color.compareTo(tRNSKeyColor,
1151:                                                    false)) // on the right color
1152:                                            {
1153:                                                color = new RGB(0);
1154:                                                color.setAlpha(0.0f);
1155:                                            }
1156:                                        }
1157:                                        rgb[y][x++] = color;
1158:                                    }
1159:                                }
1160:                            }
1161:                            break;
1162:                        case 4:
1163:                            for (int y = 0; y < height; y++) {
1164:                                int scanX = 0;
1165:                                for (int x = 0; x < width;) {
1166:                                    b = scanlines[y][scanX++];
1167:                                    bb = ((((b >> 4) & 0x0f) + 1) * 16) - 1;
1168:                                    bb = (bb < 0) ? 0 : bb;
1169:                                    RGB color = new RGB(bb, bb, bb);
1170:                                    if (tRNSPassRequired) // Apply transparency
1171:                                    {
1172:                                        if (color
1173:                                                .compareTo(tRNSKeyColor, false)) // on the right color
1174:                                        {
1175:                                            color = new RGB(0);
1176:                                            color.setAlpha(0.0f);
1177:                                        }
1178:                                    }
1179:                                    rgb[y][x++] = color;
1180:                                    if (x < width) {
1181:                                        bb = (((b & 0x0f) + 1) * 16) - 1;
1182:                                        bb = (bb < 0) ? 0 : bb;
1183:                                        color = new RGB(bb, bb, bb);
1184:                                        if (tRNSPassRequired) // Apply transparency
1185:                                        {
1186:                                            if (color.compareTo(tRNSKeyColor,
1187:                                                    false)) // on the right color
1188:                                            {
1189:                                                color = new RGB(0);
1190:                                                color.setAlpha(0.0f);
1191:                                            }
1192:                                        }
1193:                                        rgb[y][x++] = color;
1194:                                    }
1195:                                }
1196:                            }
1197:                            break;
1198:                        case 8:
1199:                            for (int y = 0; y < height; y++) {
1200:                                for (int x = 0; x < width; x++) {
1201:                                    RGB color = new RGB(scanlines[y][x]);
1202:                                    if (tRNSPassRequired) // Apply transparency
1203:                                    {
1204:                                        if (color
1205:                                                .compareTo(tRNSKeyColor, false)) // on the right color
1206:                                        {
1207:                                            color = new RGB(0);
1208:                                            color.setAlpha(0.0f);
1209:                                        }
1210:                                    }
1211:                                    rgb[y][x] = color;
1212:                                }
1213:                            }
1214:                            break;
1215:                        case 16:
1216:                            for (int y = 0; y < height; y++) {
1217:                                int scanX = 0;
1218:                                for (int x = 0; x < width; x++) {
1219:                                    RGB color = new RGB(
1220:                                            (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f);
1221:                                    if (tRNSPassRequired) // Apply transparency
1222:                                    {
1223:                                        if (color
1224:                                                .compareTo(tRNSKeyColor, false)) // on the right color
1225:                                        {
1226:                                            color = new RGB(0);
1227:                                            color.setAlpha(0.0f);
1228:                                        }
1229:                                    }
1230:                                    rgb[y][x] = color;
1231:                                }
1232:                            }
1233:                            break;
1234:                        }
1235:                        break;
1236:
1237:                    case 2: // RGB: 8, 16
1238:                        switch (bitDepth) {
1239:                        case 8:
1240:                            for (int y = 0; y < height; y++) {
1241:                                int scanX = 0;
1242:                                for (int x = 0; x < width; x++) {
1243:                                    RGB color = new RGB(scanlines[y][scanX++],
1244:                                            scanlines[y][scanX++],
1245:                                            scanlines[y][scanX++]);
1246:                                    if (tRNSPassRequired) // Apply transparency
1247:                                    {
1248:                                        if (color
1249:                                                .compareTo(tRNSKeyColor, false)) // on the right color
1250:                                        {
1251:                                            color = new RGB(0);
1252:                                            color.setAlpha(0.0f);
1253:                                        }
1254:                                    }
1255:                                    rgb[y][x] = color;
1256:                                }
1257:                            }
1258:                            break;
1259:                        case 16:
1260:                            // this one is really weird, further tests will be required
1261:                            for (int y = 0; y < height; y++) {
1262:                                int scanX = 0;
1263:                                for (int x = 0; x < width; x++) {
1264:                                    float aa = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1265:                                    float ab = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1266:                                    float ac = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1267:                                    RGB color = new RGB(aa, ab, ac);
1268:
1269:                                    if (tRNSPassRequired) // Apply transparency
1270:                                    {
1271:                                        if (color
1272:                                                .compareTo(tRNSKeyColor, false)) // on the right color
1273:                                        {
1274:                                            color = new RGB(0);
1275:                                            color.setAlpha(0.0f);
1276:                                        }
1277:                                    }
1278:                                    rgb[x][y] = color;
1279:                                }
1280:                            }
1281:                            break;
1282:                        }
1283:                        break;
1284:                    case 3: // paletted: 1, 2, 4, 8
1285:                        switch (bitDepth) {
1286:                        case 1:
1287:                            for (int y = 0; y < height; y++) {
1288:                                int scanX = 0;
1289:                                for (int x = 0; x < width;) {
1290:                                    if (scanX < bytesPerScanline) {
1291:                                        b = scanlines[y][scanX++];
1292:                                        for (int z = 7; ((x < width) && (z > -1)); z--) {
1293:                                            bb = (b >> z) & 0x01;
1294:                                            rgb[y][x++] = palette[bb];
1295:                                        }
1296:                                    } else
1297:                                        break;
1298:                                }
1299:                            }
1300:                            break;
1301:                        case 2:
1302:                            for (int y = 0; y < height; y++) {
1303:                                int scanX = 0;
1304:                                for (int x = 0; x < width;) {
1305:                                    if (scanX < bytesPerScanline) {
1306:                                        b = scanlines[y][scanX++];
1307:                                        for (int z = 6; ((x < width) && (z > -1)); z -= 2) {
1308:                                            bb = (b >> z) & 0x03;
1309:                                            rgb[y][x++] = palette[bb];
1310:                                        }
1311:                                    } else
1312:                                        break;
1313:                                }
1314:                            }
1315:                            break;
1316:                        case 4:
1317:                            for (int y = 0; y < height; y++) {
1318:                                int scanX = 0;
1319:                                for (int x = 0; x < width;) {
1320:                                    if (scanX <= bytesPerScanline) {
1321:                                        b = scanlines[y][scanX++];
1322:                                        bb = (b >> 4) & 0x0f;
1323:                                        rgb[y][x++] = palette[bb];
1324:                                        if (x < width) {
1325:                                            bb = b & 0x0f;
1326:                                            rgb[y][x++] = palette[bb];
1327:                                        }
1328:                                    } else
1329:                                        break;
1330:                                }
1331:                            }
1332:                            break;
1333:                        case 8:
1334:                            for (int y = 0; y < height; y++) {
1335:                                for (int x = 0; x < width; x++) {
1336:                                    b = scanlines[y][x];
1337:                                    // to be on the safe side
1338:                                    b = (b < palette.length) ? b : 0;
1339:                                    rgb[y][x] = palette[b];
1340:                                }
1341:                            }
1342:                            break;
1343:                        }
1344:                        break;
1345:                    case 4: // gray + alpha: 8, 16
1346:                        switch (bitDepth) {
1347:                        case 8:
1348:                            for (int y = 0; y < height; y++) {
1349:                                int scanX = 0;
1350:                                for (int x = 0; x < width; x++) {
1351:                                    // cr used as 'gray'
1352:                                    cr = scanlines[y][scanX++];
1353:                                    ca = scanlines[y][scanX++];
1354:
1355:                                    // apply alpha
1356:                                    float fa = (float) ca / 255.0f;
1357:                                    cr = (int) (cr * fa);
1358:
1359:                                    rgb[y][x] = new RGB(cr, ca);
1360:                                }
1361:                            }
1362:                            break;
1363:                        case 16:
1364:                            for (int y = 0; y < height; y++) {
1365:                                int scanX = 0;
1366:                                for (int x = 0; x < width; x++) {
1367:                                    // aa used as 'gray'
1368:                                    float aa = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1369:                                    float ab = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1370:
1371:                                    // apply alpha
1372:                                    aa *= ab;
1373:
1374:                                    rgb[y][x] = new RGB(aa, ab);
1375:                                }
1376:                            }
1377:                            break;
1378:                        }
1379:                        break;
1380:                    case 6: // RGB + alpha: 8, 16
1381:                        switch (bitDepth) {
1382:                        case 8:
1383:                            int idx = 0;
1384:                            for (int y = 0; y < height; y++) {
1385:                                int scanX = 0;
1386:                                for (int x = 0; x < width; x++) {
1387:                                    cr = scanlines[y][scanX++];
1388:                                    cg = scanlines[y][scanX++];
1389:                                    cb = scanlines[y][scanX++];
1390:                                    ca = scanlines[y][scanX++];
1391:
1392:                                    // apply alpha
1393:                                    if (ca == 0) {
1394:                                        cr = cg = cb = 0;
1395:                                    } else {
1396:                                        float fa = (float) ca / 255.0f;
1397:                                        cr = (int) ((cr) * fa);
1398:                                        cg = (int) ((cg) * fa);
1399:                                        cb = (int) ((cb) * fa);
1400:                                    }
1401:
1402:                                    rgb[y][x] = new RGB(cr, cg, cb, ca);
1403:                                }
1404:                            }
1405:                            break;
1406:                        case 16:
1407:                            for (int y = 0; y < height; y++) {
1408:                                int scanX = 0;
1409:                                for (int x = 0; x < width; x++) {
1410:                                    float aa = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1411:                                    float ab = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1412:                                    float ac = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1413:                                    float ad = (float) (scanlines[y][scanX++] << 8 | scanlines[y][scanX++]) / 65535.0f;
1414:
1415:                                    // apply alpha
1416:                                    aa *= ad;
1417:                                    ab *= ad;
1418:                                    ac *= ad;
1419:
1420:                                    rgb[y][x] = new RGB(aa, ab, ac, ad);
1421:                                }
1422:                            }
1423:                            break;
1424:                        }
1425:                    }
1426:                }
1427:                return rgb;
1428:            }
1429:
1430:            /**
1431:             * get the previous row value of the pass
1432:             * @param row int the current row
1433:             * @param pass int the current pass
1434:             * @return int
1435:             */
1436:            private int getPreviousRow(int row, int pass) {
1437:                if (interlaceMethod == 1) {
1438:                    int[] starting_Row = { 0, 0, 4, 0, 2, 0, 1 };
1439:                    int[] row_Increment = { 8, 8, 8, 4, 4, 2, 2 };
1440:                    int currentPassMin = starting_Row[pass];
1441:                    if (row == currentPassMin)
1442:                        return 0;
1443:                    else
1444:                        return ((row > (row - row_Increment[pass])) ? (row - row_Increment[pass])
1445:                                : 0);
1446:                } else {
1447:                    return ((row > 0) ? (row - 1) : 0);
1448:                }
1449:            }
1450:
1451:            /**
1452:             * get the previous column value of the pass
1453:             * @param col int the current column
1454:             * @param pass int the current pass
1455:             * @return int
1456:             */
1457:            private int getPreviousCol(int col, int pass) {
1458:                if (interlaceMethod == 1) {
1459:                    int[] starting_Col = { 0, 4, 0, 2, 0, 1, 0 };
1460:                    int[] col_Increment = { 8, 8, 4, 4, 2, 2, 1 };
1461:                    int currentPassMin = starting_Col[pass];
1462:                    if (col == currentPassMin)
1463:                        return 0;
1464:                    else
1465:                        return ((col > (col - col_Increment[pass])) ? (col - col_Increment[pass])
1466:                                : 0);
1467:                } else {
1468:                    return ((col > 0) ? (col - 1) : 0);
1469:                }
1470:            }
1471:
1472:            /**
1473:             * Decompress, deinterlace, unfilter and set the pixels colors
1474:             * Used for special interlaced images of less than 8 bit depth (padding involved)
1475:             * @param rgb RGB[][] the RGB colors of pixels
1476:             * @param inflater InputStream the inflater InputStream to read the zlib data from
1477:             * @return RGB[][] the RGB colors of pixels set
1478:             * @Exception java.io.IOException
1479:             */
1480:            private RGB[][] deCompressSpecial(RGB[][] rgb, InputStream inflater)
1481:                    throws IOException {
1482:                int[] starting_Row = { 0, 0, 4, 0, 2, 0, 1 };
1483:                int[] starting_Col = { 0, 4, 0, 2, 0, 1, 0 };
1484:                int[] row_Increment = { 8, 8, 8, 4, 4, 2, 2 };
1485:                int[] col_Increment = { 8, 8, 4, 4, 2, 2, 1 };
1486:                int[] block_Height = { 8, 8, 4, 4, 2, 2, 1 };
1487:                int[] block_Width = { 8, 4, 4, 2, 2, 1, 1 };
1488:
1489:                int row, col, filter;
1490:
1491:                int[][] pixels = new int[height][width];
1492:
1493:                int a, b, c, pa, pb, pc, p; // for paeth filter
1494:
1495:                for (int pass = 0; pass < 7; pass++) {
1496:                    row = starting_Row[pass];
1497:                    while (row < height) {
1498:                        int minHeight = (block_Height[pass] < (height - row)) ? block_Height[pass]
1499:                                : (height - row);
1500:                        b = inflater.read();
1501:                        if (b > -1) {
1502:                            filter = (b >> 4) & 0x03;
1503:
1504:                            col = starting_Col[pass];
1505:                            while (col < width) {
1506:                                int minWidth = (block_Width[pass] < (width - col)) ? block_Width[pass]
1507:                                        : (width - col);
1508:                                b = inflater.read();
1509:                                if (b > -1) {
1510:                                    switch (bitDepth) {
1511:                                    case 1:
1512:                                        for (int i = 7; i > -1; i--) {
1513:                                            if (col < width) {
1514:                                                a = (b >> i) & 0x01;
1515:                                                for (int x = 0; x < minHeight; x++) {
1516:                                                    int rowx = row + x;
1517:                                                    if (rowx < height) {
1518:                                                        for (int y = 0; y < minWidth; y++) {
1519:                                                            int coly = col + y;
1520:                                                            if (coly < width)
1521:                                                                pixels[rowx][coly] = a;
1522:                                                            else
1523:                                                                break;
1524:                                                        }
1525:                                                    } else
1526:                                                        break;
1527:                                                }
1528:                                            } else
1529:                                                break;
1530:                                            col += col_Increment[pass];
1531:                                        }
1532:                                        break;
1533:                                    case 2:
1534:                                        for (int i = 6; i > -1; i -= 2) {
1535:                                            if (col < width) {
1536:                                                a = (b >> i) & 0x03;
1537:                                                for (int x = 0; x < minHeight; x++) {
1538:                                                    int rowx = row + x;
1539:                                                    if (rowx < height) {
1540:                                                        for (int y = 0; y < minWidth; y++) {
1541:                                                            int coly = col + y;
1542:                                                            if (coly < width)
1543:                                                                pixels[rowx][coly] = a;
1544:                                                            else
1545:                                                                break;
1546:                                                        }
1547:                                                    } else
1548:                                                        break;
1549:                                                }
1550:                                            } else
1551:                                                break;
1552:                                            col += col_Increment[pass];
1553:                                        }
1554:                                        break;
1555:                                    case 4:
1556:                                        for (int i = 4; i > -1; i -= 4) {
1557:                                            if (col < width) {
1558:                                                a = (b >> i) & 0x0f;
1559:                                                for (int x = 0; x < minHeight; x++) {
1560:                                                    int rowx = row + x;
1561:                                                    if (rowx < height) {
1562:                                                        for (int y = 0; y < minWidth; y++) {
1563:                                                            int coly = col + y;
1564:                                                            if (coly < width)
1565:                                                                pixels[rowx][coly] = a;
1566:                                                            else
1567:                                                                break;
1568:                                                        }
1569:                                                    } else
1570:                                                        break;
1571:                                                }
1572:                                            } else
1573:                                                break;
1574:                                            col += col_Increment[pass];
1575:                                        }
1576:                                        break;
1577:                                    }
1578:                                } else
1579:                                    break;
1580:                            }
1581:
1582:                            // Cast to byte when filtering to use modulo 256 arithmetic
1583:                            int nbboucle = 8 / bitDepth;
1584:                            switch (filter) {
1585:                            case 0:
1586:                                // no filtering
1587:                                break;
1588:                            case 1: // sub
1589:                                col = starting_Col[pass] + col_Increment[pass];
1590:                                while (col < width) {
1591:                                    for (int i = 0; i < nbboucle; i++) {
1592:                                        if (col < width) {
1593:                                            pixels[row][col] = (byte) (pixels[row][col] + pixels[row][getPreviousCol(
1594:                                                    col, pass)]) & 0xff;
1595:                                        }
1596:                                        col += col_Increment[pass];
1597:                                    }
1598:                                }
1599:                                break;
1600:                            case 2: // up
1601:                                if (row == 0)
1602:                                    break;
1603:                                col = starting_Col[pass];
1604:                                while (col < width) {
1605:                                    for (int i = 0; i < nbboucle; i++) {
1606:                                        if (col < width) {
1607:                                            pixels[row][col] = (byte) (pixels[row][col] + pixels[getPreviousRow(
1608:                                                    row, pass)][col]) & 0xff;
1609:                                        }
1610:                                        col += col_Increment[pass];
1611:                                    }
1612:                                }
1613:                                break;
1614:                            case 3: // average
1615:                                col = starting_Col[pass];
1616:                                pixels[row][col] = (byte) (pixels[row][col] + (((row == 0) ? 0
1617:                                        : pixels[getPreviousRow(row, pass)][col]) / 2)) & 0xff;
1618:                                col += col_Increment[pass];
1619:                                while (col < width) {
1620:                                    pixels[row][col] = (byte) (pixels[row][col] + (pixels[row][getPreviousCol(
1621:                                            col, pass)] + ((row == 0) ? 0
1622:                                            : pixels[getPreviousRow(row, pass)][col])) / 2) & 0xff;
1623:
1624:                                    col += col_Increment[pass];
1625:                                }
1626:                                break;
1627:                            case 4: // paeth
1628:                                if (row == 0) {
1629:                                    col = starting_Col[pass];
1630:                                    pixels[row][col] = 0xff & pixels[row][col];
1631:                                    col += col_Increment[pass];
1632:
1633:                                    while (col < width) {
1634:                                        p = pixels[row][getPreviousCol(col,
1635:                                                pass)];
1636:                                        pixels[row][col] = 0xff & (byte) (p + pixels[row][col]);
1637:                                        col += col_Increment[pass];
1638:                                    }
1639:                                } else {
1640:                                    col = starting_Col[pass];
1641:                                    pixels[row][col] = 0xff & (byte) (pixels[getPreviousRow(
1642:                                            row, pass)][col] + pixels[row][col]);
1643:                                    col += col_Increment[pass];
1644:
1645:                                    while (col < width) {
1646:                                        a = pixels[row][getPreviousCol(col,
1647:                                                pass)]; // left
1648:                                        b = pixels[getPreviousRow(row, pass)][col]; // above
1649:                                        c = pixels[getPreviousRow(row, pass)][getPreviousCol(
1650:                                                col, pass)]; // upper left
1651:
1652:                                        // Paeth tests
1653:                                        p = (a + b) - c; // initial estimate
1654:                                        pa = p > a ? p - a : a - p; // nearest distance to a
1655:                                        pb = p > b ? p - b : b - p; // nearest distance to b
1656:                                        pc = p > c ? p - c : c - p; // nearest distance to c
1657:
1658:                                        if ((pa <= pb) && (pa <= pc))
1659:                                            p = a;
1660:                                        else if (pb <= pc)
1661:                                            p = b;
1662:                                        else
1663:                                            p = c;
1664:
1665:                                        pixels[row][col] = 0xff & (byte) (p + pixels[row][col]);
1666:
1667:                                        col += col_Increment[pass];
1668:                                    }
1669:                                }
1670:                                break;
1671:                            }
1672:                        }
1673:                        row += row_Increment[pass];
1674:                    }
1675:                }
1676:
1677:                p = 256 / (bitDepth * bitDepth); // gray multiplier
1678:                row = 0;
1679:                while (row < height) {
1680:                    col = 0;
1681:                    while (col < width) {
1682:                        if (colorType == 0) // gray
1683:                        {
1684:                            RGB color;
1685:                            if (bitDepth == 1)
1686:                                color = new RGB(pixels[row][col] * p);
1687:                            else
1688:                                color = new RGB(
1689:                                        ((pixels[row][col] + 1) * p) - 1);
1690:                            if (tRNSPassRequired) // Apply transparency
1691:                            {
1692:                                if (color.compareTo(tRNSKeyColor, false)) // on the right color
1693:                                {
1694:                                    color = new RGB(0);
1695:                                    color.setAlpha(0.0f);
1696:                                }
1697:                            }
1698:                            rgb[row][col] = color;
1699:                        } else
1700:                            // paletted
1701:                            // transparency is already integrated in the palette
1702:                            rgb[row][col] = palette[pixels[row][col]];
1703:                        col++;
1704:                    }
1705:                    row++;
1706:                }
1707:
1708:                return rgb;
1709:            }
1710:
1711:            /**
1712:             * Decompress, deinterlace, and unfilter the scanlines
1713:             * Used for special interlaced images of less than 8 bit depth (padding involved)
1714:             * @param scanlines int[][] the scanlines to decode into
1715:             * @param inflater InputStream the inflater InputStream to read the zlib data from
1716:             * @param bytesPerPixel int the number of bytes per pixel of scanlines
1717:             * @return int[][] the scanlines decoded
1718:             * @Exception java.io.IOException
1719:             */
1720:            private int[][] deCompress(int[][] scanlines, InputStream inflater,
1721:                    int bytesPerPixel) throws IOException {
1722:                int[] starting_Row = { 0, 0, 4, 0, 2, 0, 1 };
1723:                int[] starting_Col = { 0, 4, 0, 2, 0, 1, 0 };
1724:                int[] row_Increment = { 8, 8, 8, 4, 4, 2, 2 };
1725:                int[] col_Increment = { 8, 8, 4, 4, 2, 2, 1 };
1726:
1727:                int a, b, c, pa, pb, pc, p; // for paeth filter
1728:                int maxPass = 7;
1729:                if (interlaceMethod == 0)
1730:                    maxPass = 1;
1731:
1732:                int row, col;
1733:                for (int pass = 0; pass < maxPass; pass++) {
1734:                    if (interlaceMethod == 1)
1735:                        row = starting_Row[pass];
1736:                    else
1737:                        row = 0;
1738:
1739:                    while (row < height) {
1740:                        int filter = inflater.read();
1741:                        if (interlaceMethod == 1)
1742:                            col = starting_Col[pass];
1743:                        else
1744:                            col = 0;
1745:                        while (col < width) {
1746:                            for (int i = 0; i < bytesPerPixel; i++) {
1747:                                int bitcol = (col * bytesPerPixel) + i;
1748:                                if (bitcol < scanlines[row].length)
1749:                                    scanlines[row][bitcol] = inflater.read();
1750:                            }
1751:                            if (interlaceMethod == 1)
1752:                                col += col_Increment[pass];
1753:                            else
1754:                                col++;
1755:                        }
1756:
1757:                        // Cast to byte when filtering to use modulo 256 arithmetic
1758:                        switch (filter) {
1759:                        case 0:
1760:                            // no filtering
1761:                            break;
1762:                        case 1: // sub
1763:                            if (interlaceMethod == 1)
1764:                                col = starting_Col[pass] + col_Increment[pass];
1765:                            else
1766:                                col = 1;
1767:                            while (col < width) {
1768:                                for (int i = 0; i < bytesPerPixel; i++) {
1769:                                    int bitcol = (col * bytesPerPixel) + i;
1770:                                    if (bitcol < scanlines[row].length) {
1771:                                        scanlines[row][bitcol] = (byte) (scanlines[row][bitcol] + scanlines[row][(getPreviousCol(
1772:                                                col, pass) * bytesPerPixel)
1773:                                                + i]) & 0xff;
1774:                                    }
1775:                                }
1776:                                if (interlaceMethod == 1)
1777:                                    col += col_Increment[pass];
1778:                                else
1779:                                    col++;
1780:                            }
1781:                            break;
1782:                        case 2: // up
1783:                            if (row == 0)
1784:                                break;
1785:                            if (interlaceMethod == 1)
1786:                                col = starting_Col[pass];
1787:                            else
1788:                                col = 0;
1789:                            while (col < width) {
1790:                                for (int i = 0; i < bytesPerPixel; i++) {
1791:                                    int bitcol = (col * bytesPerPixel) + i;
1792:                                    if (bitcol < scanlines[row].length) {
1793:                                        scanlines[row][bitcol] = (byte) (scanlines[row][bitcol] + scanlines[getPreviousRow(
1794:                                                row, pass)][bitcol]) & 0xff;
1795:                                    }
1796:                                }
1797:                                if (interlaceMethod == 1)
1798:                                    col += col_Increment[pass];
1799:                                else
1800:                                    col++;
1801:                            }
1802:                            break;
1803:                        case 3: // average
1804:                            if (interlaceMethod == 1)
1805:                                col = starting_Col[pass];
1806:                            else
1807:                                col = 0;
1808:                            if (row > 0) {
1809:                                for (int i = 0; i < bytesPerPixel; i++) {
1810:                                    int bitcol = (col * bytesPerPixel) + i;
1811:                                    if (bitcol < scanlines[row].length) {
1812:                                        scanlines[row][bitcol] = (byte) (scanlines[row][bitcol] + (scanlines[getPreviousRow(
1813:                                                row, pass)][bitcol] / 2)) & 0xff;
1814:                                    }
1815:                                }
1816:                            }
1817:                            if (interlaceMethod == 1)
1818:                                col += col_Increment[pass];
1819:                            else
1820:                                col++;
1821:                            while (col < width) {
1822:                                for (int i = 0; i < bytesPerPixel; i++) {
1823:                                    int bitcol = (col * bytesPerPixel) + i;
1824:                                    if (bitcol < scanlines[row].length) {
1825:                                        scanlines[row][bitcol] = (byte) (scanlines[row][bitcol] + (scanlines[row][(getPreviousCol(
1826:                                                col, pass) * bytesPerPixel)
1827:                                                + i] + ((row == 0) ? 0
1828:                                                : scanlines[getPreviousRow(row,
1829:                                                        pass)][bitcol])) / 2) & 0xff;
1830:                                    }
1831:                                }
1832:                                if (interlaceMethod == 1)
1833:                                    col += col_Increment[pass];
1834:                                else
1835:                                    col++;
1836:                            }
1837:                            break;
1838:                        case 4: // paeth
1839:                            if (row == 0) {
1840:                                if (interlaceMethod == 1)
1841:                                    col = starting_Col[pass];
1842:                                else
1843:                                    col = 0;
1844:                                for (int i = 0; i < bytesPerPixel; i++) {
1845:                                    int bitcol = (col * bytesPerPixel) + i;
1846:                                    if (bitcol < scanlines[row].length)
1847:                                        scanlines[row][bitcol] = 0xff & scanlines[row][bitcol];
1848:                                }
1849:                                if (interlaceMethod == 1)
1850:                                    col += col_Increment[pass];
1851:                                else
1852:                                    col++;
1853:
1854:                                while (col < width) {
1855:                                    for (int i = 0; i < bytesPerPixel; i++) {
1856:                                        int bitcol = (col * bytesPerPixel) + i;
1857:                                        if (bitcol < scanlines[row].length) {
1858:                                            p = scanlines[row][(getPreviousCol(
1859:                                                    col, pass) * bytesPerPixel)
1860:                                                    + i];
1861:                                            scanlines[row][bitcol] = 0xff & (byte) (p + scanlines[row][bitcol]);
1862:                                        }
1863:                                    }
1864:                                    if (interlaceMethod == 1)
1865:                                        col += col_Increment[pass];
1866:                                    else
1867:                                        col++;
1868:                                }
1869:                            } else {
1870:                                if (interlaceMethod == 1)
1871:                                    col = starting_Col[pass];
1872:                                else
1873:                                    col = 0;
1874:                                for (int i = 0; i < bytesPerPixel; i++) {
1875:                                    int bitcol = (col * bytesPerPixel) + i;
1876:                                    if (bitcol < scanlines[row].length)
1877:                                        scanlines[row][bitcol] = 0xff & (byte) (scanlines[getPreviousRow(
1878:                                                row, pass)][bitcol] + scanlines[row][bitcol]);
1879:                                }
1880:                                if (interlaceMethod == 1)
1881:                                    col += col_Increment[pass];
1882:                                else
1883:                                    col++;
1884:
1885:                                while (col < width) {
1886:                                    for (int i = 0; i < bytesPerPixel; i++) {
1887:                                        int bitcol = (col * bytesPerPixel) + i;
1888:                                        if (bitcol < scanlines[row].length) {
1889:                                            a = scanlines[row][(getPreviousCol(
1890:                                                    col, pass) * bytesPerPixel)
1891:                                                    + i]; // left
1892:                                            b = scanlines[getPreviousRow(row,
1893:                                                    pass)][bitcol]; // above
1894:                                            c = scanlines[getPreviousRow(row,
1895:                                                    pass)][(getPreviousCol(col,
1896:                                                    pass) * bytesPerPixel)
1897:                                                    + i]; // upper left
1898:
1899:                                            // Paeth tests
1900:                                            p = (a + b) - c; // initial estimate
1901:                                            pa = p > a ? p - a : a - p; // nearest distance to a
1902:                                            pb = p > b ? p - b : b - p; // nearest distance to b
1903:                                            pc = p > c ? p - c : c - p; // nearest distance to c
1904:
1905:                                            if ((pa <= pb) && (pa <= pc))
1906:                                                p = a;
1907:                                            else if (pb <= pc)
1908:                                                p = b;
1909:                                            else
1910:                                                p = c;
1911:
1912:                                            scanlines[row][bitcol] = 0xff & (byte) (p + scanlines[row][bitcol]);
1913:                                        }
1914:                                    }
1915:                                    if (interlaceMethod == 1)
1916:                                        col += col_Increment[pass];
1917:                                    else
1918:                                        col++;
1919:                                }
1920:                            }
1921:                            break;
1922:                        }
1923:                        if (interlaceMethod == 1)
1924:                            row += row_Increment[pass];
1925:                        else
1926:                            row++;
1927:                    }
1928:                }
1929:                return scanlines;
1930:            }
1931:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.