1/*
2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/**
25 * @test
26 * @bug     4893408
27 *
28 * @summary Test verifies that Image I/O jpeg reader correctly handles
29 *          destination types if number of color components in destination
30 *          differs from number of color components in the jpeg image.
31 *          Particularly, it verifies reading YCbCr image as a grayscaled
32 *          and reading grayscaled jpeg as a RGB.
33 *
34 * @run     main ReadAsGrayTest
35 */
36
37import java.awt.Color;
38import java.awt.Graphics2D;
39import java.awt.color.ColorSpace;
40import java.awt.image.BufferedImage;
41import java.io.File;
42import java.io.IOException;
43import java.util.Iterator;
44import javax.imageio.ImageIO;
45import javax.imageio.ImageReadParam;
46import javax.imageio.ImageReader;
47import javax.imageio.ImageTypeSpecifier;
48import javax.imageio.stream.ImageInputStream;
49import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
50import static java.awt.image.BufferedImage.TYPE_BYTE_GRAY;
51import static java.awt.color.ColorSpace.TYPE_GRAY;
52import static java.awt.color.ColorSpace.CS_sRGB;
53
54public class ReadAsGrayTest {
55    static Color[] colors = new Color[] {
56        Color.white, Color.red, Color.green,
57        Color.blue, Color.black };
58
59    static final int dx = 50;
60    static final int h = 100;
61
62    static ColorSpace sRGB = ColorSpace.getInstance(CS_sRGB);
63
64
65    public static void main(String[] args) throws IOException {
66        System.out.println("Type TYPE_BYTE_GRAY");
67        doTest(TYPE_BYTE_GRAY);
68
69        System.out.println("Type TYPE_3BYTE_BGR");
70        doTest(TYPE_3BYTE_BGR);
71
72        System.out.println("Test PASSED.");
73    }
74
75    private static void doTest(int type) throws IOException {
76        BufferedImage src = createTestImage(type);
77
78        File f = new File("test.jpg");
79
80        if (!ImageIO.write(src, "jpg", f)) {
81            throw new RuntimeException("Failed to write test image.");
82        }
83
84        ImageInputStream iis = ImageIO.createImageInputStream(f);
85        ImageReader reader = ImageIO.getImageReaders(iis).next();
86        reader.setInput(iis);
87
88        Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
89        ImageTypeSpecifier srgb = null;
90        ImageTypeSpecifier gray = null;
91        // look for gray and srgb types
92        while ((srgb == null || gray == null) && types.hasNext()) {
93            ImageTypeSpecifier t = types.next();
94            if (t.getColorModel().getColorSpace().getType() == TYPE_GRAY) {
95                gray = t;
96            }
97            if (t.getColorModel().getColorSpace() == sRGB) {
98                srgb = t;
99            }
100        }
101        if (gray == null) {
102            throw new RuntimeException("No gray type available.");
103        }
104        if (srgb == null) {
105            throw new RuntimeException("No srgb type available.");
106        }
107
108        System.out.println("Read as GRAY...");
109        testType(reader, gray, src);
110
111        System.out.println("Read as sRGB...");
112        testType(reader, srgb, src);
113    }
114
115    private static void testType(ImageReader reader,
116                                 ImageTypeSpecifier t,
117                                 BufferedImage src)
118        throws IOException
119    {
120        ImageReadParam p = reader.getDefaultReadParam();
121        p.setDestinationType(t);
122        BufferedImage dst = reader.read(0, p);
123
124        verify(src, dst, t);
125    }
126
127    private static void verify(BufferedImage src,
128                               BufferedImage dst,
129                               ImageTypeSpecifier type)
130    {
131        BufferedImage test =
132                type.createBufferedImage(src.getWidth(), src.getHeight());
133        Graphics2D g = test.createGraphics();
134        g.drawImage(src, 0, 0, null);
135        g.dispose();
136
137        for (int i = 0; i < colors.length; i++) {
138            int x = i * dx + dx / 2;
139            int y = h / 2;
140
141            Color c_test = new Color(test.getRGB(x, y));
142            Color c_dst = new Color(dst.getRGB(x, y));
143
144            if (!compareWithTolerance(c_test, c_dst, 0.01f)) {
145                String msg = String.format("Invalid color: %x instead of %x",
146                                           c_dst.getRGB(), c_test.getRGB());
147                throw new RuntimeException("Test failed: " + msg);
148            }
149        }
150        System.out.println("Verified.");
151    }
152
153    private static boolean compareWithTolerance(Color a, Color b, float delta) {
154        float[] a_rgb = new float[3];
155        a_rgb = a.getRGBColorComponents(a_rgb);
156        float[] b_rgb = new float[3];
157        b_rgb = b.getRGBColorComponents(b_rgb);
158
159        for (int i = 0; i < 3; i++) {
160            if (Math.abs(a_rgb[i] - b_rgb[i]) > delta) {
161                return false;
162            }
163        }
164        return true;
165    }
166
167    private static BufferedImage createTestImage(int type) {
168        BufferedImage img = new BufferedImage(dx * colors.length, h, type);
169
170        Graphics2D g = img.createGraphics();
171        for (int i = 0; i < colors.length; i++) {
172            g.setColor(colors[i]);
173            g.fillRect(i * dx, 0, dx, h);
174        }
175        g.dispose();
176
177        return img;
178    }
179}
180