1 /* 2 * Copyright (c) 2012, 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 test.com.sun.javafx.iio; 27 28 import com.sun.javafx.iio.ImageFrame; 29 import com.sun.javafx.iio.ImageLoader; 30 import com.sun.javafx.iio.ImageStorage; 31 import com.sun.javafx.iio.gif.GIFImageLoader2; 32 import java.awt.image.*; 33 import java.io.*; 34 import static org.junit.Assert.*; 35 import org.junit.Test; 36 37 38 class TestStream extends InputStream { 39 byte data[]; 40 int p = 0; 41 42 public TestStream(byte data[]) { 43 this.data = data; 44 } 45 46 @Override 47 public int read() throws IOException { 48 return p < data.length ? (int)data[p++] & 0xff : -1; 49 } 50 } 51 52 public class GIFLoaderTest { 53 54 @Test 55 public void testCtorNPE() { 56 try { 57 new GIFImageLoader2(null); 58 } catch (NullPointerException ex) { 59 return; // PASSED 60 } catch (IOException ioEx) { 61 fail("unexpected IOException:" + ioEx.toString()); 62 } 63 fail("expected NPE after constructor invocation with null"); 64 } 65 66 67 68 @Test 69 public void testCtorReadBadHeader1() { 70 final byte tooShortHeaderData[] = { 71 0,1,2,3,4 72 }; 73 74 try { 75 new GIFImageLoader2(new TestStream(tooShortHeaderData)); 76 } catch (EOFException ex) { 77 return; // PASSED 78 } catch (IOException ioEx) { 79 fail("unexpected IOException:" + ioEx.toString()); 80 } 81 fail("expected EOF exception for streams lesser then 13 bytes"); 82 } 83 84 @Test 85 public void testCtorReadBadHeader2() { 86 final byte tooShortHeaderData[] = { 87 'G', 'I', 'F', '8', '9', 'a', 88 0, 0, 0, 0, 0, 0 89 }; 90 91 try { 92 new GIFImageLoader2(new TestStream(tooShortHeaderData)); 93 } catch (EOFException ex) { 94 return; // PASSED 95 } catch (IOException ioEx) { 96 fail("unexpected IOException:" + ioEx.toString()); 97 } 98 fail("expected EOF exception for streams lesser then 13 bytes"); 99 } 100 101 @Test 102 public void testCtorReadGoodHeader() { 103 final byte _87HeaderData[] = { 104 'G', 'I', 'F', '8', '7', 'a', 105 1, 0, 1, 0, 0, 0, 0 106 }; 107 final byte _89HeaderData[] = { 108 'G', 'I', 'F', '8', '9', 'a', 109 1, 0, 1, 0, 0, 0, 0 110 }; 111 try { 112 new GIFImageLoader2(new TestStream(_87HeaderData)); 113 new GIFImageLoader2(new TestStream(_89HeaderData)); 114 } catch (IOException ioEx) { 115 ioEx.printStackTrace(System.out); 116 fail("unexpected IOException:" + ioEx.toString()); 117 118 } 119 } 120 121 @Test (timeout=2000) 122 public void testCtorReadBadExtension() { 123 final byte badGifData[] = { 124 'G', 'I', 'F', '8', '9', 'a', 125 1, 0, 1, 0, -112, 0, 0, -18, 51, 34, 126 0, 0, 0, 44, 0, 0, 0, 0, 1, 0, 1, 0, 127 0, 2, 2, 4, 1, 43, 48 128 }; 129 130 // Create a loader using the data containing a bad GIF extension 131 GIFImageLoader2 loader = null; 132 try { 133 loader = new GIFImageLoader2(new TestStream(badGifData)); 134 } catch (IOException ioEx) { 135 fail("unexpected IOException:" + ioEx.toString()); 136 } 137 assertNotNull(loader); 138 139 // Now try to load the image; it should get an EOFException 140 try { 141 loader.load(0, 1, 1, true, true); 142 } catch (EOFException ex) { 143 return; // PASSED 144 } catch (IOException ioEx) { 145 fail("unexpected IOException:" + ioEx.toString()); 146 } 147 fail("expected EOF exception for streams with bad extension"); 148 } 149 150 private void compareBGRaAndIndexed(byte dataRGBA[], byte dataIndexed[], int paletteBGRA[]) { 151 assertEquals(dataIndexed.length*4, dataRGBA.length); 152 for (int i = 0, j = 0, e = dataIndexed.length; i < e; j += 4, ++i) { 153 int r = dataRGBA[j+0] & 0xFF, g = dataRGBA[j+1] & 0xFF, 154 b = dataRGBA[j+2] & 0xFF, a = dataRGBA[j+3] & 0xFF; 155 int x = b + (g<<8) + (r<<16) + (a<<24); 156 int y = paletteBGRA[dataIndexed[i] & 0xFF]; 157 158 if ((x != y) && (((x & 0xFF000000) != 0) || ((y & 0xFF000000) != 0))) { 159 fail("colors are different : JDK: " + Integer.toHexString(y) 160 + ", JavaFX: " + Integer.toHexString(x)); 161 } 162 } 163 } 164 165 private void compareBGRaAndIndexed(byte dataRGBA[], int dataIndexed[], int paletteBGRA[]) { 166 assertEquals(dataIndexed.length*4, dataRGBA.length); 167 for (int i = 0, j = 0, e = dataIndexed.length; i < e; j += 4, ++i) { 168 int r = dataRGBA[j+0] & 0xFF, g = dataRGBA[j+1] & 0xFF, 169 b = dataRGBA[j+2] & 0xFF, a = dataRGBA[j+3] & 0xFF; 170 int x = b + (g<<8) + (r<<16) + (a<<24); 171 int y = paletteBGRA[dataIndexed[i] & 0xFF]; 172 if ((x != y) && (((x & 0xFF000000) != 0) || ((y & 0xFF000000) != 0))) { 173 fail("colors are different : JDK: " + Integer.toHexString(y) 174 + ", JavaFX: " + Integer.toHexString(x)); 175 } 176 } 177 } 178 179 180 private void compareImageFrameAndBImage(ImageFrame f, BufferedImage bimg) { 181 byte dataRGBA[] = (byte[])f.getImageData().array(); 182 assertEquals(dataRGBA.length, f.getHeight() * f.getWidth() * 4); 183 assertEquals(f.getImageType(), ImageStorage.ImageType.RGBA); 184 185 assertEquals(f.getHeight(), bimg.getHeight()); 186 assertEquals(f.getWidth(), bimg.getWidth()); 187 188 if (bimg.getColorModel() instanceof IndexColorModel) { 189 IndexColorModel idx = (IndexColorModel)bimg.getColorModel(); 190 int rgb[] = new int [256]; 191 idx.getRGBs(rgb); 192 Raster r = bimg.getData(); 193 DataBuffer db = r.getDataBuffer(); 194 assertTrue( db instanceof DataBufferByte); 195 DataBufferByte bdb = (DataBufferByte)db; 196 assertEquals(bdb.getNumBanks(), 1); 197 byte dataIndexed[] = bdb.getData(0); 198 int bitsPerPixel = idx.getPixelSize(); 199 if (bitsPerPixel == 8) { 200 assertEquals(dataIndexed.length, f.getHeight()*f.getWidth()); 201 compareBGRaAndIndexed(dataRGBA, dataIndexed, rgb); 202 } else { 203 int rgbData[] = new int[bimg.getWidth() * bimg.getHeight()]; 204 r.getPixels(0, 0, bimg.getWidth(), bimg.getHeight(), rgbData); 205 compareBGRaAndIndexed(dataRGBA, rgbData, rgb); 206 } 207 } else { 208 Raster r = bimg.getData(); 209 // System.out.println("" + r.getWidth() + "," + r.getHeight() + "," + r.getNumBands() 210 // + "," + r.getDataBuffer() + "," + r.getSampleModel()); 211 fail("Unexpected image form AWT"); 212 } 213 } 214 215 private void testReadGIFFile(String fname) throws IOException { 216 InputStream i = this.getClass().getResourceAsStream(fname); 217 InputStream testStream = ImageTestHelper.createStutteringInputStream(i); 218 ImageLoader l = new GIFImageLoader2(testStream); 219 ImageFrame f = l.load(0, 0, 0, true, false); 220 InputStream i2 = this.getClass().getResourceAsStream(fname); 221 BufferedImage bimg = javax.imageio.ImageIO.read(i2); 222 223 compareImageFrameAndBImage(f, bimg); 224 } 225 226 @Test 227 public void testReadGIFFile() throws Exception { 228 for (String s : fileList) { 229 try { 230 testReadGIFFile(s); 231 } catch (Exception ex) { 232 System.err.println("Failure in test file " + s); 233 throw ex; 234 } 235 } 236 } 237 238 // public static void main(String[] args) throws IOException { 239 // new GIFLoaderTest().testReadGIFFile(); 240 // } 241 242 final static String fileList[] = { 243 "gif/adam_7_interlacing/basi0g01.gif", 244 "gif/adam_7_interlacing/basi0g02.gif", 245 "gif/adam_7_interlacing/basi0g04.gif", 246 "gif/adam_7_interlacing/basi0g08.gif", 247 "gif/adam_7_interlacing/basi0g16.gif", 248 "gif/adam_7_interlacing/basi2c08.gif", 249 "gif/adam_7_interlacing/basi2c16.gif", 250 "gif/adam_7_interlacing/basi3p01.gif", 251 "gif/adam_7_interlacing/basi3p02.gif", 252 "gif/adam_7_interlacing/basi3p04.gif", 253 "gif/adam_7_interlacing/basi3p08.gif", 254 "gif/adam_7_interlacing/basi4a08.gif", 255 "gif/adam_7_interlacing/basi4a16.gif", 256 "gif/adam_7_interlacing/basi6a08.gif", 257 "gif/adam_7_interlacing/basi6a16.gif", 258 "gif/base/basn0g01.gif", 259 "gif/base/basn0g02.gif", 260 "gif/base/basn0g04.gif", 261 "gif/base/basn0g08.gif", 262 "gif/base/basn0g16.gif", 263 "gif/base/basn2c08.gif", 264 "gif/base/basn2c16.gif", 265 "gif/base/basn3p01.gif", 266 "gif/base/basn3p02.gif", 267 "gif/base/basn3p04.gif", 268 "gif/base/basn3p08.gif", 269 "gif/base/basn4a08.gif", 270 "gif/base/basn4a16.gif", 271 "gif/base/basn6a08.gif", 272 "gif/base/basn6a16.gif", 273 "gif/background/bgai4a08.gif", 274 "gif/background/bgai4a16.gif", 275 "gif/background/bgan6a08.gif", 276 "gif/background/bgan6a16.gif", 277 "gif/background/bgbn4a08.gif", 278 "gif/background/bggn4a16.gif", 279 "gif/background/bgwn6a08.gif", 280 "gif/background/bgyn6a16.gif", 281 "gif/ancillary_chunks/ccwn2c08.gif", 282 "gif/ancillary_chunks/ccwn3p08.gif", 283 "gif/ancillary_chunks/cdfn2c08.gif", 284 "gif/ancillary_chunks/cdhn2c08.gif", 285 "gif/ancillary_chunks/cdsn2c08.gif", 286 "gif/ancillary_chunks/cdun2c08.gif", 287 "gif/ancillary_chunks/ch1n3p04.gif", 288 "gif/ancillary_chunks/ch2n3p08.gif", 289 "gif/ancillary_chunks/cm0n0g04.gif", 290 "gif/ancillary_chunks/cm7n0g04.gif", 291 "gif/ancillary_chunks/cm9n0g04.gif", 292 "gif/ancillary_chunks/cs3n2c16.gif", 293 "gif/ancillary_chunks/cs3n3p08.gif", 294 "gif/ancillary_chunks/cs5n2c08.gif", 295 "gif/ancillary_chunks/cs5n3p08.gif", 296 "gif/ancillary_chunks/cs8n2c08.gif", 297 "gif/ancillary_chunks/cs8n3p08.gif", 298 "gif/ancillary_chunks/ct0n0g04.gif", 299 "gif/ancillary_chunks/ct1n0g04.gif", 300 "gif/ancillary_chunks/cten0g04.gif", 301 "gif/ancillary_chunks/ctfn0g04.gif", 302 "gif/ancillary_chunks/ctgn0g04.gif", 303 "gif/ancillary_chunks/cthn0g04.gif", 304 "gif/ancillary_chunks/ctjn0g04.gif", 305 "gif/filtering/f00n0g08.gif", 306 "gif/filtering/f00n2c08.gif", 307 "gif/filtering/f01n0g08.gif", 308 "gif/filtering/f01n2c08.gif", 309 "gif/filtering/f02n0g08.gif", 310 "gif/filtering/f02n2c08.gif", 311 "gif/filtering/f03n0g08.gif", 312 "gif/filtering/f03n2c08.gif", 313 "gif/filtering/f04n0g08.gif", 314 "gif/filtering/f04n2c08.gif", 315 "gif/filtering/f99n0g04.gif", 316 "gif/gamma/g03n0g16.gif", 317 "gif/gamma/g03n2c08.gif", 318 "gif/gamma/g03n3p04.gif", 319 "gif/gamma/g04n0g16.gif", 320 "gif/gamma/g04n2c08.gif", 321 "gif/gamma/g04n3p04.gif", 322 "gif/gamma/g05n0g16.gif", 323 "gif/gamma/g05n2c08.gif", 324 "gif/gamma/g05n3p04.gif", 325 "gif/gamma/g07n0g16.gif", 326 "gif/gamma/g07n2c08.gif", 327 "gif/gamma/g07n3p04.gif", 328 "gif/gamma/g10n0g16.gif", 329 "gif/gamma/g10n2c08.gif", 330 "gif/gamma/g10n3p04.gif", 331 "gif/gamma/g25n0g16.gif", 332 "gif/gamma/g25n2c08.gif", 333 "gif/gamma/g25n3p04.gif", 334 "gif/chunk_ordering/oi1n0g16.gif", 335 "gif/chunk_ordering/oi1n2c16.gif", 336 "gif/chunk_ordering/oi2n0g16.gif", 337 "gif/chunk_ordering/oi2n2c16.gif", 338 "gif/chunk_ordering/oi4n0g16.gif", 339 "gif/chunk_ordering/oi4n2c16.gif", 340 "gif/chunk_ordering/oi9n0g16.gif", 341 "gif/chunk_ordering/oi9n2c16.gif", 342 "gif/add_palets/pp0n2c16.gif", 343 "gif/add_palets/pp0n6a08.gif", 344 "gif/add_palets/ps1n0g08.gif", 345 "gif/add_palets/ps1n2c16.gif", 346 "gif/add_palets/ps2n0g08.gif", 347 "gif/add_palets/ps2n2c16.gif", 348 "gif/odd_sizes/s01i3p01.gif", 349 "gif/odd_sizes/s01n3p01.gif", 350 "gif/odd_sizes/s02i3p01.gif", 351 "gif/odd_sizes/s02n3p01.gif", 352 "gif/odd_sizes/s03i3p01.gif", 353 "gif/odd_sizes/s03n3p01.gif", 354 "gif/odd_sizes/s04i3p01.gif", 355 "gif/odd_sizes/s04n3p01.gif", 356 "gif/odd_sizes/s05i3p02.gif", 357 "gif/odd_sizes/s05n3p02.gif", 358 "gif/odd_sizes/s06i3p02.gif", 359 "gif/odd_sizes/s06n3p02.gif", 360 "gif/odd_sizes/s07i3p02.gif", 361 "gif/odd_sizes/s07n3p02.gif", 362 "gif/odd_sizes/s08i3p02.gif", 363 "gif/odd_sizes/s08n3p02.gif", 364 "gif/odd_sizes/s09i3p02.gif", 365 "gif/odd_sizes/s09n3p02.gif", 366 "gif/odd_sizes/s32i3p04.gif", 367 "gif/odd_sizes/s32n3p04.gif", 368 "gif/odd_sizes/s33i3p04.gif", 369 "gif/odd_sizes/s33n3p04.gif", 370 "gif/odd_sizes/s34i3p04.gif", 371 "gif/odd_sizes/s34n3p04.gif", 372 "gif/odd_sizes/s35i3p04.gif", 373 "gif/odd_sizes/s35n3p04.gif", 374 "gif/odd_sizes/s36i3p04.gif", 375 "gif/odd_sizes/s36n3p04.gif", 376 "gif/odd_sizes/s37i3p04.gif", 377 "gif/odd_sizes/s37n3p04.gif", 378 "gif/odd_sizes/s38i3p04.gif", 379 "gif/odd_sizes/s38n3p04.gif", 380 "gif/odd_sizes/s39i3p04.gif", 381 "gif/odd_sizes/s39n3p04.gif", 382 "gif/odd_sizes/s40i3p04.gif", 383 "gif/odd_sizes/s40n3p04.gif", 384 "gif/transparency/tbbn0g04.gif", 385 "gif/transparency/tbbn2c16.gif", 386 "gif/transparency/tbbn3p08.gif", 387 "gif/transparency/tbgn2c16.gif", 388 "gif/transparency/tbgn3p08.gif", 389 "gif/transparency/tbrn2c08.gif", 390 "gif/transparency/tbwn0g16.gif", 391 "gif/transparency/tbwn3p08.gif", 392 "gif/transparency/tbyn3p08.gif", 393 "gif/transparency/tp0n0g08.gif", 394 "gif/transparency/tp0n2c08.gif", 395 "gif/transparency/tp0n3p08.gif", 396 "gif/transparency/tp1n3p08.gif", 397 "gif/corrupted/xc1n0g08.gif", 398 "gif/corrupted/xc9n2c08.gif", 399 "gif/corrupted/xcrn0g04.gif", 400 "gif/corrupted/xcsn0g01.gif", 401 "gif/corrupted/xd0n2c08.gif", 402 "gif/corrupted/xd3n2c08.gif", 403 "gif/corrupted/xd9n2c08.gif", 404 "gif/corrupted/xdtn0g01.gif", 405 "gif/corrupted/xhdn0g08.gif", 406 "gif/corrupted/xlfn0g04.gif", 407 "gif/corrupted/xs1n0g01.gif", 408 "gif/corrupted/xs2n0g01.gif", 409 "gif/corrupted/xs4n0g01.gif", 410 "gif/corrupted/xs7n0g01.gif", 411 "gif/zlib_compression_level/z00n2c08.gif", 412 "gif/zlib_compression_level/z03n2c08.gif", 413 "gif/zlib_compression_level/z06n2c08.gif", 414 "gif/zlib_compression_level/z09n2c08.gif" 415 }; 416 }