--- old/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java 2018-06-06 12:58:51.944659139 -0700 +++ new/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEG.java 2018-06-06 12:58:51.680659149 -0700 @@ -187,13 +187,7 @@ 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 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 --- old/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java 2018-06-06 12:58:52.600659113 -0700 +++ new/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java 2018-06-06 12:58:52.264659126 -0700 @@ -933,21 +933,6 @@ 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 @@ } 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 @@ 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 @@ 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; } --- old/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java 2018-06-06 12:58:53.240659089 -0700 +++ new/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java 2018-06-06 12:58:52.952659100 -0700 @@ -754,115 +754,47 @@ } break; case ColorSpace.TYPE_RGB: - if (!alpha) { - 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; - 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; - } - } + if (jfif != null) { + outCsType = JPEG.JCS_YCbCr; + if (JPEG.isNonStandardICC(cs) + || ((cs instanceof ICC_ColorSpace) + && (jfif.iccSegment != null))) { + iccProfile = + ((ICC_ColorSpace) cs).getProfile(); } - } else { // RGBA - if (jfif != null) { - ignoreJFIF = true; + } 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_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; - } else { - boolean subsampled = - isSubsampled(sof.componentSpecs); - outCsType = subsampled ? - JPEG.JCS_YCbCrA : JPEG.JCS_RGBA; - } - } - } - 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); + boolean subsampled = + isSubsampled(sof.componentSpecs); + if (subsampled) { 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_RGB; } - outCsType = JPEG.JCS_YCCA; } } + break; } } } // else no dest, metadata, not an image. Defaults ok @@ -1564,27 +1496,10 @@ 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 @@ 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 @@ 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; --- old/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java 2018-06-06 12:58:53.684659072 -0700 +++ new/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java 2018-06-06 12:58:53.460659081 -0700 @@ -73,7 +73,11 @@ 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]; --- old/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java 2018-06-06 12:58:54.276659049 -0700 +++ new/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java 2018-06-06 12:58:53.992659060 -0700 @@ -491,17 +491,6 @@ 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; --- old/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOFMarkerSegment.java 2018-06-06 12:58:54.892659026 -0700 +++ new/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/SOFMarkerSegment.java 2018-06-06 12:58:54.632659036 -0700 @@ -182,29 +182,11 @@ 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; --- old/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c 2018-06-06 12:58:55.368659007 -0700 +++ new/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c 2018-06-06 12:58:55.124659017 -0700 @@ -1762,11 +1762,6 @@ } } 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)) { /* --- old/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c 2018-06-06 12:58:55.844658989 -0700 +++ new/src/java.desktop/share/native/libjavajpeg/jpegdecoder.c 2018-06-06 12:58:55.608658998 -0700 @@ -569,11 +569,7 @@ /* 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) --- old/test/jdk/javax/imageio/plugins/shared/BitDepth.java 2018-06-06 12:58:56.488658965 -0700 +++ new/test/jdk/javax/imageio/plugins/shared/BitDepth.java 2018-06-06 12:58:56.172658977 -0700 @@ -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 @@ 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 @@ } catch (Exception e) { System.out.println("\tCan't write a type " + biTypeNames[type] + " BufferedImage!"); - return null; + throw new RuntimeException(e); } } --- /dev/null 2018-05-25 11:37:39.280540387 -0700 +++ new/test/jdk/javax/imageio/plugins/jpeg/TestWriteARGBJPEG.java 2018-06-06 12:58:56.744658955 -0700 @@ -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 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; + } + } + } +}