Source Code Cross Referenced for PNGEncodeParam.java in  » 6.0-JDK-Modules » Java-Advanced-Imaging » com » sun » media » jai » codec » 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 » 6.0 JDK Modules » Java Advanced Imaging » com.sun.media.jai.codec 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: PNGEncodeParam.java,v $
0003:         *
0004:         * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * Use is subject to license terms.
0007:         *
0008:         * $Revision: 1.1 $
0009:         * $Date: 2005/02/11 04:55:32 $
0010:         * $State: Exp $
0011:         */
0012:        package com.sun.media.jai.codec;
0013:
0014:        import java.awt.image.ColorModel;
0015:        import java.awt.image.IndexColorModel;
0016:        import java.awt.image.RenderedImage;
0017:        import java.awt.image.SampleModel;
0018:        import java.awt.color.ICC_Profile;
0019:        import java.awt.color.ICC_ProfileGray;
0020:        import java.awt.color.ICC_ProfileRGB;
0021:        import java.util.Date;
0022:        import java.util.Vector;
0023:
0024:        /**
0025:         * An instance of <code>ImageEncodeParam</code> for encoding images in
0026:         * the PNG format.
0027:         *
0028:         * <p><b> This class is not a committed part of the JAI API.  It may
0029:         * be removed or changed in future releases of JAI.</b>
0030:         */
0031:        public abstract class PNGEncodeParam implements  ImageEncodeParam {
0032:
0033:            /** Constant for use with the sRGB chunk. */
0034:            public static final int INTENT_PERCEPTUAL = 0;
0035:
0036:            /** Constant for use with the sRGB chunk. */
0037:            public static final int INTENT_RELATIVE = 1;
0038:
0039:            /** Constant for use with the sRGB chunk. */
0040:            public static final int INTENT_SATURATION = 2;
0041:
0042:            /** Constant for use with the sRGB chunk. */
0043:            public static final int INTENT_ABSOLUTE = 3;
0044:
0045:            /** Constant for use in filtering. */
0046:            public static final int PNG_FILTER_NONE = 0;
0047:
0048:            /** Constant for use in filtering. */
0049:            public static final int PNG_FILTER_SUB = 1;
0050:
0051:            /** Constant for use in filtering. */
0052:            public static final int PNG_FILTER_UP = 2;
0053:
0054:            /** Constant for use in filtering. */
0055:            public static final int PNG_FILTER_AVERAGE = 3;
0056:
0057:            /** Constant for use in filtering. */
0058:            public static final int PNG_FILTER_PAETH = 4;
0059:
0060:            /**
0061:             * Returns an instance of <code>PNGEncodeParam.Palette</code>,
0062:             * <code>PNGEncodeParam.Gray</code>, or
0063:             * <code>PNGEncodeParam.RGB</code> appropriate for encoding
0064:             * the given image.
0065:             *
0066:             * <p> If the image has an <code>IndexColorModel</code>, an
0067:             * instance of <code>PNGEncodeParam.Palette</code> is returned.
0068:             * Otherwise, if the image has 1 or 2 bands an instance of
0069:             * <code>PNGEncodeParam.Gray</code> is returned.  In all other
0070:             * cases an instance of <code>PNGEncodeParam.RGB</code> is
0071:             * returned.
0072:             *
0073:             * <p> Note that this method does not provide any guarantee that
0074:             * the given image will be successfully encoded by the PNG
0075:             * encoder, as it only performs a very superficial analysis of
0076:             * the image structure. 
0077:             */
0078:            public static PNGEncodeParam getDefaultEncodeParam(RenderedImage im) {
0079:                ColorModel colorModel = im.getColorModel();
0080:                if (colorModel instanceof  IndexColorModel) {
0081:                    return new PNGEncodeParam.Palette();
0082:                }
0083:
0084:                SampleModel sampleModel = im.getSampleModel();
0085:                int numBands = sampleModel.getNumBands();
0086:
0087:                if (numBands == 1 || numBands == 2) {
0088:                    return new PNGEncodeParam.Gray();
0089:                } else {
0090:                    return new PNGEncodeParam.RGB();
0091:                }
0092:            }
0093:
0094:            public static class Palette extends PNGEncodeParam {
0095:
0096:                /** Constructs an instance of <code>PNGEncodeParam.Palette</code>. */
0097:                public Palette() {
0098:                }
0099:
0100:                // bKGD chunk
0101:
0102:                private boolean backgroundSet = false;
0103:
0104:                /**
0105:                 * Suppresses the 'bKGD' chunk from being output.
0106:                 */
0107:                public void unsetBackground() {
0108:                    backgroundSet = false;
0109:                }
0110:
0111:                /**
0112:                 * Returns true if a 'bKGD' chunk will be output.
0113:                 */
0114:                public boolean isBackgroundSet() {
0115:                    return backgroundSet;
0116:                }
0117:
0118:                /**
0119:                 * Sets the desired bit depth for a palette image.  The bit
0120:                 * depth must be one of 1, 2, 4, or 8, or else an
0121:                 * <code>IllegalArgumentException</code> will be thrown.
0122:                 */
0123:                public void setBitDepth(int bitDepth) {
0124:                    if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4
0125:                            && bitDepth != 8) {
0126:                        throw new IllegalArgumentException(JaiI18N
0127:                                .getString("PNGEncodeParam2"));
0128:                    }
0129:                    this .bitDepth = bitDepth;
0130:                    bitDepthSet = true;
0131:                }
0132:
0133:                // PLTE chunk
0134:
0135:                private int[] palette = null;
0136:                private boolean paletteSet = false;
0137:
0138:                /**
0139:                 * Sets the RGB palette of the image to be encoded.
0140:                 * The <code>rgb</code> parameter contains alternating
0141:                 * R, G, B values for each color index used in the image.
0142:                 * The number of elements must be a multiple of 3 between
0143:                 * 3 and 3*256.
0144:                 *
0145:                 * <p> The 'PLTE' chunk will encode this information.
0146:                 *
0147:                 * @param rgb An array of <code>int</code>s.
0148:                 */
0149:                public void setPalette(int[] rgb) {
0150:                    if (rgb.length < 1 * 3 || rgb.length > 256 * 3) {
0151:                        throw new IllegalArgumentException(JaiI18N
0152:                                .getString("PNGEncodeParam0"));
0153:                    }
0154:                    if ((rgb.length % 3) != 0) {
0155:                        throw new IllegalArgumentException(JaiI18N
0156:                                .getString("PNGEncodeParam1"));
0157:                    }
0158:
0159:                    palette = (int[]) (rgb.clone());
0160:                    paletteSet = true;
0161:                }
0162:
0163:                /**
0164:                 * Returns the current RGB palette.
0165:                 *
0166:                 * <p> If the palette has not previously been set, or has been
0167:                 * unset, an <code>IllegalStateException</code> will be thrown.
0168:                 *
0169:                 * @throws IllegalStateException if the palette is not set.
0170:                 *
0171:                 * @return An array of <code>int</code>s.
0172:                 */
0173:                public int[] getPalette() {
0174:                    if (!paletteSet) {
0175:                        throw new IllegalStateException(JaiI18N
0176:                                .getString("PNGEncodeParam3"));
0177:                    }
0178:                    return (int[]) (palette.clone());
0179:                }
0180:
0181:                /**
0182:                 * Suppresses the 'PLTE' chunk from being output.
0183:                 */
0184:                public void unsetPalette() {
0185:                    palette = null;
0186:                    paletteSet = false;
0187:                }
0188:
0189:                /**
0190:                 * Returns true if a 'PLTE' chunk will be output.
0191:                 */
0192:                public boolean isPaletteSet() {
0193:                    return paletteSet;
0194:                }
0195:
0196:                // bKGD chunk
0197:
0198:                private int backgroundPaletteIndex;
0199:
0200:                /**
0201:                 * Sets the palette index of the suggested background color.
0202:                 *
0203:                 * <p> The 'bKGD' chunk will encode this information.
0204:                 */
0205:                public void setBackgroundPaletteIndex(int index) {
0206:                    backgroundPaletteIndex = index;
0207:                    backgroundSet = true;
0208:                }
0209:
0210:                /**
0211:                 * Returns the palette index of the suggested background color.
0212:                 *
0213:                 * <p> If the background palette index has not previously been
0214:                 * set, or has been unset, an
0215:                 * <code>IllegalStateException</code> will be thrown.
0216:                 *
0217:                 * @throws IllegalStateException if the palette index is not set.
0218:                 */
0219:                public int getBackgroundPaletteIndex() {
0220:                    if (!backgroundSet) {
0221:                        throw new IllegalStateException(JaiI18N
0222:                                .getString("PNGEncodeParam4"));
0223:                    }
0224:                    return backgroundPaletteIndex;
0225:                }
0226:
0227:                // tRNS chunk
0228:
0229:                private int[] transparency;
0230:
0231:                /**
0232:                 * Sets the alpha values associated with each palette entry.
0233:                 * The <code>alpha</code> parameter should have as many entries
0234:                 * as there are RGB triples in the palette.
0235:                 *
0236:                 * <p> The 'tRNS' chunk will encode this information.
0237:                 */
0238:                public void setPaletteTransparency(byte[] alpha) {
0239:                    transparency = new int[alpha.length];
0240:                    for (int i = 0; i < alpha.length; i++) {
0241:                        transparency[i] = alpha[i] & 0xff;
0242:                    }
0243:                    transparencySet = true;
0244:                }
0245:
0246:                /**
0247:                 * Returns the alpha values associated with each palette entry.
0248:                 *
0249:                 * <p> If the palette transparency has not previously been
0250:                 * set, or has been unset, an
0251:                 * <code>IllegalStateException</code> will be thrown.
0252:                 *
0253:                 * @throws IllegalStateException if the palette transparency is
0254:                 *        not set.
0255:                 */
0256:                public byte[] getPaletteTransparency() {
0257:                    if (!transparencySet) {
0258:                        throw new IllegalStateException(JaiI18N
0259:                                .getString("PNGEncodeParam5"));
0260:                    }
0261:                    byte[] alpha = new byte[transparency.length];
0262:                    for (int i = 0; i < alpha.length; i++) {
0263:                        alpha[i] = (byte) transparency[i];
0264:                    }
0265:                    return alpha;
0266:                }
0267:            }
0268:
0269:            public static class Gray extends PNGEncodeParam {
0270:
0271:                /** Constructs an instance of <code>PNGEncodeParam.Gray</code>. */
0272:                public Gray() {
0273:                }
0274:
0275:                // bKGD chunk
0276:
0277:                private boolean backgroundSet = false;
0278:
0279:                /**
0280:                 * Suppresses the 'bKGD' chunk from being output.
0281:                 */
0282:                public void unsetBackground() {
0283:                    backgroundSet = false;
0284:                }
0285:
0286:                /**
0287:                 * Returns true if a 'bKGD' chunk will be output.
0288:                 */
0289:                public boolean isBackgroundSet() {
0290:                    return backgroundSet;
0291:                }
0292:
0293:                /**
0294:                 * Sets the desired bit depth for a grayscale image.  The bit
0295:                 * depth must be one of 1, 2, 4, 8, or 16.
0296:                 *
0297:                 * <p> When encoding a source image of a greater bit depth,
0298:                 * pixel values will be clamped to the smaller range after
0299:                 * shifting by the value given by <code>getBitShift()</code>.
0300:                 * When encoding a source image of a smaller bit depth, pixel
0301:                 * values will be shifted and left-filled with zeroes.
0302:                 */
0303:                public void setBitDepth(int bitDepth) {
0304:                    if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4
0305:                            && bitDepth != 8 && bitDepth != 16) {
0306:                        throw new IllegalArgumentException();
0307:                    }
0308:                    this .bitDepth = bitDepth;
0309:                    bitDepthSet = true;
0310:                }
0311:
0312:                // bKGD chunk
0313:
0314:                private int backgroundPaletteGray;
0315:
0316:                /**
0317:                 * Sets the suggested gray level of the background.
0318:                 *
0319:                 * <p> The 'bKGD' chunk will encode this information.
0320:                 */
0321:                public void setBackgroundGray(int gray) {
0322:                    backgroundPaletteGray = gray;
0323:                    backgroundSet = true;
0324:                }
0325:
0326:                /**
0327:                 * Returns the suggested gray level of the background.
0328:                 *
0329:                 * <p> If the background gray level has not previously been
0330:                 * set, or has been unset, an
0331:                 * <code>IllegalStateException</code> will be thrown.
0332:                 *
0333:                 * @throws IllegalStateException if the background gray level
0334:                 *        is not set.
0335:                 */
0336:                public int getBackgroundGray() {
0337:                    if (!backgroundSet) {
0338:                        throw new IllegalStateException(JaiI18N
0339:                                .getString("PNGEncodeParam6"));
0340:                    }
0341:                    return backgroundPaletteGray;
0342:                }
0343:
0344:                // tRNS chunk
0345:
0346:                private int[] transparency;
0347:
0348:                /**
0349:                 * Sets the gray value to be used to denote transparency.
0350:                 *
0351:                 * <p> Setting this attribute will cause the alpha channel
0352:                 * of the input image to be ignored.
0353:                 *
0354:                 * <p> The 'tRNS' chunk will encode this information.
0355:                 */
0356:                public void setTransparentGray(int transparentGray) {
0357:                    transparency = new int[1];
0358:                    transparency[0] = transparentGray;
0359:                    transparencySet = true;
0360:                }
0361:
0362:                /**
0363:                 * Returns the gray value to be used to denote transparency.
0364:                 *
0365:                 * <p> If the transparent gray value has not previously been
0366:                 * set, or has been unset, an
0367:                 * <code>IllegalStateException</code> will be thrown.
0368:                 *
0369:                 * @throws IllegalStateException if the transparent gray value
0370:                 *        is not set.
0371:                 */
0372:                public int getTransparentGray() {
0373:                    if (!transparencySet) {
0374:                        throw new IllegalStateException(JaiI18N
0375:                                .getString("PNGEncodeParam7"));
0376:                    }
0377:                    int gray = transparency[0];
0378:                    return gray;
0379:                }
0380:
0381:                private int bitShift;
0382:                private boolean bitShiftSet = false;
0383:
0384:                /**
0385:                 * Sets the desired bit shift for a grayscale image.
0386:                 * Pixels in the source image will be shifted right by
0387:                 * the given amount prior to being clamped to the maximum
0388:                 * value given by the encoded image's bit depth.
0389:                 */
0390:                public void setBitShift(int bitShift) {
0391:                    if (bitShift < 0) {
0392:                        throw new RuntimeException();
0393:                    }
0394:                    this .bitShift = bitShift;
0395:                    bitShiftSet = true;
0396:                }
0397:
0398:                /** 
0399:                 * Returns the desired bit shift for a grayscale image.
0400:                 *
0401:                 * <p> If the bit shift has not previously been set, or has been
0402:                 * unset, an <code>IllegalStateException</code> will be thrown.
0403:                 *
0404:                 * @throws IllegalStateException if the bit shift is not set.
0405:                 */
0406:                public int getBitShift() {
0407:                    if (!bitShiftSet) {
0408:                        throw new IllegalStateException(JaiI18N
0409:                                .getString("PNGEncodeParam8"));
0410:                    }
0411:                    return bitShift;
0412:                }
0413:
0414:                /**
0415:                 * Suppresses the setting of the bit shift of a grayscale image.
0416:                 * Pixels in the source image will not be shifted prior to encoding.
0417:                 */
0418:                public void unsetBitShift() {
0419:                    bitShiftSet = false;
0420:                }
0421:
0422:                /**
0423:                 * Returns true if the bit shift has been set.
0424:                 */
0425:                public boolean isBitShiftSet() {
0426:                    return bitShiftSet;
0427:                }
0428:
0429:                /**
0430:                 * Returns true if the bit depth has been set.
0431:                 */
0432:                public boolean isBitDepthSet() {
0433:                    return bitDepthSet;
0434:                }
0435:            }
0436:
0437:            public static class RGB extends PNGEncodeParam {
0438:
0439:                /** Constructs an instance of <code>PNGEncodeParam.RGB</code>. */
0440:                public RGB() {
0441:                }
0442:
0443:                // bKGD chunk
0444:
0445:                private boolean backgroundSet = false;
0446:
0447:                /**
0448:                 * Suppresses the 'bKGD' chunk from being output.
0449:                 */
0450:                public void unsetBackground() {
0451:                    backgroundSet = false;
0452:                }
0453:
0454:                /**
0455:                 * Returns true if a 'bKGD' chunk will be output.
0456:                 */
0457:                public boolean isBackgroundSet() {
0458:                    return backgroundSet;
0459:                }
0460:
0461:                /**
0462:                 * Sets the desired bit depth for an RGB image.  The bit
0463:                 * depth must be 8 or 16.
0464:                 */
0465:                public void setBitDepth(int bitDepth) {
0466:                    if (bitDepth != 8 && bitDepth != 16) {
0467:                        throw new RuntimeException();
0468:                    }
0469:                    this .bitDepth = bitDepth;
0470:                    bitDepthSet = true;
0471:                }
0472:
0473:                // bKGD chunk
0474:
0475:                private int[] backgroundRGB;
0476:
0477:                /**
0478:                 * Sets the RGB value of the suggested background color.
0479:                 * The <code>rgb</code> parameter should have 3 entries. 
0480:                 *
0481:                 * <p> The 'bKGD' chunk will encode this information.
0482:                 */
0483:                public void setBackgroundRGB(int[] rgb) {
0484:                    if (rgb.length != 3) {
0485:                        throw new RuntimeException();
0486:                    }
0487:                    backgroundRGB = rgb;
0488:                    backgroundSet = true;
0489:                }
0490:
0491:                /**
0492:                 * Returns the RGB value of the suggested background color.
0493:                 *
0494:                 * <p> If the background color has not previously been set, or has been
0495:                 * unset, an <code>IllegalStateException</code> will be thrown.
0496:                 *
0497:                 * @throws IllegalStateException if the background color is not set.
0498:                 */
0499:                public int[] getBackgroundRGB() {
0500:                    if (!backgroundSet) {
0501:                        throw new IllegalStateException(JaiI18N
0502:                                .getString("PNGEncodeParam9"));
0503:                    }
0504:                    return backgroundRGB;
0505:                }
0506:
0507:                // tRNS chunk
0508:
0509:                private int[] transparency;
0510:
0511:                /**
0512:                 * Sets the RGB value to be used to denote transparency.
0513:                 *
0514:                 * <p> Setting this attribute will cause the alpha channel
0515:                 * of the input image to be ignored.
0516:                 *
0517:                 * <p> The 'tRNS' chunk will encode this information.
0518:                 */
0519:                public void setTransparentRGB(int[] transparentRGB) {
0520:                    transparency = (int[]) (transparentRGB.clone());
0521:                    transparencySet = true;
0522:                }
0523:
0524:                /**
0525:                 * Returns the RGB value to be used to denote transparency.
0526:                 *
0527:                 * <p> If the transparent color has not previously been set,
0528:                 * or has been unset, an <code>IllegalStateException</code>
0529:                 * will be thrown.
0530:                 *
0531:                 * @throws IllegalStateException if the transparent color is not set.
0532:                 */
0533:                public int[] getTransparentRGB() {
0534:                    if (!transparencySet) {
0535:                        throw new IllegalStateException(JaiI18N
0536:                                .getString("PNGEncodeParam10"));
0537:                    }
0538:                    return (int[]) (transparency.clone());
0539:                }
0540:            }
0541:
0542:            protected int bitDepth;
0543:            protected boolean bitDepthSet = false;
0544:
0545:            /**
0546:             * Sets the desired bit depth of an image.
0547:             */
0548:            public abstract void setBitDepth(int bitDepth);
0549:
0550:            /** 
0551:             * Returns the desired bit depth for a grayscale image.
0552:             *
0553:             * <p> If the bit depth has not previously been set, or has been
0554:             * unset, an <code>IllegalStateException</code> will be thrown.
0555:             *
0556:             * @throws IllegalStateException if the bit depth is not set.
0557:             */
0558:            public int getBitDepth() {
0559:                if (!bitDepthSet) {
0560:                    throw new IllegalStateException(JaiI18N
0561:                            .getString("PNGEncodeParam11"));
0562:                }
0563:                return bitDepth;
0564:            }
0565:
0566:            /**
0567:             * Suppresses the setting of the bit depth of a grayscale image.
0568:             * The depth of the encoded image will be inferred from the source
0569:             * image bit depth, rounded up to the next power of 2 between 1 
0570:             * and 16.
0571:             */
0572:            public void unsetBitDepth() {
0573:                bitDepthSet = false;
0574:            }
0575:
0576:            private boolean useInterlacing = false;
0577:
0578:            /**
0579:             * Turns Adam7 interlacing on or off.
0580:             */
0581:            public void setInterlacing(boolean useInterlacing) {
0582:                this .useInterlacing = useInterlacing;
0583:            }
0584:
0585:            /**
0586:             * Returns <code>true</code> if Adam7 interlacing will be used.
0587:             */
0588:            public boolean getInterlacing() {
0589:                return useInterlacing;
0590:            }
0591:
0592:            // bKGD chunk - delegate to subclasses
0593:
0594:            // In JAI 1.0, 'backgroundSet' was private.  The JDK 1.2 compiler
0595:            // was lenient and incorrectly allowed this variable to be
0596:            // accessed from the subclasses.  The JDK 1.3 compiler correctly
0597:            // flags this as a use of a non-static variable in a static
0598:            // context.  Changing 'backgroundSet' to protected would have
0599:            // solved the problem, but would have introduced a visible API
0600:            // change.  Thus we are forced to adopt the solution of placing a
0601:            // separate private variable in each subclass and providing
0602:            // separate implementations of 'unsetBackground' and
0603:            // 'isBackgroundSet' in each concrete subclass.
0604:
0605:            /**
0606:             * Suppresses the 'bKGD' chunk from being output.
0607:             * For API compatibility with JAI 1.0, the superclass
0608:             * defines this method to throw a <code>RuntimeException</code>;
0609:             * accordingly, subclasses must provide their own implementations.
0610:             */
0611:            public void unsetBackground() {
0612:                throw new RuntimeException(JaiI18N
0613:                        .getString("PNGEncodeParam23"));
0614:            }
0615:
0616:            /**
0617:             * Returns true if a 'bKGD' chunk will be output.
0618:             * For API compatibility with JAI 1.0, the superclass
0619:             * defines this method to throw a <code>RuntimeException</code>;
0620:             * accordingly, subclasses must provide their own implementations.
0621:             */
0622:            public boolean isBackgroundSet() {
0623:                throw new RuntimeException(JaiI18N
0624:                        .getString("PNGEncodeParam24"));
0625:            }
0626:
0627:            // cHRM chunk
0628:
0629:            private float[] chromaticity = null;
0630:            private boolean chromaticitySet = false;
0631:
0632:            /**
0633:             * Sets the white point and primary chromaticities in CIE (x, y)
0634:             * space.
0635:             *
0636:             * <p> The <code>chromaticity</code> parameter should be a
0637:             * <code>float</code> array of length 8 containing the white point
0638:             * X and Y, red X and Y, green X and Y, and blue X and Y values in
0639:             * order.
0640:             *
0641:             * <p> The 'cHRM' chunk will encode this information.
0642:             */
0643:            public void setChromaticity(float[] chromaticity) {
0644:                if (chromaticity.length != 8) {
0645:                    throw new IllegalArgumentException();
0646:                }
0647:                this .chromaticity = (float[]) (chromaticity.clone());
0648:                chromaticitySet = true;
0649:            }
0650:
0651:            /**
0652:             * A convenience method that calls the array version.
0653:             */
0654:            public void setChromaticity(float whitePointX, float whitePointY,
0655:                    float redX, float redY, float greenX, float greenY,
0656:                    float blueX, float blueY) {
0657:                float[] chroma = new float[8];
0658:                chroma[0] = whitePointX;
0659:                chroma[1] = whitePointY;
0660:                chroma[2] = redX;
0661:                chroma[3] = redY;
0662:                chroma[4] = greenX;
0663:                chroma[5] = greenY;
0664:                chroma[6] = blueX;
0665:                chroma[7] = blueY;
0666:                setChromaticity(chroma);
0667:            }
0668:
0669:            /**
0670:             * Returns the white point and primary chromaticities in
0671:             * CIE (x, y) space.
0672:             *
0673:             * <p> See the documentation for the <code>setChromaticity</code>
0674:             * method for the format of the returned data.
0675:             *
0676:             * <p> If the chromaticity has not previously been set, or has been
0677:             * unset, an <code>IllegalStateException</code> will be thrown.
0678:             *
0679:             * @throws IllegalStateException if the chromaticity is not set.
0680:             */
0681:            public float[] getChromaticity() {
0682:                if (!chromaticitySet) {
0683:                    throw new IllegalStateException(JaiI18N
0684:                            .getString("PNGEncodeParam12"));
0685:                }
0686:                return (float[]) (chromaticity.clone());
0687:            }
0688:
0689:            /**
0690:             * Suppresses the 'cHRM' chunk from being output.
0691:             */
0692:            public void unsetChromaticity() {
0693:                chromaticity = null;
0694:                chromaticitySet = false;
0695:            }
0696:
0697:            /**
0698:             * Returns true if a 'cHRM' chunk will be output.
0699:             */
0700:            public boolean isChromaticitySet() {
0701:                return chromaticitySet;
0702:            }
0703:
0704:            // gAMA chunk
0705:
0706:            private float gamma;
0707:            private boolean gammaSet = false;
0708:
0709:            /**
0710:             * Sets the file gamma value for the image.
0711:             *
0712:             * <p> The 'gAMA' chunk will encode this information.
0713:             */
0714:            public void setGamma(float gamma) {
0715:                this .gamma = gamma;
0716:                gammaSet = true;
0717:            }
0718:
0719:            /**
0720:             * Returns the file gamma value for the image.
0721:             *
0722:             * <p> If the file gamma has not previously been set, or has been
0723:             * unset, an <code>IllegalStateException</code> will be thrown.
0724:             *
0725:             * @throws IllegalStateException if the gamma is not set.
0726:             */
0727:            public float getGamma() {
0728:                if (!gammaSet) {
0729:                    throw new IllegalStateException(JaiI18N
0730:                            .getString("PNGEncodeParam13"));
0731:                }
0732:                return gamma;
0733:            }
0734:
0735:            /**
0736:             * Suppresses the 'gAMA' chunk from being output.
0737:             */
0738:            public void unsetGamma() {
0739:                gammaSet = false;
0740:            }
0741:
0742:            /**
0743:             * Returns true if a 'gAMA' chunk will be output.
0744:             */
0745:            public boolean isGammaSet() {
0746:                return gammaSet;
0747:            }
0748:
0749:            // hIST chunk
0750:
0751:            private int[] paletteHistogram = null;
0752:            private boolean paletteHistogramSet = false;
0753:
0754:            /**
0755:             * Sets the palette histogram to be stored with this image.
0756:             * The histogram consists of an array of integers, one per
0757:             * palette entry.
0758:             *
0759:             * <p> The 'hIST' chunk will encode this information.
0760:             */
0761:            public void setPaletteHistogram(int[] paletteHistogram) {
0762:                this .paletteHistogram = (int[]) (paletteHistogram.clone());
0763:                paletteHistogramSet = true;
0764:            }
0765:
0766:            /**
0767:             * Returns the palette histogram to be stored with this image.
0768:             *
0769:             * <p> If the histogram has not previously been set, or has been
0770:             * unset, an <code>IllegalStateException</code> will be thrown.
0771:             *
0772:             * @throws IllegalStateException if the histogram is not set.
0773:             */
0774:            public int[] getPaletteHistogram() {
0775:                if (!paletteHistogramSet) {
0776:                    throw new IllegalStateException(JaiI18N
0777:                            .getString("PNGEncodeParam14"));
0778:                }
0779:                return paletteHistogram;
0780:            }
0781:
0782:            /**
0783:             * Suppresses the 'hIST' chunk from being output.
0784:             */
0785:            public void unsetPaletteHistogram() {
0786:                paletteHistogram = null;
0787:                paletteHistogramSet = false;
0788:            }
0789:
0790:            /**
0791:             * Returns true if a 'hIST' chunk will be output.
0792:             */
0793:            public boolean isPaletteHistogramSet() {
0794:                return paletteHistogramSet;
0795:            }
0796:
0797:            // iCCP chunk
0798:
0799:            private byte[] ICCProfileData = null;
0800:            private boolean ICCProfileDataSet = false;
0801:            private String ICCProfileName = null;
0802:
0803:            /**
0804:             * Sets the ICC profile data to be stored with this image.
0805:             * The profile is represented in raw binary form.
0806:             *
0807:             * <p> The 'iCCP' chunk will encode this information.
0808:             */
0809:            public void setICCProfileData(byte[] ICCProfileData) {
0810:                this .ICCProfileData = (byte[]) (ICCProfileData.clone());
0811:                ICCProfileDataSet = true;
0812:                ICC_Profile profile = ICC_Profile
0813:                        .getInstance(this .ICCProfileData);
0814:                if (!(profile instanceof  ICC_ProfileRGB || profile instanceof  ICC_ProfileGray))
0815:                    return;
0816:
0817:                //Set gamma	
0818:                try {
0819:                    if (profile instanceof  ICC_ProfileRGB)
0820:                        setGamma(((ICC_ProfileRGB) profile)
0821:                                .getGamma(ICC_ProfileRGB.REDCOMPONENT));
0822:                    else if (profile instanceof  ICC_ProfileGray)
0823:                        setGamma(((ICC_ProfileGray) profile).getGamma());
0824:                } catch (Exception e) {
0825:                    //Gamma is not defined.  TRC is defined.  So ignore.
0826:                }
0827:
0828:                if (profile instanceof  ICC_ProfileGray)
0829:                    return;
0830:
0831:                // Set cHRM
0832:                float[] chrom = new float[8];
0833:                float[] whitePoint = ((ICC_ProfileRGB) profile)
0834:                        .getMediaWhitePoint();
0835:                if (whitePoint == null)
0836:                    return;
0837:
0838:                float sum = whitePoint[0] + whitePoint[1] + whitePoint[2];
0839:                chrom[0] = whitePoint[0] / sum;
0840:                chrom[1] = whitePoint[1] / sum;
0841:
0842:                float[][] temp = ((ICC_ProfileRGB) profile).getMatrix();
0843:                if (temp == null)
0844:                    return;
0845:
0846:                for (int i = 0; i < 3; i++) {
0847:                    sum = temp[0][i] + temp[1][i] + temp[2][i];
0848:                    chrom[2 + (i << 1)] = temp[0][i] / sum;
0849:                    chrom[3 + (i << 1)] = temp[1][i] / sum;
0850:                }
0851:
0852:                setChromaticity(chrom);
0853:            }
0854:
0855:            /**
0856:             * Returns the ICC profile data to be stored with this image.
0857:             *
0858:             * <p> If the ICC profile has not previously been set, or has been
0859:             * unset, an <code>IllegalStateException</code> will be thrown.
0860:             *
0861:             * @throws IllegalStateException if the ICC profile is not set.
0862:             */
0863:            public byte[] getICCProfileData() {
0864:                if (!ICCProfileDataSet) {
0865:                    throw new IllegalStateException(JaiI18N
0866:                            .getString("PNGEncodeParam15"));
0867:                }
0868:                return (byte[]) (ICCProfileData.clone());
0869:            }
0870:
0871:            /**
0872:             * Suppresses the 'iCCP' chunk from being output.
0873:             */
0874:            public void unsetICCProfileData() {
0875:                ICCProfileData = null;
0876:                ICCProfileDataSet = false;
0877:                ICCProfileName = null;
0878:            }
0879:
0880:            /**
0881:             * Sets the ICC profile name.
0882:             */
0883:            public void setICCProfileName(String name) {
0884:                if (!ICCProfileDataSet) {
0885:                    throw new IllegalStateException(JaiI18N
0886:                            .getString("PNGEncodeParam15"));
0887:                }
0888:                this .ICCProfileName = name;
0889:            }
0890:
0891:            /** Returns the ICC profile name.
0892:             */
0893:            public String getICCProfileName() {
0894:                if (!ICCProfileDataSet) {
0895:                    throw new IllegalStateException(JaiI18N
0896:                            .getString("PNGEncodeParam15"));
0897:                }
0898:                return ICCProfileName;
0899:            }
0900:
0901:            /**
0902:             * Returns true if a 'iCCP' chunk will be output.
0903:             */
0904:            public boolean isICCProfileDataSet() {
0905:                return ICCProfileDataSet;
0906:            }
0907:
0908:            // pHYS chunk
0909:
0910:            private int[] physicalDimension = null;
0911:            private boolean physicalDimensionSet = false;
0912:
0913:            /**
0914:             * Sets the physical dimension information to be stored with this
0915:             * image.  The physicalDimension parameter should be a 3-entry
0916:             * array containing the number of pixels per unit in the X
0917:             * direction, the number of pixels per unit in the Y direction,
0918:             * and the unit specifier (0 = unknown, 1 = meters).
0919:             *
0920:             * <p> The 'pHYS' chunk will encode this information.
0921:             */
0922:            public void setPhysicalDimension(int[] physicalDimension) {
0923:                this .physicalDimension = (int[]) (physicalDimension.clone());
0924:                physicalDimensionSet = true;
0925:            }
0926:
0927:            /**
0928:             * A convenience method that calls the array version.
0929:             */
0930:            public void setPhysicalDimension(int xPixelsPerUnit,
0931:                    int yPixelsPerUnit, int unitSpecifier) {
0932:                int[] pd = new int[3];
0933:                pd[0] = xPixelsPerUnit;
0934:                pd[1] = yPixelsPerUnit;
0935:                pd[2] = unitSpecifier;
0936:
0937:                setPhysicalDimension(pd);
0938:            }
0939:
0940:            /**
0941:             * Returns the physical dimension information to be stored
0942:             * with this image.
0943:             *
0944:             * <p> If the physical dimension information has not previously
0945:             * been set, or has been unset, an
0946:             * <code>IllegalStateException</code> will be thrown.
0947:             *
0948:             * @throws IllegalStateException if the physical dimension information
0949:             *        is not set.
0950:             */
0951:            public int[] getPhysicalDimension() {
0952:                if (!physicalDimensionSet) {
0953:                    throw new IllegalStateException(JaiI18N
0954:                            .getString("PNGEncodeParam16"));
0955:                }
0956:                return (int[]) (physicalDimension.clone());
0957:            }
0958:
0959:            /**
0960:             * Suppresses the 'pHYS' chunk from being output.
0961:             */
0962:            public void unsetPhysicalDimension() {
0963:                physicalDimension = null;
0964:                physicalDimensionSet = false;
0965:            }
0966:
0967:            /**
0968:             * Returns true if a 'pHYS' chunk will be output.
0969:             */
0970:            public boolean isPhysicalDimensionSet() {
0971:                return physicalDimensionSet;
0972:            }
0973:
0974:            // sPLT chunk
0975:
0976:            private PNGSuggestedPaletteEntry[] suggestedPalette = null;
0977:            private boolean suggestedPaletteSet = false;
0978:
0979:            /**
0980:             * Sets the suggested palette information to be stored with this
0981:             * image.  The information is passed to this method as an array of
0982:             * <code>PNGSuggestedPaletteEntry</code> objects.
0983:             *
0984:             * <p> The 'sPLT' chunk will encode this information.
0985:             */
0986:            public void setSuggestedPalette(PNGSuggestedPaletteEntry[] palette) {
0987:                suggestedPalette = (PNGSuggestedPaletteEntry[]) (palette
0988:                        .clone());
0989:                suggestedPaletteSet = true;
0990:            }
0991:
0992:            /**
0993:             * Returns the suggested palette information to be stored with this
0994:             * image.
0995:             *
0996:             * <p> If the suggested palette information has not previously
0997:             * been set, or has been unset, an
0998:             * <code>IllegalStateException</code> will be thrown.
0999:             *
1000:             * @throws IllegalStateException if the suggested palette
1001:             *        information is not set.
1002:             */
1003:            public PNGSuggestedPaletteEntry[] getSuggestedPalette() {
1004:                if (!suggestedPaletteSet) {
1005:                    throw new IllegalStateException(JaiI18N
1006:                            .getString("PNGEncodeParam17"));
1007:                }
1008:                return (PNGSuggestedPaletteEntry[]) (suggestedPalette.clone());
1009:            }
1010:
1011:            /**
1012:             * Suppresses the 'sPLT' chunk from being output.
1013:             */
1014:            public void unsetSuggestedPalette() {
1015:                suggestedPalette = null;
1016:                suggestedPaletteSet = false;
1017:            }
1018:
1019:            /**
1020:             * Returns true if a 'sPLT' chunk will be output.
1021:             */
1022:            public boolean isSuggestedPaletteSet() {
1023:                return suggestedPaletteSet;
1024:            }
1025:
1026:            // sBIT chunk
1027:
1028:            private int[] significantBits = null;
1029:            private boolean significantBitsSet = false;
1030:
1031:            /**
1032:             * Sets the number of significant bits for each band of the image.
1033:             * 
1034:             * <p> The number of entries in the <code>significantBits</code>
1035:             * array must be equal to the number of output bands in the image:
1036:             * 1 for a gray image, 2 for gray+alpha, 3 for index or truecolor,
1037:             * and 4 for truecolor+alpha.
1038:             *
1039:             * <p> The 'sBIT' chunk will encode this information.
1040:             */
1041:            public void setSignificantBits(int[] significantBits) {
1042:                this .significantBits = (int[]) (significantBits.clone());
1043:                significantBitsSet = true;
1044:            }
1045:
1046:            /**
1047:             * Returns the number of significant bits for each band of the image.
1048:             *
1049:             * <p> If the significant bits values have not previously been
1050:             * set, or have been unset, an <code>IllegalStateException</code>
1051:             * will be thrown.
1052:             *
1053:             * @throws IllegalStateException if the significant bits values are
1054:             *        not set.
1055:             */
1056:            public int[] getSignificantBits() {
1057:                if (!significantBitsSet) {
1058:                    throw new IllegalStateException(JaiI18N
1059:                            .getString("PNGEncodeParam18"));
1060:                }
1061:                return (int[]) significantBits.clone();
1062:            }
1063:
1064:            /**
1065:             * Suppresses the 'sBIT' chunk from being output.
1066:             */
1067:            public void unsetSignificantBits() {
1068:                significantBits = null;
1069:                significantBitsSet = false;
1070:            }
1071:
1072:            /**
1073:             * Returns true if an 'sBIT' chunk will be output.
1074:             */
1075:            public boolean isSignificantBitsSet() {
1076:                return significantBitsSet;
1077:            }
1078:
1079:            // sRGB chunk
1080:
1081:            private int SRGBIntent;
1082:            private boolean SRGBIntentSet = false;
1083:
1084:            /**
1085:             * Sets the sRGB rendering intent to be stored with this image.
1086:             * The legal values are 0 = Perceptual, 1 = Relative Colorimetric,
1087:             * 2 = Saturation, and 3 = Absolute Colorimetric.  Refer to the
1088:             * PNG specification for information on these values.
1089:             *
1090:             * <p> The 'sRGB' chunk will encode this information.
1091:             */
1092:            public void setSRGBIntent(int SRGBIntent) {
1093:                this .SRGBIntent = SRGBIntent;
1094:                SRGBIntentSet = true;
1095:            }
1096:
1097:            /**
1098:             * Returns the sRGB rendering intent to be stored with this image.
1099:             *
1100:             * <p> If the sRGB intent has not previously been set, or has been
1101:             * unset, an <code>IllegalStateException</code> will be thrown.
1102:             *
1103:             * @throws IllegalStateException if the sRGB intent is not set.
1104:             */
1105:            public int getSRGBIntent() {
1106:                if (!SRGBIntentSet) {
1107:                    throw new IllegalStateException(JaiI18N
1108:                            .getString("PNGEncodeParam19"));
1109:                }
1110:                return SRGBIntent;
1111:            }
1112:
1113:            /**
1114:             * Suppresses the 'sRGB' chunk from being output.
1115:             */
1116:            public void unsetSRGBIntent() {
1117:                SRGBIntentSet = false;
1118:            }
1119:
1120:            /**
1121:             * Returns true if an 'sRGB' chunk will be output.
1122:             */
1123:            public boolean isSRGBIntentSet() {
1124:                return SRGBIntentSet;
1125:            }
1126:
1127:            // tEXt chunk
1128:
1129:            private String[] text = null;
1130:            private boolean textSet = false;
1131:
1132:            /**
1133:             * Sets the textual data to be stored in uncompressed form with this
1134:             * image.  The data is passed to this method as an array of
1135:             * <code>String</code>s.
1136:             *
1137:             * <p> The 'tEXt' chunk will encode this information.
1138:             */
1139:            public void setText(String[] text) {
1140:                this .text = text;
1141:                textSet = true;
1142:            }
1143:
1144:            /**
1145:             * Returns the text strings to be stored in uncompressed form with this
1146:             * image as an array of <code>String</code>s.
1147:             *
1148:             * <p> If the text strings have not previously been set, or have been
1149:             * unset, an <code>IllegalStateException</code> will be thrown.
1150:             *
1151:             * @throws IllegalStateException if the text strings are not set.
1152:             */
1153:            public String[] getText() {
1154:                if (!textSet) {
1155:                    throw new IllegalStateException(JaiI18N
1156:                            .getString("PNGEncodeParam20"));
1157:                }
1158:                return text;
1159:            }
1160:
1161:            /**
1162:             * Suppresses the 'tEXt' chunk from being output.
1163:             */
1164:            public void unsetText() {
1165:                text = null;
1166:                textSet = false;
1167:            }
1168:
1169:            /**
1170:             * Returns true if a 'tEXt' chunk will be output.
1171:             */
1172:            public boolean isTextSet() {
1173:                return textSet;
1174:            }
1175:
1176:            // tIME chunk
1177:
1178:            private Date modificationTime;
1179:            private boolean modificationTimeSet = false;
1180:
1181:            /**
1182:             * Sets the modification time, as a <code>Date</code>, to be
1183:             * stored with this image.  The internal storage format will use
1184:             * UTC regardless of how the <code>modificationTime</code>
1185:             * parameter was created.
1186:             *
1187:             * <p> The 'tIME' chunk will encode this information.
1188:             */
1189:            public void setModificationTime(Date modificationTime) {
1190:                this .modificationTime = modificationTime;
1191:                modificationTimeSet = true;
1192:            }
1193:
1194:            /**
1195:             * Returns the modification time to be stored with this image.
1196:             *
1197:             * <p> If the bit depth has not previously been set, or has been
1198:             * unset, an <code>IllegalStateException</code> will be thrown.
1199:             *
1200:             * @throws IllegalStateException if the bit depth is not set.
1201:             */
1202:            public Date getModificationTime() {
1203:                if (!modificationTimeSet) {
1204:                    throw new IllegalStateException(JaiI18N
1205:                            .getString("PNGEncodeParam21"));
1206:                }
1207:                return modificationTime;
1208:            }
1209:
1210:            /**
1211:             * Suppresses the 'tIME' chunk from being output.
1212:             */
1213:            public void unsetModificationTime() {
1214:                modificationTime = null;
1215:                modificationTimeSet = false;
1216:            }
1217:
1218:            /**
1219:             * Returns true if a 'tIME' chunk will be output.
1220:             */
1221:            public boolean isModificationTimeSet() {
1222:                return modificationTimeSet;
1223:            }
1224:
1225:            // tRNS chunk
1226:
1227:            boolean transparencySet = false;
1228:
1229:            /**
1230:             * Suppresses the 'tRNS' chunk from being output.
1231:             */
1232:            public void unsetTransparency() {
1233:                transparencySet = false;
1234:            }
1235:
1236:            /**
1237:             * Returns true if a 'tRNS' chunk will be output.
1238:             */
1239:            public boolean isTransparencySet() {
1240:                return transparencySet;
1241:            }
1242:
1243:            // zTXT chunk
1244:
1245:            private String[] zText = null;
1246:            private boolean zTextSet = false;
1247:
1248:            /**
1249:             * Sets the text strings to be stored in compressed form with this
1250:             * image.  The data is passed to this method as an array of
1251:             * <code>String</code>s.
1252:             *
1253:             * <p> The 'zTXt' chunk will encode this information.
1254:             */
1255:            public void setCompressedText(String[] text) {
1256:                this .zText = text;
1257:                zTextSet = true;
1258:            }
1259:
1260:            /**
1261:             * Returns the text strings to be stored in compressed form with
1262:             * this image as an array of <code>String</code>s.
1263:             *
1264:             * <p> If the compressed text strings have not previously been
1265:             * set, or have been unset, an <code>IllegalStateException</code>
1266:             * will be thrown.
1267:             *
1268:             * @throws IllegalStateException if the compressed text strings are
1269:             *        not set.
1270:             */
1271:            public String[] getCompressedText() {
1272:                if (!zTextSet) {
1273:                    throw new IllegalStateException(JaiI18N
1274:                            .getString("PNGEncodeParam22"));
1275:                }
1276:                return zText;
1277:            }
1278:
1279:            /**
1280:             * Suppresses the 'zTXt' chunk from being output.
1281:             */
1282:            public void unsetCompressedText() {
1283:                zText = null;
1284:                zTextSet = false;
1285:            }
1286:
1287:            /**
1288:             * Returns true if a 'zTXT' chunk will be output.
1289:             */
1290:            public boolean isCompressedTextSet() {
1291:                return zTextSet;
1292:            }
1293:
1294:            // Other chunk types
1295:
1296:            Vector chunkType = new Vector();
1297:            Vector chunkData = new Vector();
1298:
1299:            /**
1300:             * Adds a private chunk, in binary form, to the list of chunks to
1301:             * be stored with this image.
1302:             *
1303:             * @param type a 4-character String giving the chunk type name.
1304:             * @param data an array of <code>byte</code>s containing the
1305:             *        chunk data.
1306:             */
1307:            public synchronized void addPrivateChunk(String type, byte[] data) {
1308:                chunkType.add(type);
1309:                chunkData.add((byte[]) data.clone());
1310:            }
1311:
1312:            /**
1313:             * Returns the number of private chunks to be written to the
1314:             * output file.
1315:             */
1316:            public synchronized int getNumPrivateChunks() {
1317:                return chunkType.size();
1318:            }
1319:
1320:            /**
1321:             * Returns the type of the private chunk at a given index, as a
1322:             * 4-character <code>String</code>.  The index must be smaller
1323:             * than the return value of <code>getNumPrivateChunks</code>.
1324:             */
1325:            public synchronized String getPrivateChunkType(int index) {
1326:                return (String) chunkType.elementAt(index);
1327:            }
1328:
1329:            /**
1330:             * Returns the data associated of the private chunk at a given
1331:             * index, as an array of <code>byte</code>s.  The index must be
1332:             * smaller than the return value of
1333:             * <code>getNumPrivateChunks</code>.
1334:             */
1335:            public synchronized byte[] getPrivateChunkData(int index) {
1336:                return (byte[]) chunkData.elementAt(index);
1337:            }
1338:
1339:            /**
1340:             * Remove all private chunks associated with this parameter instance
1341:             * whose 'safe-to-copy' bit is not set.  This may be advisable when
1342:             * transcoding PNG images.
1343:             */
1344:            public synchronized void removeUnsafeToCopyPrivateChunks() {
1345:                Vector newChunkType = new Vector();
1346:                Vector newChunkData = new Vector();
1347:
1348:                int len = getNumPrivateChunks();
1349:                for (int i = 0; i < len; i++) {
1350:                    String type = getPrivateChunkType(i);
1351:                    char lastChar = type.charAt(3);
1352:                    if (lastChar >= 'a' && lastChar <= 'z') {
1353:                        newChunkType.add(type);
1354:                        newChunkData.add(getPrivateChunkData(i));
1355:                    }
1356:                }
1357:
1358:                chunkType = newChunkType;
1359:                chunkData = newChunkData;
1360:            }
1361:
1362:            /**
1363:             * Remove all private chunks associated with this parameter instance.
1364:             */
1365:            public synchronized void removeAllPrivateChunks() {
1366:                chunkType = new Vector();
1367:                chunkData = new Vector();
1368:            }
1369:
1370:            /**
1371:             * An abs() function for use by the Paeth predictor.
1372:             */
1373:            private static final int abs(int x) {
1374:                return (x < 0) ? -x : x;
1375:            }
1376:
1377:            /**
1378:             * The Paeth predictor routine used in PNG encoding.  This routine
1379:             * is included as a convenience to subclasses that override the
1380:             * <code>filterRow</code> method.
1381:             */
1382:            public static final int paethPredictor(int a, int b, int c) {
1383:                int p = a + b - c;
1384:                int pa = abs(p - a);
1385:                int pb = abs(p - b);
1386:                int pc = abs(p - c);
1387:
1388:                if ((pa <= pb) && (pa <= pc)) {
1389:                    return a;
1390:                } else if (pb <= pc) {
1391:                    return b;
1392:                } else {
1393:                    return c;
1394:                }
1395:            }
1396:
1397:            /**
1398:             * Performs filtering on a row of an image.  This method may be
1399:             * overridden in order to provide a custom algorithm for choosing
1400:             * the filter type for a given row.
1401:             *
1402:             * <p> The method is supplied with the current and previous rows
1403:             * of the image.  For the first row of the image, or of an
1404:             * interlacing pass, the previous row array will be filled with
1405:             * zeros as required by the PNG specification.
1406:             *
1407:             * <p> The method is also supplied with five scratch arrays.
1408:             * These arrays may be used within the method for any purpose.
1409:             * At method exit, the array at the index given by the return
1410:             * value of the method should contain the filtered data.  The
1411:             * return value will also be used as the filter type.
1412:             *
1413:             * <p> The default implementation of the method performs a trial
1414:             * encoding with each of the filter types, and computes the sum of
1415:             * absolute values of the differences between the raw bytes of the
1416:             * current row and the predicted values.  The index of the filter
1417:             * producing the smallest result is returned.
1418:             *
1419:             * <p> As an example, to perform only 'sub' filtering, this method
1420:             * could be implemented (non-optimally) as follows:
1421:             *
1422:             * <pre>
1423:             * for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
1424:             *     int curr = currRow[i] & 0xff;
1425:             *     int left = currRow[i - bytesPerPixel] & 0xff;
1426:             *     scratchRow[PNG_FILTER_SUB][i] = (byte)(curr - left);
1427:             * }
1428:             * return PNG_FILTER_SUB;
1429:             * </pre>
1430:             *
1431:             * @param currRow The current row as an array of <code>byte</code>s
1432:             *        of length at least <code>bytesPerRow + bytesPerPixel</code>.
1433:             *        The pixel data starts at index <code>bytesPerPixel</code>;
1434:             *        the initial <code>bytesPerPixel</code> bytes are zero.
1435:             * @param prevRow The current row as an array of <code>byte</code>s
1436:             *        The pixel data starts at index <code>bytesPerPixel</code>;
1437:             *        the initial <code>bytesPerPixel</code> bytes are zero.
1438:             * @param scratchRows An array of 5 <code>byte</code> arrays of
1439:             *        length at least <code>bytesPerRow +
1440:             *        bytesPerPixel</code>, useable to hold temporary results.
1441:             *        The filtered row will be returned as one of the entries
1442:             *        of this array.  The returned filtered data should start
1443:             *        at index <code>bytesPerPixel</code>; The initial
1444:             *        <code>bytesPerPixel</code> bytes are not used.
1445:             * @param bytesPerRow The number of bytes in the image row.
1446:             *        This value will always be greater than 0.
1447:             * @param bytesPerPixel The number of bytes representing a single
1448:             *        pixel, rounded up to an integer.  This is the 'bpp' parameter
1449:             *        described in the PNG specification.
1450:             *
1451:             * @return The filter type to be used.  The entry of
1452:             *         <code>scratchRows[]</code> at this index holds the
1453:             *         filtered data.  */
1454:            public int filterRow(byte[] currRow, byte[] prevRow,
1455:                    byte[][] scratchRows, int bytesPerRow, int bytesPerPixel) {
1456:                int[] filterBadness = new int[5];
1457:                for (int i = 0; i < 5; i++) {
1458:                    filterBadness[i] = Integer.MAX_VALUE;
1459:                }
1460:
1461:                {
1462:                    int badness = 0;
1463:
1464:                    for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
1465:                        int curr = currRow[i] & 0xff;
1466:                        badness += curr;
1467:                    }
1468:
1469:                    filterBadness[0] = badness;
1470:                }
1471:
1472:                {
1473:                    byte[] subFilteredRow = scratchRows[1];
1474:                    int badness = 0;
1475:
1476:                    for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
1477:                        int curr = currRow[i] & 0xff;
1478:                        int left = currRow[i - bytesPerPixel] & 0xff;
1479:                        int difference = curr - left;
1480:                        subFilteredRow[i] = (byte) difference;
1481:
1482:                        badness += abs(difference);
1483:                    }
1484:
1485:                    filterBadness[1] = badness;
1486:                }
1487:
1488:                {
1489:                    byte[] upFilteredRow = scratchRows[2];
1490:                    int badness = 0;
1491:
1492:                    for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
1493:                        int curr = currRow[i] & 0xff;
1494:                        int up = prevRow[i] & 0xff;
1495:                        int difference = curr - up;
1496:                        upFilteredRow[i] = (byte) difference;
1497:
1498:                        badness += abs(difference);
1499:                    }
1500:
1501:                    filterBadness[2] = badness;
1502:                }
1503:
1504:                {
1505:                    byte[] averageFilteredRow = scratchRows[3];
1506:                    int badness = 0;
1507:
1508:                    for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
1509:                        int curr = currRow[i] & 0xff;
1510:                        int left = currRow[i - bytesPerPixel] & 0xff;
1511:                        int up = prevRow[i] & 0xff;
1512:                        int difference = curr - (left + up) / 2;
1513:                        ;
1514:                        averageFilteredRow[i] = (byte) difference;
1515:
1516:                        badness += abs(difference);
1517:                    }
1518:
1519:                    filterBadness[3] = badness;
1520:                }
1521:
1522:                {
1523:                    byte[] paethFilteredRow = scratchRows[4];
1524:                    int badness = 0;
1525:
1526:                    for (int i = bytesPerPixel; i < bytesPerRow + bytesPerPixel; i++) {
1527:                        int curr = currRow[i] & 0xff;
1528:                        int left = currRow[i - bytesPerPixel] & 0xff;
1529:                        int up = prevRow[i] & 0xff;
1530:                        int upleft = prevRow[i - bytesPerPixel] & 0xff;
1531:                        int predictor = paethPredictor(left, up, upleft);
1532:                        int difference = curr - predictor;
1533:                        paethFilteredRow[i] = (byte) difference;
1534:
1535:                        badness += abs(difference);
1536:                    }
1537:
1538:                    filterBadness[4] = badness;
1539:                }
1540:
1541:                int filterType = 0;
1542:                int minBadness = filterBadness[0];
1543:
1544:                for (int i = 1; i < 5; i++) {
1545:                    if (filterBadness[i] < minBadness) {
1546:                        minBadness = filterBadness[i];
1547:                        filterType = i;
1548:                    }
1549:                }
1550:
1551:                if (filterType == 0) {
1552:                    System.arraycopy(currRow, bytesPerPixel, scratchRows[0],
1553:                            bytesPerPixel, bytesPerRow);
1554:                }
1555:
1556:                return filterType;
1557:            }
1558:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.