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 4892194 8014427
27  * @summary Test checks that we able to encode TYPE_3BYTE_BGR images to bmp
28  *          format. Test failed if ArrayIndexOutOfBoundsException will be thrown
29  *          or pixel colors will be changed by the writing/reading.
30  */
31 
32 import java.awt.Color;
33 import java.awt.Dimension;
34 import java.awt.Graphics;
35 import java.awt.Graphics2D;
36 import java.awt.color.ColorSpace;
37 import java.awt.image.BufferedImage;
38 import java.awt.image.ColorModel;
39 import java.awt.image.ComponentColorModel;
40 import java.awt.image.DataBuffer;
41 import java.awt.image.Raster;
42 import java.awt.image.WritableRaster;
43 import java.io.ByteArrayInputStream;
44 import java.io.ByteArrayOutputStream;
45 import java.io.File;
46 import java.io.FileOutputStream;
47 import java.io.IOException;
48 
49 import javax.imageio.IIOImage;
50 import javax.imageio.ImageIO;
51 import javax.imageio.ImageWriter;
52 import javax.imageio.stream.ImageOutputStream;
53 import javax.swing.JComponent;
54 import javax.swing.JFrame;
55 
56 public class Write3ByteBgrTest {
57     private static int width = 100;
58     private static int height = 100;
59     private static Color color = new Color(0x10, 0x20, 0x30);
60 
61     static int bufferedImageType[] = {
62         BufferedImage.TYPE_CUSTOM,
63         BufferedImage.TYPE_BYTE_BINARY,
64         BufferedImage.TYPE_3BYTE_BGR
65     };
66 
67     static String bufferedImageStringType[] = {
68         "BufferedImage.TYPE_CUSTOM: test for BandedSampleModel",
69         "BufferedImage.TYPE_BYTE_BINARY",
70         "BufferedImage.TYPE_3BYTE_BGR"
71     };
72 
73     private static String writingFormat = "BMP";
74     private static ImageWriter writer = (ImageWriter)ImageIO.getImageWritersByFormatName(writingFormat).next();
75     private int type;
76 
main(String[] args)77     public static void main(String[] args) {
78 
79         //int i = 0;
80         for(int i=0; i<bufferedImageType.length; i++) {
81             Write3ByteBgrTest t1 = new Write3ByteBgrTest(bufferedImageType[i]);
82 
83             System.out.println("\n\nImage test for type " + bufferedImageStringType[i]);
84             t1.doImageTest();
85         }
86     }
87 
Write3ByteBgrTest(int type)88     private Write3ByteBgrTest(int type) {
89         this.type = type;
90     }
91 
doImageTest()92     private void doImageTest() {
93         try {
94             BufferedImage src = createTestImage(type);
95             BufferedImage dst = writeImage(src);
96 
97             compareImages(src, dst);
98         } catch (ArrayIndexOutOfBoundsException e) {
99             throw new RuntimeException("Test failed: index out of array bounds!");
100         }
101     }
102 
103 
compareImages(BufferedImage src, BufferedImage dst)104     private void compareImages(BufferedImage src, BufferedImage dst) {
105         Object dstPixel = dst.getRaster().getDataElements(width/2, height/2, null);
106         Object srcPixel = src.getRaster().getDataElements(width/2, height/2, null);
107 
108         if ( (src.getColorModel().getRed(srcPixel) != dst.getColorModel().getRed(dstPixel)) ||
109              (src.getColorModel().getGreen(srcPixel) != dst.getColorModel().getGreen(dstPixel)) ||
110              (src.getColorModel().getBlue(srcPixel) != dst.getColorModel().getBlue(dstPixel)) ||
111              (src.getColorModel().getAlpha(srcPixel) != dst.getColorModel().getAlpha(dstPixel)) ) {
112 
113             showPixel(src, width/2, height/2);
114             showPixel(dst, width/2, height/2);
115 
116             showRes(dst, src);
117             throw new RuntimeException(
118                 "Colors are different: " +
119                 Integer.toHexString(src.getColorModel().getRGB(srcPixel)) + " and " +
120                 Integer.toHexString(dst.getColorModel().getRGB(dstPixel)));
121         }
122     }
123 
writeImage(BufferedImage src)124     private BufferedImage writeImage(BufferedImage src) {
125         try {
126             BufferedImage dst = null;
127             if (!writer.getOriginatingProvider().canEncodeImage(src)) {
128                 throw new RuntimeException(writingFormat+" writer does not support the image type "+type);
129             }
130             System.out.println(writingFormat+" writer claims it can encode the image "+type);
131             ByteArrayOutputStream baos = new ByteArrayOutputStream();
132             ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
133             writer.setOutput(ios);
134             IIOImage img = new IIOImage(src.getRaster(), null, null);
135             writer.write(img);
136             ios.close();
137             baos.close();
138 
139             // save to file
140             File f = new File("test"+src.getType()+".bmp");
141             FileOutputStream fos = new FileOutputStream(f);
142             fos.write(baos.toByteArray());
143             fos.close();
144 
145 
146             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
147             dst = ImageIO.read(bais);
148             return dst;
149         } catch (IOException e) {
150             e.printStackTrace();
151             throw new RuntimeException(e);
152         }
153     }
154 
showPixel(BufferedImage src, int x, int y)155     private static void showPixel(BufferedImage src, int x, int y) {
156         System.out.println("Img is " + src);
157         Object p = src.getRaster().getDataElements(x, y, null);
158         System.out.println("RGB:   " +
159                            Integer.toHexString(src.getColorModel().getRGB(p)));
160         System.out.println("Red:   " +
161                            Integer.toHexString(src.getColorModel().getRed(p)));
162         System.out.println("Green: " +
163                            Integer.toHexString(src.getColorModel().getGreen(p)));
164         System.out.println("Blue:  " +
165                            Integer.toHexString(src.getColorModel().getBlue(p)));
166         System.out.println("Alpha: " +
167                            Integer.toHexString(src.getColorModel().getAlpha(p)));
168     }
169 
createTestImage(int type)170     private static BufferedImage createTestImage(int type) {
171         return createTestImage(type, color);
172     }
173 
createTestImage(int type, Color c)174     private static BufferedImage createTestImage(int type, Color c) {
175         BufferedImage i = null;
176         if (type == BufferedImage.TYPE_CUSTOM) {
177             WritableRaster wr = Raster.createBandedRaster(
178                 DataBuffer.TYPE_BYTE,
179                 width, height,
180                 width,               // scanlineStride
181                 new int[] { 0, 1, 2},// bankIndices[],
182                 new int[] { 1, 2, 0},// bankOffsets[],
183                 null);
184 
185             ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
186 
187             ColorModel cm = new ComponentColorModel(cs,
188                                                     new int[] { 8, 8, 8},
189                                                     false,
190                                                     false,
191                                                     ColorModel.OPAQUE,
192                                                     DataBuffer.TYPE_BYTE);
193             i = new BufferedImage(cm, wr, false, null);
194         } else {
195             i = new BufferedImage(width, height, type);
196         }
197 
198         Graphics2D g = i.createGraphics();
199 
200         g.setColor(c);
201         g.fillRect(0, 0, width, height);
202         g.setColor(Color.white);
203         g.drawRect(10,10, width-20, height-20);
204 
205         return i;
206     }
207 
showRes(final BufferedImage src, final BufferedImage dst)208     private static void showRes(final BufferedImage src,
209                                 final BufferedImage dst)
210         {
211         final int w = src.getWidth()+  dst.getWidth();
212         final int h = Math.max(src.getHeight(), dst.getHeight());
213 
214         JFrame f = new JFrame("Test results");
215         f.getContentPane().add( new JComponent() {
216                 public Dimension getPreferredSize() {
217                     return new Dimension(w,h);
218                 }
219 
220                 public void paintComponent(Graphics g) {
221                     g.drawImage(src,0,0, null);
222                     g.drawImage(dst, src.getWidth(),0, null);
223                 }
224             });
225         f.pack();
226         f.setVisible(true);
227     }
228 }
229