view j2se/src/share/demo/java2d/J2DBench/src/j2dbench/tests/ImageTests.java @ 2:16f2b6c91171 trunk

[svn] Load openjdk/jdk7/b14 into jdk/trunk.
author xiomara
date Fri, 22 Jun 2007 00:46:43 +0000
parents a4ed3fb96592
children
line wrap: on
line source

/*
 * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package j2dbench.tests;

import j2dbench.Destinations;
import j2dbench.Group;
import j2dbench.Modifier;
import j2dbench.Option;
import j2dbench.TestEnvironment;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.Image;
import java.awt.Canvas;
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ByteLookupTable;
import java.awt.image.ConvolveOp;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.Kernel;
import java.awt.image.LookupOp;
import java.awt.image.Raster;
import java.awt.image.RasterOp;
import java.awt.image.RescaleOp;
import java.awt.image.ShortLookupTable;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import java.awt.Transparency;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import javax.swing.JComponent;

public abstract class ImageTests extends GraphicsTests {
    public static boolean hasVolatileImage;
    public static boolean hasCompatImage;

    static {
	try {
	    hasVolatileImage = (VolatileImage.class != null);
	} catch (NoClassDefFoundError e) {
	}
        try {
            new Canvas().getGraphicsConfiguration();
            hasCompatImage = true;
        } catch (NoSuchMethodError e) {
        }
    }

    static Group imageroot;
    static Group.EnableSet imgsrcroot;
    static Group.EnableSet bufimgsrcroot;

    static Group imgtestroot;

    static Group imageOpRoot;
    static Group imageOpOptRoot;
    static Group imageOpTestRoot;
    static Group graphicsTestRoot;
    static Group bufImgOpTestRoot;
    static Group rasterOpTestRoot;
    static Option opList;

    static String transNodeNames[] = {
	null, "opaque", "bitmask", "translucent",
    };

    static String transDescriptions[] = {
	null, "Opaque", "Bitmask", "Translucent",
    };

    public static void init() {
	imageroot = new Group(graphicsroot, "imaging",
			      "Imaging Benchmarks");
        imageroot.setTabbed();
	imgsrcroot = new Group.EnableSet(imageroot, "src",
					 "Image Rendering Sources");
        imgsrcroot.setBordered(true);
	imgtestroot = new Group(imageroot, "tests",
				"Image Rendering Tests");
        imgtestroot.setBordered(true);

	new OffScreen();

	if (hasGraphics2D) {
            if (hasCompatImage) {
                new CompatImg(Transparency.OPAQUE);
                new CompatImg(Transparency.BITMASK);
                new CompatImg(Transparency.TRANSLUCENT);
            }

	    if (hasVolatileImage) {
		new VolatileImg();
	    }

	    bufimgsrcroot =
		new Group.EnableSet(imgsrcroot, "bufimg",
				    "BufferedImage Rendering Sources");
	    new BufImg(BufferedImage.TYPE_INT_RGB);
	    new BufImg(BufferedImage.TYPE_INT_ARGB);
	    new BufImg(BufferedImage.TYPE_BYTE_GRAY);
	    new BmByteIndexBufImg();

            imageOpRoot = new Group(imageroot, "imageops",
                                    "Image Op Benchmarks");
            imageOpOptRoot = new Group(imageOpRoot, "opts", "Options");
            imageOpTestRoot = new Group(imageOpRoot, "tests", "Tests");
            graphicsTestRoot = new Group(imageOpTestRoot, "graphics2d",
                                         "Graphics2D Tests");
            bufImgOpTestRoot = new Group(imageOpTestRoot, "bufimgop",
                                         "BufferedImageOp Tests");
            rasterOpTestRoot = new Group(imageOpTestRoot, "rasterop",
                                         "RasterOp Tests");

            ArrayList opStrs = new ArrayList();
            ArrayList opDescs = new ArrayList();
            opStrs.add("convolve3x3zero");
            opDescs.add("ConvolveOp (3x3 blur, zero)");
            opStrs.add("convolve3x3noop");
            opDescs.add("ConvolveOp (3x3 blur, noop)");
            opStrs.add("convolve5x5zero");
            opDescs.add("ConvolveOp (5x5 edge, zero)");
            opStrs.add("convolve5x5noop");
            opDescs.add("ConvolveOp (5x5 edge, noop)");
            opStrs.add("lookup1byte");
            opDescs.add("LookupOp (1 band, byte)");
            opStrs.add("lookup1short");
            opDescs.add("LookupOp (1 band, short)");
            opStrs.add("lookup3byte");
            opDescs.add("LookupOp (3 band, byte)");
            opStrs.add("lookup3short");
            opDescs.add("LookupOp (3 band, short)");
            opStrs.add("rescale1band");
            opDescs.add("RescaleOp (1 band)");
            opStrs.add("rescale3band");
            opDescs.add("RescaleOp (3 band)");
            String[] opStrArr = new String[opStrs.size()];
            opStrArr = (String[])opStrs.toArray(opStrArr);
            String[] opDescArr = new String[opDescs.size()];
            opDescArr = (String[])opDescs.toArray(opDescArr);
            opList =
                new Option.ObjectList(imageOpOptRoot,
                                      "op", "Operation",
                                      opStrArr, opStrArr,
                                      opStrArr, opDescArr,
                                      0x1);
            ((Option.ObjectList) opList).setNumRows(4);

            new DrawImageOp();
            new BufImgOpFilter(false);
            new BufImgOpFilter(true);
            new RasterOpFilter(false);
            new RasterOpFilter(true);
	}

	new DrawImage();
	new DrawImageBg();
	new DrawImageScale("up", 1.5f);
	new DrawImageScale("down", .75f);
	new DrawImageTransform();
    }

    public static class Context extends GraphicsTests.Context {
	Image src;
	AffineTransform tx;
    }

    public ImageTests(Group parent, String nodeName, String description) {
	this(parent, nodeName, description, null);
    }

    public ImageTests(Group parent, String nodeName, String description,
		      Modifier.Filter srcFilter)
    {
	super(parent, nodeName, description);
	addDependency(imgsrcroot, srcFilter);
    }

    public GraphicsTests.Context createContext() {
	return new ImageTests.Context();
    }

    public void initContext(TestEnvironment env, GraphicsTests.Context ctx) {
	super.initContext(env, ctx);
	ImageTests.Context ictx = (ImageTests.Context) ctx;

	ictx.src = env.getSrcImage();
    }

    public abstract static class TriStateImageType extends Group {
	Image theImage;

	public TriStateImageType(Group parent, String nodename, String desc,
				 int transparency)
	{
	    super(parent, nodename, desc);
	    setHorizontal();
	    new DrawableImage(this, Transparency.OPAQUE, true);
	    new DrawableImage(this, Transparency.BITMASK,
			      (transparency != Transparency.OPAQUE));
	    new DrawableImage(this, Transparency.TRANSLUCENT,
			      (transparency == Transparency.TRANSLUCENT));
	}

	public Image getImage(TestEnvironment env, int w, int h) {
	    if (theImage == null ||
		theImage.getWidth(null) != w ||
		theImage.getHeight(null) != h)
	    {
		theImage = makeImage(env, w, h);
	    }
	    return theImage;
	}

	public abstract Image makeImage(TestEnvironment env, int w, int h);
    }

    public static class OffScreen extends TriStateImageType {
	public OffScreen() {
	    super(imgsrcroot, "offscr", "Offscreen Image", Transparency.OPAQUE);
	}

	public Image makeImage(TestEnvironment env, int w, int h) {
	    Canvas c = env.getCanvas();
	    return c.createImage(w, h);
	}
    }

    public static class VolatileImg extends TriStateImageType {
	public VolatileImg() {
	    super(imgsrcroot, "volimg", "Volatile Image", Transparency.OPAQUE);
	}

	public Image makeImage(TestEnvironment env, int w, int h) {
	    Canvas c = env.getCanvas();
	    return c.createVolatileImage(w, h);
	}
    }

    public static class CompatImg extends TriStateImageType {
	int transparency;

	public static String Descriptions[] = {
	    "Default Compatible Image",
	    "Opaque Compatible Image",
	    "Bitmask Compatible Image",
	    "Translucent Compatible Image",
	};

	public CompatImg(int transparency) {
	    super(imgsrcroot,
		  Destinations.CompatImg.ShortNames[transparency],
		  Destinations.CompatImg.LongDescriptions[transparency],
		  transparency);
	    this.transparency = transparency;
	}

	public Image makeImage(TestEnvironment env, int w, int h) {
	    Canvas c = env.getCanvas();
	    GraphicsConfiguration gc = c.getGraphicsConfiguration();
	    return gc.createCompatibleImage(w, h, transparency);
	}
    }

    public static class BufImg extends TriStateImageType {
	int type;

	static int Transparencies[] = {
	    Transparency.TRANSLUCENT, // "custom",
	    Transparency.OPAQUE,      // "IntXrgb",
	    Transparency.TRANSLUCENT, // "IntArgb",
	    Transparency.TRANSLUCENT, // "IntArgbPre",
	    Transparency.OPAQUE,      // "IntXbgr",
	    Transparency.OPAQUE,      // "3ByteBgr",
	    Transparency.TRANSLUCENT, // "4ByteAbgr",
	    Transparency.TRANSLUCENT, // "4ByteAbgrPre",
	    Transparency.OPAQUE,      // "Short565",
	    Transparency.OPAQUE,      // "Short555",
	    Transparency.OPAQUE,      // "ByteGray",
	    Transparency.OPAQUE,      // "ShortGray",
	    Transparency.OPAQUE,      // "ByteBinary",
	    Transparency.OPAQUE,      // "ByteIndexed",
	};

	public BufImg(int type) {
	    super(bufimgsrcroot,
		  Destinations.BufImg.ShortNames[type],
		  Destinations.BufImg.Descriptions[type],
		  Transparencies[type]);
	    this.type = type;
	}

	public Image makeImage(TestEnvironment env, int w, int h) {
	    return new BufferedImage(w, h, type);
	}
    }

    public static class BmByteIndexBufImg extends TriStateImageType {
	static IndexColorModel icm;

	public BmByteIndexBufImg() {
	    super(bufimgsrcroot,
		  "ByteIndexedBm",
		  "8-bit Transparent Indexed Image",
		  Transparency.BITMASK);
	}

	public Image makeImage(TestEnvironment env, int w, int h) {
	    if (icm == null) {
		int cmap[] = new int[256];
		// Workaround for transparency rendering bug in earlier VMs
		// Can only render transparency if first cmap entry is 0x0
		// This bug is fixed in 1.4.2 (Mantis)
                int i = 1;
                for (int r = 0; r < 256; r += 51) {
                    for (int g = 0; g < 256; g += 51) {
                        for (int b = 0; b < 256; b += 51) {
                            cmap[i++] = (0xff<<24)|(r<<16)|(g<<8)|b;
                        }
                    }
                }

		// Leave the rest of the colormap transparent

                icm = new IndexColorModel(8, 256, cmap, 0, true, 255,
					  DataBuffer.TYPE_BYTE);
	    }
	    return new BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED,
				     icm);
	}
    }

    public static class DrawableImage extends Option.Enable {
	static Color transparentBlack  = makeAlphaColor(Color.black, 0);
	static Color translucentRed    = makeAlphaColor(Color.red, 192);
	static Color translucentGreen  = makeAlphaColor(Color.green, 128);
	static Color translucentYellow = makeAlphaColor(Color.yellow, 64);

	static Color colorsets[][] = new Color[][] {
	    null,
	    {
		Color.blue,       Color.red,
		Color.green,      Color.yellow,
		Color.blue,
	    },
	    {
		transparentBlack, Color.red,
		Color.green,      transparentBlack,
		transparentBlack,
	    },
	    {
		Color.blue,       translucentRed,
		translucentGreen, translucentYellow,
		translucentRed,
	    },
	};

	TriStateImageType tsit;
	int transparency;
	boolean possible;

	public DrawableImage(TriStateImageType parent, int transparency,
			     boolean possible)
	{
	    super(parent,
		  transNodeNames[transparency],
		  transDescriptions[transparency],
		  false);
	    this.tsit = parent;
	    this.transparency = transparency;
	    this.possible = possible;
	}

	public int getTransparency() {
	    return transparency;
	}

	public JComponent getJComponent() {
	    JComponent comp = super.getJComponent();
	    comp.setEnabled(possible);
	    return comp;
	}

	public String setValueFromString(String value) {
	    if (!possible && !value.equalsIgnoreCase("disabled")) {
		return "Bad Value";
	    }
	    return super.setValueFromString(value);
	}

	public void modifyTest(TestEnvironment env) {
	    int size = env.getIntValue(sizeList);
	    Image src = tsit.getImage(env, size, size);
	    Graphics g = src.getGraphics();
	    if (hasGraphics2D) {
		((Graphics2D) g).setComposite(AlphaComposite.Src);
	    }
	    if (size == 1) {
		g.setColor(colorsets[transparency][4]);
		g.fillRect(0, 0, 1, 1);
	    } else {
		int mid = size/2;
		g.setColor(colorsets[transparency][0]);
		g.fillRect(0, 0, mid, mid);
		g.setColor(colorsets[transparency][1]);
		g.fillRect(mid, 0, size-mid, mid);
		g.setColor(colorsets[transparency][2]);
		g.fillRect(0, mid, mid, size-mid);
		g.setColor(colorsets[transparency][3]);
		g.fillRect(mid, mid, size-mid, size-mid);
	    }
	    g.dispose();
	    env.setSrcImage(src);
	}

	public void restoreTest(TestEnvironment env) {
	    env.setSrcImage(null);
	}

	public String getAbbreviatedModifierDescription(Object value) {
	    return "from "+getModifierValueName(value);
	}

	public String getModifierValueName(Object val) {
	    return getParent().getNodeName()+" "+getNodeName();
	}
    }

    public static class DrawImage extends ImageTests {
	public DrawImage() {
	    super(imgtestroot, "drawimage", "drawImage(img, x, y, obs);");
	}

	public void runTest(Object ctx, int numReps) {
	    ImageTests.Context ictx = (ImageTests.Context) ctx;
	    int x = ictx.initX;
	    int y = ictx.initY;
	    Graphics g = ictx.graphics;
	    g.translate(ictx.orgX, ictx.orgY);
	    Image src = ictx.src;
	    if (ictx.animate) {
		do {
		    g.drawImage(src, x, y, null);
		    if ((x -= 3) < 0) x += ictx.maxX;
		    if ((y -= 1) < 0) y += ictx.maxY;
		} while (--numReps > 0);
	    } else {
		do {
		    g.drawImage(src, x, y, null);
		} while (--numReps > 0);
	    }
	    g.translate(-ictx.orgX, -ictx.orgY);
	}
    }

    public static class DrawImageBg extends ImageTests {
	public DrawImageBg() {
	    super(imgtestroot, "drawimagebg", "drawImage(img, x, y, bg, obs);",
		  new Modifier.Filter() {
		      public boolean isCompatible(Object val) {
			  DrawableImage di = (DrawableImage) val;
			  return (di.getTransparency() != Transparency.OPAQUE);
		      }
		  });
	}

	public void runTest(Object ctx, int numReps) {
	    ImageTests.Context ictx = (ImageTests.Context) ctx;
	    int x = ictx.initX;
	    int y = ictx.initY;
	    Graphics g = ictx.graphics;
	    g.translate(ictx.orgX, ictx.orgY);
	    Image src = ictx.src;
	    Color bg = Color.orange;
	    if (ictx.animate) {
		do {
		    g.drawImage(src, x, y, bg, null);
		    if ((x -= 3) < 0) x += ictx.maxX;
		    if ((y -= 1) < 0) y += ictx.maxY;
		} while (--numReps > 0);
	    } else {
		do {
		    g.drawImage(src, x, y, bg, null);
		} while (--numReps > 0);
	    }
	    g.translate(-ictx.orgX, -ictx.orgY);
	}
    }

    public static class DrawImageScale extends ImageTests {
	float scale;

	public DrawImageScale(String dir, float scale) {
	    super(imgtestroot, "drawimagescale"+dir,
		  "drawImage(img, x, y, w*"+scale+", h*"+scale+", obs);");
	    this.scale = scale;
	}

	public Dimension getOutputSize(int w, int h) {
	    int neww = (int) (w * scale);
	    int newh = (int) (h * scale);
	    if (neww == w && scale > 1f) neww = w+1;
	    if (newh == h && scale > 1f) newh = h+1;
	    return new Dimension(neww, newh);
	}

	public void runTest(Object ctx, int numReps) {
	    ImageTests.Context ictx = (ImageTests.Context) ctx;
	    int x = ictx.initX;
	    int y = ictx.initY;
	    int w = ictx.outdim.width;
	    int h = ictx.outdim.height;
	    Graphics g = ictx.graphics;
	    g.translate(ictx.orgX, ictx.orgY);
	    Image src = ictx.src;
	    if (ictx.animate) {
		do {
		    g.drawImage(src, x, y, w, h, null);
		    if ((x -= 3) < 0) x += ictx.maxX;
		    if ((y -= 1) < 0) y += ictx.maxY;
		} while (--numReps > 0);
	    } else {
		do {
		    g.drawImage(src, x, y, w, h, null);
		} while (--numReps > 0);
	    }
	    g.translate(-ictx.orgX, -ictx.orgY);
	}
    }

    public static class DrawImageTransform extends ImageTests {
	public DrawImageTransform() {
	    super(imgtestroot, "drawimagetxform", "drawImage(img, tx, obs);");
	}

	public Dimension getOutputSize(int w, int h) {
	    int neww = (int) Math.ceil(w * 1.1);
	    int newh = (int) Math.ceil(h * 1.1);
	    return new Dimension(neww, newh);
	}

	public void initContext(TestEnvironment env, GraphicsTests.Context ctx)
	{
	    super.initContext(env, ctx);
	    ImageTests.Context ictx = (ImageTests.Context) ctx;

	    ictx.tx = new AffineTransform();
	}

	public void runTest(Object ctx, int numReps) {
	    ImageTests.Context ictx = (ImageTests.Context) ctx;
	    int x = ictx.initX;
	    int y = ictx.initY;
	    Graphics2D g = (Graphics2D) ictx.graphics;
	    g.translate(ictx.orgX, ictx.orgY);
	    Image src = ictx.src;
	    AffineTransform tx = ictx.tx;
	    if (ictx.animate) {
		do {
		    tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
		    g.drawImage(src, tx, null);
		    if ((x -= 3) < 0) x += ictx.maxX;
		    if ((y -= 1) < 0) y += ictx.maxY;
		} while (--numReps > 0);
	    } else {
		tx.setTransform(1.0, 0.1, 0.1, 1.0, x, y);
		do {
		    g.drawImage(src, tx, null);
		} while (--numReps > 0);
	    }
	    g.translate(-ictx.orgX, -ictx.orgY);
	}
    }

    private static abstract class ImageOpTests extends ImageTests {
        ImageOpTests(Group parent, String nodeName, String desc) {
            super(parent, nodeName, desc,
                  new Modifier.Filter() {
                      public boolean isCompatible(Object val) {
                          // Filter out all non-BufferedImage sources
                          DrawableImage di = (DrawableImage) val;
                          Group imgtype = di.getParent();
                          return
                              !(imgtype instanceof VolatileImg) &&
                              !(imgtype instanceof OffScreen);
                      }
                  });
            addDependencies(imageOpOptRoot, true);
        }

        private static class Context extends ImageTests.Context {
            BufferedImageOp bufImgOp;
            BufferedImage   bufSrc;
            BufferedImage   bufDst;

            RasterOp        rasterOp;
            Raster          rasSrc;
            WritableRaster  rasDst;
        }

        public GraphicsTests.Context createContext() {
            return new ImageOpTests.Context();
        }

        public void initContext(TestEnvironment env,
                                GraphicsTests.Context ctx)
        {
            super.initContext(env, ctx);
            ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;

            // Note: We filter out all non-BufferedImage sources in the
            // ImageOpTests constructor above, so the following is safe...
            ictx.bufSrc = (BufferedImage)ictx.src;

            String op = (String)env.getModifier(opList);
            if (op.startsWith("convolve")) {
                Kernel kernel;
                if (op.startsWith("convolve3x3")) {
                    // 3x3 blur
                    float[] data = {
                        0.1f, 0.1f, 0.1f,
                        0.1f, 0.2f, 0.1f,
                        0.1f, 0.1f, 0.1f,
                    };
                    kernel = new Kernel(3, 3, data);
                } else { // (op.startsWith("convolve5x5"))
                    // 5x5 edge
                    float[] data = {
                        -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
                        -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
                        -1.0f, -1.0f, 24.0f, -1.0f, -1.0f,
                        -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
                        -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,
                    };
                    kernel = new Kernel(5, 5, data);
                }
                int edge = op.endsWith("zero") ?
                    ConvolveOp.EDGE_ZERO_FILL : ConvolveOp.EDGE_NO_OP;
                ictx.bufImgOp = new ConvolveOp(kernel, edge, null);
            } else if (op.startsWith("lookup")) {
                if (op.endsWith("byte")) {
                    byte invert[] = new byte[256];
                    byte ordered[] = new byte[256];
                    for (int j = 0; j < 256 ; j++) {
                        invert[j] = (byte)(255-j);
                        ordered[j] = (byte)j;
                    }
                    if (op.equals("lookup1byte")) {
                        ictx.bufImgOp =
                            new LookupOp(new ByteLookupTable(0, invert),
                                         null);
                    } else { // (op.equals("lookup3byte"))
                        byte[][] yellowInvert =
                            new byte[][] { invert, invert, ordered };
                        ictx.bufImgOp =
                            new LookupOp(new ByteLookupTable(0, yellowInvert),
                                         null);
                    }
                } else { // (op.endsWith("short"))
                    short invert[] = new short[256];
                    short ordered[] = new short[256];
                    for (int j = 0; j < 256 ; j++) {
                        invert[j] = (short)((255-j) * 255);
                        ordered[j] = (short)(j * 255);
                    }
                    if (op.equals("lookup1short")) {
                        ictx.bufImgOp =
                            new LookupOp(new ShortLookupTable(0, invert),
                                         null);
                    } else { // (op.equals("lookup3short"))
                        short[][] yellowInvert =
                            new short[][] { invert, invert, ordered };
                        ictx.bufImgOp =
                            new LookupOp(new ShortLookupTable(0, yellowInvert),
                                         null);
                    }
                }
            } else if (op.equals("rescale1band")) {
                ictx.bufImgOp = new RescaleOp(0.5f, 10.0f, null);
            } else if (op.equals("rescale3band")) {
                float[] scaleFactors = { 0.5f,  0.3f, 0.8f };
                float[] offsets      = { 5.0f, -7.5f, 1.0f };
                ictx.bufImgOp = new RescaleOp(scaleFactors, offsets, null);
            } else {
                throw new InternalError("Invalid image op");
            }

            ictx.rasterOp = (RasterOp)ictx.bufImgOp;
        }
    }

    private static class DrawImageOp extends ImageOpTests {
        DrawImageOp() {
            super(graphicsTestRoot, "drawimageop",
                  "drawImage(srcBufImg, op, x, y);");
        }

        public void runTest(Object ctx, int numReps) {
            ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
            int x = ictx.initX;
            int y = ictx.initY;
            BufferedImageOp op = ictx.bufImgOp;
            BufferedImage src = ictx.bufSrc;
            Graphics2D g2 = (Graphics2D)ictx.graphics;
            g2.translate(ictx.orgX, ictx.orgY);
            if (ictx.animate) {
                do {
                    g2.drawImage(src, op, x, y);
                    if ((x -= 3) < 0) x += ictx.maxX;
                    if ((y -= 1) < 0) y += ictx.maxY;
                } while (--numReps > 0);
            } else {
                do {
                    g2.drawImage(src, op, x, y);
                } while (--numReps > 0);
            }
            g2.translate(-ictx.orgX, -ictx.orgY);
        }
    }

    private static class BufImgOpFilter extends ImageOpTests {
        private boolean cached;

        BufImgOpFilter(boolean cached) {
            super(bufImgOpTestRoot,
                  "filter" + (cached ? "cached" : "null"),
                  "op.filter(srcBufImg, " +
                  (cached ? "cachedCompatibleDestImg" : "null") + ");");
            this.cached = cached;
        }

        public void initContext(TestEnvironment env,
                                GraphicsTests.Context ctx)
        {
            super.initContext(env, ctx);
            ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;

            if (cached) {
                ictx.bufDst =
                    ictx.bufImgOp.createCompatibleDestImage(ictx.bufSrc, null);
            }
        }

        public void runTest(Object ctx, int numReps) {
            ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
            BufferedImageOp op = ictx.bufImgOp;
            BufferedImage src = ictx.bufSrc;
            BufferedImage dst = ictx.bufDst;
            do {
                op.filter(src, dst);
            } while (--numReps > 0);
        }
    }

    private static class RasterOpFilter extends ImageOpTests {
        private boolean cached;

        RasterOpFilter(boolean cached) {
            super(rasterOpTestRoot,
                  "filter" + (cached ? "cached" : "null"),
                  "op.filter(srcRaster, " +
                  (cached ? "cachedCompatibleDestRaster" : "null") + ");");
            this.cached = cached;
        }

        public void initContext(TestEnvironment env,
                                GraphicsTests.Context ctx)
        {
            super.initContext(env, ctx);
            ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;

            ictx.rasSrc = ictx.bufSrc.getRaster();
            if (cached) {
                ictx.bufDst =
                    ictx.bufImgOp.createCompatibleDestImage(ictx.bufSrc, null);
                ictx.rasDst = ictx.bufDst.getRaster();
            }
        }

        public void runTest(Object ctx, int numReps) {
            ImageOpTests.Context ictx = (ImageOpTests.Context)ctx;
            RasterOp op = ictx.rasterOp;
            Raster src = ictx.rasSrc;
            WritableRaster dst = ictx.rasDst;
            do {
                op.filter(src, dst);
            } while (--numReps > 0);
        }
    }
}