1 /*
   2  * Copyright (c) 2006, 2011, 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.Graphics;
  44 import java.awt.image.BufferedImage;
  45 import java.io.BufferedOutputStream;
  46 import java.io.ByteArrayOutputStream;
  47 import java.io.File;
  48 import java.io.FileOutputStream;
  49 import java.io.IOException;
  50 import java.io.OutputStream;
  51 import java.util.ArrayList;
  52 import java.util.List;
  53 import javax.imageio.ImageIO;
  54 import javax.imageio.ImageWriter;
  55 import javax.imageio.event.IIOWriteProgressListener;
  56 import javax.imageio.spi.IIORegistry;
  57 import javax.imageio.spi.ImageWriterSpi;
  58 import javax.imageio.stream.ImageOutputStream;
  59 
  60 import j2dbench.Group;
  61 import j2dbench.Modifier;
  62 import j2dbench.Option;
  63 import j2dbench.Result;
  64 import j2dbench.Test;
  65 import j2dbench.TestEnvironment;
  66 
  67 abstract class OutputImageTests extends OutputTests {
  68 
  69     private static final int TEST_IMAGEIO     = 1;
  70     private static final int TEST_IMAGEWRITER = 2;
  71 
  72     private static Group imageRoot;
  73 
  74     private static Group imageioRoot;
  75     private static Group imageioOptRoot;
  76     private static ImageWriterSpi[] imageioWriterSpis;
  77     private static String[] imageioWriteFormatShortNames;
  78     private static Option imageioWriteFormatList;
  79     private static Group imageioTestRoot;
  80 
  81     private static Group imageWriterRoot;
  82     private static Group imageWriterOptRoot;
  83     private static Option installListenerTog;
  84     private static Group imageWriterTestRoot;
  85 
  86     public static void init() {
  87         imageRoot = new Group(outputRoot, "image", "Image Writing Benchmarks");
  88         imageRoot.setTabbed();
  89 
  90         // Image I/O Benchmarks
  91         if (hasImageIO) {
  92             imageioRoot = new Group(imageRoot, "imageio", "Image I/O");
  93 
  94             // Image I/O Options
  95             imageioOptRoot = new Group(imageioRoot, "opts",
  96                                        "Image I/O Options");
  97             initIIOWriteFormats();
  98             imageioWriteFormatList =
  99                 new Option.ObjectList(imageioOptRoot,
 100                                       "format", "Image Format",
 101                                       imageioWriteFormatShortNames,
 102                                       imageioWriterSpis,
 103                                       imageioWriteFormatShortNames,
 104                                       imageioWriteFormatShortNames,
 105                                       0x0);
 106 
 107             // Image I/O Tests
 108             imageioTestRoot = new Group(imageioRoot, "tests",
 109                                         "Image I/O Tests");
 110             new ImageIOWrite();
 111 
 112             // ImageWriter Options
 113             imageWriterRoot = new Group(imageioRoot, "writer",
 114                                         "ImageWriter Benchmarks");
 115             imageWriterOptRoot = new Group(imageWriterRoot, "opts",
 116                                            "ImageWriter Options");
 117             installListenerTog =
 118                 new Option.Toggle(imageWriterOptRoot,
 119                                   "installListener",
 120                                   "Install Progress Listener",
 121                                   Option.Toggle.Off);
 122 
 123             // ImageWriter Tests
 124             imageWriterTestRoot = new Group(imageWriterRoot, "tests",
 125                                             "ImageWriter Tests");
 126             new ImageWriterWrite();
 127         }
 128     }
 129 
 130     private static void initIIOWriteFormats() {
 131         List spis = new ArrayList();
 132         List shortNames = new ArrayList();
 133 
 134         ImageIO.scanForPlugins();
 135         IIORegistry registry = IIORegistry.getDefaultInstance();
 136         java.util.Iterator writerspis =
 137             registry.getServiceProviders(ImageWriterSpi.class, false);
 138         while (writerspis.hasNext()) {
 139             // REMIND: there could be more than one non-core plugin for
 140             // a particular format, as is the case for JPEG2000 in the JAI
 141             // IIO Tools package, so we should support that somehow
 142             ImageWriterSpi spi = (ImageWriterSpi)writerspis.next();
 143             String klass = spi.getClass().getName();
 144             String format = spi.getFormatNames()[0].toLowerCase();
 145             String suffix = spi.getFileSuffixes()[0].toLowerCase();
 146             if (suffix == null || suffix.equals("")) {
 147                 suffix = format;
 148             }
 149             String shortName;
 150             if (klass.startsWith("com.sun.imageio.plugins")) {
 151                 shortName = "core-" + suffix;
 152             } else {
 153                 shortName = "ext-" + suffix;
 154             }
 155             spis.add(spi);
 156             shortNames.add(shortName);
 157         }
 158 
 159         imageioWriterSpis = new ImageWriterSpi[spis.size()];
 160         imageioWriterSpis = (ImageWriterSpi[])spis.toArray(imageioWriterSpis);
 161         imageioWriteFormatShortNames = new String[shortNames.size()];
 162         imageioWriteFormatShortNames =
 163             (String[])shortNames.toArray(imageioWriteFormatShortNames);
 164     }
 165 
 166     protected OutputImageTests(Group parent,
 167                                String nodeName, String description)
 168     {
 169         super(parent, nodeName, description);
 170     }
 171 
 172     public void cleanupTest(TestEnvironment env, Object ctx) {
 173         Context iioctx = (Context)ctx;
 174         iioctx.cleanup(env);
 175     }
 176 
 177     private static class Context extends OutputTests.Context {
 178         String format;
 179         BufferedImage image;
 180         ImageWriter writer;
 181 
 182         Context(TestEnvironment env, Result result, int testType) {
 183             super(env, result);
 184 
 185             String content = (String)env.getModifier(contentList);
 186             if (content == null) {
 187                 content = CONTENT_BLANK;
 188             }
 189             // REMIND: add option for non-opaque images
 190             image = createBufferedImage(size, size, content, false);
 191 
 192             result.setUnits(size*size);
 193             result.setUnitName("pixel");
 194 
 195             if (testType == TEST_IMAGEIO || testType == TEST_IMAGEWRITER) {
 196                 ImageWriterSpi writerspi =
 197                     (ImageWriterSpi)env.getModifier(imageioWriteFormatList);
 198                 format = writerspi.getFileSuffixes()[0].toLowerCase();
 199                 if (testType == TEST_IMAGEWRITER) {
 200                     try {
 201                         writer = writerspi.createWriterInstance();
 202                     } catch (IOException e) {
 203                         System.err.println("error creating writer");
 204                         e.printStackTrace();
 205                     }
 206                     if (env.isEnabled(installListenerTog)) {
 207                         writer.addIIOWriteProgressListener(
 208                             new WriteProgressListener());
 209                     }
 210                 }
 211                 if (format.equals("wbmp")) {
 212                     // REMIND: this is a hack to create an image that the
 213                     //         WBMPImageWriter can handle (a better approach
 214                     //         would involve checking the ImageTypeSpecifier
 215                     //         of the writer's default image param)
 216                     BufferedImage newimg =
 217                         new BufferedImage(size, size,
 218                                           BufferedImage.TYPE_BYTE_BINARY);
 219                     Graphics g = newimg.createGraphics();
 220                     g.drawImage(image, 0, 0, null);
 221                     g.dispose();
 222                     image = newimg;
 223                 }
 224             } else { // testType == TEST_JPEGCODEC
 225                 format = "jpeg";
 226             }
 227 
 228             initOutput();
 229         }
 230 
 231         void initContents(File f) throws IOException {
 232             ImageIO.write(image, format, f);
 233         }
 234 
 235         void initContents(OutputStream out) throws IOException {
 236             ImageIO.write(image, format, out);
 237         }
 238 
 239         void cleanup(TestEnvironment env) {
 240             super.cleanup(env);
 241             if (writer != null) {
 242                 writer.dispose();
 243                 writer = null;
 244             }
 245         }
 246     }
 247 
 248     private static class ImageIOWrite extends OutputImageTests {
 249         public ImageIOWrite() {
 250             super(imageioTestRoot,
 251                   "imageioWrite",
 252                   "ImageIO.write()");
 253             addDependency(generalDestRoot,
 254                 new Modifier.Filter() {
 255                     public boolean isCompatible(Object val) {
 256                         // ImageIO.write() handles FILE and ARRAY, but
 257                         // not FILECHANNEL (well, I suppose we could create
 258                         // an ImageOutputStream from a FileChannel source,
 259                         // but that's not a common use case; FileChannel is
 260                         // better handled by the ImageWriter tests below)
 261                         OutputType t = (OutputType)val;
 262                         return (t.getType() != OUTPUT_FILECHANNEL);
 263                     }
 264                 });
 265             addDependencies(imageioOptRoot, true);
 266         }
 267 
 268         public Object initTest(TestEnvironment env, Result result) {
 269             return new Context(env, result, TEST_IMAGEIO);
 270         }
 271 
 272         public void runTest(Object ctx, int numReps) {
 273             final Context ictx = (Context)ctx;
 274             final Object output = ictx.output;
 275             final BufferedImage image = ictx.image;
 276             final String format = ictx.format;
 277             final int outputType = ictx.outputType;
 278             switch (outputType) {
 279             case OUTPUT_FILE:
 280                 do {
 281                     try {
 282                         ImageIO.write(image, format, (File)output);
 283                     } catch (Exception e) {
 284                         e.printStackTrace();
 285                     }
 286                 } while (--numReps >= 0);
 287                 break;
 288             case OUTPUT_ARRAY:
 289                 do {
 290                     try {
 291                         ByteArrayOutputStream baos =
 292                             new ByteArrayOutputStream();
 293                         BufferedOutputStream bos =
 294                             new BufferedOutputStream(baos);
 295                         ImageIO.write(image, format, bos);
 296                         baos.close();
 297                     } catch (Exception e) {
 298                         e.printStackTrace();
 299                     }
 300                 } while (--numReps >= 0);
 301                 break;
 302             default:
 303                 throw new IllegalArgumentException("Invalid output type");
 304             }
 305         }
 306     }
 307 
 308     private static class ImageWriterWrite extends OutputImageTests {
 309         public ImageWriterWrite() {
 310             super(imageWriterTestRoot,
 311                   "write",
 312                   "ImageWriter.write()");
 313             addDependency(generalDestRoot);
 314             addDependencies(imageioGeneralOptRoot, true);
 315             addDependencies(imageioOptRoot, true);
 316             addDependencies(imageWriterOptRoot, true);
 317         }
 318 
 319         public Object initTest(TestEnvironment env, Result result) {
 320             return new Context(env, result, TEST_IMAGEWRITER);
 321         }
 322 
 323         public void runTest(Object ctx, int numReps) {
 324             final Context ictx = (Context)ctx;
 325             final ImageWriter writer = ictx.writer;
 326             final BufferedImage image = ictx.image;
 327             do {
 328                 try {
 329                     ImageOutputStream ios = ictx.createImageOutputStream();
 330                     writer.setOutput(ios);
 331                     writer.write(image);
 332                     writer.reset();
 333                     ios.close();
 334                     ictx.closeOriginalStream();
 335                 } catch (IOException e) {
 336                     e.printStackTrace();
 337                 }
 338             } while (--numReps >= 0);
 339         }
 340     }
 341 
 342     private static class WriteProgressListener
 343         implements IIOWriteProgressListener
 344     {
 345         public void imageStarted(ImageWriter source, int imageIndex) {}
 346         public void imageProgress(ImageWriter source,
 347                                   float percentageDone) {}
 348         public void imageComplete(ImageWriter source) {}
 349         public void thumbnailStarted(ImageWriter source,
 350                                      int imageIndex, int thumbnailIndex) {}
 351         public void thumbnailProgress(ImageWriter source,
 352                                       float percentageDone) {}
 353         public void thumbnailComplete(ImageWriter source) {}
 354         public void writeAborted(ImageWriter source) {}
 355     }
 356 }