8204187: Remove proprietary JPEG code from javax.imageio

Reviewed-by: bpb, serb, kaddepalli
This commit is contained in:
Phil Race 2018-06-06 13:04:25 -07:00
parent 3d93888690
commit 7845dac7cf
10 changed files with 134 additions and 303 deletions

View File

@ -187,13 +187,7 @@ public class JPEG {
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 JCS_YCCK = 5; // Y/Cb/Cr/K
public static final int NUM_JCS_CODES = JCS_YCCK+1;
@ -212,22 +206,6 @@ public class JPEG {
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

View File

@ -933,21 +933,6 @@ public class JPEGImageReader extends ImageReader {
case JPEG.JCS_RGB:
list.add(raw);
list.add(getImageType(JPEG.JCS_GRAYSCALE));
list.add(getImageType(JPEG.JCS_YCC));
break;
case JPEG.JCS_RGBA:
list.add(raw);
break;
case JPEG.JCS_YCC:
if (raw != null) { // Might be null if PYCC.pf not installed
list.add(raw);
list.add(getImageType(JPEG.JCS_RGB));
}
break;
case JPEG.JCS_YCCA:
if (raw != null) { // Might be null if PYCC.pf not installed
list.add(raw);
}
break;
case JPEG.JCS_YCbCr:
// As there is no YCbCr ColorSpace, we can't support
@ -972,12 +957,6 @@ public class JPEGImageReader extends ImageReader {
}
list.add(getImageType(JPEG.JCS_GRAYSCALE));
list.add(getImageType(JPEG.JCS_YCC));
break;
case JPEG.JCS_YCbCrA: // Default is to convert to RGBA
// As there is no YCbCr ColorSpace, we can't support
// the raw type.
list.add(getImageType(JPEG.JCS_RGBA));
break;
}
@ -1065,36 +1044,6 @@ public class JPEGImageReader extends ImageReader {
throw new IIOException("Incompatible color conversion");
}
break;
case JPEG.JCS_RGBA:
// No conversions available; image must be RGBA
if ((csType != ColorSpace.TYPE_RGB) ||
(cm.getNumComponents() != numComponents)) {
throw new IIOException("Incompatible color conversion");
}
break;
case JPEG.JCS_YCC:
{
ColorSpace YCC = JPEG.JCS.getYCC();
if (YCC == null) { // We can't do YCC at all
throw new IIOException("Incompatible color conversion");
}
if ((cs != YCC) &&
(cm.getNumComponents() == numComponents)) {
convert = new ColorConvertOp(YCC, cs, null);
}
}
break;
case JPEG.JCS_YCCA:
{
ColorSpace YCC = JPEG.JCS.getYCC();
// No conversions available; image must be YCCA
if ((YCC == null) || // We can't do YCC at all
(cs != YCC) ||
(cm.getNumComponents() != numComponents)) {
throw new IIOException("Incompatible color conversion");
}
}
break;
default:
// Anything else we can't handle at all
throw new IIOException("Incompatible color conversion");
@ -1929,36 +1878,6 @@ class ImageTypeProducer {
DataBuffer.TYPE_BYTE,
false,
false);
case JPEG.JCS_RGBA:
return ImageTypeSpecifier.createPacked(JPEG.JCS.sRGB,
0xff000000,
0x00ff0000,
0x0000ff00,
0x000000ff,
DataBuffer.TYPE_INT,
false);
case JPEG.JCS_YCC:
if (JPEG.JCS.getYCC() != null) {
return ImageTypeSpecifier.createInterleaved(
JPEG.JCS.getYCC(),
JPEG.bandOffsets[2],
DataBuffer.TYPE_BYTE,
false,
false);
} else {
return null;
}
case JPEG.JCS_YCCA:
if (JPEG.JCS.getYCC() != null) {
return ImageTypeSpecifier.createInterleaved(
JPEG.JCS.getYCC(),
JPEG.bandOffsets[3],
DataBuffer.TYPE_BYTE,
true,
false);
} else {
return null;
}
default:
return null;
}

View File

@ -754,115 +754,47 @@ public class JPEGImageWriter extends ImageWriter {
}
break;
case ColorSpace.TYPE_RGB:
if (!alpha) {
if (jfif != null) {
if (jfif != null) {
outCsType = JPEG.JCS_YCbCr;
if (JPEG.isNonStandardICC(cs)
|| ((cs instanceof ICC_ColorSpace)
&& (jfif.iccSegment != null))) {
iccProfile =
((ICC_ColorSpace) cs).getProfile();
}
} else if (adobe != null) {
switch (adobe.transform) {
case JPEG.ADOBE_UNKNOWN:
outCsType = JPEG.JCS_RGB;
break;
case JPEG.ADOBE_YCC:
outCsType = JPEG.JCS_YCbCr;
if (JPEG.isNonStandardICC(cs)
|| ((cs instanceof ICC_ColorSpace)
&& (jfif.iccSegment != null))) {
iccProfile =
((ICC_ColorSpace) cs).getProfile();
}
} else if (adobe != null) {
switch (adobe.transform) {
case JPEG.ADOBE_UNKNOWN:
outCsType = JPEG.JCS_RGB;
break;
case JPEG.ADOBE_YCC:
outCsType = JPEG.JCS_YCbCr;
break;
default:
warningOccurred
(WARNING_IMAGE_METADATA_ADOBE_MISMATCH);
newAdobeTransform = JPEG.ADOBE_UNKNOWN;
outCsType = JPEG.JCS_RGB;
break;
}
} else {
// consult the ids
int outCS = sof.getIDencodedCSType();
// if they don't resolve it,
// consult the sampling factors
if (outCS != JPEG.JCS_UNKNOWN) {
outCsType = outCS;
} else {
boolean subsampled =
isSubsampled(sof.componentSpecs);
if (subsampled) {
outCsType = JPEG.JCS_YCbCr;
} else {
outCsType = JPEG.JCS_RGB;
}
}
}
} else { // RGBA
if (jfif != null) {
ignoreJFIF = true;
break;
default:
warningOccurred
(WARNING_IMAGE_METADATA_JFIF_MISMATCH);
(WARNING_IMAGE_METADATA_ADOBE_MISMATCH);
newAdobeTransform = JPEG.ADOBE_UNKNOWN;
outCsType = JPEG.JCS_RGB;
break;
}
if (adobe != null) {
if (adobe.transform
!= JPEG.ADOBE_UNKNOWN) {
newAdobeTransform = JPEG.ADOBE_UNKNOWN;
warningOccurred
(WARNING_IMAGE_METADATA_ADOBE_MISMATCH);
}
outCsType = JPEG.JCS_RGBA;
} else {
// consult the ids
int outCS = sof.getIDencodedCSType();
// if they don't resolve it,
// consult the sampling factors
if (outCS != JPEG.JCS_UNKNOWN) {
outCsType = outCS;
} else {
// consult the ids
int outCS = sof.getIDencodedCSType();
// if they don't resolve it,
// consult the sampling factors
if (outCS != JPEG.JCS_UNKNOWN) {
outCsType = outCS;
boolean subsampled =
isSubsampled(sof.componentSpecs);
if (subsampled) {
outCsType = JPEG.JCS_YCbCr;
} else {
boolean subsampled =
isSubsampled(sof.componentSpecs);
outCsType = subsampled ?
JPEG.JCS_YCbCrA : JPEG.JCS_RGBA;
outCsType = JPEG.JCS_RGB;
}
}
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.JCS.getYCC()) {
if (!alpha) {
if (jfif != null) {
convertTosRGB = true;
convertOp =
new ColorConvertOp(cs,
JPEG.JCS.sRGB,
null);
outCsType = JPEG.JCS_YCbCr;
} else if (adobe != null) {
if (adobe.transform
!= JPEG.ADOBE_YCC) {
newAdobeTransform = JPEG.ADOBE_YCC;
warningOccurred
(WARNING_IMAGE_METADATA_ADOBE_MISMATCH);
}
outCsType = JPEG.JCS_YCC;
} else {
outCsType = JPEG.JCS_YCC;
}
} else { // PhotoYCCA
if (jfif != null) {
ignoreJFIF = true;
warningOccurred
(WARNING_IMAGE_METADATA_JFIF_MISMATCH);
} else if (adobe != null) {
if (adobe.transform
!= JPEG.ADOBE_UNKNOWN) {
newAdobeTransform
= JPEG.ADOBE_UNKNOWN;
warningOccurred
(WARNING_IMAGE_METADATA_ADOBE_MISMATCH);
}
}
outCsType = JPEG.JCS_YCCA;
}
}
}
}
} // else no dest, metadata, not an image. Defaults ok
@ -1564,27 +1496,10 @@ public class JPEGImageWriter extends ImageWriter {
retval = JPEG.JCS_GRAYSCALE;
break;
case ColorSpace.TYPE_RGB:
if (alpha) {
retval = JPEG.JCS_RGBA;
} else {
retval = JPEG.JCS_RGB;
}
retval = JPEG.JCS_RGB;
break;
case ColorSpace.TYPE_YCbCr:
if (alpha) {
retval = JPEG.JCS_YCbCrA;
} else {
retval = JPEG.JCS_YCbCr;
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.JCS.getYCC()) {
if (alpha) {
retval = JPEG.JCS_YCCA;
} else {
retval = JPEG.JCS_YCC;
}
}
retval = JPEG.JCS_YCbCr;
break;
case ColorSpace.TYPE_CMYK:
retval = JPEG.JCS_CMYK;
@ -1604,27 +1519,10 @@ public class JPEGImageWriter extends ImageWriter {
retval = JPEG.JCS_GRAYSCALE;
break;
case ColorSpace.TYPE_RGB:
if (alpha) {
retval = JPEG.JCS_RGBA;
} else {
retval = JPEG.JCS_RGB;
}
retval = JPEG.JCS_RGB;
break;
case ColorSpace.TYPE_YCbCr:
if (alpha) {
retval = JPEG.JCS_YCbCrA;
} else {
retval = JPEG.JCS_YCbCr;
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.JCS.getYCC()) {
if (alpha) {
retval = JPEG.JCS_YCCA;
} else {
retval = JPEG.JCS_YCC;
}
}
retval = JPEG.JCS_YCbCr;
break;
case ColorSpace.TYPE_CMYK:
retval = JPEG.JCS_CMYK;
@ -1651,27 +1549,10 @@ public class JPEGImageWriter extends ImageWriter {
retval = JPEG.JCS_GRAYSCALE;
break;
case ColorSpace.TYPE_RGB:
if (alpha) {
retval = JPEG.JCS_YCbCrA;
} else {
retval = JPEG.JCS_YCbCr;
}
retval = JPEG.JCS_YCbCr;
break;
case ColorSpace.TYPE_YCbCr:
if (alpha) {
retval = JPEG.JCS_YCbCrA;
} else {
retval = JPEG.JCS_YCbCr;
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.JCS.getYCC()) {
if (alpha) {
retval = JPEG.JCS_YCCA;
} else {
retval = JPEG.JCS_YCC;
}
}
retval = JPEG.JCS_YCbCr;
break;
case ColorSpace.TYPE_CMYK:
retval = JPEG.JCS_YCCK;

View File

@ -73,7 +73,11 @@ public class JPEGImageWriterSpi extends ImageWriterSpi {
public boolean canEncodeImage(ImageTypeSpecifier type) {
SampleModel sampleModel = type.getSampleModel();
ColorModel cm = type.getColorModel();
if (cm.hasAlpha()) {
return false;
}
// Find the maximum bit depth across all channels
int[] sampleSize = sampleModel.getSampleSize();
int bitDepth = sampleSize[0];

View File

@ -491,17 +491,6 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable {
wantJFIF = false;
}
break;
case ColorSpace.TYPE_3CLR:
if (cs == JPEG.JCS.getYCC()) {
wantJFIF = false;
componentIDs[0] = (byte) 'Y';
componentIDs[1] = (byte) 'C';
componentIDs[2] = (byte) 'c';
if (hasAlpha) {
componentIDs[3] = (byte) 'A';
}
}
break;
case ColorSpace.TYPE_YCbCr:
if (hasExtraComponents) { // e.g. K or alpha
wantJFIF = false;

View File

@ -182,29 +182,11 @@ class SOFMarkerSegment extends MarkerSegment {
switch(componentSpecs.length) {
case 3:
if ((componentSpecs[0].componentId == 'R')
&&(componentSpecs[0].componentId == 'G')
&&(componentSpecs[0].componentId == 'B')) {
&&(componentSpecs[1].componentId == 'G')
&&(componentSpecs[2].componentId == 'B')) {
return JPEG.JCS_RGB;
}
if ((componentSpecs[0].componentId == 'Y')
&&(componentSpecs[0].componentId == 'C')
&&(componentSpecs[0].componentId == 'c')) {
return JPEG.JCS_YCC;
}
break;
case 4:
if ((componentSpecs[0].componentId == 'R')
&&(componentSpecs[0].componentId == 'G')
&&(componentSpecs[0].componentId == 'B')
&&(componentSpecs[0].componentId == 'A')) {
return JPEG.JCS_RGBA;
}
if ((componentSpecs[0].componentId == 'Y')
&&(componentSpecs[0].componentId == 'C')
&&(componentSpecs[0].componentId == 'c')
&&(componentSpecs[0].componentId == 'A')) {
return JPEG.JCS_YCCA;
}
}
return JPEG.JCS_UNKNOWN;

View File

@ -1762,11 +1762,6 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_readImageHeader
}
}
break;
#ifdef YCCALPHA
case JCS_YCC:
cinfo->out_color_space = JCS_YCC;
break;
#endif
case JCS_YCCK:
if ((cinfo->saw_Adobe_marker) && (cinfo->Adobe_transform != 2)) {
/*

View File

@ -569,11 +569,7 @@ Java_sun_awt_image_JPEGImageDecoder_readImage(JNIEnv *env,
/* select buffered-image mode if it is a progressive JPEG only */
buffered_mode = cinfo.buffered_image = jpeg_has_multiple_scans(&cinfo);
grayscale = (cinfo.out_color_space == JCS_GRAYSCALE);
#ifdef YCCALPHA
hasalpha = (cinfo.out_color_space == JCS_RGBA);
#else
hasalpha = 0;
#endif
/* We can ignore the return value from jpeg_read_header since
* (a) suspension is not possible with the stdio data source, and
* (nor with the Java input source)

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2018, 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.
*
* 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.
*/
/**
* @test
* @bug 8204187
* @run main TestWriteARGBJPEG
* @summary verify JPEG Alpha support is as reported.
*/
import java.io.IOException;
import java.util.Iterator;
import java.io.ByteArrayOutputStream;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.MemoryCacheImageOutputStream;
public class TestWriteARGBJPEG {
public static void main(String args[]) throws IOException {
BufferedImage bi =
new BufferedImage(10,10,BufferedImage.TYPE_INT_ARGB);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// There should be no exception from the next line
// which internally should be relying on the canEncodeImage
// method which we'll also test directly.
boolean ret = ImageIO.write(bi, "jpeg", baos);
System.out.println("ImageIO.write(..) returned " + ret);
ImageTypeSpecifier its = new ImageTypeSpecifier(bi);
Iterator<ImageWriter> writers = ImageIO.getImageWriters(its, "jpeg");
boolean hasWriter = writers.hasNext();
// If this can't write it, an exception will be thrown.
if (writers.hasNext()) {
System.out.println("A writer was found.");
ImageWriter iw = writers.next();
MemoryCacheImageOutputStream mos =
new MemoryCacheImageOutputStream(baos);
iw.setOutput(mos);
iw.write(bi);
}
// Now Let's also ask the default JPEG writer's SPI if it
// can write an ARGB image.
ImageWriter iw = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriterSpi iwSpi = iw.getOriginatingProvider();
boolean canEncode = iwSpi.canEncodeImage(bi);
System.out.println("SPI canEncodeImage returned " + canEncode);
// Now let's see if it is telling the truth.
try {
MemoryCacheImageOutputStream mos =
new MemoryCacheImageOutputStream(baos);
iw.setOutput(mos);
iw.write(bi);
} catch (IOException e) {
if (canEncode) {
throw e;
}
}
}
}

View File

@ -23,7 +23,7 @@
/**
* @test
* @bug 4413109 4418221 6607198 8147448
* @bug 4413109 4418221 6607198 8147448 8204187
* @run main BitDepth
* @summary Checks that ImageIO writers for standard formats can handle
* various BufferedImage RGB types. An optional list of arguments
@ -197,6 +197,7 @@ public class BitDepth {
if (!writers.hasNext()) {
System.out.println("\tNo writers available for type " + biTypeNames[type]
+ " BufferedImage!");
return null;
} else {
ImageWriter writer = writers.next();
try (ImageOutputStream out = ImageIO.createImageOutputStream(file)) {
@ -205,7 +206,7 @@ public class BitDepth {
} catch (Exception e) {
System.out.println("\tCan't write a type " + biTypeNames[type]
+ " BufferedImage!");
return null;
throw new RuntimeException(e);
}
}