1/*
2 * Copyright (c) 2003, 2017, 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 4893446
27 * @summary Tests that we get IOException if we try to encode the incompatible
28 *          image with RLE compression
29 */
30
31import java.awt.Color;
32import java.awt.Graphics;
33import java.awt.image.BufferedImage;
34import java.awt.image.IndexColorModel;
35import java.io.ByteArrayInputStream;
36import java.io.ByteArrayOutputStream;
37import java.io.IOException;
38
39import javax.imageio.IIOImage;
40import javax.imageio.ImageIO;
41import javax.imageio.ImageWriteParam;
42import javax.imageio.ImageWriter;
43import javax.imageio.stream.ImageInputStream;
44import javax.imageio.stream.ImageOutputStream;
45
46public class RleEncodingTest {
47
48    private static int testIdx = 1;
49
50    public static void main(String args[]) throws Exception {
51        try {
52            int mode = ImageWriteParam.MODE_EXPLICIT;
53            String type = "BI_RLE4";
54            doTest(type, mode);
55
56            type = "BI_RLE8";
57            doTest(type, mode);
58
59            mode = ImageWriteParam.MODE_DEFAULT;
60            type = "BI_RLE4";
61            doTest(type, mode);
62
63            type = "BI_RLE8";
64            doTest(type, mode);
65
66            System.out.println("Test 4bpp image.");
67            encodeRLE4Test();
68
69            System.out.println("Test 8bpp image.");
70            encodeRLE8Test();
71        } catch (IOException e) {
72            e.printStackTrace();
73            throw new RuntimeException("Unexpected exception. Test failed");
74        }
75    }
76
77    private static void doTest(String compressionType,
78                               int compressionMode) throws IOException
79    {
80        BufferedImage bimg = new BufferedImage(100, 100,
81                                               BufferedImage.TYPE_INT_RGB);
82        Graphics g = bimg.getGraphics();
83        g.setColor(Color.green);
84        g.fillRect(0, 0, 100, 100);
85
86        doTest(bimg, compressionType, compressionMode);
87    }
88
89    private static void encodeRLE4Test() throws IOException {
90        // create 4bpp image
91        byte[] r = new byte[16];
92        r[0] = (byte)0xff;
93        byte[] g = new byte[16];
94        g[1] = (byte)0xff;
95        byte[] b = new byte[16];
96        b[2] = (byte)0xff;
97        IndexColorModel icm = new IndexColorModel(4, 16, r, g, b);
98
99        BufferedImage bimg = new BufferedImage(100, 100,
100                                               BufferedImage.TYPE_BYTE_BINARY,
101                                               icm);
102
103        Graphics gr = bimg.getGraphics();
104        gr.setColor(Color.green);
105        gr.fillRect(0, 0, 100, 100);
106
107        doTest(bimg, "BI_RLE4", ImageWriteParam.MODE_EXPLICIT);
108    }
109
110    private static void encodeRLE8Test() throws IOException {
111        // create 8bpp image
112        byte[] r = new byte[256];
113        r[0] = (byte)0xff;
114        byte[] g = new byte[256];
115        g[1] = (byte)0xff;
116        byte[] b = new byte[256];
117        b[2] = (byte)0xff;
118        IndexColorModel icm = new IndexColorModel(8, 256, r, g, b);
119
120        BufferedImage bimg = new BufferedImage(100, 100,
121                                               BufferedImage.TYPE_BYTE_INDEXED,
122                                               icm);
123        Graphics gr = bimg.getGraphics();
124        gr.setColor(Color.green);
125        gr.fillRect(0, 0, 100, 100);
126
127        doTest(bimg, "BI_RLE8", ImageWriteParam.MODE_EXPLICIT);
128    }
129
130    private static void doTest(BufferedImage src,
131                               String compressionType,
132                               int compressionMode) throws IOException
133    {
134
135        ImageWriter iw =  (ImageWriter)ImageIO.getImageWritersBySuffix("bmp").next();
136        if (iw == null) {
137            throw new RuntimeException("No available writer. Test failed.");
138        }
139
140        IIOImage iioImg = new IIOImage(src, null, null);
141        ImageWriteParam param = iw.getDefaultWriteParam();
142
143
144        ByteArrayOutputStream baos = new ByteArrayOutputStream();
145        ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
146        iw.setOutput(ios);
147
148        System.out.println("Compression Type is " + compressionType);
149        System.out.println("Compression Mode is " + compressionMode);
150
151        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
152        param.setCompressionType(compressionType);
153        if (compressionMode != ImageWriteParam.MODE_EXPLICIT) {
154            param.setCompressionMode(compressionMode);
155        }
156        try {
157            iw.write(null, iioImg, param);
158        } catch (IOException e) {
159            int bpp = src.getColorModel().getPixelSize();
160            if (compressionMode == ImageWriteParam.MODE_EXPLICIT) {
161                if ((compressionType.equals("BI_RLE4") && bpp != 4)
162                    || (compressionType.equals("BI_RLE8") && bpp != 8))
163                {
164                    System.out.println("Can not encode "+ bpp+ "bpp image as"
165                                      + compressionType);
166                    return;
167                } else {
168                    throw new RuntimeException("Unable to encode "
169                                               + bpp + "bpp image as "
170                                               + compressionType
171                                               + ". Test failed");
172                }
173            }
174        }
175        baos.close();
176
177        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
178        ImageInputStream iis = ImageIO.createImageInputStream(bais);
179
180        BufferedImage dst = ImageIO.read(iis);
181
182        int w = src.getWidth();
183        int h = src.getHeight();
184
185        Object dstPixel = dst.getRaster().getDataElements(w/2, h/2, null);
186        Object srcPixel = src.getRaster().getDataElements(w/2, h/2, null);
187
188        if ( (src.getColorModel().getRed(srcPixel)
189              != dst.getColorModel().getRed(dstPixel))
190             || (src.getColorModel().getGreen(srcPixel)
191                 != dst.getColorModel().getGreen(dstPixel))
192             || (src.getColorModel().getBlue(srcPixel)
193                 != dst.getColorModel().getBlue(dstPixel))
194             || (src.getColorModel().getAlpha(srcPixel)
195                 != dst.getColorModel().getAlpha(dstPixel)) ) {
196
197            showPixel(src, w/2, h/2);
198            showPixel(dst, w/2, h/2);
199
200            throw new RuntimeException(
201                "Colors are different: " +
202                Integer.toHexString(src.getColorModel().getRGB(srcPixel))
203                + " and " +
204                Integer.toHexString(dst.getColorModel().getRGB(dstPixel)));
205        }
206
207    }
208
209    private static void showPixel(BufferedImage src, int x, int y) {
210        System.out.println("Img is " + src);
211        Object p = src.getRaster().getDataElements(x, y, null);
212        System.out.println("RGB:   " +
213                           Integer.toHexString(src.getColorModel().getRGB(p)));
214        System.out.println("Red:   " +
215                           Integer.toHexString(src.getColorModel().getRed(p)));
216        System.out.println("Green: " +
217                           Integer.toHexString(src.getColorModel().getGreen(p)));
218        System.out.println("Blue:  " +
219                           Integer.toHexString(src.getColorModel().getBlue(p)));
220        System.out.println("Alpha: " +
221                           Integer.toHexString(src.getColorModel().getAlpha(p)));
222    }
223}
224