/*
* Copyright (c) 2000, 2010, 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 com.sun.imageio.plugins.jpeg;
import javax.imageio.metadata.IIOMetadataFormatImpl;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.plugins.jpeg.JPEGQTable;
import javax.imageio.plugins.jpeg.JPEGHuffmanTable;
import java.awt.image.ColorModel;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
A class containing JPEG-related constants, definitions, and
static methods. This class and its constants must be public so that
JPEGImageWriteParam
can see it.
/**
* A class containing JPEG-related constants, definitions, and
* static methods. This class and its constants must be public so that
* <code>JPEGImageWriteParam</code> can see it.
*/
public class JPEG {
// List of all the JPEG markers (pre-JPEG2000)
For temporary use in arithmetic coding /** For temporary use in arithmetic coding */
public static final int TEM = 0x01;
// Codes 0x02 - 0xBF are reserved
// SOF markers for Nondifferential Huffman coding
Baseline DCT /** Baseline DCT */
public static final int SOF0 = 0xC0;
Extended Sequential DCT /** Extended Sequential DCT */
public static final int SOF1 = 0xC1;
Progressive DCT /** Progressive DCT */
public static final int SOF2 = 0xC2;
Lossless Sequential /** Lossless Sequential */
public static final int SOF3 = 0xC3;
Define Huffman Tables /** Define Huffman Tables */
public static final int DHT = 0xC4;
// SOF markers for Differential Huffman coding
Differential Sequential DCT /** Differential Sequential DCT */
public static final int SOF5 = 0xC5;
Differential Progressive DCT /** Differential Progressive DCT */
public static final int SOF6 = 0xC6;
Differential Lossless /** Differential Lossless */
public static final int SOF7 = 0xC7;
Reserved for JPEG extensions /** Reserved for JPEG extensions */
public static final int JPG = 0xC8;
// SOF markers for Nondifferential arithmetic coding
Extended Sequential DCT, Arithmetic coding /** Extended Sequential DCT, Arithmetic coding */
public static final int SOF9 = 0xC9;
Progressive DCT, Arithmetic coding /** Progressive DCT, Arithmetic coding */
public static final int SOF10 = 0xCA;
Lossless Sequential, Arithmetic coding /** Lossless Sequential, Arithmetic coding */
public static final int SOF11 = 0xCB;
Define Arithmetic conditioning tables /** Define Arithmetic conditioning tables */
public static final int DAC = 0xCC;
// SOF markers for Differential arithmetic coding
Differential Sequential DCT, Arithmetic coding /** Differential Sequential DCT, Arithmetic coding */
public static final int SOF13 = 0xCD;
Differential Progressive DCT, Arithmetic coding /** Differential Progressive DCT, Arithmetic coding */
public static final int SOF14 = 0xCE;
Differential Lossless, Arithmetic coding /** Differential Lossless, Arithmetic coding */
public static final int SOF15 = 0xCF;
// Restart Markers
public static final int RST0 = 0xD0;
public static final int RST1 = 0xD1;
public static final int RST2 = 0xD2;
public static final int RST3 = 0xD3;
public static final int RST4 = 0xD4;
public static final int RST5 = 0xD5;
public static final int RST6 = 0xD6;
public static final int RST7 = 0xD7;
Number of restart markers /** Number of restart markers */
public static final int RESTART_RANGE = 8;
Start of Image /** Start of Image */
public static final int SOI = 0xD8;
End of Image /** End of Image */
public static final int EOI = 0xD9;
Start of Scan /** Start of Scan */
public static final int SOS = 0xDA;
Define Quantisation Tables /** Define Quantisation Tables */
public static final int DQT = 0xDB;
Define Number of lines /** Define Number of lines */
public static final int DNL = 0xDC;
Define Restart Interval /** Define Restart Interval */
public static final int DRI = 0xDD;
Define Heirarchical progression /** Define Heirarchical progression */
public static final int DHP = 0xDE;
Expand reference image(s) /** Expand reference image(s) */
public static final int EXP = 0xDF;
// Application markers
APP0 used by JFIF /** APP0 used by JFIF */
public static final int APP0 = 0xE0;
public static final int APP1 = 0xE1;
public static final int APP2 = 0xE2;
public static final int APP3 = 0xE3;
public static final int APP4 = 0xE4;
public static final int APP5 = 0xE5;
public static final int APP6 = 0xE6;
public static final int APP7 = 0xE7;
public static final int APP8 = 0xE8;
public static final int APP9 = 0xE9;
public static final int APP10 = 0xEA;
public static final int APP11 = 0xEB;
public static final int APP12 = 0xEC;
public static final int APP13 = 0xED;
APP14 used by Adobe /** APP14 used by Adobe */
public static final int APP14 = 0xEE;
public static final int APP15 = 0xEF;
// codes 0xF0 to 0xFD are reserved
Comment marker /** Comment marker */
public static final int COM = 0xFE;
// JFIF Resolution units
The X and Y units simply indicate the aspect ratio of the pixels. /** The X and Y units simply indicate the aspect ratio of the pixels. */
public static final int DENSITY_UNIT_ASPECT_RATIO = 0;
Pixel density is in pixels per inch. /** Pixel density is in pixels per inch. */
public static final int DENSITY_UNIT_DOTS_INCH = 1;
Pixel density is in pixels per centemeter. /** Pixel density is in pixels per centemeter. */
public static final int DENSITY_UNIT_DOTS_CM = 2;
The max known value for DENSITY_UNIT /** The max known value for DENSITY_UNIT */
public static final int NUM_DENSITY_UNIT = 3;
// Adobe transform values
public static final int ADOBE_IMPOSSIBLE = -1;
public static final int ADOBE_UNKNOWN = 0;
public static final int ADOBE_YCC = 1;
public static final int ADOBE_YCCK = 2;
// Spi initialization stuff
public static final String vendor = "Oracle Corporation";
public static final String version = "0.5";
// Names of the formats we can read or write
public static final String [] names = {"JPEG", "jpeg", "JPG", "jpg"};
public static final String [] suffixes = {"jpg", "jpeg"};
public static final String [] MIMETypes = {"image/jpeg"};
public static final String nativeImageMetadataFormatName =
"javax_imageio_jpeg_image_1.0";
public static final String nativeImageMetadataFormatClassName =
"com.sun.imageio.plugins.jpeg.JPEGImageMetadataFormat";
public static final String nativeStreamMetadataFormatName =
"javax_imageio_jpeg_stream_1.0";
public static final String nativeStreamMetadataFormatClassName =
"com.sun.imageio.plugins.jpeg.JPEGStreamMetadataFormat";
// IJG Color codes.
public static final int JCS_UNKNOWN = 0; // error/unspecified
public static final int JCS_GRAYSCALE = 1; // monochrome
public static final int JCS_RGB = 2; // red/green/blue
public static final int JCS_YCbCr = 3; // Y/Cb/Cr (also known as YUV)
public static final int JCS_CMYK = 4; // C/M/Y/K
public static final int JCS_YCC = 5; // PhotoYCC
public static final int JCS_RGBA = 6; // RGB-Alpha
public static final int JCS_YCbCrA = 7; // Y/Cb/Cr/Alpha
// 8 and 9 were old "Legacy" codes which the old code never identified
// on reading anyway. Support for writing them is being dropped, too.
public static final int JCS_YCCA = 10; // PhotoYCC-Alpha
public static final int JCS_YCCK = 11; // Y/Cb/Cr/K
public static final int NUM_JCS_CODES = JCS_YCCK+1;
IJG can handle up to 4-channel JPEGs /** IJG can handle up to 4-channel JPEGs */
public static final int [] [] bandOffsets = {{0},
{0, 1},
{0, 1, 2},
{0, 1, 2, 3}};
public static final int [] bOffsRGB = { 2, 1, 0 };
/* These are kept in the inner class to avoid static initialization
* of the CMM class until someone actually needs it.
* (e.g. do not init CMM on the request for jpeg mime types)
*/
public static class JCS {
public static final ColorSpace sRGB =
ColorSpace.getInstance(ColorSpace.CS_sRGB);
private static ColorSpace YCC = null;
private static boolean yccInited = false;
public static ColorSpace getYCC() {
if (!yccInited) {
try {
YCC = ColorSpace.getInstance(ColorSpace.CS_PYCC);
} catch (IllegalArgumentException e) {
// PYCC.pf may not always be installed
} finally {
yccInited = true;
}
}
return YCC;
}
}
// Default value for ImageWriteParam
public static final float DEFAULT_QUALITY = 0.75F;
Returns true
if the given ColorSpace
object is an instance of ICC_ColorSpace but is not one of the
standard ColorSpaces
returned by
ColorSpace.getInstance()
.
/**
* Returns <code>true</code> if the given <code>ColorSpace</code>
* object is an instance of ICC_ColorSpace but is not one of the
* standard <code>ColorSpaces</code> returned by
* <code>ColorSpace.getInstance()</code>.
*/
static boolean isNonStandardICC(ColorSpace cs) {
boolean retval = false;
if ((cs instanceof ICC_ColorSpace)
&& (!cs.isCS_sRGB())
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ)))
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_GRAY)))
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB)))
&& (!cs.equals(ColorSpace.getInstance(ColorSpace.CS_PYCC)))
) {
retval = true;
}
return retval;
}
Returns true
if the given imageType can be used
in a JFIF file. If input
is true, then the
image type is considered before colorspace conversion.
/**
* Returns <code>true</code> if the given imageType can be used
* in a JFIF file. If <code>input</code> is true, then the
* image type is considered before colorspace conversion.
*/
static boolean isJFIFcompliant(ImageTypeSpecifier imageType,
boolean input) {
ColorModel cm = imageType.getColorModel();
// Can't have alpha
if (cm.hasAlpha()) {
return false;
}
// Gray is OK, always
int numComponents = imageType.getNumComponents();
if (numComponents == 1) {
return true;
}
// If it isn't gray, it must have 3 channels
if (numComponents != 3) {
return false;
}
if (input) {
// Must be RGB
if (cm.getColorSpace().getType() == ColorSpace.TYPE_RGB) {
return true;
}
} else {
// Must be YCbCr
if (cm.getColorSpace().getType() == ColorSpace.TYPE_YCbCr) {
return true;
}
}
return false;
}
Given an image type, return the Adobe transform corresponding to
that type, or ADOBE_IMPOSSIBLE if the image type is incompatible
with an Adobe marker segment. If input
is true, then
the image type is considered before colorspace conversion.
/**
* Given an image type, return the Adobe transform corresponding to
* that type, or ADOBE_IMPOSSIBLE if the image type is incompatible
* with an Adobe marker segment. If <code>input</code> is true, then
* the image type is considered before colorspace conversion.
*/
static int transformForType(ImageTypeSpecifier imageType, boolean input) {
int retval = ADOBE_IMPOSSIBLE;
ColorModel cm = imageType.getColorModel();
switch (cm.getColorSpace().getType()) {
case ColorSpace.TYPE_GRAY:
retval = ADOBE_UNKNOWN;
break;
case ColorSpace.TYPE_RGB:
retval = input ? ADOBE_YCC : ADOBE_UNKNOWN;
break;
case ColorSpace.TYPE_YCbCr:
retval = ADOBE_YCC;
break;
case ColorSpace.TYPE_CMYK:
retval = input ? ADOBE_YCCK : ADOBE_IMPOSSIBLE;
}
return retval;
}
Converts an ImageWriteParam (i.e. IJG) non-linear quality value
to a float suitable for passing to JPEGQTable.getScaledInstance().
/**
* Converts an ImageWriteParam (i.e. IJG) non-linear quality value
* to a float suitable for passing to JPEGQTable.getScaledInstance().
*/
static float convertToLinearQuality(float quality) {
// The following is converted from the IJG code.
if (quality <= 0.0F) {
quality = 0.01F;
}
if (quality > 1.00F) {
quality = 1.00F;
}
if (quality < 0.5F) {
quality = 0.5F / quality;
} else {
quality = 2.0F - (quality * 2.0F);
}
return quality;
}
Return an array of default, visually lossless quantization tables.
/**
* Return an array of default, visually lossless quantization tables.
*/
static JPEGQTable [] getDefaultQTables() {
JPEGQTable [] qTables = new JPEGQTable[2];
qTables[0] = JPEGQTable.K1Div2Luminance;
qTables[1] = JPEGQTable.K2Div2Chrominance;
return qTables;
}
Return an array of default Huffman tables.
/**
* Return an array of default Huffman tables.
*/
static JPEGHuffmanTable [] getDefaultHuffmanTables(boolean wantDC) {
JPEGHuffmanTable [] tables = new JPEGHuffmanTable[2];
if (wantDC) {
tables[0] = JPEGHuffmanTable.StdDCLuminance;
tables[1] = JPEGHuffmanTable.StdDCChrominance;
} else {
tables[0] = JPEGHuffmanTable.StdACLuminance;
tables[1] = JPEGHuffmanTable.StdACChrominance;
}
return tables;
}
}