001 /* JPEGImageWriteParam.java --
002 Copyright (C) 2006 Free Software Foundation, Inc.
003
004 This file is part of GNU Classpath.
005
006 GNU Classpath is free software; you can redistribute it and/or modify
007 it under the terms of the GNU General Public License as published by
008 the Free Software Foundation; either version 2, or (at your option)
009 any later version.
010
011 GNU Classpath is distributed in the hope that it will be useful, but
012 WITHOUT ANY WARRANTY; without even the implied warranty of
013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 General Public License for more details.
015
016 You should have received a copy of the GNU General Public License
017 along with GNU Classpath; see the file COPYING. If not, write to the
018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019 02110-1301 USA.
020
021 Linking this library statically or dynamically with other modules is
022 making a combined work based on this library. Thus, the terms and
023 conditions of the GNU General Public License cover the whole
024 combination.
025
026 As a special exception, the copyright holders of this library give you
027 permission to link this library with independent modules to produce an
028 executable, regardless of the license terms of these independent
029 modules, and to copy and distribute the resulting executable under
030 terms of your choice, provided that you also meet, for each linked
031 independent module, the terms and conditions of the license of that
032 module. An independent module is a module which is not derived from
033 or based on this library. If you modify this library, you may extend
034 this exception to your version of the library, but you are not
035 obligated to do so. If you do not wish to do so, delete this
036 exception statement from your version. */
037
038
039 package javax.imageio.plugins.jpeg;
040
041 import java.util.Locale;
042 import java.util.PropertyResourceBundle;
043 import java.util.ResourceBundle;
044 import javax.imageio.ImageWriteParam;
045
046 /**
047 * The JPEGImageWriteParam class can be used to specify tables and
048 * settings used in the JPEG encoding process. Encoding tables are
049 * taken from the metadata associated with the output stream, and
050 * failing that (if the metadata tables are null) from an instance of
051 * JPEGImageWriteParam. The default metadata uses the standard JPEG
052 * tables from the JPEGQTable and JPEGHuffmanTable classes. Non-null
053 * metadata tables override JPEGImageWriteParam tables. Compression
054 * settings range from 1.0, best compression, through 0.75, default
055 * compression, to 0.0, worst compression.
056 *
057 * A JPEGImageWriteParam instance is retrieved from the built-in JPEG
058 * ImageWriter using the getDefaultImageWriteParam method.
059 */
060 public class JPEGImageWriteParam
061 extends ImageWriteParam
062 {
063 private JPEGQTable[] qTables;
064 private JPEGHuffmanTable[] DCHuffmanTables;
065 private JPEGHuffmanTable[] ACHuffmanTables;
066 private boolean optimize;
067 private String[] compressionQualityDescriptions;
068 private float[] compressionQualityValues;
069
070 /**
071 * Localized messages are stored in separate files.
072 */
073 private ResourceBundle messages;
074
075 /**
076 * Construct a JPEGImageWriteParam with the following state: tiling
077 * is not supported, progressive mode is supported, initial
078 * progressive mode is MODE_DISABLED, compression is supported, one
079 * compression type named "JPEG" is supported and the default
080 * compression quality is 0.75f. Compression type names and
081 * compression quality descriptions are localized to the given
082 * locale.
083 *
084 * @param locale the locale used for message localization
085 */
086 public JPEGImageWriteParam(Locale locale)
087 {
088 super(locale);
089
090 // Get localized compression type and compression quality
091 // description strings for the given locale.
092 messages = PropertyResourceBundle.getBundle
093 ("javax/imageio/plugins/jpeg/MessagesBundle", locale);
094
095 // Initialize inherited ImageWriter fields.
096 canWriteTiles = false;
097 canWriteProgressive = true;
098 progressiveMode = MODE_DISABLED;
099 canWriteCompressed = true;
100 compressionTypes = new String[]
101 {
102 messages.getString("compression.types.jpeg")
103 };
104 compressionType = compressionTypes[0];
105 compressionQuality = 0.75f;
106 }
107
108 /**
109 * Reset the compression quality to 0.75f.
110 */
111 public void unsetCompression()
112 {
113 compressionQuality = 0.75f;
114 }
115
116 /**
117 * Check if compression algorithm is lossless. JPEGImageWriteParam
118 * overrides this ImageWriteParam method to always return false
119 * since JPEG compression is inherently lossy.
120 *
121 * @return false
122 */
123 public boolean isCompressionLossless()
124 {
125 return false;
126 }
127
128 /**
129 * Retrieve an array of compression quality descriptions. These
130 * messages are localized using the locale provided upon
131 * construction. Each compression quality description in the
132 * returned array corresponds to the compression quality value at
133 * the same index in the array returned by
134 * getCompressionQualityValues.
135 *
136 * @return an array of strings each of which describes a compression
137 * quality value
138 */
139 public String[] getCompressionQualityDescriptions()
140 {
141 // Make sure exceptions are thrown when this image write param is
142 // in the wrong state.
143 super.getCompressionQualityDescriptions();
144
145 if (compressionQualityDescriptions == null)
146 {
147 compressionQualityDescriptions = new String[]
148 {
149 messages.getString("compression.minimum"),
150 messages.getString("compression.default"),
151 messages.getString("compression.maximum")
152 };
153 }
154
155 return compressionQualityDescriptions;
156 }
157
158 /**
159 * Retrieve an array of compression quality values, ordered from
160 * lowest quality to highest quality.
161 *
162 * @return an array of compressions quality values
163 */
164 public float[] getCompressionQualityValues()
165 {
166 // Make sure exceptions are thrown when this image write param is
167 // in the wrong state.
168 super.getCompressionQualityValues();
169
170 if (compressionQualityValues == null)
171 compressionQualityValues = new float[] { 0.05f, 0.75f, 0.95f };
172
173 return compressionQualityValues;
174 }
175
176 /**
177 * Check if the encoding tables are set.
178 *
179 * @return true if the encoding tables are set, false otherwise
180 */
181 public boolean areTablesSet()
182 {
183 // If qTables is not null then all tables are set.
184 return (qTables != null);
185 }
186
187 /**
188 * Set the quantization and Huffman tables that will be used to
189 * encode the stream. Copies are created of the array arguments.
190 * The number of Huffman tables must be the same in both Huffman
191 * table arrays. No argument may be null and no array may be longer
192 * than four elements.
193 *
194 * @param qTables JPEG quantization tables
195 * @param DCHuffmanTables JPEG DC Huffman tables
196 * @param ACHuffmanTables JPEG AC Huffman tables
197 *
198 * @throws IllegalArgumentException if any argument is null, if any
199 * of the arrays are longer than four elements, or if the Huffman
200 * table arrays do not have the same number of elements
201 */
202 public void setEncodeTables(JPEGQTable[] qTables,
203 JPEGHuffmanTable[] DCHuffmanTables,
204 JPEGHuffmanTable[] ACHuffmanTables)
205 {
206 if (qTables == null || DCHuffmanTables == null || ACHuffmanTables == null)
207 throw new IllegalArgumentException("null argument");
208
209 if (qTables.length > 4 || DCHuffmanTables.length > 4
210 || ACHuffmanTables.length > 4)
211 throw new IllegalArgumentException("argument has too many elements");
212
213 if (DCHuffmanTables.length != ACHuffmanTables.length)
214 throw new IllegalArgumentException("Huffman table arrays differ in length");
215
216 // Do a shallow copy. JPEGQTable's data is not directly
217 // modifyable since JPEGQTable.getTable returns a copy. Therefore
218 // it is safe to have multiple references to a single JPEGQTable.
219 // Likewise for JPEGHuffmanTable.
220 this.qTables = (JPEGQTable[]) qTables.clone();
221 this.DCHuffmanTables = (JPEGHuffmanTable[]) DCHuffmanTables.clone();
222 this.ACHuffmanTables = (JPEGHuffmanTable[]) ACHuffmanTables.clone();
223 }
224
225 /**
226 * Clear the quantization and Huffman encoding tables.
227 */
228 public void unsetEncodeTables()
229 {
230 qTables = null;
231 DCHuffmanTables = null;
232 ACHuffmanTables = null;
233 }
234
235 /**
236 * Retrieve the quantization tables.
237 *
238 * @returns an array of JPEG quantization tables
239 */
240 public JPEGQTable[] getQTables()
241 {
242 return qTables == null ? qTables : (JPEGQTable[]) qTables.clone();
243 }
244
245 /**
246 * Retrieve the DC Huffman tables.
247 *
248 * @return an array of JPEG DC Huffman tables
249 */
250 public JPEGHuffmanTable[] getDCHuffmanTables()
251 {
252 return DCHuffmanTables == null ? DCHuffmanTables
253 : (JPEGHuffmanTable[]) DCHuffmanTables.clone();
254 }
255
256 /**
257 * Retrieve the AC Huffman tables.
258 *
259 * @return an array of JPEG AC Huffman tables
260 */
261 public JPEGHuffmanTable[] getACHuffmanTables()
262 {
263 return ACHuffmanTables == null ? ACHuffmanTables
264 : (JPEGHuffmanTable[]) ACHuffmanTables.clone();
265 }
266
267 /**
268 * Specify whether or not Huffman tables written to the output
269 * stream should be optimized. Every image encoded with this flag
270 * set will contain a Huffman table, and the generated Huffman
271 * tables will override those specified in the metadata.
272 *
273 * @param optimize true to generate optimized Huffman tables, false
274 * otherwise
275 */
276 public void setOptimizeHuffmanTables(boolean optimize)
277 {
278 this.optimize = optimize;
279 }
280
281 /**
282 * Check whether or not Huffman tables written to the output stream
283 * will be optimized. Unless otherwise set using
284 * setOptimizeHuffmanTables, this returns false.
285 *
286 * @return true Huffman tables written to the output stream will be
287 * optimized, false otherwise
288 */
289 public boolean getOptimizeHuffmanTables()
290 {
291 return optimize;
292 }
293 }