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