/*
* Copyright (c) 2009, 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 4893408
*
* @summary Test verifies that Image I/O jpeg reader correctly handles
* destination types if number of color components in destination
* differs from number of color components in the jpeg image.
* Particularly, it verifies reading YCbCr image as a grayscaled
* and reading grayscaled jpeg as a RGB.
*
* @run main ReadAsGrayTest
*/
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.stream.ImageInputStream;
import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
import static java.awt.image.BufferedImage.TYPE_BYTE_GRAY;
import static java.awt.color.ColorSpace.TYPE_GRAY;
import static java.awt.color.ColorSpace.CS_sRGB;
public class ReadAsGrayTest {
static Color[] colors = new Color[] {
Color.white, Color.red, Color.green,
Color.blue, Color.black };
static final int dx = 50;
static final int h = 100;
static ColorSpace sRGB = ColorSpace.getInstance(CS_sRGB);
public static void main(String[] args) throws IOException {
System.out.println("Type TYPE_BYTE_GRAY");
doTest(TYPE_BYTE_GRAY);
System.out.println("Type TYPE_3BYTE_BGR");
doTest(TYPE_3BYTE_BGR);
System.out.println("Test PASSED.");
}
private static void doTest(int type) throws IOException {
BufferedImage src = createTestImage(type);
File f = new File("test.jpg");
if (!ImageIO.write(src, "jpg", f)) {
throw new RuntimeException("Failed to write test image.");
}
ImageInputStream iis = ImageIO.createImageInputStream(f);
ImageReader reader = ImageIO.getImageReaders(iis).next();
reader.setInput(iis);
Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
ImageTypeSpecifier srgb = null;
ImageTypeSpecifier gray = null;
// look for gray and srgb types
while ((srgb == null || gray == null) && types.hasNext()) {
ImageTypeSpecifier t = types.next();
if (t.getColorModel().getColorSpace().getType() == TYPE_GRAY) {
gray = t;
}
if (t.getColorModel().getColorSpace() == sRGB) {
srgb = t;
}
}
if (gray == null) {
throw new RuntimeException("No gray type available.");
}
if (srgb == null) {
throw new RuntimeException("No srgb type available.");
}
System.out.println("Read as GRAY...");
testType(reader, gray, src);
System.out.println("Read as sRGB...");
testType(reader, srgb, src);
}
private static void testType(ImageReader reader,
ImageTypeSpecifier t,
BufferedImage src)
throws IOException
{
ImageReadParam p = reader.getDefaultReadParam();
p.setDestinationType(t);
BufferedImage dst = reader.read(0, p);
verify(src, dst, t);
}
private static void verify(BufferedImage src,
BufferedImage dst,
ImageTypeSpecifier type)
{
BufferedImage test =
type.createBufferedImage(src.getWidth(), src.getHeight());
Graphics2D g = test.createGraphics();
g.drawImage(src, 0, 0, null);
g.dispose();
for (int i = 0; i < colors.length; i++) {
int x = i * dx + dx / 2;
int y = h / 2;
Color c_test = new Color(test.getRGB(x, y));
Color c_dst = new Color(dst.getRGB(x, y));
if (!compareWithTolerance(c_test, c_dst, 0.01f)) {
String msg = String.format("Invalid color: %x instead of %x",
c_dst.getRGB(), c_test.getRGB());
throw new RuntimeException("Test failed: " + msg);
}
}
System.out.println("Verified.");
}
private static boolean compareWithTolerance(Color a, Color b, float delta) {
float[] a_rgb = new float[3];
a_rgb = a.getRGBColorComponents(a_rgb);
float[] b_rgb = new float[3];
b_rgb = b.getRGBColorComponents(b_rgb);
for (int i = 0; i < 3; i++) {
if (Math.abs(a_rgb[i] - b_rgb[i]) > delta) {
return false;
}
}
return true;
}
private static BufferedImage createTestImage(int type) {
BufferedImage img = new BufferedImage(dx * colors.length, h, type);
Graphics2D g = img.createGraphics();
for (int i = 0; i < colors.length; i++) {
g.setColor(colors[i]);
g.fillRect(i * dx, 0, dx, h);
}
g.dispose();
return img;
}
}