1 /* 2 * Copyright (c) 2006, 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 5076878 27 * @summary Test verifies that ImageIO creates BMP images with correct bpp 28 */ 29 30 import java.awt.Color; 31 import java.awt.Graphics; 32 import java.awt.Transparency; 33 import java.awt.color.ColorSpace; 34 import java.awt.image.BufferedImage; 35 import java.awt.image.ColorModel; 36 import java.awt.image.ComponentColorModel; 37 import java.awt.image.DataBuffer; 38 import java.awt.image.DirectColorModel; 39 import java.awt.image.Raster; 40 import java.awt.image.WritableRaster; 41 import java.io.File; 42 import java.io.FileInputStream; 43 import java.io.IOException; 44 import java.util.Hashtable; 45 46 import javax.imageio.IIOImage; 47 import javax.imageio.ImageIO; 48 import javax.imageio.ImageReader; 49 import javax.imageio.metadata.IIOMetadata; 50 import javax.imageio.stream.ImageInputStream; 51 52 import org.w3c.dom.Node; 53 54 public class NoExtraBytesTest { 55 56 private static Hashtable<Integer, Integer> tests = null; 57 private static Color[] usedColors = new Color[] { Color.red, Color.green, Color.blue, Color.yellow, Color.white, Color.black }; 58 59 private static final int TYPE_INT_GRB = 0x100; 60 private static final int TYPE_INT_GBR = 0x101; 61 private static final int TYPE_INT_RBG = 0x102; 62 private static final int TYPE_INT_BRG = 0x103; 63 private static final int TYPE_INT_555_GRB = 0x104; 64 private static final int TYPE_3BYTE_RGB = 0x105; 65 private static final int TYPE_3BYTE_GRB = 0x106; 66 67 private static final int w = 300; 68 private static final int h = 200; 69 private static final int dx = w / usedColors.length; 70 71 public static void main(String[] args) throws IOException { 72 initTests(); 73 74 for (Integer type : tests.keySet()) { 75 new NoExtraBytesTest(type.intValue(), tests.get(type).intValue()).doTest(); 76 } 77 System.out.println("Test passed."); 78 } 79 80 private static void initTests() { 81 tests = new Hashtable<Integer, Integer>(); 82 83 tests.put(new Integer(BufferedImage.TYPE_INT_RGB), new Integer(24)); 84 tests.put(new Integer(BufferedImage.TYPE_INT_BGR), new Integer(24)); 85 tests.put(new Integer(BufferedImage.TYPE_3BYTE_BGR), new Integer(24)); 86 tests.put(new Integer(TYPE_INT_GRB), new Integer(24)); 87 tests.put(new Integer(TYPE_INT_GBR), new Integer(24)); 88 tests.put(new Integer(TYPE_INT_RBG), new Integer(24)); 89 tests.put(new Integer(TYPE_INT_BRG), new Integer(24)); 90 tests.put(new Integer(BufferedImage.TYPE_USHORT_555_RGB), new Integer(16)); 91 tests.put(new Integer(BufferedImage.TYPE_USHORT_565_RGB), new Integer(16)); 92 tests.put(new Integer(TYPE_INT_555_GRB), new Integer(16)); 93 tests.put(new Integer(TYPE_3BYTE_RGB), new Integer(24)); 94 tests.put(new Integer(TYPE_3BYTE_GRB), new Integer(24)); 95 } 96 97 private static String getImageTypeName(int t) { 98 switch(t) { 99 case BufferedImage.TYPE_INT_RGB: 100 return "TYPE_INT_RGB"; 101 case BufferedImage.TYPE_INT_BGR: 102 return "TYPE_INT_BGR"; 103 case BufferedImage.TYPE_3BYTE_BGR: 104 return "TYPE_3BYTE_BGR"; 105 case BufferedImage.TYPE_USHORT_555_RGB: 106 return "TYPE_USHORT_555_RGB"; 107 case BufferedImage.TYPE_USHORT_565_RGB: 108 return "TYPE_USHORT_565_RGB"; 109 case TYPE_INT_GRB: 110 return "TYPE_INT_GRB"; 111 case TYPE_INT_GBR: 112 return "TYPE_INT_GBR"; 113 case TYPE_INT_RBG: 114 return "TYPE_INT_RBG"; 115 case TYPE_INT_BRG: 116 return "TYPE_INT_BRG"; 117 case TYPE_INT_555_GRB: 118 return "TYPE_INT_555_GRB"; 119 case TYPE_3BYTE_RGB: 120 return "TYPE_3BYTE_RGB"; 121 case TYPE_3BYTE_GRB: 122 return "TYPE_3BYTE_GRB"; 123 default: 124 throw new IllegalArgumentException("Unknown image type: " + t); 125 } 126 } 127 private static BufferedImage createTestImage(int type) { 128 BufferedImage dst = null; 129 ColorModel colorModel = null; 130 WritableRaster raster = null; 131 ColorSpace cs = null; 132 System.out.println("Create image for " + getImageTypeName(type)); 133 switch(type) { 134 case TYPE_INT_GRB: 135 colorModel = new DirectColorModel(24, 136 0x0000ff00, 137 0x00ff0000, 138 0x000000ff); 139 break; 140 case TYPE_INT_GBR: 141 colorModel = new DirectColorModel(24, 142 0x000000ff, 143 0x00ff0000, 144 0x0000ff00); 145 break; 146 case TYPE_INT_RBG: 147 colorModel = new DirectColorModel(24, 148 0x00ff0000, 149 0x000000ff, 150 0x0000ff00); 151 break; 152 case TYPE_INT_BRG: 153 colorModel = new DirectColorModel(24, 154 0x0000ff00, 155 0x000000ff, 156 0x00ff0000); 157 break; 158 case TYPE_INT_555_GRB: 159 colorModel = new DirectColorModel(24, 160 0x0000001F, 161 0x000003e0, 162 0x00007c00); 163 break; 164 case TYPE_3BYTE_RGB: 165 cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 166 int[] nBits = {8, 8, 8}; 167 int[] bOffs = {0, 1, 2}; 168 colorModel = new ComponentColorModel(cs, nBits, false, false, 169 Transparency.OPAQUE, 170 DataBuffer.TYPE_BYTE); 171 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 172 w, h, 173 w*3, 3, 174 bOffs, null); 175 break; 176 case TYPE_3BYTE_GRB: 177 cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); 178 //nBits = {8, 8, 8}; 179 //bOffs = {0, 1, 2}; 180 colorModel = new ComponentColorModel(cs, new int[] { 8, 8, 8 }, false, false, 181 Transparency.OPAQUE, 182 DataBuffer.TYPE_BYTE); 183 raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 184 w, h, 185 w*3, 3, 186 new int[] { 1, 0, 2}, null); 187 break; 188 default: 189 dst = new BufferedImage(w, h, type); 190 //colorModel = ImageTypeSpecifier.createFromBufferedImageType(type).getColorModel(); 191 } 192 193 if (dst == null) { 194 if (raster == null) { 195 raster = colorModel.createCompatibleWritableRaster(w, h); 196 } 197 198 dst = new BufferedImage(colorModel, raster, false, null); 199 } 200 Graphics g = dst.createGraphics(); 201 for (int i = 0; i < usedColors.length; i ++) { 202 g.setColor(usedColors[i]); 203 g.fillRect(i * dx, 0, dx, h); 204 } 205 g.dispose(); 206 207 return dst; 208 } 209 210 private BufferedImage src; 211 private int expectedColorDepth; 212 private int type; 213 214 private IIOImage iio_dst; 215 216 public NoExtraBytesTest(int type, int expectedColorDepth) { 217 this.type = type; 218 this.src = createTestImage(type); 219 this.expectedColorDepth = expectedColorDepth; 220 } 221 222 public void doTest() throws IOException { 223 // write src as BMP 224 System.out.println("Test for image: " + getImageTypeName(type)); 225 System.out.println("image is " + src); 226 227 File f = File.createTempFile("sizeTest_", ".bmp", new File(".")); 228 System.out.println("Use file " + f.getCanonicalPath()); 229 ImageIO.write(src, "BMP", f); 230 231 //read it again 232 read(f); 233 234 checkColorDepth(); 235 236 checkImageContent(); 237 } 238 239 private void read(File f) throws IOException { 240 ImageReader reader = ImageIO.getImageReadersByFormatName("BMP").next(); 241 242 ImageInputStream iis = 243 ImageIO.createImageInputStream(new FileInputStream(f)); 244 245 reader.setInput(iis); 246 247 iio_dst = reader.readAll(0, reader.getDefaultReadParam()); 248 } 249 250 private void checkColorDepth() { 251 IIOMetadata dst = iio_dst.getMetadata(); 252 253 Node data = dst.getAsTree("javax_imageio_bmp_1.0"); 254 255 Node n = data.getFirstChild(); 256 257 while (n != null && !("BitsPerPixel".equals(n.getNodeName()))) { 258 System.out.println("Node " + n.getNodeName()); 259 n = n.getNextSibling(); 260 } 261 if (n == null) { 262 throw new RuntimeException("No BitsPerSample node!"); 263 } 264 265 int bpp = 0; 266 String value = n.getNodeValue(); 267 System.out.println("value = " + value); 268 try { 269 bpp = Integer.parseInt(value); 270 } catch (NumberFormatException e) { 271 throw new RuntimeException("Wrong bpp value: " + value, e); 272 } 273 274 if (bpp != this.expectedColorDepth) { 275 throw new RuntimeException("Wrong color depth: " + bpp + 276 " (should be " + this.expectedColorDepth + ")"); 277 } 278 } 279 280 private void checkImageContent() { 281 BufferedImage dst = 282 (BufferedImage)iio_dst.getRenderedImage(); 283 int y = h / 2; 284 int x = dx / 2; 285 286 for (int i = 0; i < usedColors.length; i++, x += dx) { 287 int srcRgb = src.getRGB(x, y); 288 int dstRgb = dst.getRGB(x, y); 289 int rgb = usedColors[i].getRGB(); 290 291 if (dstRgb != srcRgb || dstRgb != rgb) { 292 throw new RuntimeException("Wrong color at [" + x + ", " + y + 293 "] " + Integer.toHexString(dstRgb) + 294 " (srcRgb=" + Integer.toHexString(srcRgb) + 295 ", original color is " + Integer.toHexString(rgb) + ")"); 296 } 297 298 } 299 System.out.println("Image colors are OK."); 300 } 301 }