| /* |
| * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package javax.imageio.plugins.jpeg; |
| |
| import java.util.Locale; |
| import javax.imageio.ImageWriteParam; |
| |
| import com.sun.imageio.plugins.jpeg.JPEG; |
| |
| /** |
| * This class adds the ability to set JPEG quantization and Huffman |
| * tables when using the built-in JPEG writer plug-in, and to request that |
| * optimized Huffman tables be computed for an image. An instance of |
| * this class will be returned from the |
| * <code>getDefaultImageWriteParam</code> methods of the built-in JPEG |
| * <code>ImageWriter</code>. |
| |
| * <p> The principal purpose of these additions is to allow the |
| * specification of tables to use in encoding abbreviated streams. |
| * The built-in JPEG writer will also accept an ordinary |
| * <code>ImageWriteParam</code>, in which case the writer will |
| * construct the necessary tables internally. |
| * |
| * <p> In either case, the quality setting in an <code>ImageWriteParam</code> |
| * has the same meaning as for the underlying library: 1.00 means a |
| * quantization table of all 1's, 0.75 means the "standard", visually |
| * lossless quantization table, and 0.00 means aquantization table of |
| * all 255's. |
| * |
| * <p> While tables for abbreviated streams are often specified by |
| * first writing an abbreviated stream containing only the tables, in |
| * some applications the tables are fixed ahead of time. This class |
| * allows the tables to be specified directly from client code. |
| * |
| * <p> Normally, the tables are specified in the |
| * <code>IIOMetadata</code> objects passed in to the writer, and any |
| * tables included in these objects are written to the stream. |
| * If no tables are specified in the metadata, then an abbreviated |
| * stream is written. If no tables are included in the metadata and |
| * no tables are specified in a <code>JPEGImageWriteParam</code>, then |
| * an abbreviated stream is encoded using the "standard" visually |
| * lossless tables. This class is necessary for specifying tables |
| * when an abbreviated stream must be written without writing any tables |
| * to a stream first. In order to use this class, the metadata object |
| * passed into the writer must contain no tables, and no stream metadata |
| * must be provided. See {@link JPEGQTable <code>JPEGQTable</code>} and |
| * {@link JPEGHuffmanTable <code>JPEGHuffmanTable</code>} for more |
| * information on the default tables. |
| * |
| * <p> The default <code>JPEGImageWriteParam</code> returned by the |
| * <code>getDefaultWriteParam</code> method of the writer contains no |
| * tables. Default tables are included in the default |
| * <code>IIOMetadata</code> objects returned by the writer. |
| * |
| * <p> If the metadata does contain tables, the tables given in a |
| * <code>JPEGImageWriteParam</code> are ignored. Furthermore, once a |
| * set of tables has been written, only tables in the metadata can |
| * override them for subsequent writes, whether to the same stream or |
| * a different one. In order to specify new tables using this class, |
| * the {@link javax.imageio.ImageWriter#reset <code>reset</code>} |
| * method of the writer must be called. |
| * |
| * <p> |
| * For more information about the operation of the built-in JPEG plug-ins, |
| * see the <A HREF="../../metadata/doc-files/jpeg_metadata.html">JPEG |
| * metadata format specification and usage notes</A>. |
| * |
| */ |
| public class JPEGImageWriteParam extends ImageWriteParam { |
| |
| private JPEGQTable[] qTables = null; |
| private JPEGHuffmanTable[] DCHuffmanTables = null; |
| private JPEGHuffmanTable[] ACHuffmanTables = null; |
| private boolean optimizeHuffman = false; |
| private String[] compressionNames = {"JPEG"}; |
| private float[] qualityVals = { 0.00F, 0.30F, 0.75F, 1.00F }; |
| private String[] qualityDescs = { |
| "Low quality", // 0.00 -> 0.30 |
| "Medium quality", // 0.30 -> 0.75 |
| "Visually lossless" // 0.75 -> 1.00 |
| }; |
| |
| /** |
| * Constructs a <code>JPEGImageWriteParam</code>. Tiling is not |
| * supported. Progressive encoding is supported. The default |
| * progressive mode is MODE_DISABLED. A single form of compression, |
| * named "JPEG", is supported. The default compression quality is |
| * 0.75. |
| * |
| * @param locale a <code>Locale</code> to be used by the |
| * superclass to localize compression type names and quality |
| * descriptions, or <code>null</code>. |
| */ |
| public JPEGImageWriteParam(Locale locale) { |
| super(locale); |
| this.canWriteProgressive = true; |
| this.progressiveMode = MODE_DISABLED; |
| this.canWriteCompressed = true; |
| this.compressionTypes = compressionNames; |
| this.compressionType = compressionTypes[0]; |
| this.compressionQuality = JPEG.DEFAULT_QUALITY; |
| } |
| |
| /** |
| * Removes any previous compression quality setting. |
| * |
| * <p> The default implementation resets the compression quality |
| * to <code>0.75F</code>. |
| * |
| * @exception IllegalStateException if the compression mode is not |
| * <code>MODE_EXPLICIT</code>. |
| */ |
| public void unsetCompression() { |
| if (getCompressionMode() != MODE_EXPLICIT) { |
| throw new IllegalStateException |
| ("Compression mode not MODE_EXPLICIT!"); |
| } |
| this.compressionQuality = JPEG.DEFAULT_QUALITY; |
| } |
| |
| /** |
| * Returns <code>false</code> since the JPEG plug-in only supports |
| * lossy compression. |
| * |
| * @return <code>false</code>. |
| * |
| * @exception IllegalStateException if the compression mode is not |
| * <code>MODE_EXPLICIT</code>. |
| */ |
| public boolean isCompressionLossless() { |
| if (getCompressionMode() != MODE_EXPLICIT) { |
| throw new IllegalStateException |
| ("Compression mode not MODE_EXPLICIT!"); |
| } |
| return false; |
| } |
| |
| public String[] getCompressionQualityDescriptions() { |
| if (getCompressionMode() != MODE_EXPLICIT) { |
| throw new IllegalStateException |
| ("Compression mode not MODE_EXPLICIT!"); |
| } |
| if ((getCompressionTypes() != null) && |
| (getCompressionType() == null)) { |
| throw new IllegalStateException("No compression type set!"); |
| } |
| return (String[])qualityDescs.clone(); |
| } |
| |
| public float[] getCompressionQualityValues() { |
| if (getCompressionMode() != MODE_EXPLICIT) { |
| throw new IllegalStateException |
| ("Compression mode not MODE_EXPLICIT!"); |
| } |
| if ((getCompressionTypes() != null) && |
| (getCompressionType() == null)) { |
| throw new IllegalStateException("No compression type set!"); |
| } |
| return (float[])qualityVals.clone(); |
| } |
| /** |
| * Returns <code>true</code> if tables are currently set. |
| * |
| * @return <code>true</code> if tables are present. |
| */ |
| public boolean areTablesSet() { |
| return (qTables != null); |
| } |
| |
| /** |
| * Sets the quantization and Huffman tables to use in encoding |
| * abbreviated streams. There may be a maximum of 4 tables of |
| * each type. These tables are ignored if tables are specified in |
| * the metadata. All arguments must be non-<code>null</code>. |
| * The two arrays of Huffman tables must have the same number of |
| * elements. The table specifiers in the frame and scan headers |
| * in the metadata are assumed to be equivalent to indices into |
| * these arrays. The argument arrays are copied by this method. |
| * |
| * @param qTables An array of quantization table objects. |
| * @param DCHuffmanTables An array of Huffman table objects. |
| * @param ACHuffmanTables An array of Huffman table objects. |
| * |
| * @exception IllegalArgumentException if any of the arguments |
| * is <code>null</code> or has more than 4 elements, or if the |
| * numbers of DC and AC tables differ. |
| * |
| * @see #unsetEncodeTables |
| */ |
| public void setEncodeTables(JPEGQTable[] qTables, |
| JPEGHuffmanTable[] DCHuffmanTables, |
| JPEGHuffmanTable[] ACHuffmanTables) { |
| if ((qTables == null) || |
| (DCHuffmanTables == null) || |
| (ACHuffmanTables == null) || |
| (qTables.length > 4) || |
| (DCHuffmanTables.length > 4) || |
| (ACHuffmanTables.length > 4) || |
| (DCHuffmanTables.length != ACHuffmanTables.length)) { |
| throw new IllegalArgumentException("Invalid JPEG table arrays"); |
| } |
| this.qTables = (JPEGQTable[])qTables.clone(); |
| this.DCHuffmanTables = (JPEGHuffmanTable[])DCHuffmanTables.clone(); |
| this.ACHuffmanTables = (JPEGHuffmanTable[])ACHuffmanTables.clone(); |
| } |
| |
| /** |
| * Removes any quantization and Huffman tables that are currently |
| * set. |
| * |
| * @see #setEncodeTables |
| */ |
| public void unsetEncodeTables() { |
| this.qTables = null; |
| this.DCHuffmanTables = null; |
| this.ACHuffmanTables = null; |
| } |
| |
| /** |
| * Returns a copy of the array of quantization tables set on the |
| * most recent call to <code>setEncodeTables</code>, or |
| * <code>null</code> if tables are not currently set. |
| * |
| * @return an array of <code>JPEGQTable</code> objects, or |
| * <code>null</code>. |
| * |
| * @see #setEncodeTables |
| */ |
| public JPEGQTable[] getQTables() { |
| return (qTables != null) ? (JPEGQTable[])qTables.clone() : null; |
| } |
| |
| /** |
| * Returns a copy of the array of DC Huffman tables set on the |
| * most recent call to <code>setEncodeTables</code>, or |
| * <code>null</code> if tables are not currently set. |
| * |
| * @return an array of <code>JPEGHuffmanTable</code> objects, or |
| * <code>null</code>. |
| * |
| * @see #setEncodeTables |
| */ |
| public JPEGHuffmanTable[] getDCHuffmanTables() { |
| return (DCHuffmanTables != null) |
| ? (JPEGHuffmanTable[])DCHuffmanTables.clone() |
| : null; |
| } |
| |
| /** |
| * Returns a copy of the array of AC Huffman tables set on the |
| * most recent call to <code>setEncodeTables</code>, or |
| * <code>null</code> if tables are not currently set. |
| * |
| * @return an array of <code>JPEGHuffmanTable</code> objects, or |
| * <code>null</code>. |
| * |
| * @see #setEncodeTables |
| */ |
| public JPEGHuffmanTable[] getACHuffmanTables() { |
| return (ACHuffmanTables != null) |
| ? (JPEGHuffmanTable[])ACHuffmanTables.clone() |
| : null; |
| } |
| |
| /** |
| * Tells the writer to generate optimized Huffman tables |
| * for the image as part of the writing process. The |
| * default is <code>false</code>. If this flag is set |
| * to <code>true</code>, it overrides any tables specified |
| * in the metadata. Note that this means that any image |
| * written with this flag set to <code>true</code> will |
| * always contain Huffman tables. |
| * |
| * @param optimize A boolean indicating whether to generate |
| * optimized Huffman tables when writing. |
| * |
| * @see #getOptimizeHuffmanTables |
| */ |
| public void setOptimizeHuffmanTables(boolean optimize) { |
| optimizeHuffman = optimize; |
| } |
| |
| /** |
| * Returns the value passed into the most recent call |
| * to <code>setOptimizeHuffmanTables</code>, or |
| * <code>false</code> if <code>setOptimizeHuffmanTables</code> |
| * has never been called. |
| * |
| * @return <code>true</code> if the writer will generate optimized |
| * Huffman tables. |
| * |
| * @see #setOptimizeHuffmanTables |
| */ |
| public boolean getOptimizeHuffmanTables() { |
| return optimizeHuffman; |
| } |
| } |