1. /*
  2. * @(#)JPEGQTable.java 1.12 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. **********************************************************************
  9. **********************************************************************
  10. *** COPYRIGHT (c) 1997-1998 Eastman Kodak Company. ***
  11. *** As an unpublished work pursuant to Title 17 of the United ***
  12. *** States Code. All rights reserved. ***
  13. **********************************************************************
  14. **********************************************************************
  15. **********************************************************************/
  16. package javax.imageio.plugins.jpeg;
  17. /**
  18. * A class encapsulating a single JPEG quantization table. The
  19. * elements appear in natural order (as opposed to zig-zag order).
  20. * Static variables are provided for the "standard" tables taken from
  21. * Annex K of the JPEG spec, as well as the default tables
  22. * conventionally used for visually lossless encoding.
  23. *
  24. * <p>
  25. * For more information about the operation of the built-in JPEG plug-ins,
  26. * see the <A HREF="../../metadata/doc-files/jpeg_metadata.html">JPEG
  27. * metadata format specification and usage notes</A>.
  28. *
  29. * @version 0.5
  30. */
  31. public class JPEGQTable {
  32. /** Table */
  33. private int[] table;
  34. /** The number of coefficients in a quantization table. */
  35. private static final byte QTABLESIZE = 64;
  36. /**
  37. * The sample luminance quantization table given in the JPEG
  38. * specification, table K.1. According to the specification,
  39. * these values produce "good" quality output.
  40. *
  41. * @see #K1Div2Luminance
  42. */
  43. public static final JPEGQTable K1Luminance = new JPEGQTable();
  44. static {
  45. int [] lumVals = {
  46. 16, 11, 10, 16, 24, 40, 51, 61,
  47. 12, 12, 14, 19, 26, 58, 60, 55,
  48. 14, 13, 16, 24, 40, 57, 69, 56,
  49. 14, 17, 22, 29, 51, 87, 80, 62,
  50. 18, 22, 37, 56, 68, 109, 103, 77,
  51. 24, 35, 55, 64, 81, 104, 113, 92,
  52. 49, 64, 78, 87, 103, 121, 120, 101,
  53. 72, 92, 95, 98, 112, 100, 103, 99
  54. };
  55. K1Luminance.table = lumVals;
  56. }
  57. /**
  58. * The sample luminance quantization table given in the JPEG
  59. * specification, table K.1, with all elements divided by 2.
  60. * According to the specification, these values produce "very
  61. * good" quality output. This is the table usually used for
  62. * "visually lossless" encoding, and is the default luminance
  63. * table used if the default tables and quality settings are used.
  64. *
  65. * @see #K1Luminance
  66. */
  67. public static final JPEGQTable K1Div2Luminance =
  68. K1Luminance.getScaledInstance(0.5f, true);
  69. /**
  70. * The sample chrominance quantization table given in the JPEG
  71. * specification, table K.2. According to the specification,
  72. * these values produce "good" quality output.
  73. *
  74. * @see #K2Div2Chrominance
  75. */
  76. public static final JPEGQTable K2Chrominance = new JPEGQTable();
  77. static {
  78. int [] chromVals = {
  79. 17, 18, 24, 47, 99, 99, 99, 99,
  80. 18, 21, 26, 66, 99, 99, 99, 99,
  81. 24, 26, 56, 99, 99, 99, 99, 99,
  82. 47, 66, 99, 99, 99, 99, 99, 99,
  83. 99, 99, 99, 99, 99, 99, 99, 99,
  84. 99, 99, 99, 99, 99, 99, 99, 99,
  85. 99, 99, 99, 99, 99, 99, 99, 99,
  86. 99, 99, 99, 99, 99, 99, 99, 99
  87. };
  88. K2Chrominance.table = chromVals;
  89. }
  90. /**
  91. * The sample chrominance quantization table given in the JPEG
  92. * specification, table K.2, with all elements divided by 2.
  93. * According to the specification, these values produce "very
  94. * good" quality output. This is the table usually used for
  95. * "visually lossless" encoding, and is the default chrominance
  96. * table used if the default tables and quality settings are used.
  97. *
  98. * @see #K2Chrominance
  99. */
  100. public static final JPEGQTable K2Div2Chrominance =
  101. K2Chrominance.getScaledInstance(0.5f, true);
  102. /**
  103. * Constructs an empty quantization table. This is used to create
  104. * the standard tables.
  105. */
  106. private JPEGQTable() {}
  107. /**
  108. * Constructs a quantization table from the argument, which must
  109. * contain 64 elements in natural order (not zig-zag order).
  110. * A copy is made of the the input array.
  111. *
  112. * @param table the quantization table, as an <code>int</code>
  113. * array.
  114. *
  115. * @exception IllegalArgumentException if <code>table</code> is
  116. * <code>null</code> or <code>table.length</code> is not equal to
  117. * 64.
  118. */
  119. public JPEGQTable(int[] table) {
  120. if (table == null) {
  121. throw new IllegalArgumentException("table == null!");
  122. }
  123. if (table.length != QTABLESIZE) {
  124. throw new IllegalArgumentException
  125. ("Quantization table is the wrong size.");
  126. }
  127. this.table = (int[])table.clone();
  128. }
  129. /**
  130. * Returns a copy of the current quantization table as an array of
  131. * ints in natural (not zig-zag) order.
  132. *
  133. * @return A copy of the current quantization table.
  134. */
  135. public int[] getTable() {
  136. return (int[])table.clone();
  137. }
  138. /**
  139. * Returns a new quantization table where the values are
  140. * multiplied by <code>scaleFactor</code> and then clamped to the
  141. * range 1..32767 (or to 1..255 if <code>forceBaseline</code> is
  142. * <code>true</code>).
  143. *
  144. * <p> Values of <code>scaleFactorless</code> than 1 tend to
  145. * improve the quality level of the table, and values greater than
  146. * <code>1.0</code> degrade the quality level of the table.
  147. * @param scaleFactor the multiplicative factor for the table.
  148. * @param forceBaseline if <code>true</code>, the values will be
  149. * clamped to the range 1..255.
  150. *
  151. * @return a new quantization table that is a linear multiple of
  152. * the current table.
  153. */
  154. public JPEGQTable getScaledInstance(float scaleFactor,
  155. boolean forceBaseline) {
  156. int max = (forceBaseline) ? 255 : 32767;
  157. int[] ret = new int[QTABLESIZE];
  158. for (int i = 0; i < QTABLESIZE; i++) {
  159. float scaledValue = (float)Math.round(table[i]*scaleFactor);
  160. int holder;
  161. // limit to valid range
  162. if (scaledValue <= 1.0F) {
  163. holder = 1;
  164. } else if (scaledValue >= max) {
  165. holder = max;
  166. } else {
  167. holder = (int)scaledValue;
  168. }
  169. ret[i] = holder;
  170. }
  171. return new JPEGQTable(ret);
  172. }
  173. public String toString() {
  174. StringBuffer sb = new StringBuffer();
  175. sb.append("JPEGQTable:\n");
  176. for (int i = 0; i< 8; i++) {
  177. sb.append('\t');
  178. for (int j = 0; j < 8; j++) {
  179. sb.append(table[i]).append(" ");
  180. }
  181. sb.append('\n');
  182. }
  183. return sb.toString();
  184. }
  185. }