1 /* 2 * Copyright (c) 2014, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.javafx.iio; 27 28 import com.sun.javafx.iio.bmp.BMPImageLoaderFactory; 29 import com.sun.prism.Image; 30 import java.awt.image.BufferedImage; 31 import java.awt.image.DataBuffer; 32 import java.awt.image.IndexColorModel; 33 import java.io.ByteArrayInputStream; 34 import java.io.ByteArrayOutputStream; 35 import java.io.File; 36 import java.io.FileInputStream; 37 import java.io.IOException; 38 import java.io.InputStream; 39 import javax.imageio.ImageIO; 40 import javax.imageio.stream.MemoryCacheImageInputStream; 41 import static org.junit.Assert.*; 42 import org.junit.Test; 43 44 public class BMPImageLoaderTest { 45 // if true, the test will write BMP files generated by JDK to the current directory 46 static final boolean writeFiles = false; 47 static final int testWidth = 509, testHeight = 157; 48 49 ByteArrayInputStream constructStream(int[] bytes) { 50 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 51 for (int b : bytes) { 52 baos.write(b); 53 } 54 return new ByteArrayInputStream(baos.toByteArray()); 55 } 56 57 int getByte(int dword, int shift) { 58 return (dword >> shift) & 0xff; 59 } 60 61 boolean compareByte(int p1, int p2, int shift, int tolerance) { 62 return Math.abs(getByte(p1, shift) - getByte(p2, shift)) <= tolerance; 63 } 64 65 boolean compareRGB(int p1, int p2, int tolerance) { 66 return compareByte(p1, p2, 24, tolerance) && 67 compareByte(p1, p2, 16, tolerance) && 68 compareByte(p1, p2, 8, tolerance); 69 } 70 71 void compare(Image img, BufferedImage bImg) { 72 assertNotNull(img); 73 assertNotNull(bImg); 74 int w = bImg.getWidth(), h = bImg.getHeight(); 75 assertEquals("Unmatched width", w, img.getWidth()); 76 assertEquals("Unmatched height", h, img.getHeight()); 77 78 for (int y = 0; y < h; y++) { 79 for (int x = 0; x < w; x++) { 80 int p1 = bImg.getRGB(x, y); 81 int p2 = img.getArgb(x, y); 82 if (!compareRGB(p1, p2, 1)) { 83 throw new org.junit.ComparisonFailure( 84 "pixel " + x + ", " + y + " does not match", 85 String.format("0x%08X", p1), String.format("0x%08X", p2) 86 ); 87 } 88 } 89 } 90 } 91 92 Image loadImage(InputStream stream) { 93 ImageLoaderFactory loaderFactory = BMPImageLoaderFactory.getInstance(); 94 ImageLoader loader = null; 95 try { 96 loader = loaderFactory.createImageLoader(stream); 97 } catch (IOException ioEx) { 98 fail("unexpected IOException: " + ioEx); 99 } 100 assertNotNull(loader); 101 102 try { 103 ImageFrame frame = loader.load(0, 0, 0, true, true); 104 return Image.convertImageFrame(frame); 105 } catch (IOException e) { 106 fail("unexpected IOException: " + e); 107 } 108 return null; 109 } 110 111 BufferedImage create4BitImage() { 112 int[] cmap = new int[16]; 113 int i = 0; 114 for (int r = 0; r < 2; r++) { 115 for (int g = 0; g < 2; g++) { 116 for (int b = 0; b < 2; b++) { 117 cmap[i++] = 0xff << 24 | r * 255 << 16 | g * 255 << 8 | b * 255; 118 if ((r | g | b) == 0) { 119 cmap[i++] = 0xffc0c0c0; 120 } else { 121 cmap[i++] = 0xff << 24 | r * 128 << 16 | g * 128 << 8 | b * 128; 122 } 123 } 124 } 125 } 126 IndexColorModel cm = new IndexColorModel(4, 16, cmap, 0, false, -1, DataBuffer.TYPE_BYTE); 127 return new BufferedImage(testWidth, testHeight, BufferedImage.TYPE_BYTE_BINARY, cm); 128 } 129 130 BufferedImage createImage(int type) { 131 return new BufferedImage(testWidth, testHeight, type); 132 } 133 134 void writeBMPImage(BufferedImage bImg, String fileName, String compression) { 135 ImageTestHelper.writeImage(bImg, fileName, "bmp", compression); 136 } 137 138 Image getImage(BufferedImage bImg, String compression) { 139 ByteArrayInputStream stream = 140 ImageTestHelper.writeImageToStream(bImg, "bmp", compression, null); 141 return loadImage(stream); 142 } 143 144 void testImageType(int type, String fileName, String compression) { 145 BufferedImage bImg = createImage(type); 146 testImage(bImg, fileName, compression); 147 } 148 149 void testImageType(int type, String fileName) { 150 BufferedImage bImg = createImage(type); 151 testImage(bImg, fileName, null); 152 } 153 154 void testImage(BufferedImage bImg, String fileName, String compression) { 155 //ImageTestHelper.drawImageHue(bImg); 156 //ImageTestHelper.drawImageAll(bImg); 157 ImageTestHelper.drawImageRandom(bImg); 158 if (writeFiles) { 159 writeBMPImage(bImg, fileName, compression); 160 } 161 Image image = getImage(bImg, compression); 162 compare(image, bImg); 163 } 164 165 @Test 166 public void testRT32213() { 167 final int[] bytes = { 168 0x42, 0x4d, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 169 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x28, 0x00, 170 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 171 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 172 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 175 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x80, 0x00, 176 0x00, 0x00 177 }; 178 179 ByteArrayInputStream stream = constructStream(bytes); 180 Image image = loadImage(stream); 181 stream.reset(); 182 try { 183 BufferedImage bImg = ImageIO.read(new MemoryCacheImageInputStream(stream)); 184 compare(image, bImg); 185 } catch (IOException e) { 186 fail("unexpected IOException: " + e); 187 } 188 } 189 190 @Test 191 public void test1Bit() { 192 testImageType(BufferedImage.TYPE_BYTE_BINARY, "out1bit.bmp"); 193 } 194 195 @Test 196 public void test4Bit() { 197 testImage(create4BitImage(), "out4bit.bmp", null); 198 } 199 200 //@Test 201 public void test4BitRLE() { 202 testImage(create4BitImage(), "out4bitRLE.bmp", "BI_RLE4"); 203 } 204 205 @Test 206 public void test8Bit() { 207 testImageType(BufferedImage.TYPE_BYTE_INDEXED, "out8bit.bmp"); 208 } 209 210 @Test 211 public void test8BitRLE() { 212 testImageType(BufferedImage.TYPE_BYTE_INDEXED, "out8bitRLE.bmp", "BI_RLE8"); 213 } 214 215 @Test 216 public void test16Bit() { 217 testImageType(BufferedImage.TYPE_USHORT_555_RGB, "out16bit.bmp"); 218 } 219 220 @Test 221 public void test24Bit() { 222 testImageType(BufferedImage.TYPE_INT_RGB, "out24bit.bmp"); 223 } 224 225 void testFile(String fileName, String outFileName, String compression) { 226 try { 227 Image image = loadImage(new FileInputStream(fileName)); 228 BufferedImage bImg = ImageIO.read(new File(fileName)); 229 if (writeFiles) { 230 writeBMPImage(bImg, outFileName, compression); 231 } 232 compare(image, bImg); 233 } catch (IOException e) { 234 fail("unexpected IOException: " + e); 235 } 236 } 237 238 //@Test 239 public void testFiles() { 240 testFile("pal4rle.bmp", "pal4rleOut.bmp", "BI_RLE4"); 241 testFile("out4bitRLE.bmp", "out4bitRLEOut.bmp", "BI_RLE4"); 242 testFile("pal8rletrns.bmp", "pal8rletrnsOut.bmp", null); 243 } 244 }