1 /* 2 * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41 package j2dbench.tests.iio; 42 43 import java.awt.Component; 44 import java.awt.Graphics; 45 import java.awt.Image; 46 import java.awt.MediaTracker; 47 import java.awt.Toolkit; 48 import java.awt.image.BufferedImage; 49 import java.io.BufferedInputStream; 50 import java.io.ByteArrayInputStream; 51 import java.io.ByteArrayOutputStream; 52 import java.io.File; 53 import java.io.FileInputStream; 54 import java.io.IOException; 55 import java.io.InputStream; 56 import java.io.OutputStream; 57 import java.net.URL; 58 import java.util.ArrayList; 59 import java.util.List; 60 import javax.imageio.ImageIO; 61 import javax.imageio.ImageReader; 62 import javax.imageio.event.IIOReadProgressListener; 63 import javax.imageio.spi.IIORegistry; 64 import javax.imageio.spi.ImageReaderSpi; 65 import javax.imageio.stream.ImageInputStream; 66 67 import j2dbench.Group; 68 import j2dbench.Modifier; 69 import j2dbench.Option; 70 import j2dbench.Result; 71 import j2dbench.Test; 72 import j2dbench.TestEnvironment; 73 74 abstract class InputImageTests extends InputTests { 75 76 private static final int TEST_TOOLKIT = 1; 77 private static final int TEST_IMAGEIO = 2; 78 private static final int TEST_IMAGEREADER = 3; 79 80 private static Group imageRoot; 81 82 private static Group toolkitRoot; 83 private static Group toolkitOptRoot; 84 private static Option toolkitReadFormatList; 85 private static Group toolkitTestRoot; 86 87 private static Group imageioRoot; 88 private static Group imageioOptRoot; 89 private static ImageReaderSpi[] imageioReaderSpis; 90 private static String[] imageioReadFormatShortNames; 91 private static Option imageioReadFormatList; 92 private static Group imageioTestRoot; 93 94 private static Group imageReaderRoot; 95 private static Group imageReaderOptRoot; 96 private static Option seekForwardOnlyTog; 97 private static Option ignoreMetadataTog; 98 private static Option installListenerTog; 99 private static Group imageReaderTestRoot; 100 101 public static void init() { 102 imageRoot = new Group(inputRoot, "image", "Image Reading Benchmarks"); 103 imageRoot.setTabbed(); 104 105 // Toolkit Benchmarks 106 toolkitRoot = new Group(imageRoot, "toolkit", "Toolkit"); 107 108 toolkitOptRoot = new Group(toolkitRoot, "opts", "Toolkit Options"); 109 String[] tkFormats = new String[] {"gif", "jpg", "png"}; 110 toolkitReadFormatList = 111 new Option.ObjectList(toolkitOptRoot, 112 "format", "Image Format", 113 tkFormats, tkFormats, 114 tkFormats, tkFormats, 115 0x0); 116 117 toolkitTestRoot = new Group(toolkitRoot, "tests", "Toolkit Tests"); 118 new ToolkitCreateImage(); 119 120 // Image I/O Benchmarks 121 if (hasImageIO) { 122 imageioRoot = new Group(imageRoot, "imageio", "Image I/O"); 123 124 // Image I/O Options 125 imageioOptRoot = new Group(imageioRoot, "opts", 126 "Image I/O Options"); 127 initIIOReadFormats(); 128 imageioReadFormatList = 129 new Option.ObjectList(imageioOptRoot, 130 "format", "Image Format", 131 imageioReadFormatShortNames, 132 imageioReaderSpis, 133 imageioReadFormatShortNames, 134 imageioReadFormatShortNames, 135 0x0); 136 137 // Image I/O Tests 138 imageioTestRoot = new Group(imageioRoot, "tests", 139 "Image I/O Tests"); 140 new ImageIORead(); 141 142 // ImageReader Options 143 imageReaderRoot = new Group(imageioRoot, "reader", 144 "ImageReader Benchmarks"); 145 imageReaderOptRoot = new Group(imageReaderRoot, "opts", 146 "ImageReader Options"); 147 seekForwardOnlyTog = 148 new Option.Toggle(imageReaderOptRoot, 149 "seekForwardOnly", 150 "Seek Forward Only", 151 Option.Toggle.On); 152 ignoreMetadataTog = 153 new Option.Toggle(imageReaderOptRoot, 154 "ignoreMetadata", 155 "Ignore Metadata", 156 Option.Toggle.On); 157 installListenerTog = 158 new Option.Toggle(imageReaderOptRoot, 159 "installListener", 160 "Install Progress Listener", 161 Option.Toggle.Off); 162 163 // ImageReader Tests 164 imageReaderTestRoot = new Group(imageReaderRoot, "tests", 165 "ImageReader Tests"); 166 new ImageReaderRead(); 167 new ImageReaderGetImageMetadata(); 168 } 169 } 170 171 private static void initIIOReadFormats() { 172 List spis = new ArrayList(); 173 List shortNames = new ArrayList(); 174 175 ImageIO.scanForPlugins(); 176 IIORegistry registry = IIORegistry.getDefaultInstance(); 177 java.util.Iterator readerspis = 178 registry.getServiceProviders(ImageReaderSpi.class, false); 179 while (readerspis.hasNext()) { 180 // REMIND: there could be more than one non-core plugin for 181 // a particular format, as is the case for JPEG2000 in the JAI 182 // IIO Tools package, so we should support that somehow 183 ImageReaderSpi spi = (ImageReaderSpi)readerspis.next(); 184 String klass = spi.getClass().getName(); 185 String format = spi.getFormatNames()[0].toLowerCase(); 186 String suffix = spi.getFileSuffixes()[0].toLowerCase(); 187 if (suffix == null || suffix.isEmpty()) { 188 suffix = format; 189 } 190 String shortName; 191 if (klass.startsWith("com.sun.imageio.plugins")) { 192 shortName = "core-" + suffix; 193 } else { 194 shortName = "ext-" + suffix; 195 } 196 spis.add(spi); 197 shortNames.add(shortName); 198 } 199 200 imageioReaderSpis = new ImageReaderSpi[spis.size()]; 201 imageioReaderSpis = (ImageReaderSpi[])spis.toArray(imageioReaderSpis); 202 imageioReadFormatShortNames = new String[shortNames.size()]; 203 imageioReadFormatShortNames = 204 (String[])shortNames.toArray(imageioReadFormatShortNames); 205 } 206 207 protected InputImageTests(Group parent, 208 String nodeName, String description) 209 { 210 super(parent, nodeName, description); 211 } 212 213 public void cleanupTest(TestEnvironment env, Object ctx) { 214 Context iioctx = (Context)ctx; 215 iioctx.cleanup(env); 216 } 217 218 private static class Context extends InputTests.Context { 219 String format; 220 BufferedImage image; 221 ImageReader reader; 222 boolean seekForwardOnly; 223 boolean ignoreMetadata; 224 225 Context(TestEnvironment env, Result result, int testType) { 226 super(env, result); 227 228 String content = (String)env.getModifier(contentList); 229 if (content == null) { 230 content = CONTENT_BLANK; 231 } 232 // REMIND: add option for non-opaque images 233 image = createBufferedImage(size, size, content, false); 234 235 result.setUnits(size*size); 236 result.setUnitName("pixel"); 237 238 if (testType == TEST_IMAGEIO || testType == TEST_IMAGEREADER) { 239 ImageReaderSpi readerspi = 240 (ImageReaderSpi)env.getModifier(imageioReadFormatList); 241 format = readerspi.getFileSuffixes()[0].toLowerCase(); 242 if (testType == TEST_IMAGEREADER) { 243 seekForwardOnly = env.isEnabled(seekForwardOnlyTog); 244 ignoreMetadata = env.isEnabled(ignoreMetadataTog); 245 try { 246 reader = readerspi.createReaderInstance(); 247 } catch (IOException e) { 248 System.err.println("error creating reader"); 249 e.printStackTrace(); 250 } 251 if (env.isEnabled(installListenerTog)) { 252 reader.addIIOReadProgressListener( 253 new ReadProgressListener()); 254 } 255 } 256 if (format.equals("wbmp")) { 257 // REMIND: this is a hack to create an image that the 258 // WBMPImageWriter can handle (a better approach 259 // would involve checking the ImageTypeSpecifier 260 // of the writer's default image param) 261 BufferedImage newimg = 262 new BufferedImage(size, size, 263 BufferedImage.TYPE_BYTE_BINARY); 264 Graphics g = newimg.createGraphics(); 265 g.drawImage(image, 0, 0, null); 266 g.dispose(); 267 image = newimg; 268 } 269 } else if (testType == TEST_TOOLKIT) { 270 format = (String)env.getModifier(toolkitReadFormatList); 271 } else { // testType == TEST_JPEGCODEC 272 format = "jpeg"; 273 } 274 275 initInput(); 276 } 277 278 void initContents(File f) throws IOException { 279 ImageIO.write(image, format, f); 280 } 281 282 void initContents(OutputStream out) throws IOException { 283 ImageIO.write(image, format, out); 284 } 285 286 void cleanup(TestEnvironment env) { 287 super.cleanup(env); 288 if (reader != null) { 289 reader.dispose(); 290 reader = null; 291 } 292 } 293 } 294 295 private static class ToolkitCreateImage extends InputImageTests { 296 private static final Component canvas = new Component() {}; 297 298 public ToolkitCreateImage() { 299 super(toolkitTestRoot, 300 "createImage", 301 "Toolkit.createImage()"); 302 addDependency(generalSourceRoot, 303 new Modifier.Filter() { 304 public boolean isCompatible(Object val) { 305 // Toolkit handles FILE, URL, and ARRAY, but 306 // not FILECHANNEL 307 InputType t = (InputType)val; 308 return (t.getType() != INPUT_FILECHANNEL); 309 } 310 }); 311 addDependencies(toolkitOptRoot, true); 312 } 313 314 public Object initTest(TestEnvironment env, Result result) { 315 return new Context(env, result, TEST_TOOLKIT); 316 } 317 318 public void runTest(Object ctx, int numReps) { 319 final Context ictx = (Context)ctx; 320 final Object input = ictx.input; 321 final int inputType = ictx.inputType; 322 final Toolkit tk = Toolkit.getDefaultToolkit(); 323 final MediaTracker mt = new MediaTracker(canvas); 324 switch (inputType) { 325 case INPUT_FILE: 326 String filename = ((File)input).getAbsolutePath(); 327 do { 328 try { 329 Image img = tk.createImage(filename); 330 mt.addImage(img, 0); 331 mt.waitForID(0, 0); 332 mt.removeImage(img, 0); 333 } catch (Exception e) { 334 e.printStackTrace(); 335 } 336 } while (--numReps >= 0); 337 break; 338 case INPUT_URL: 339 do { 340 try { 341 Image img = tk.createImage((URL)input); 342 mt.addImage(img, 0); 343 mt.waitForID(0, 0); 344 mt.removeImage(img, 0); 345 } catch (Exception e) { 346 e.printStackTrace(); 347 } 348 } while (--numReps >= 0); 349 break; 350 case INPUT_ARRAY: 351 do { 352 try { 353 Image img = tk.createImage((byte[])input); 354 mt.addImage(img, 0); 355 mt.waitForID(0, 0); 356 mt.removeImage(img, 0); 357 } catch (Exception e) { 358 e.printStackTrace(); 359 } 360 } while (--numReps >= 0); 361 break; 362 default: 363 throw new IllegalArgumentException("Invalid input type"); 364 } 365 } 366 } 367 368 private static class ImageIORead extends InputImageTests { 369 public ImageIORead() { 370 super(imageioTestRoot, 371 "imageioRead", 372 "ImageIO.read()"); 373 addDependency(generalSourceRoot, 374 new Modifier.Filter() { 375 public boolean isCompatible(Object val) { 376 // ImageIO.read() handles FILE, URL, and ARRAY, but 377 // not FILECHANNEL (well, I suppose we could create 378 // an ImageInputStream from a FileChannel source, 379 // but that's not a common use case; FileChannel is 380 // better handled by the ImageReader tests below) 381 InputType t = (InputType)val; 382 return (t.getType() != INPUT_FILECHANNEL); 383 } 384 }); 385 addDependencies(imageioOptRoot, true); 386 } 387 388 public Object initTest(TestEnvironment env, Result result) { 389 return new Context(env, result, TEST_IMAGEIO); 390 } 391 392 public void runTest(Object ctx, int numReps) { 393 final Context ictx = (Context)ctx; 394 final Object input = ictx.input; 395 final int inputType = ictx.inputType; 396 switch (inputType) { 397 case INPUT_FILE: 398 do { 399 try { 400 ImageIO.read((File)input); 401 } catch (Exception e) { 402 e.printStackTrace(); 403 } 404 } while (--numReps >= 0); 405 break; 406 case INPUT_URL: 407 do { 408 try { 409 ImageIO.read((URL)input); 410 } catch (Exception e) { 411 e.printStackTrace(); 412 } 413 } while (--numReps >= 0); 414 break; 415 case INPUT_ARRAY: 416 do { 417 try { 418 ByteArrayInputStream bais = 419 new ByteArrayInputStream((byte[])input); 420 BufferedInputStream bis = 421 new BufferedInputStream(bais); 422 ImageIO.read(bis); 423 bais.close(); 424 } catch (Exception e) { 425 e.printStackTrace(); 426 } 427 } while (--numReps >= 0); 428 break; 429 default: 430 throw new IllegalArgumentException("Invalid input type"); 431 } 432 } 433 } 434 435 private static class ImageReaderRead extends InputImageTests { 436 public ImageReaderRead() { 437 super(imageReaderTestRoot, 438 "read", 439 "ImageReader.read()"); 440 addDependency(generalSourceRoot); 441 addDependencies(imageioGeneralOptRoot, true); 442 addDependencies(imageioOptRoot, true); 443 addDependencies(imageReaderOptRoot, true); 444 } 445 446 public Object initTest(TestEnvironment env, Result result) { 447 return new Context(env, result, TEST_IMAGEREADER); 448 } 449 450 public void runTest(Object ctx, int numReps) { 451 final Context ictx = (Context)ctx; 452 final ImageReader reader = ictx.reader; 453 final boolean seekForwardOnly = ictx.seekForwardOnly; 454 final boolean ignoreMetadata = ictx.ignoreMetadata; 455 do { 456 try { 457 ImageInputStream iis = ictx.createImageInputStream(); 458 reader.setInput(iis, seekForwardOnly, ignoreMetadata); 459 reader.read(0); 460 reader.reset(); 461 iis.close(); 462 ictx.closeOriginalStream(); 463 } catch (IOException e) { 464 e.printStackTrace(); 465 } 466 } while (--numReps >= 0); 467 } 468 } 469 470 private static class ImageReaderGetImageMetadata extends InputImageTests { 471 public ImageReaderGetImageMetadata() { 472 super(imageReaderTestRoot, 473 "getImageMetadata", 474 "ImageReader.getImageMetadata()"); 475 addDependency(generalSourceRoot); 476 addDependencies(imageioGeneralOptRoot, true); 477 addDependencies(imageioOptRoot, true); 478 addDependencies(imageReaderOptRoot, true); 479 } 480 481 public Object initTest(TestEnvironment env, Result result) { 482 Context ctx = new Context(env, result, TEST_IMAGEREADER); 483 // override units since this test doesn't read "pixels" 484 result.setUnits(1); 485 result.setUnitName("image"); 486 return ctx; 487 } 488 489 public void runTest(Object ctx, int numReps) { 490 final Context ictx = (Context)ctx; 491 final ImageReader reader = ictx.reader; 492 final boolean seekForwardOnly = ictx.seekForwardOnly; 493 final boolean ignoreMetadata = ictx.ignoreMetadata; 494 do { 495 try { 496 ImageInputStream iis = ictx.createImageInputStream(); 497 reader.setInput(iis, seekForwardOnly, ignoreMetadata); 498 reader.getImageMetadata(0); 499 reader.reset(); 500 iis.close(); 501 ictx.closeOriginalStream(); 502 } catch (IOException e) { 503 e.printStackTrace(); 504 } 505 } while (--numReps >= 0); 506 } 507 } 508 509 private static class ReadProgressListener 510 implements IIOReadProgressListener 511 { 512 public void sequenceStarted(ImageReader source, int minIndex) {} 513 public void sequenceComplete(ImageReader source) {} 514 public void imageStarted(ImageReader source, int imageIndex) {} 515 public void imageProgress(ImageReader source, float percentageDone) {} 516 public void imageComplete(ImageReader source) {} 517 public void thumbnailStarted(ImageReader source, 518 int imageIndex, int thumbnailIndex) {} 519 public void thumbnailProgress(ImageReader source, 520 float percentageDone) {} 521 public void thumbnailComplete(ImageReader source) {} 522 public void readAborted(ImageReader source) {} 523 } 524 }