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 
31 import java.awt.Color;
32 import java.awt.Graphics;
33 import java.awt.image.BufferedImage;
34 import java.awt.image.IndexColorModel;
35 import java.io.ByteArrayInputStream;
36 import java.io.ByteArrayOutputStream;
37 import java.io.IOException;
38 
39 import javax.imageio.IIOImage;
40 import javax.imageio.ImageIO;
41 import javax.imageio.ImageWriteParam;
42 import javax.imageio.ImageWriter;
43 import javax.imageio.stream.ImageInputStream;
44 import javax.imageio.stream.ImageOutputStream;
45 
46 public class RleEncodingTest {
47 
48     private static int testIdx = 1;
49 
main(String args[])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 
doTest(String compressionType, int compressionMode)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 
encodeRLE4Test()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 
encodeRLE8Test()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 
doTest(BufferedImage src, String compressionType, int compressionMode)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 
showPixel(BufferedImage src, int x, int y)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