/* * @(#)JPEGQTable.java 1.12 03/12/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ /********************************************************************** ********************************************************************** ********************************************************************** *** COPYRIGHT (c) 1997-1998 Eastman Kodak Company. *** *** As an unpublished work pursuant to Title 17 of the United *** *** States Code. All rights reserved. *** ********************************************************************** ********************************************************************** **********************************************************************/ package javax.imageio.plugins.jpeg; /** * A class encapsulating a single JPEG quantization table. The * elements appear in natural order (as opposed to zig-zag order). * Static variables are provided for the "standard" tables taken from * Annex K of the JPEG spec, as well as the default tables * conventionally used for visually lossless encoding. * *

* For more information about the operation of the built-in JPEG plug-ins, * see the JPEG * metadata format specification and usage notes. * * @version 0.5 */ public class JPEGQTable { /** Table */ private int[] table; /** The number of coefficients in a quantization table. */ private static final byte QTABLESIZE = 64; /** * The sample luminance quantization table given in the JPEG * specification, table K.1. According to the specification, * these values produce "good" quality output. * * @see #K1Div2Luminance */ public static final JPEGQTable K1Luminance = new JPEGQTable(); static { int [] lumVals = { 16, 11, 10, 16, 24, 40, 51, 61, 12, 12, 14, 19, 26, 58, 60, 55, 14, 13, 16, 24, 40, 57, 69, 56, 14, 17, 22, 29, 51, 87, 80, 62, 18, 22, 37, 56, 68, 109, 103, 77, 24, 35, 55, 64, 81, 104, 113, 92, 49, 64, 78, 87, 103, 121, 120, 101, 72, 92, 95, 98, 112, 100, 103, 99 }; K1Luminance.table = lumVals; } /** * The sample luminance quantization table given in the JPEG * specification, table K.1, with all elements divided by 2. * According to the specification, these values produce "very * good" quality output. This is the table usually used for * "visually lossless" encoding, and is the default luminance * table used if the default tables and quality settings are used. * * @see #K1Luminance */ public static final JPEGQTable K1Div2Luminance = K1Luminance.getScaledInstance(0.5f, true); /** * The sample chrominance quantization table given in the JPEG * specification, table K.2. According to the specification, * these values produce "good" quality output. * * @see #K2Div2Chrominance */ public static final JPEGQTable K2Chrominance = new JPEGQTable(); static { int [] chromVals = { 17, 18, 24, 47, 99, 99, 99, 99, 18, 21, 26, 66, 99, 99, 99, 99, 24, 26, 56, 99, 99, 99, 99, 99, 47, 66, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 }; K2Chrominance.table = chromVals; } /** * The sample chrominance quantization table given in the JPEG * specification, table K.2, with all elements divided by 2. * According to the specification, these values produce "very * good" quality output. This is the table usually used for * "visually lossless" encoding, and is the default chrominance * table used if the default tables and quality settings are used. * * @see #K2Chrominance */ public static final JPEGQTable K2Div2Chrominance = K2Chrominance.getScaledInstance(0.5f, true); /** * Constructs an empty quantization table. This is used to create * the standard tables. */ private JPEGQTable() {} /** * Constructs a quantization table from the argument, which must * contain 64 elements in natural order (not zig-zag order). * A copy is made of the the input array. * * @param table the quantization table, as an int * array. * * @exception IllegalArgumentException if table is * null or table.length is not equal to * 64. */ public JPEGQTable(int[] table) { if (table == null) { throw new IllegalArgumentException("table == null!"); } if (table.length != QTABLESIZE) { throw new IllegalArgumentException ("Quantization table is the wrong size."); } this.table = (int[])table.clone(); } /** * Returns a copy of the current quantization table as an array of * ints in natural (not zig-zag) order. * * @return A copy of the current quantization table. */ public int[] getTable() { return (int[])table.clone(); } /** * Returns a new quantization table where the values are * multiplied by scaleFactor and then clamped to the * range 1..32767 (or to 1..255 if forceBaseline is * true). * *

Values of scaleFactorless than 1 tend to * improve the quality level of the table, and values greater than * 1.0 degrade the quality level of the table. * @param scaleFactor the multiplicative factor for the table. * @param forceBaseline if true, the values will be * clamped to the range 1..255. * * @return a new quantization table that is a linear multiple of * the current table. */ public JPEGQTable getScaledInstance(float scaleFactor, boolean forceBaseline) { int max = (forceBaseline) ? 255 : 32767; int[] ret = new int[QTABLESIZE]; for (int i = 0; i < QTABLESIZE; i++) { float scaledValue = (float)Math.round(table[i]*scaleFactor); int holder; // limit to valid range if (scaledValue <= 1.0F) { holder = 1; } else if (scaledValue >= max) { holder = max; } else { holder = (int)scaledValue; } ret[i] = holder; } return new JPEGQTable(ret); } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("JPEGQTable:\n"); for (int i = 0; i< 8; i++) { sb.append('\t'); for (int j = 0; j < 8; j++) { sb.append(table[i]).append(" "); } sb.append('\n'); } return sb.toString(); } }