KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > batik > ext > awt > image > codec > PNGEncodeParam


1 /*
2
3    Copyright 2001,2003 The Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16
17  */

18 package org.apache.batik.ext.awt.image.codec;
19
20 import java.awt.image.ColorModel JavaDoc;
21 import java.awt.image.IndexColorModel JavaDoc;
22 import java.awt.image.RenderedImage JavaDoc;
23 import java.awt.image.SampleModel JavaDoc;
24 import java.util.Date JavaDoc;
25 import java.util.Vector JavaDoc;
26
27 /**
28  * An instance of <code>ImageEncodeParam</code> for encoding images in
29  * the PNG format.
30  *
31  * <p><b> This class is not a committed part of the JAI API. It may
32  * be removed or changed in future releases of JAI.</b>
33  */

34 public abstract class PNGEncodeParam implements ImageEncodeParam {
35
36     /** Constant for use with the sRGB chunk. */
37     public static final int INTENT_PERCEPTUAL = 0;
38
39     /** Constant for use with the sRGB chunk. */
40     public static final int INTENT_RELATIVE = 1;
41
42     /** Constant for use with the sRGB chunk. */
43     public static final int INTENT_SATURATION = 2;
44
45     /** Constant for use with the sRGB chunk. */
46     public static final int INTENT_ABSOLUTE = 3;
47
48     /** Constant for use in filtering. */
49     public static final int PNG_FILTER_NONE = 0;
50
51     /** Constant for use in filtering. */
52     public static final int PNG_FILTER_SUB = 1;
53
54     /** Constant for use in filtering. */
55     public static final int PNG_FILTER_UP = 2;
56
57     /** Constant for use in filtering. */
58     public static final int PNG_FILTER_AVERAGE = 3;
59
60     /** Constant for use in filtering. */
61     public static final int PNG_FILTER_PAETH = 4;
62
63
64     /**
65      * Returns an instance of <code>PNGEncodeParam.Palette</code>,
66      * <code>PNGEncodeParam.Gray</code>, or
67      * <code>PNGEncodeParam.RGB</code> appropriate for encoding
68      * the given image.
69      *
70      * <p> If the image has an <code>IndexColorModel</code>, an
71      * instance of <code>PNGEncodeParam.Palette</code> is returned.
72      * Otherwise, if the image has 1 or 2 bands an instance of
73      * <code>PNGEncodeParam.Gray</code> is returned. In all other
74      * cases an instance of <code>PNGEncodeParam.RGB</code> is
75      * returned.
76      *
77      * <p> Note that this method does not provide any guarantee that
78      * the given image will be successfully encoded by the PNG
79      * encoder, as it only performs a very superficial analysis of
80      * the image structure.
81      */

82     public static PNGEncodeParam getDefaultEncodeParam(RenderedImage JavaDoc im) {
83         ColorModel JavaDoc colorModel = im.getColorModel();
84         if (colorModel instanceof IndexColorModel JavaDoc) {
85             return new PNGEncodeParam.Palette();
86         }
87
88         SampleModel JavaDoc sampleModel = im.getSampleModel();
89         int numBands = sampleModel.getNumBands();
90
91         if (numBands == 1 || numBands == 2) {
92             return new PNGEncodeParam.Gray();
93         } else {
94             return new PNGEncodeParam.RGB();
95         }
96     }
97
98     public static class Palette extends PNGEncodeParam {
99
100         /** Constructs an instance of <code>PNGEncodeParam.Palette</code>. */
101         public Palette() {}
102
103         // bKGD chunk
104

105         private boolean backgroundSet = false;
106         
107         /**
108          * Suppresses the 'bKGD' chunk from being output.
109          */

110         public void unsetBackground() {
111             backgroundSet = false;
112         }
113         
114         /**
115          * Returns true if a 'bKGD' chunk will be output.
116          */

117         public boolean isBackgroundSet() {
118             return backgroundSet;
119         }
120
121         /**
122          * Sets the desired bit depth for a palette image. The bit
123          * depth must be one of 1, 2, 4, or 8, or else an
124          * <code>IllegalArgumentException</code> will be thrown.
125          */

126         public void setBitDepth(int bitDepth) {
127             if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 &&
128                 bitDepth != 8) {
129                 throw new IllegalArgumentException JavaDoc(PropertyUtil.getString("PNGEncodeParam2"));
130             }
131             this.bitDepth = bitDepth;
132             bitDepthSet = true;
133         }
134     
135         // PLTE chunk
136

137         private int[] palette = null;
138         private boolean paletteSet = false;
139
140         /**
141          * Sets the RGB palette of the image to be encoded.
142          * The <code>rgb</code> parameter contains alternating
143          * R, G, B values for each color index used in the image.
144          * The number of elements must be a multiple of 3 between
145          * 3 and 3*256.
146          *
147          * <p> The 'PLTE' chunk will encode this information.
148          *
149          * @param rgb An array of <code>int</code>s.
150          */

151         public void setPalette(int[] rgb) {
152             if (rgb.length < 1*3 || rgb.length > 256*3) {
153         throw new
154           IllegalArgumentException JavaDoc(PropertyUtil.getString("PNGEncodeParam0"));
155             }
156             if ((rgb.length % 3) != 0) {
157                 throw new
158               IllegalArgumentException JavaDoc(PropertyUtil.getString("PNGEncodeParam1"));
159             }
160             
161             palette = (int[])(rgb.clone());
162             paletteSet = true;
163         }
164         
165         /**
166          * Returns the current RGB palette.
167          *
168          * <p> If the palette has not previously been set, or has been
169          * unset, an <code>IllegalStateException</code> will be thrown.
170          *
171          * @throws IllegalStateException if the palette is not set.
172          *
173          * @return An array of <code>int</code>s.
174          */

175         public int[] getPalette() {
176             if (!paletteSet) {
177                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam3"));
178             }
179             return (int[])(palette.clone());
180         }
181
182         /**
183          * Suppresses the 'PLTE' chunk from being output.
184          */

185         public void unsetPalette() {
186             palette = null;
187             paletteSet = false;
188         }
189         
190         /**
191          * Returns true if a 'PLTE' chunk will be output.
192          */

193         public boolean isPaletteSet() {
194             return paletteSet;
195         }
196
197         // bKGD chunk
198

199         private int backgroundPaletteIndex;
200         
201         /**
202          * Sets the palette index of the suggested background color.
203          *
204          * <p> The 'bKGD' chunk will encode this information.
205          */

206         public void setBackgroundPaletteIndex(int index) {
207             backgroundPaletteIndex = index;
208             backgroundSet = true;
209         }
210         
211         /**
212          * Returns the palette index of the suggested background color.
213          *
214          * <p> If the background palette index has not previously been
215          * set, or has been unset, an
216          * <code>IllegalStateException</code> will be thrown.
217          *
218          * @throws IllegalStateException if the palette index is not set.
219          */

220         public int getBackgroundPaletteIndex() {
221             if (!backgroundSet) {
222                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam4"));
223             }
224             return backgroundPaletteIndex;
225         }
226
227         // tRNS chunk
228

229         private int[] transparency;
230
231         /**
232          * Sets the alpha values associated with each palette entry.
233          * The <code>alpha</code> parameter should have as many entries
234          * as there are RGB triples in the palette.
235          *
236          * <p> The 'tRNS' chunk will encode this information.
237          */

238         public void setPaletteTransparency(byte[] alpha) {
239             transparency = new int[alpha.length];
240             for (int i = 0; i < alpha.length; i++) {
241                 transparency[i] = alpha[i] & 0xff;
242             }
243             transparencySet = true;
244         }
245         
246         /**
247          * Returns the alpha values associated with each palette entry.
248          *
249          * <p> If the palette transparency has not previously been
250          * set, or has been unset, an
251          * <code>IllegalStateException</code> will be thrown.
252          *
253          * @throws IllegalStateException if the palette transparency is
254          * not set.
255          */

256         public byte[] getPaletteTransparency() {
257             if (!transparencySet) {
258                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam5"));
259             }
260             byte[] alpha = new byte[transparency.length];
261             for (int i = 0; i < alpha.length; i++) {
262                 alpha[i] = (byte)transparency[i];
263             }
264             return alpha;
265         }
266     }
267
268     public static class Gray extends PNGEncodeParam {
269
270         /** Constructs an instance of <code>PNGEncodeParam.Gray</code>. */
271         public Gray() {}
272
273         // bKGD chunk
274

275         private boolean backgroundSet = false;
276         
277         /**
278          * Suppresses the 'bKGD' chunk from being output.
279          */

280         public void unsetBackground() {
281             backgroundSet = false;
282         }
283         
284         /**
285          * Returns true if a 'bKGD' chunk will be output.
286          */

287         public boolean isBackgroundSet() {
288             return backgroundSet;
289         }
290
291         /**
292          * Sets the desired bit depth for a grayscale image. The bit
293          * depth must be one of 1, 2, 4, 8, or 16.
294          *
295          * <p> When encoding a source image of a greater bit depth,
296          * pixel values will be clamped to the smaller range after
297          * shifting by the value given by <code>getBitShift()</code>.
298          * When encoding a source image of a smaller bit depth, pixel
299          * values will be shifted and left-filled with zeroes.
300          */

301         public void setBitDepth(int bitDepth) {
302             if (bitDepth != 1 && bitDepth != 2 && bitDepth != 4 &&
303                 bitDepth != 8 && bitDepth != 16) {
304                 throw new IllegalArgumentException JavaDoc();
305             }
306             this.bitDepth = bitDepth;
307             bitDepthSet = true;
308         }
309     
310         // bKGD chunk
311

312         private int backgroundPaletteGray;
313
314         /**
315          * Sets the suggested gray level of the background.
316          *
317          * <p> The 'bKGD' chunk will encode this information.
318          */

319         public void setBackgroundGray(int gray) {
320             backgroundPaletteGray = gray;
321             backgroundSet = true;
322         }
323         
324         /**
325          * Returns the suggested gray level of the background.
326          *
327          * <p> If the background gray level has not previously been
328          * set, or has been unset, an
329          * <code>IllegalStateException</code> will be thrown.
330          *
331          * @throws IllegalStateException if the background gray level
332          * is not set.
333          */

334         public int getBackgroundGray() {
335             if (!backgroundSet) {
336                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam6"));
337             }
338             return backgroundPaletteGray;
339         }
340
341         // tRNS chunk
342

343         private int[] transparency;
344
345         /**
346          * Sets the gray value to be used to denote transparency.
347          *
348          * <p> Setting this attribute will cause the alpha channel
349          * of the input image to be ignored.
350          *
351          * <p> The 'tRNS' chunk will encode this information.
352          */

353         public void setTransparentGray(int transparentGray) {
354             transparency = new int[1];
355             transparency[0] = transparentGray;
356             transparencySet = true;
357         }
358         
359         /**
360          * Returns the gray value to be used to denote transparency.
361          *
362          * <p> If the transparent gray value has not previously been
363          * set, or has been unset, an
364          * <code>IllegalStateException</code> will be thrown.
365          *
366          * @throws IllegalStateException if the transparent gray value
367          * is not set.
368          */

369         public int getTransparentGray() {
370             if (!transparencySet) {
371                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam7"));
372             }
373             int gray = transparency[0];
374             return gray;
375         }
376
377         private int bitShift;
378         private boolean bitShiftSet = false;
379
380         /**
381          * Sets the desired bit shift for a grayscale image.
382          * Pixels in the source image will be shifted right by
383          * the given amount prior to being clamped to the maximum
384          * value given by the encoded image's bit depth.
385          */

386         public void setBitShift(int bitShift) {
387             if (bitShift < 0) {
388                 throw new RuntimeException JavaDoc();
389             }
390             this.bitShift = bitShift;
391             bitShiftSet = true;
392         }
393
394         /**
395          * Returns the desired bit shift for a grayscale image.
396          *
397          * <p> If the bit shift has not previously been set, or has been
398          * unset, an <code>IllegalStateException</code> will be thrown.
399          *
400          * @throws IllegalStateException if the bit shift is not set.
401          */

402         public int getBitShift() {
403             if (!bitShiftSet) {
404                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam8"));
405             }
406             return bitShift;
407         }
408
409         /**
410          * Suppresses the setting of the bit shift of a grayscale image.
411          * Pixels in the source image will not be shifted prior to encoding.
412          */

413         public void unsetBitShift() {
414             bitShiftSet = false;
415         }
416
417         /**
418          * Returns true if the bit shift has been set.
419          */

420         public boolean isBitShiftSet() {
421             return bitShiftSet;
422         }
423
424         /**
425          * Returns true if the bit depth has been set.
426          */

427         public boolean isBitDepthSet() {
428             return bitDepthSet;
429         }
430     }
431
432     public static class RGB extends PNGEncodeParam {
433
434         /** Constructs an instance of <code>PNGEncodeParam.RGB</code>. */
435         public RGB() {}
436
437         // bKGD chunk
438

439         private boolean backgroundSet = false;
440         
441         /**
442          * Suppresses the 'bKGD' chunk from being output.
443          */

444         public void unsetBackground() {
445             backgroundSet = false;
446         }
447         
448         /**
449          * Returns true if a 'bKGD' chunk will be output.
450          */

451         public boolean isBackgroundSet() {
452             return backgroundSet;
453         }
454
455         /**
456          * Sets the desired bit depth for an RGB image. The bit
457          * depth must be 8 or 16.
458          */

459         public void setBitDepth(int bitDepth) {
460             if (bitDepth != 8 && bitDepth != 16) {
461                 throw new RuntimeException JavaDoc();
462             }
463             this.bitDepth = bitDepth;
464             bitDepthSet = true;
465         }
466     
467         // bKGD chunk
468

469         private int[] backgroundRGB;
470
471         /**
472          * Sets the RGB value of the suggested background color.
473          * The <code>rgb</code> parameter should have 3 entries.
474          *
475          * <p> The 'bKGD' chunk will encode this information.
476          */

477         public void setBackgroundRGB(int[] rgb) {
478             if (rgb.length != 3) {
479                 throw new RuntimeException JavaDoc();
480             }
481             backgroundRGB = rgb;
482             backgroundSet = true;
483         }
484         
485         /**
486          * Returns the RGB value of the suggested background color.
487          *
488          * <p> If the background color has not previously been set, or has been
489          * unset, an <code>IllegalStateException</code> will be thrown.
490          *
491          * @throws IllegalStateException if the background color is not set.
492          */

493         public int[] getBackgroundRGB() {
494             if (!backgroundSet) {
495                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam9"));
496             }
497             return backgroundRGB;
498         }
499
500         // tRNS chunk
501

502         private int[] transparency;
503         
504         /**
505          * Sets the RGB value to be used to denote transparency.
506          *
507          * <p> Setting this attribute will cause the alpha channel
508          * of the input image to be ignored.
509          *
510          * <p> The 'tRNS' chunk will encode this information.
511          */

512         public void setTransparentRGB(int[] transparentRGB) {
513             transparency = (int[])(transparentRGB.clone());
514             transparencySet = true;
515         }
516         
517         /**
518          * Returns the RGB value to be used to denote transparency.
519          *
520          * <p> If the transparent color has not previously been set,
521          * or has been unset, an <code>IllegalStateException</code>
522          * will be thrown.
523          *
524          * @throws IllegalStateException if the transparent color is not set.
525          */

526         public int[] getTransparentRGB() {
527             if (!transparencySet) {
528                 throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam10"));
529             }
530             return (int[])(transparency.clone());
531         }
532     }
533
534     protected int bitDepth;
535     protected boolean bitDepthSet = false;
536
537     /**
538      * Sets the desired bit depth of an image.
539      */

540     public abstract void setBitDepth(int bitDepth);
541     
542     /**
543      * Returns the desired bit depth for a grayscale image.
544      *
545      * <p> If the bit depth has not previously been set, or has been
546      * unset, an <code>IllegalStateException</code> will be thrown.
547      *
548      * @throws IllegalStateException if the bit depth is not set.
549      */

550     public int getBitDepth() {
551         if (!bitDepthSet) {
552             throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam11"));
553         }
554         return bitDepth;
555     }
556
557     /**
558      * Suppresses the setting of the bit depth of a grayscale image.
559      * The depth of the encoded image will be inferred from the source
560      * image bit depth, rounded up to the next power of 2 between 1
561      * and 16.
562      */

563     public void unsetBitDepth() {
564         bitDepthSet = false;
565     }
566
567     private boolean useInterlacing = false;
568
569     /**
570      * Turns Adam7 interlacing on or off.
571      */

572     public void setInterlacing(boolean useInterlacing) {
573         this.useInterlacing = useInterlacing;
574     }
575
576     /**
577      * Returns <code>true</code> if Adam7 interlacing will be used.
578      */

579     public boolean getInterlacing() {
580         return useInterlacing;
581     }
582     
583     // bKGD chunk - delegate to subclasses
584

585     // In JAI 1.0, 'backgroundSet' was private. The JDK 1.2 compiler
586
// was lenient and incorrectly allowed this variable to be
587
// accessed from the subclasses. The JDK 1.3 compiler correctly
588
// flags this as a use of a non-static variable in a static
589
// context. Changing 'backgroundSet' to protected would have
590
// solved the problem, but would have introduced a visible API
591
// change. Thus we are forced to adopt the solution of placing a
592
// separate private variable in each subclass and providing
593
// separate implementations of 'unsetBackground' and
594
// 'isBackgroundSet' in each concrete subclass.
595

596     /**
597      * Suppresses the 'bKGD' chunk from being output.
598      * For API compatibility with JAI 1.0, the superclass
599      * defines this method to throw a <code>RuntimeException</code>;
600      * accordingly, subclasses must provide their own implementations.
601      */

602     public void unsetBackground() {
603         throw new RuntimeException JavaDoc(PropertyUtil.getString("PNGEncodeParam23"));
604     }
605
606     /**
607      * Returns true if a 'bKGD' chunk will be output.
608      * For API compatibility with JAI 1.0, the superclass
609      * defines this method to throw a <code>RuntimeException</code>;
610      * accordingly, subclasses must provide their own implementations.
611      */

612     public boolean isBackgroundSet() {
613         throw new RuntimeException JavaDoc(PropertyUtil.getString("PNGEncodeParam24"));
614     }
615
616     // cHRM chunk
617

618     private float[] chromaticity = null;
619     private boolean chromaticitySet = false;
620
621     /**
622      * Sets the white point and primary chromaticities in CIE (x, y)
623      * space.
624      *
625      * <p> The <code>chromaticity</code> parameter should be a
626      * <code>float</code> array of length 8 containing the white point
627      * X and Y, red X and Y, green X and Y, and blue X and Y values in
628      * order.
629      *
630      * <p> The 'cHRM' chunk will encode this information.
631      */

632     public void setChromaticity(float[] chromaticity) {
633         if (chromaticity.length != 8) {
634             throw new IllegalArgumentException JavaDoc();
635         }
636         this.chromaticity = (float[])(chromaticity.clone());
637         chromaticitySet = true;
638     }
639
640     /**
641      * A convenience method that calls the array version.
642      */

643     public void setChromaticity(float whitePointX, float whitePointY,
644                                 float redX, float redY,
645                                 float greenX, float greenY,
646                                 float blueX, float blueY) {
647         float[] chroma = new float[8];
648         chroma[0] = whitePointX;
649         chroma[1] = whitePointY;
650         chroma[2] = redX;
651         chroma[3] = redY;
652         chroma[4] = greenX;
653         chroma[5] = greenY;
654         chroma[6] = blueX;
655         chroma[7] = blueY;
656         setChromaticity(chroma);
657     }
658
659     /**
660      * Returns the white point and primary chromaticities in
661      * CIE (x, y) space.
662      *
663      * <p> See the documentation for the <code>setChromaticity</code>
664      * method for the format of the returned data.
665      *
666      * <p> If the chromaticity has not previously been set, or has been
667      * unset, an <code>IllegalStateException</code> will be thrown.
668      *
669      * @throws IllegalStateException if the chromaticity is not set.
670      */

671     public float[] getChromaticity() {
672         if (!chromaticitySet) {
673             throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam12"));
674         }
675         return (float[])(chromaticity.clone());
676     }
677
678     /**
679      * Suppresses the 'cHRM' chunk from being output.
680      */

681     public void unsetChromaticity() {
682         chromaticity = null;
683         chromaticitySet = false;
684     }
685
686     /**
687      * Returns true if a 'cHRM' chunk will be output.
688      */

689     public boolean isChromaticitySet() {
690         return chromaticitySet;
691     }
692
693     // gAMA chunk
694

695     private float gamma;
696     private boolean gammaSet = false;
697
698     /**
699      * Sets the file gamma value for the image.
700      *
701      * <p> The 'gAMA' chunk will encode this information.
702      */

703     public void setGamma(float gamma) {
704         this.gamma = gamma;
705         gammaSet = true;
706     }
707
708     /**
709      * Returns the file gamma value for the image.
710      *
711      * <p> If the file gamma has not previously been set, or has been
712      * unset, an <code>IllegalStateException</code> will be thrown.
713      *
714      * @throws IllegalStateException if the gamma is not set.
715      */

716     public float getGamma() {
717         if (!gammaSet) {
718             throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam13"));
719         }
720         return gamma;
721     }
722
723     /**
724      * Suppresses the 'gAMA' chunk from being output.
725      */

726     public void unsetGamma() {
727         gammaSet = false;
728     }
729
730     /**
731      * Returns true if a 'gAMA' chunk will be output.
732      */

733     public boolean isGammaSet() {
734         return gammaSet;
735     }
736
737     // hIST chunk
738

739     private int[] paletteHistogram = null;
740     private boolean paletteHistogramSet = false;
741
742     /**
743      * Sets the palette histogram to be stored with this image.
744      * The histogram consists of an array of integers, one per
745      * palette entry.
746      *
747      * <p> The 'hIST' chunk will encode this information.
748      */

749     public void setPaletteHistogram(int[] paletteHistogram) {
750         this.paletteHistogram = (int[])(paletteHistogram.clone());
751         paletteHistogramSet = true;
752     }
753
754     /**
755      * Returns the palette histogram to be stored with this image.
756      *
757      * <p> If the histogram has not previously been set, or has been
758      * unset, an <code>IllegalStateException</code> will be thrown.
759      *
760      * @throws IllegalStateException if the histogram is not set.
761      */

762     public int[] getPaletteHistogram() {
763         if (!paletteHistogramSet) {
764             throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam14"));
765         }
766         return paletteHistogram;
767     }
768
769     /**
770      * Suppresses the 'hIST' chunk from being output.
771      */

772     public void unsetPaletteHistogram() {
773         paletteHistogram = null;
774         paletteHistogramSet = false;
775     }
776
777     /**
778      * Returns true if a 'hIST' chunk will be output.
779      */

780     public boolean isPaletteHistogramSet() {
781         return paletteHistogramSet;
782     }
783
784     // iCCP chunk
785

786     private byte[] ICCProfileData = null;
787     private boolean ICCProfileDataSet = false;
788
789     /**
790      * Sets the ICC profile data to be stored with this image.
791      * The profile is represented in raw binary form.
792      *
793      * <p> The 'iCCP' chunk will encode this information.
794      */

795     public void setICCProfileData(byte[] ICCProfileData) {
796         this.ICCProfileData = (byte[])(ICCProfileData.clone());
797         ICCProfileDataSet = true;
798     }
799
800     /**
801      * Returns the ICC profile data to be stored with this image.
802      *
803      * <p> If the ICC profile has not previously been set, or has been
804      * unset, an <code>IllegalStateException</code> will be thrown.
805      *
806      * @throws IllegalStateException if the ICC profile is not set.
807      */

808     public byte[] getICCProfileData() {
809         if (!ICCProfileDataSet) {
810             throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam15"));
811         }
812         return (byte[])(ICCProfileData.clone());
813     }
814
815     /**
816      * Suppresses the 'iCCP' chunk from being output.
817      */

818     public void unsetICCProfileData() {
819         ICCProfileData = null;
820         ICCProfileDataSet = false;
821     }
822
823     /**
824      * Returns true if a 'iCCP' chunk will be output.
825      */

826     public boolean isICCProfileDataSet() {
827         return ICCProfileDataSet;
828     }
829
830     // pHYS chunk
831

832     private int[] physicalDimension = null;
833     private boolean physicalDimensionSet = false;
834
835     /**
836      * Sets the physical dimension information to be stored with this
837      * image. The physicalDimension parameter should be a 3-entry
838      * array containing the number of pixels per unit in the X
839      * direction, the number of pixels per unit in the Y direction,
840      * and the unit specifier (0 = unknown, 1 = meters).
841      *
842      * <p> The 'pHYS' chunk will encode this information.
843      */

844     public void setPhysicalDimension(int[] physicalDimension) {
845         this.physicalDimension = (int[])(physicalDimension.clone());
846         physicalDimensionSet = true;
847     }
848
849     /**
850      * A convenience method that calls the array version.
851      */

852     public void setPhysicalDimension(int xPixelsPerUnit,
853                                      int yPixelsPerUnit,
854                                      int unitSpecifier) {
855         int[] pd = new int[3];
856         pd[0] = xPixelsPerUnit;
857         pd[1] = yPixelsPerUnit;
858         pd[2] = unitSpecifier;
859         
860         setPhysicalDimension(pd);
861     }
862
863     /**
864      * Returns the physical dimension information to be stored
865      * with this image.
866      *
867      * <p> If the physical dimension information has not previously
868      * been set, or has been unset, an
869      * <code>IllegalStateException</code> will be thrown.
870      *
871      * @throws IllegalStateException if the physical dimension information
872      * is not set.
873      */

874     public int[] getPhysicalDimension() {
875         if (!physicalDimensionSet) {
876             throw new IllegalStateException JavaDoc(PropertyUtil.getString("PNGEncodeParam16"));
877         }
878         return (int[])(physicalDimension.clone());
879     }
880
881     /**
882      * Suppresses the 'pHYS' chunk from being output.
883      */

884     public void unsetPhysicalDimension() {
885         physicalDimension = null;
886         physicalDimensionSet = false;
887     }
888
889     /**
890      * Returns true if a 'pHYS' chunk will be output.
891      */

892     public boolean isPhysicalDimensionSet() {
893         return physicalDimensionSet;
894     }
895
896     // sPLT chunk
897

898     private PNGSuggestedPaletteEntry[] suggestedPalette = null;
899     private boolean suggestedPaletteSet = false;
900
901     /**
902      * Sets the suggested palette information to be stored with this
903      * image. The information is passed to this method as an array of
904      * <code>PNGSuggestedPaletteEntry</code> objects.
905      *
906      * <p> The 'sPLT' chunk will encode this information.
907      */

908     public void setSuggestedPalette(PNGSuggestedPaletteEntry[] palette) {
909         suggestedPalette = (PNGSuggestedPaletteEntry[])(palette.clone());
910         suggestedPaletteSet = true;
911     }
912
913     /**
914      * Returns the suggested palette information to be stored with this
915      * image.
916      *
917      * <p> If the suggested palette information has not previously
918 &nb