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.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 
init()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 
initIIOReadFormats()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.equals("")) {
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 
InputImageTests(Group parent, String nodeName, String description)207     protected InputImageTests(Group parent,
208                               String nodeName, String description)
209     {
210         super(parent, nodeName, description);
211     }
212 
cleanupTest(TestEnvironment env, Object ctx)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 
Context(TestEnvironment env, Result result, int testType)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 
initContents(File f)278         void initContents(File f) throws IOException {
279             ImageIO.write(image, format, f);
280         }
281 
initContents(OutputStream out)282         void initContents(OutputStream out) throws IOException {
283             ImageIO.write(image, format, out);
284         }
285 
cleanup(TestEnvironment env)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 
ToolkitCreateImage()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 
initTest(TestEnvironment env, Result result)314         public Object initTest(TestEnvironment env, Result result) {
315             return new Context(env, result, TEST_TOOLKIT);
316         }
317 
runTest(Object ctx, int numReps)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 {
ImageIORead()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 
initTest(TestEnvironment env, Result result)388         public Object initTest(TestEnvironment env, Result result) {
389             return new Context(env, result, TEST_IMAGEIO);
390         }
391 
runTest(Object ctx, int numReps)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 {
ImageReaderRead()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 
initTest(TestEnvironment env, Result result)446         public Object initTest(TestEnvironment env, Result result) {
447             return new Context(env, result, TEST_IMAGEREADER);
448         }
449 
runTest(Object ctx, int numReps)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 {
ImageReaderGetImageMetadata()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 
initTest(TestEnvironment env, Result result)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 
runTest(Object ctx, int numReps)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     {
sequenceStarted(ImageReader source, int minIndex)512         public void sequenceStarted(ImageReader source, int minIndex) {}
sequenceComplete(ImageReader source)513         public void sequenceComplete(ImageReader source) {}
imageStarted(ImageReader source, int imageIndex)514         public void imageStarted(ImageReader source, int imageIndex) {}
imageProgress(ImageReader source, float percentageDone)515         public void imageProgress(ImageReader source, float percentageDone) {}
imageComplete(ImageReader source)516         public void imageComplete(ImageReader source) {}
thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex)517         public void thumbnailStarted(ImageReader source,
518                                      int imageIndex, int thumbnailIndex) {}
thumbnailProgress(ImageReader source, float percentageDone)519         public void thumbnailProgress(ImageReader source,
520                                       float percentageDone) {}
thumbnailComplete(ImageReader source)521         public void thumbnailComplete(ImageReader source) {}
readAborted(ImageReader source)522         public void readAborted(ImageReader source) {}
523     }
524 }
525