1 /*
   2  * Copyright (c) 2002, 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;
  42 
  43 import j2dbench.Destinations;
  44 import j2dbench.Group;
  45 import j2dbench.Modifier;
  46 import j2dbench.Option;
  47 import j2dbench.TestEnvironment;
  48 import java.awt.Graphics;
  49 import java.awt.Graphics2D;
  50 import java.awt.Color;
  51 import java.awt.Image;
  52 import java.awt.Canvas;
  53 import java.awt.AlphaComposite;
  54 import java.awt.Dimension;
  55 import java.awt.GraphicsConfiguration;
  56 import java.awt.image.BufferedImage;
  57 import java.awt.image.BufferedImageOp;
  58 import java.awt.image.ByteLookupTable;
  59 import java.awt.image.ConvolveOp;
  60 import java.awt.image.DataBuffer;
  61 import java.awt.image.IndexColorModel;
  62 import java.awt.image.Kernel;
  63 import java.awt.image.LookupOp;
  64 import java.awt.image.Raster;
  65 import java.awt.image.RasterOp;
  66 import java.awt.image.RescaleOp;
  67 import java.awt.image.ShortLookupTable;
  68 import java.awt.image.VolatileImage;
  69 import java.awt.image.WritableRaster;
  70 import java.awt.Transparency;
  71 import java.awt.geom.AffineTransform;
  72 import java.awt.image.DataBufferByte;
  73 import java.awt.image.DataBufferInt;
  74 import java.awt.image.DataBufferShort;
  75 import java.util.ArrayList;
  76 import javax.swing.JComponent;
  77 
  78 public abstract class ImageTests extends GraphicsTests {
  79     public static boolean hasVolatileImage;
  80     public static boolean hasCompatImage;
  81 
  82     static {
  83         try {
  84             hasVolatileImage = (VolatileImage.class != null);
  85         } catch (NoClassDefFoundError e) {
  86         }
  87         try {
  88             new Canvas().getGraphicsConfiguration();
  89             hasCompatImage = true;
  90         } catch (NoSuchMethodError e) {
  91         }
  92     }
  93 
  94     static Group imageroot;
  95     static Group.EnableSet imgsrcroot;
  96     static Group.EnableSet bufimgsrcroot;
  97 
  98     static Group imgtestroot;
  99     static Group imgoptionsroot;
 100 
 101     static Group imageOpRoot;
 102     static Group imageOpOptRoot;
 103     static Group imageOpTestRoot;
 104     static Group graphicsTestRoot;
 105     static Group bufImgOpTestRoot;
 106     static Group rasterOpTestRoot;
 107     static Option opList;
 108     static Option doTouchSrc;
 109 
 110     static String transNodeNames[] = {
 111         null, "opaque", "bitmask", "translucent",
 112     };
 113 
 114     static String transDescriptions[] = {
 115         null, "Opaque", "Bitmask", "Translucent",
 116     };
 117 
 118     public static void init() {
 119         imageroot = new Group(graphicsroot, "imaging",
 120                               "Imaging Benchmarks");
 121         imageroot.setTabbed();
 122 
 123         imgsrcroot = new Group.EnableSet(imageroot, "src",
 124                                          "Image Rendering Sources");
 125         imgsrcroot.setBordered(true);
 126 
 127         imgoptionsroot = new Group(imgsrcroot, "options",
 128                                 "Image Source Options");
 129         imgoptionsroot.setBordered(true);
 130         doTouchSrc =
 131             new Option.Toggle(imgoptionsroot, "touchsrc",
 132                               "Touch src image before every operation",
 133                                Option.Toggle.Off);
 134 
 135         imgtestroot = new Group(imageroot, "tests",
 136                                 "Image Rendering Tests");
 137         imgtestroot.setBordered(true);
 138 
 139         new OffScreen();
 140 
 141         if (hasGraphics2D) {
 142             if (hasCompatImage) {
 143                 new CompatImg(Transparency.OPAQUE);
 144                 new CompatImg(Transparency.BITMASK);
 145                 new CompatImg(Transparency.TRANSLUCENT);
 146             }
 147 
 148             if (hasVolatileImage) {
 149                 new VolatileImg();
 150             }
 151 
 152             bufimgsrcroot =
 153                 new Group.EnableSet(imgsrcroot, "bufimg",
 154                                     "BufferedImage Rendering Sources");
 155             new BufImg(BufferedImage.TYPE_INT_RGB);
 156             new BufImg(BufferedImage.TYPE_INT_ARGB);
 157             new BufImg(BufferedImage.TYPE_BYTE_GRAY);
 158             new BufImg(BufferedImage.TYPE_3BYTE_BGR);
 159             new BmByteIndexBufImg();
 160             new BufImg(BufferedImage.TYPE_INT_RGB, true);
 161             new BufImg(BufferedImage.TYPE_INT_ARGB, true);
 162             new BufImg(BufferedImage.TYPE_3BYTE_BGR, true);
 163 
 164             imageOpRoot = new Group(imageroot, "imageops",
 165                                     "Image Op Benchmarks");
 166             imageOpOptRoot = new Group(imageOpRoot, "opts", "Options");
 167             imageOpTestRoot = new Group(imageOpRoot, "tests", "Tests");
 168             graphicsTestRoot = new Group(imageOpTestRoot, "graphics2d",
 169                                          "Graphics2D Tests");
 170             bufImgOpTestRoot = new Group(imageOpTestRoot, "bufimgop",
 171                                          "BufferedImageOp Tests");
 172             rasterOpTestRoot = new Group(imageOpTestRoot, "rasterop",
 173                                          "RasterOp Tests");
 174 
 175             ArrayList opStrs = new ArrayList();
 176             ArrayList opDescs = new ArrayList();
 177             opStrs.add("convolve3x3zero");
 178             opDescs.add("ConvolveOp (3x3 blur, zero)");
 179             opStrs.add("convolve3x3noop");
 180             opDescs.add("ConvolveOp (3x3 blur, noop)");
 181             opStrs.add("convolve5x5zero");
 182             opDescs.add("ConvolveOp (5x5 edge, zero)");
 183             opStrs.add("convolve5x5noop");
 184             opDescs.add("ConvolveOp (5x5 edge, noop)");
 185             opStrs.add("lookup1byte");
 186             opDescs.add("LookupOp (1 band, byte)");
 187             opStrs.add("lookup1short");
 188             opDescs.add("LookupOp (1 band, short)");
 189             opStrs.add("lookup3byte");
 190             opDescs.add("LookupOp (3 band, byte)");
 191             opStrs.add("lookup3short");
 192             opDescs.add("LookupOp (3 band, short)");
 193             opStrs.add("rescale1band");
 194             opDescs.add("RescaleOp (1 band)");
 195             opStrs.add("rescale3band");
 196             opDescs.add("RescaleOp (3 band)");
 197             String[] opStrArr = new String[opStrs.size()];
 198             opStrArr = (String[])opStrs.toArray(opStrArr);
 199             String[] opDescArr = new String[opDescs.size()];
 200             opDescArr = (String[])opDescs.toArray(opDescArr);
 201             opList =
 202                 new Option.ObjectList(imageOpOptRoot,
 203                                       "op", "Operation",
 204                                       opStrArr, opStrArr,
 205                                       opStrArr, opDescArr,
 206                                       0x1);
 207             ((Option.ObjectList) opList).setNumRows(4);
 208 
 209             new DrawImageOp();
 210             new BufImgOpFilter(false);
 211             new BufImgOpFilter(true);
 212             new RasterOpFilter(false);
 213             new RasterOpFilter(true);
 214         }
 215 
 216         new DrawImage();
 217         new DrawImageBg();
 218         new DrawImageScale("up", 1.5f);
 219         new DrawImageScale("down", .75f);
 220         new DrawImageTransform();
 221     }
 222 
 223     public static class Context extends GraphicsTests.Context {
 224         boolean touchSrc;
 225         Image src;
 226         AffineTransform tx;
 227     }
 228 
 229     public ImageTests(Group parent, String nodeName, String description) {
 230         this(parent, nodeName, description, null);
 231     }
 232 
 233     public ImageTests(Group parent, String nodeName, String description,
 234                       Modifier.Filter srcFilter)
 235     {
 236         super(parent, nodeName, description);
 237         addDependency(imgsrcroot, srcFilter);
 238         addDependency(doTouchSrc);
 239     }
 240 
 241     public GraphicsTests.Context createContext() {
 242         return new ImageTests.Context();
 243     }
 244 
 245     public void initContext(TestEnvironment env, GraphicsTests.Context ctx) {
 246         super.initContext(env, ctx);
 247         ImageTests.Context ictx = (ImageTests.Context) ctx;
 248 
 249         ictx.src = env.getSrcImage();
 250         ictx.touchSrc = env.isEnabled(doTouchSrc);
 251     }
 252 
 253     public abstract static class TriStateImageType extends Group {
 254         Image theImage;
 255 
 256         public TriStateImageType(Group parent, String nodename, String desc,
 257                                  int transparency)
 258         {
 259             super(parent, nodename, desc);
 260             setHorizontal();
 261             new DrawableImage(this, Transparency.OPAQUE, true);
 262             new DrawableImage(this, Transparency.BITMASK,
 263                               (transparency != Transparency.OPAQUE));
 264             new DrawableImage(this, Transparency.TRANSLUCENT,
 265                               (transparency == Transparency.TRANSLUCENT));
 266         }
 267 
 268         public Image getImage(TestEnvironment env, int w, int h) {
 269             if (theImage == null ||
 270                 theImage.getWidth(null) != w ||
 271                 theImage.getHeight(null) != h)
 272             {
 273                 theImage = makeImage(env, w, h);
 274             }
 275             return theImage;
 276         }
 277 
 278         public abstract Image makeImage(TestEnvironment env, int w, int h);
 279     }
 280 
 281     public static class OffScreen extends TriStateImageType {
 282         public OffScreen() {
 283             super(imgsrcroot, "offscr", "Offscreen Image", Transparency.OPAQUE);
 284         }
 285 
 286         public Image makeImage(TestEnvironment env, int w, int h) {
 287             Canvas c = env.getCanvas();
 288             return c.createImage(w, h);
 289         }
 290     }
 291 
 292     public static class VolatileImg extends TriStateImageType {
 293         public VolatileImg() {
 294             super(imgsrcroot, "volimg", "Volatile Image", Transparency.OPAQUE);
 295         }
 296 
 297         public Image makeImage(TestEnvironment env, int w, int h) {
 298             Canvas c = env.getCanvas();
 299             return c.createVolatileImage(w, h);
 300         }
 301     }
 302 
 303     public static class CompatImg extends TriStateImageType {
 304         int transparency;
 305 
 306         public CompatImg(int transparency) {
 307             super(imgsrcroot,
 308                   Destinations.CompatImg.ShortNames[transparency],
 309                   Destinations.CompatImg.LongDescriptions[transparency],
 310                   transparency);
 311             this.transparency = transparency;
 312         }
 313 
 314         public Image makeImage(TestEnvironment env, int w, int h) {
 315             Canvas c = env.getCanvas();
 316             GraphicsConfiguration gc = c.getGraphicsConfiguration();
 317             return gc.createCompatibleImage(w, h, transparency);
 318         }
 319     }
 320 
 321     public static class BufImg extends TriStateImageType {
 322         int type;
 323         boolean unmanaged;
 324 
 325         static int Transparencies[] = {
 326             Transparency.TRANSLUCENT, // "custom",
 327             Transparency.OPAQUE,      // "IntXrgb",
 328             Transparency.TRANSLUCENT, // "IntArgb",
 329             Transparency.TRANSLUCENT, // "IntArgbPre",
 330             Transparency.OPAQUE,      // "IntXbgr",
 331             Transparency.OPAQUE,      // "3ByteBgr",
 332             Transparency.TRANSLUCENT, // "4ByteAbgr",
 333             Transparency.TRANSLUCENT, // "4ByteAbgrPre",
 334             Transparency.OPAQUE,      // "Short565",
 335             Transparency.OPAQUE,      // "Short555",
 336             Transparency.OPAQUE,      // "ByteGray",
 337             Transparency.OPAQUE,      // "ShortGray",
 338             Transparency.OPAQUE,      // "ByteBinary",
 339             Transparency.OPAQUE,      // "ByteIndexed",
 340         };
 341 
 342         public BufImg(int type) {
 343             this(type, false);
 344         }
 345 
 346         public BufImg(int type, boolean unmanaged) {
 347             super(bufimgsrcroot,
 348                   (unmanaged ? "unmanaged" : "") +
 349                   Destinations.BufImg.ShortNames[type],
 350                   (unmanaged ? "Unmanaged " : "") +
 351                   Destinations.BufImg.Descriptions[type],
 352                   Transparencies[type]);
 353             this.type = type;
 354             this.unmanaged = unmanaged;
 355         }
 356 
 357         public Image makeImage(TestEnvironment env, int w, int h) {
 358             BufferedImage img = new BufferedImage(w, h, type);
 359             if (unmanaged) {
 360                 DataBuffer db = img.getRaster().getDataBuffer();
 361                 if (db instanceof DataBufferInt) {
 362                     ((DataBufferInt)db).getData();
 363                 } else if (db instanceof DataBufferShort) {
 364                     ((DataBufferShort)db).getData();
 365                 } else if (db instanceof DataBufferByte) {
 366                     ((DataBufferByte)db).getData();
 367                 } else {
 368                     try {
 369                         img.setAccelerationPriority(0.0f);
 370                     } catch (Throwable e) {}
 371                 }
 372             }
 373             return img;
 374         }
 375     }
 376 
 377     public static class BmByteIndexBufImg extends TriStateImageType {
 378         static IndexColorModel icm;
 379 
 380         public BmByteIndexBufImg() {
 381             super(bufimgsrcroot,
 382                   "ByteIndexedBm",
 383                   "8-bit Transparent Indexed Image",
 384                   Transparency.BITMASK);
 385         }
 386 
 387         public Image makeImage(TestEnvironment env, int w, int h) {
 388             if (icm == null) {
 389                 int cmap[] = new int[256];
 390                 // Workaround for transparency rendering bug in earlier VMs
 391                 // Can only render transparency if first cmap entry is 0x0
 392                 // This bug is fixed in 1.4.2 (Mantis)
 393                 int i = 1;
 394                 for (int r = 0; r < 256; r += 51) {
 395                     for (int g = 0; g < 256; g += 51) {
 396                         for (int b = 0; b < 256; b += 51) {
 397                             cmap[i++] = (0xff<<24)|(r<<16)|(g<<8)|b;
 398                         }
 399                     }
 400                 }
 401 
 402                 // Leave the rest of the colormap transparent
 403 
 404                 icm = new IndexColorModel(8, 256, cmap, 0, true, 255,
 405                                           DataBuffer.TYPE_BYTE);
 406             }
 407             return new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED,
 408                                      icm);
 409         }
 410     }
 411 
 412     public static class DrawableImage extends Option.Enable {
 413         static Color transparentBlack  = makeAlphaColor(Color.black, 0);
 414         static Color translucentRed    = makeAlphaColor(Color.red, 192);
 415         static Color translucentGreen  = makeAlphaColor(Color.green, 128);
 416         static Color translucentYellow = makeAlphaColor(Color.yellow, 64);
 417 
 418         static Color colorsets[][] = new Color[][] {
 419             null,
 420             {
 421                 Color.blue,       Color.red,
 422                 Color.green,      Color.yellow,
 423                 Color.blue,
 424             },
 425             {
 426                 transparentBlack, Color.red,
 427                 Color.green,      transparentBlack,
 428                 transparentBlack,
 429             },
 430             {
 431                 Color.blue,       translucentRed,
 432                 translucentGreen, translucentYellow,
 433                 translucentRed,
 434             },
 435         };
 436 
 437         TriStateImageType tsit;
 438         int transparency;
 439         boolean possible;
 440 
 441         public DrawableImage(TriStateImageType parent, int transparency,
 442                              boolean possible)
 443         {
 444             super(parent,
 445                   transNodeNames[transparency],
 446                   transDescriptions[transparency],
 447                   false);
 448             this.tsit = parent;
 449             this.transparency = transparency;
 450             this.possible = possible;
 451         }
 452 
 453         public int getTransparency() {
 454             return transparency;
 455         }
 456 
 457         public JComponent getJComponent() {
 458             JComponent comp = super.getJComponent();
 459             comp.setEnabled(possible);
 460             return comp;
 461         }
 462 
 463         public String setValueFromString(String value) {
 464             if (!possible && !value.equalsIgnoreCase("disabled")) {
 465                 return "Bad Value";
 466             }
 467             return super.setValueFromString(value);
 468         }
 469 
 470         public void modifyTest(TestEnvironment env) {
 471             int size = env.getIntValue(sizeList);
 472             Image src = tsit.getImage(env, size, size);
 473             Graphics g = src.getGraphics();
 474             if (hasGraphics2D) {
 475                 ((Graphics2D) g).setComposite(AlphaComposite.Src);
 476             }
 477             if (size == 1) {
 478                 g.setColor(colorsets[transparency][4]);
 479                 g.fillRect(0, 0, 1, 1);
 480             } else {
 481                 int mid = size/2;
 482                 g.setColor(colorsets[transparency][0]);
 483                 g.fillRect(0, 0, mid, mid);
 484                 g.setColor(colorsets[transparency][1]);
 485                 g.fillRect(mid, 0, size-mid, mid);
 486                 g.setColor(colorsets[transparency][2]);
 487                 g.fillRect(0, mid, mid, size-mid);
 488                 g.setColor(colorsets[transparency][3]);
 489                 g.fillRect(mid, mid, size-mid, size-mid);
 490             }
 491             g.dispose();
 492             env.setSrcImage(src);
 493         }
 494 
 495         public void restoreTest(TestEnvironment env) {
 496             env.setSrcImage(null);
 497         }
 498 
 499         public String getAbbreviatedModifierDescription(Object value) {
 500             return "from "+getModifierValueName(value);
 501         }
 502 
 503         public String getModifierValueName(Object val) {
 504             return getParent().getNodeName()+" "+getNodeName();
 505         }
 506     }
 507 
 508     public static class DrawImage extends ImageTests {
 509         public DrawImage() {
 510             super(imgtestroot, "drawimage", "drawImage(img, x, y, obs);");
 511         }
 512 
 513         public void runTest(Object ctx, int numReps) {
 514             ImageTests.Context ictx = (ImageTests.Context) ctx;
 515             int x = ictx.initX;
 516             int y = ictx.initY;
 517             Graphics g = ictx.graphics;
 518             g.translate(ictx.orgX, ictx.orgY);
 519             Image src = ictx.src;
 520             if (ictx.animate) {
 521                 if (ictx.touchSrc) {
 522                     Graphics srcG = src.getGraphics();
 523                     do {
 524                         srcG.fillRect(0, 0, 1, 1);
 525                         g.drawImage(src, x, y, null);
 526                         if ((x -= 3) < 0) x += ictx.maxX;
 527                         if ((y -= 1) < 0) y += ictx.maxY;
 528                     } while (--numReps > 0);
 529                 } else {
 530                     do {
 531                         g.drawImage(src, x, y, null);
 532                         if ((x -= 3) < 0) x += ictx.maxX;
 533                         if ((y -= 1) < 0) y += ictx.maxY;
 534                     } while (--numReps > 0);
 535                 }
 536             } else {
 537                 if (ictx.touchSrc) {
 538                     Graphics srcG = src.getGraphics();
 539                     do {
 540                         srcG.fillRect(0, 0, 1, 1);
 541                         g.drawImage(src, x, y, null);
 542                     } while (--numReps > 0);
 543                 } else {
 544                     do {
 545                         g.drawImage(src, x, y, null);
 546                     } while (--numReps > 0);
 547                 }
 548             }
 549             g.translate(-ictx.orgX, -ictx.orgY);
 550         }
 551     }
 552 
 553     public static class DrawImageBg extends ImageTests {
 554         public DrawImageBg() {
 555             super(imgtestroot, "drawimagebg", "drawImage(img, x, y, bg, obs);",
 556                   new Modifier.Filter() {
 557                       public boolean isCompatible(Object val) {
 558                           DrawableImage di = (DrawableImage) val;
 559                           return (di.getTransparency() != Transparency.OPAQUE);
 560                       }
 561                   });
 562         }
 563 
 564         public void runTest(Object ctx, int numReps) {
 565             ImageTests.Context ictx = (ImageTests.Context) ctx;
 566             int x = ictx.initX;
 567             int y = ictx.initY;
 568             Graphics g = ictx.graphics;
 569             g.translate(ictx.orgX, ictx.orgY);
 570             Image src = ictx.src;
 571             Color bg = Color.orange;
 572             if (ictx.animate) {
 573                 if (ictx.touchSrc) {
 574                     Graphics srcG = src.getGraphics();
 575                     do {
 576                         srcG.fillRect(0, 0, 1, 1);
 577                         g.drawImage(src, x, y, bg, null);
 578                         if ((x -= 3) < 0) x += ictx.maxX;
 579                         if ((y -= 1) < 0) y += ictx.maxY;
 580                     } while (--numReps > 0);
 581                 } else {
 582                     do {
 583                         g.drawImage(src, x, y, bg, null);
 584                         if ((x -= 3) < 0) x += ictx.maxX;
 585                         if ((y -= 1) < 0) y += ictx.maxY;
 586                     } while (--numReps > 0);
 587                 }
 588             } else {
 589                 if (ictx.touchSrc) {
 590                     Graphics srcG = src.getGraphics();
 591                     do {
 592                         srcG.fillRect(0, 0, 1, 1);
 593                         g.drawImage(src, x, y, bg, null);
 594                     } while (--numReps > 0);
 595                 } else {
 596                     do {
 597                         g.drawImage(src, x, y, bg, null);
 598                     } while (--numReps > 0);
 599                 }
 600             }
 601             g.translate(-ictx.orgX, -ictx.orgY);
 602         }
 603     }
 604 
 605     public static class DrawImageScale extends ImageTests {
 606         float scale;
 607 
 608         public DrawImageScale(String dir, float scale) {
 609             super(imgtestroot, "drawimagescale"+dir,
 610                                "drawImage(img, x, y, w*"+scale+", h*"+scale+", obs);");
 611             this.scale = scale;
 612         }
 613 
 614         public Dimension getOutputSize(int w, int h) {
 615             int neww = (int) (w * scale);
 616             int newh = (int) (h * scale);
 617             if (neww == w && scale > 1f) neww = w+1;
 618             if (newh == h && scale > 1f) newh = h+1;
 619             return new Dimension(neww, newh);
 620         }
 621 
 622         public void runTest(Object ctx, int numReps) {
 623             ImageTests.Context ictx = (ImageTests.Context) ctx;
 624             int x = ictx.initX;
 625             int y = ictx.initY;
 626             int w = ictx.outdim.width;
 627             int h = ictx.outdim.height;
 628             Graphics g = ictx.graphics;
 629             g.translate(ictx.orgX, ictx.orgY);
 630             Image src = ictx.src;
 631             if (ictx.animate) {
 632                 if (ictx.touchSrc) {
 633                     Graphics srcG = src.getGraphics();
 634                     do {
 635                         srcG.fillRect(0, 0, 1, 1);
 636                         g.drawImage(src, x, y, w, h, null);
 637                         if ((x -= 3) < 0) x += ictx.maxX;
 638                         if ((y -= 1) < 0) y += ictx.maxY;
 639                     } while (--numReps > 0);
 640                 } else {
 641                     do {
 642                         g.drawImage(src, x, y, w, h, null);
 643                         if ((x -= 3) < 0) x += ictx.maxX;
 644                         if ((y -= 1) < 0) y += ictx.maxY;
 645                     } while (--numReps > 0);
 646                 }
 647             } else {
 648                 Graphics srcG = src.getGraphics();
 649                 if (ictx.touchSrc) {
 650                     do {
 651                         srcG.fillRect(0, 0, 1, 1);
 652                         g.drawImage(src, x, y, w, h, null);
 653                     } while (--numReps > 0);
 654                 } else {
 655                     do {
 656                         g.drawImage(src, x, y, w, h, null);
 657                     } while (--numReps > 0);
 658                 }
 659             }
 660             g.translate(-ictx.orgX, -ictx.orgY);
 661         }
 662     }
 663 
 664     public static class DrawImageTransform extends ImageTests {
 665         public DrawImageTransform() {
 666             super(imgtestroot, "drawimagetxform", "drawImage(img, tx, obs);");
 667         }
 668 
 669         public Dimension getOutputSize(int w, int h) {
 670             int neww = (int) Math.ceil(w * 1.1);
 671             int newh = (int) Math.ceil(h * 1.1);
 672             return new Dimension(neww, newh);
 673         }
 674 
 675         public void initContext(TestEnvironment env, GraphicsTests.Context ctx)
 676         {
 677             super.initContext(env, ctx);
 678             ImageTests.Context ictx = (ImageTests.Context) ctx;
 679 
 680             ictx.tx = new AffineTransform();
 681         }
 682 
 683         public void runTest(Object ctx, int numReps) {
 684             ImageTests.Context ictx = (ImageTests.Context) ctx;
 685             int x = ictx.initX;
 686             int y = ictx.initY;
 687             Graphics2D g = (Graphics2D) ictx.graphics;
 688             g.translate(ictx.orgX, ictx.orgY);
 689             Image src = ictx.src;
 690             AffineTransform tx = ictx.tx;
 691             if (ictx.animate) {
 692                 if (ictx.touchSrc) {
 693                     Graphics srcG = src.getGraphics();
 694                     do {
 695                         tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
 696                         srcG.fillRect(0, 0, 1, 1);
 697                         g.drawImage(src, tx, null);
 698                         if ((x -= 3) < 0) x += ictx.maxX;
 699                         if ((y -= 1) < 0) y += ictx.maxY;
 700                     } while (--numReps > 0);
 701                 } else {
 702                     do {
 703                         tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
 704                         g.drawImage(src, tx, null);
 705                         if ((x -= 3) < 0) x += ictx.maxX;
 706                         if ((y -= 1) < 0) y += ictx.maxY;
 707                     } while (--numReps > 0);
 708                 }
 709             } else {
 710                 tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
 711                 if (ictx.touchSrc) {
 712                     Graphics srcG = src.getGraphics();
 713                     do {
 714                         srcG.fillRect(0, 0, 1, 1);
 715                         g.drawImage(src, tx, null);
 716                     } while (--numReps > 0);
 717                 } else {
 718                     do {
 719                         g.drawImage(src, tx, null);
 720                     } while (--numReps > 0);
 721                 }
 722             }
 723             g.translate(-ictx.orgX, -ictx.orgY);
 724         }
 725     }
 726 
 727     private static abstract class ImageOpTests extends ImageTests {
 728         ImageOpTests(Group parent, String nodeName, String desc) {
 729             super(parent, nodeName, desc,
 730                   new Modifier.Filter() {
 731                       public boolean isCompatible(Object val) {
 732                           // Filter out all non-BufferedImage sources
 733                           DrawableImage di = (DrawableImage) val;
 734                           Group imgtype = di.getParent();
 735                           return
 736                               !(imgtype instanceof VolatileImg) &&
 737                               !(imgtype instanceof OffScreen);
 738                       }
 739                   });
 740             addDependencies(imageOpOptRoot, true);
 741         }
 742 
 743         private static class Context extends ImageTests.Context {
 744             BufferedImageOp bufImgOp;
 745             BufferedImage   bufSrc;
 746             BufferedImage   bufDst;
 747 
 748             RasterOp        rasterOp;
 749             Raster          rasSrc;
 750             WritableRaster  rasDst;
 751         }
 752 
 753         public GraphicsTests.Context createContext() {
 754             return new ImageOpTests.Context();
 755         }
 756 
 757         public void initContext(TestEnvironment env,
 758                                 GraphicsTests.Context ctx)
 759         {
 760             super.initContext(env, ctx);
 761             ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
 762 
 763             // Note: We filter out all non-BufferedImage sources in the
 764             // ImageOpTests constructor above, so the following is safe...
 765             ictx.bufSrc = (BufferedImage)ictx.src;
 766 
 767             String op = (String)env.getModifier(opList);
 768             if (op.startsWith("convolve")) {
 769                 Kernel kernel;
 770                 if (op.startsWith("convolve3x3")) {
 771                     // 3x3 blur
 772                     float[] data = {
 773                         0.1f, 0.1f, 0.1f,
 774                         0.1f, 0.2f, 0.1f,
 775                         0.1f, 0.1f, 0.1f,
 776                     };
 777                     kernel = new Kernel(3, 3, data);
 778                 } else { // (op.startsWith("convolve5x5"))
 779                     // 5x5 edge
 780                     float[] data = {
 781                         -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
 782                         -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
 783                         -1.0f, -1.0f, 24.0f, -1.0f, -1.0f,
 784                         -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
 785                         -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
 786                     };
 787                     kernel = new Kernel(5, 5, data);
 788                 }
 789                 int edge = op.endsWith("zero") ?
 790                     ConvolveOp.EDGE_ZERO_FILL : ConvolveOp.EDGE_NO_OP;
 791                 ictx.bufImgOp = new ConvolveOp(kernel, edge, null);
 792             } else if (op.startsWith("lookup")) {
 793                 if (op.endsWith("byte")) {
 794                     byte invert[] = new byte[256];
 795                     byte ordered[] = new byte[256];
 796                     for (int j = 0; j < 256 ; j++) {
 797                         invert[j] = (byte)(255-j);
 798                         ordered[j] = (byte)j;
 799                     }
 800                     if (op.equals("lookup1byte")) {
 801                         ictx.bufImgOp =
 802                             new LookupOp(new ByteLookupTable(0, invert),
 803                                          null);
 804                     } else { // (op.equals("lookup3byte"))
 805                         byte[][] yellowInvert =
 806                             new byte[][] { invert, invert, ordered };
 807                         ictx.bufImgOp =
 808                             new LookupOp(new ByteLookupTable(0, yellowInvert),
 809                                          null);
 810                     }
 811                 } else { // (op.endsWith("short"))
 812                     short invert[] = new short[256];
 813                     short ordered[] = new short[256];
 814                     for (int j = 0; j < 256 ; j++) {
 815                         invert[j] = (short)((255-j) * 255);
 816                         ordered[j] = (short)(j * 255);
 817                     }
 818                     if (op.equals("lookup1short")) {
 819                         ictx.bufImgOp =
 820                             new LookupOp(new ShortLookupTable(0, invert),
 821                                          null);
 822                     } else { // (op.equals("lookup3short"))
 823                         short[][] yellowInvert =
 824                             new short[][] { invert, invert, ordered };
 825                         ictx.bufImgOp =
 826                             new LookupOp(new ShortLookupTable(0, yellowInvert),
 827                                          null);
 828                     }
 829                 }
 830             } else if (op.equals("rescale1band")) {
 831                 ictx.bufImgOp = new RescaleOp(0.5f, 10.0f, null);
 832             } else if (op.equals("rescale3band")) {
 833                 float[] scaleFactors = { 0.5f,  0.3f, 0.8f };
 834                 float[] offsets      = { 5.0f, -7.5f, 1.0f };
 835                 ictx.bufImgOp = new RescaleOp(scaleFactors, offsets, null);
 836             } else {
 837                 throw new InternalError("Invalid image op");
 838             }
 839 
 840             ictx.rasterOp = (RasterOp)ictx.bufImgOp;
 841         }
 842     }
 843 
 844     private static class DrawImageOp extends ImageOpTests {
 845         DrawImageOp() {
 846             super(graphicsTestRoot, "drawimageop",
 847                   "drawImage(srcBufImg, op, x, y);");
 848         }
 849 
 850         public void runTest(Object ctx, int numReps) {
 851             ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
 852             int x = ictx.initX;
 853             int y = ictx.initY;
 854             BufferedImageOp op = ictx.bufImgOp;
 855             BufferedImage src = ictx.bufSrc;
 856             Graphics2D g2 = (Graphics2D)ictx.graphics;
 857             g2.translate(ictx.orgX, ictx.orgY);
 858             if (ictx.animate) {
 859                 if (ictx.touchSrc) {
 860                     Graphics gSrc = src.getGraphics();
 861                     do {
 862                         gSrc.fillRect(0, 0, 1, 1);
 863                         g2.drawImage(src, op, x, y);
 864                         if ((x -= 3) < 0) x += ictx.maxX;
 865                         if ((y -= 1) < 0) y += ictx.maxY;
 866                     } while (--numReps > 0);
 867                 } else {
 868                     do {
 869                         g2.drawImage(src, op, x, y);
 870                         if ((x -= 3) < 0) x += ictx.maxX;
 871                         if ((y -= 1) < 0) y += ictx.maxY;
 872                     } while (--numReps > 0);
 873                 }
 874             } else {
 875                 if (ictx.touchSrc) {
 876                     Graphics gSrc = src.getGraphics();
 877                     do {
 878                         gSrc.fillRect(0, 0, 1, 1);
 879                         g2.drawImage(src, op, x, y);
 880                     } while (--numReps > 0);
 881                 } else {
 882                     do {
 883                         g2.drawImage(src, op, x, y);
 884                     } while (--numReps > 0);
 885                 }
 886             }
 887             g2.translate(-ictx.orgX, -ictx.orgY);
 888         }
 889     }
 890 
 891     private static class BufImgOpFilter extends ImageOpTests {
 892         private boolean cached;
 893 
 894         BufImgOpFilter(boolean cached) {
 895             super(bufImgOpTestRoot,
 896                   "filter" + (cached ? "cached" : "null"),
 897                   "op.filter(srcBufImg, " +
 898                   (cached ? "cachedCompatibleDestImg" : "null") + ");");
 899             this.cached = cached;
 900         }
 901 
 902         public void initContext(TestEnvironment env,
 903                                 GraphicsTests.Context ctx)
 904         {
 905             super.initContext(env, ctx);
 906             ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
 907 
 908             if (cached) {
 909                 ictx.bufDst =
 910                     ictx.bufImgOp.createCompatibleDestImage(ictx.bufSrc, null);
 911             }
 912         }
 913 
 914         public void runTest(Object ctx, int numReps) {
 915             ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
 916             BufferedImageOp op = ictx.bufImgOp;
 917             BufferedImage src = ictx.bufSrc;
 918             BufferedImage dst = ictx.bufDst;
 919             if (ictx.touchSrc) {
 920                 Graphics gSrc = src.getGraphics();
 921                 do {
 922                     gSrc.fillRect(0, 0, 1, 1);
 923                     op.filter(src, dst);
 924                 } while (--numReps > 0);
 925             } else {
 926                 do {
 927                     op.filter(src, dst);
 928                 } while (--numReps > 0);
 929             }
 930         }
 931     }
 932 
 933     private static class RasterOpFilter extends ImageOpTests {
 934         private boolean cached;
 935 
 936         RasterOpFilter(boolean cached) {
 937             super(rasterOpTestRoot,
 938                   "filter" + (cached ? "cached" : "null"),
 939                   "op.filter(srcRaster, " +
 940                   (cached ? "cachedCompatibleDestRaster" : "null") + ");");
 941             this.cached = cached;
 942         }
 943 
 944         public void initContext(TestEnvironment env,
 945                                 GraphicsTests.Context ctx)
 946         {
 947             super.initContext(env, ctx);
 948             ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
 949 
 950             ictx.rasSrc = ictx.bufSrc.getRaster();
 951             if (cached) {
 952                 ictx.bufDst =
 953                     ictx.bufImgOp.createCompatibleDestImage(ictx.bufSrc, null);
 954                 ictx.rasDst = ictx.bufDst.getRaster();
 955             }
 956         }
 957 
 958         public void runTest(Object ctx, int numReps) {
 959             ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
 960             RasterOp op = ictx.rasterOp;
 961             Raster src = ictx.rasSrc;
 962             WritableRaster dst = ictx.rasDst;
 963             if (ictx.touchSrc) {
 964                 Graphics gSrc = ictx.bufSrc.getGraphics();
 965                 do {
 966                     gSrc.fillRect(0, 0, 1, 1);
 967                     op.filter(src, dst);
 968                 } while (--numReps > 0);
 969             } else {
 970                 do {
 971                     op.filter(src, dst);
 972                 } while (--numReps > 0);
 973             }
 974         }
 975     }
 976 }