KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > imageio > plugins > jpeg > JPEGImageWriteParam


1 /*
2  * @(#)JPEGImageWriteParam.java 1.18 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.imageio.plugins.jpeg;
9
10 import java.util.Locale JavaDoc;
11 import javax.imageio.ImageWriteParam JavaDoc;
12
13 import com.sun.imageio.plugins.jpeg.JPEG;
14
15 /**
16  * This class adds the ability to set JPEG quantization and Huffman
17  * tables when using the built-in JPEG writer plug-in, and to request that
18  * optimized Huffman tables be computed for an image. An instance of
19  * this class will be returned from the
20  * <code>getDefaultImageWriteParam</code> methods of the built-in JPEG
21  * <code>ImageWriter</code>.
22
23  * <p> The principal purpose of these additions is to allow the
24  * specification of tables to use in encoding abbreviated streams.
25  * The built-in JPEG writer will also accept an ordinary
26  * <code>ImageWriteParam</code>, in which case the writer will
27  * construct the necessary tables internally.
28  *
29  * <p> In either case, the quality setting in an <code>ImageWriteParam</code>
30  * has the same meaning as for the underlying library: 1.00 means a
31  * quantization table of all 1's, 0.75 means the "standard", visually
32  * lossless quantization table, and 0.00 means aquantization table of
33  * all 255's.
34  *
35  * <p> While tables for abbreviated streams are often specified by
36  * first writing an abbreviated stream containing only the tables, in
37  * some applications the tables are fixed ahead of time. This class
38  * allows the tables to be specified directly from client code.
39  *
40  * <p> Normally, the tables are specified in the
41  * <code>IIOMetadata</code> objects passed in to the writer, and any
42  * tables included in these objects are written to the stream.
43  * If no tables are specified in the metadata, then an abbreviated
44  * stream is written. If no tables are included in the metadata and
45  * no tables are specified in a <code>JPEGImageWriteParam</code>, then
46  * an abbreviated stream is encoded using the "standard" visually
47  * lossless tables. This class is necessary for specifying tables
48  * when an abbreviated stream must be written without writing any tables
49  * to a stream first. In order to use this class, the metadata object
50  * passed into the writer must contain no tables, and no stream metadata
51  * must be provided. See {@link JPEGQTable <code>JPEGQTable</code>} and
52  * {@link JPEGHuffmanTable <code>JPEGHuffmanTable</code>} for more
53  * information on the default tables.
54  *
55  * <p> The default <code>JPEGImageWriteParam</code> returned by the
56  * <code>getDefaultWriteParam</code> method of the writer contains no
57  * tables. Default tables are included in the default
58  * <code>IIOMetadata</code> objects returned by the writer.
59  *
60  * <p> If the metadata does contain tables, the tables given in a
61  * <code>JPEGImageWriteParam</code> are ignored. Furthermore, once a
62  * set of tables has been written, only tables in the metadata can
63  * override them for subsequent writes, whether to the same stream or
64  * a different one. In order to specify new tables using this class,
65  * the {@link javax.imageio.ImageWriter#reset <code>reset</code>}
66  * method of the writer must be called.
67  *
68  * <p>
69  * For more information about the operation of the built-in JPEG plug-ins,
70  * see the <A HREF="../../metadata/doc-files/jpeg_metadata.html">JPEG
71  * metadata format specification and usage notes</A>.
72  *
73  * @version 0.5
74  */

75 public class JPEGImageWriteParam extends ImageWriteParam JavaDoc {
76
77     private JPEGQTable JavaDoc[] qTables = null;
78     private JPEGHuffmanTable JavaDoc[] DCHuffmanTables = null;
79     private JPEGHuffmanTable JavaDoc[] ACHuffmanTables = null;
80     private boolean optimizeHuffman = false;
81     private String JavaDoc[] compressionNames = {"JPEG"};
82     private float[] qualityVals = { 0.05F, 0.75F, 0.95F };
83     private String JavaDoc[] qualityDescs = { "Minimum useful", // .05
84
"Visually lossless", // .75
85
"Maximum useful" // .95
86
};
87
88     /**
89      * Constructs a <code>JPEGImageWriteParam</code>. Tiling is not
90      * supported. Progressive encoding is supported. The default
91      * progressive mode is MODE_DISABLED. A single form of compression,
92      * named "JPEG", is supported. The default compression quality is
93      * 0.75.
94      *
95      * @param locale a <code>Locale</code> to be used by the
96      * superclass to localize compression type names and quality
97      * descriptions, or <code>null</code>.
98      */

99     public JPEGImageWriteParam(Locale JavaDoc locale) {
100         super(locale);
101         this.canWriteProgressive = true;
102         this.progressiveMode = MODE_DISABLED;
103         this.canWriteCompressed = true;
104         this.compressionTypes = compressionNames;
105         this.compressionType = compressionTypes[0];
106         this.compressionQuality = JPEG.DEFAULT_QUALITY;
107     }
108
109     /**
110      * Removes any previous compression quality setting.
111      *
112      * <p> The default implementation resets the compression quality
113      * to <code>0.75F</code>.
114      *
115      * @exception IllegalStateException if the compression mode is not
116      * <code>MODE_EXPLICIT</code>.
117      */

118     public void unsetCompression() {
119         if (getCompressionMode() != MODE_EXPLICIT) {
120             throw new IllegalStateException JavaDoc
121                 ("Compression mode not MODE_EXPLICIT!");
122         }
123         this.compressionQuality = JPEG.DEFAULT_QUALITY;
124     }
125
126     /**
127      * Returns <code>false</code> since the JPEG plug-in only supports
128      * lossy compression.
129      *
130      * @return <code>false</code>.
131      *
132      * @exception IllegalStateException if the compression mode is not
133      * <code>MODE_EXPLICIT</code>.
134      */

135     public boolean isCompressionLossless() {
136         if (getCompressionMode() != MODE_EXPLICIT) {
137             throw new IllegalStateException JavaDoc
138                 ("Compression mode not MODE_EXPLICIT!");
139         }
140         return false;
141     }
142
143     public String JavaDoc[] getCompressionQualityDescriptions() {
144         if (getCompressionMode() != MODE_EXPLICIT) {
145             throw new IllegalStateException JavaDoc
146                 ("Compression mode not MODE_EXPLICIT!");
147         }
148         if ((getCompressionTypes() != null) &&
149             (getCompressionType() == null)) {
150             throw new IllegalStateException JavaDoc("No compression type set!");
151         }
152         return (String JavaDoc[])qualityDescs.clone();
153     }
154
155     public float[] getCompressionQualityValues() {
156         if (getCompressionMode() != MODE_EXPLICIT) {
157             throw new IllegalStateException JavaDoc
158                 ("Compression mode not MODE_EXPLICIT!");
159         }
160         if ((getCompressionTypes() != null) &&
161             (getCompressionType() == null)) {
162             throw new IllegalStateException JavaDoc("No compression type set!");
163         }
164         return (float[])qualityVals.clone();
165     }
166     /**
167      * Returns <code>true</code> if tables are currently set.
168      *
169      * @return <code>true</code> if tables are present.
170      */

171     public boolean areTablesSet() {
172         return (qTables != null);
173     }
174
175     /**
176      * Sets the quantization and Huffman tables to use in encoding
177      * abbreviated streams. There may be a maximum of 4 tables of
178      * each type. These tables are ignored if tables are specified in
179      * the metadata. All arguments must be non-<code>null</code>.
180      * The two arrays of Huffman tables must have the same number of
181      * elements. The table specifiers in the frame and scan headers
182      * in the metadata are assumed to be equivalent to indices into
183      * these arrays. The argument arrays are copied by this method.
184      *
185      * @param qTables An array of quantization table objects.
186      * @param DCHuffmanTables An array of Huffman table objects.
187      * @param ACHuffmanTables An array of Huffman table objects.
188      *
189      * @exception IllegalArgumentException if any of the arguments
190      * is <code>null</code> or has more than 4 elements, or if the
191      * numbers of DC and AC tables differ.
192      *
193      * @see #unsetEncodeTables
194      */

195     public void setEncodeTables(JPEGQTable JavaDoc[] qTables,
196                                 JPEGHuffmanTable JavaDoc[] DCHuffmanTables,
197                                 JPEGHuffmanTable JavaDoc[] ACHuffmanTables) {
198         if ((qTables == null) ||
199             (DCHuffmanTables == null) ||
200             (ACHuffmanTables == null) ||
201             (qTables.length > 4) ||
202             (DCHuffmanTables.length > 4) ||
203             (ACHuffmanTables.length > 4) ||
204             (DCHuffmanTables.length != ACHuffmanTables.length)) {
205                 throw new IllegalArgumentException JavaDoc("Invalid JPEG table arrays");
206         }
207         this.qTables = (JPEGQTable JavaDoc[])qTables.clone();
208         this.DCHuffmanTables = (JPEGHuffmanTable JavaDoc[])DCHuffmanTables.clone();
209         this.ACHuffmanTables = (JPEGHuffmanTable JavaDoc[])ACHuffmanTables.clone();
210     }
211
212     /**
213      * Removes any quantization and Huffman tables that are currently
214      * set.
215      *
216      * @see #setEncodeTables
217      */

218     public void unsetEncodeTables() {
219         this.qTables = null;
220         this.DCHuffmanTables = null;
221         this.ACHuffmanTables = null;
222     }
223
224     /**
225      * Returns a copy of the array of quantization tables set on the
226      * most recent call to <code>setEncodeTables</code>, or
227      * <code>null</code> if tables are not currently set.
228      *
229      * @return an array of <code>JPEGQTable</code> objects, or
230      * <code>null</code>.
231      *
232      * @see #setEncodeTables
233      */

234     public JPEGQTable JavaDoc[] getQTables() {
235         return (qTables != null) ? (JPEGQTable JavaDoc[])qTables.clone() : null;
236     }
237     
238     /**
239      * Returns a copy of the array of DC Huffman tables set on the
240      * most recent call to <code>setEncodeTables</code>, or
241      * <code>null</code> if tables are not currently set.
242      *
243      * @return an array of <code>JPEGHuffmanTable</code> objects, or
244      * <code>null</code>.
245      *
246      * @see #setEncodeTables
247      */

248     public JPEGHuffmanTable JavaDoc[] getDCHuffmanTables() {
249         return (DCHuffmanTables != null)
250             ? (JPEGHuffmanTable JavaDoc[])DCHuffmanTables.clone()
251             : null;
252     }
253
254     /**
255      * Returns a copy of the array of AC Huffman tables set on the
256      * most recent call to <code>setEncodeTables</code>, or
257      * <code>null</code> if tables are not currently set.
258      *
259      * @return an array of <code>JPEGHuffmanTable</code> objects, or
260      * <code>null</code>.
261      *
262      * @see #setEncodeTables
263      */

264     public JPEGHuffmanTable JavaDoc[] getACHuffmanTables() {
265         return (ACHuffmanTables != null)
266             ? (JPEGHuffmanTable JavaDoc[])ACHuffmanTables.clone()
267             : null;
268     }
269
270     /**
271      * Tells the writer to generate optimized Huffman tables
272      * for the image as part of the writing process. The
273      * default is <code>false</code>. If this flag is set
274      * to <code>true</code>, it overrides any tables specified
275      * in the metadata. Note that this means that any image
276      * written with this flag set to <code>true</code> will
277      * always contain Huffman tables.
278      *
279      * @param optimize A boolean indicating whether to generate
280      * optimized Huffman tables when writing.
281      *
282      * @see #getOptimizeHuffmanTables
283      */

284     public void setOptimizeHuffmanTables(boolean optimize) {
285         optimizeHuffman = optimize;
286     }
287
288     /**
289      * Returns the value passed into the most recent call
290      * to <code>setOptimizeHuffmanTables</code>, or
291      * <code>false</code> if <code>setOptimizeHuffmanTables</code>
292      * has never been called.
293      *
294      * @return <code>true</code> if the writer will generate optimized
295      * Huffman tables.
296      *
297      * @see #setOptimizeHuffmanTables
298      */

299     public boolean getOptimizeHuffmanTables() {
300         return optimizeHuffman;
301     }
302 }
303
Popular Tags