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 
  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 }