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