Java Code Examples for java.awt.Transparency#OPAQUE

The following examples show how to use java.awt.Transparency#OPAQUE . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: GLXVolatileSurfaceManager.java    From TencentKona-8 with GNU General Public License v2.0 6 votes vote down vote up
public GLXVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
    super(vImg, context);

    /*
     * We will attempt to accelerate this image only under the
     * following conditions:
     *   - the image is opaque OR
     *   - the image is translucent AND
     *       - the GraphicsConfig supports the FBO extension OR
     *       - the GraphicsConfig has a stored alpha channel
     */
    int transparency = vImg.getTransparency();
    GLXGraphicsConfig gc = (GLXGraphicsConfig)vImg.getGraphicsConfig();
    accelerationEnabled =
        (transparency == Transparency.OPAQUE) ||
        ((transparency == Transparency.TRANSLUCENT) &&
         (gc.isCapPresent(CAPS_EXT_FBOBJECT) ||
          gc.isCapPresent(CAPS_STORED_ALPHA)));
}
 
Example 2
Source File: ImageTypeSpecifier.java    From dragonwell8_jdk with GNU General Public License v2.0 6 votes vote down vote up
static ColorModel createComponentCM(ColorSpace colorSpace,
                                    int numBands,
                                    int dataType,
                                    boolean hasAlpha,
                                    boolean isAlphaPremultiplied) {
    int transparency =
        hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;

    int[] numBits = new int[numBands];
    int bits = DataBuffer.getDataTypeSize(dataType);

    for (int i = 0; i < numBands; i++) {
        numBits[i] = bits;
    }

    return new ComponentColorModel(colorSpace,
                                   numBits,
                                   hasAlpha,
                                   isAlphaPremultiplied,
                                   transparency,
                                   dataType);
}
 
Example 3
Source File: X11VolatileSurfaceManager.java    From TencentKona-8 with GNU General Public License v2.0 6 votes vote down vote up
public X11VolatileSurfaceManager(SunVolatileImage vImg, Object context) {
    super(vImg, context);

    // We only accelerated opaque vImages currently
    accelerationEnabled = X11SurfaceData.isAccelerationEnabled() &&
        (vImg.getTransparency() == Transparency.OPAQUE);

    if ((context != null) && !accelerationEnabled) {
        // if we're wrapping a backbuffer drawable, we must ensure that
        // the accelerated surface is initialized up front, regardless
        // of whether acceleration is enabled. But we need to set
        // the  accelerationEnabled field to true to reflect that this
        // SM is actually accelerated.
        accelerationEnabled = true;
        sdAccel = initAcceleratedSurface();
        sdCurrent = sdAccel;

        if (sdBackup != null) {
            // release the system memory backup surface, as we won't be
            // needing it in this case
            sdBackup = null;
        }
    }
}
 
Example 4
Source File: OGLSurfaceDataProxy.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean isSupportedOperation(SurfaceData srcData,
                                    int txtype,
                                    CompositeType comp,
                                    Color bgColor)
{
    return comp.isDerivedFrom(CompositeType.AnyAlpha) &&
           (bgColor == null || transparency == Transparency.OPAQUE);
}
 
Example 5
Source File: OGLSurfaceDataProxy.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean isSupportedOperation(SurfaceData srcData,
                                    int txtype,
                                    CompositeType comp,
                                    Color bgColor)
{
    return comp.isDerivedFrom(CompositeType.AnyAlpha) &&
           (bgColor == null || transparency == Transparency.OPAQUE);
}
 
Example 6
Source File: D3DGraphicsConfig.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
/**
 * {@inheritDoc}
 *
 * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
 */
@Override
public VolatileImage
    createCompatibleVolatileImage(int width, int height,
                                  int transparency, int type)
{
    if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
        transparency == Transparency.BITMASK)
    {
        return null;
    }
    boolean isOpaque = transparency == Transparency.OPAQUE;
    if (type == RT_TEXTURE) {
        int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
        if (!device.isCapPresent(cap)) {
            return null;
        }
    } else if (type == RT_PLAIN) {
        if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) {
            return null;
        }
    }

    SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
                                                      transparency, type);
    Surface sd = vi.getDestSurface();
    if (!(sd instanceof AccelSurface) ||
        ((AccelSurface)sd).getType() != type)
    {
        vi.flush();
        vi = null;
    }

    return vi;
}
 
Example 7
Source File: ImageTests.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
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);
              }
          });
}
 
Example 8
Source File: BMPSubsamplingTest.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
private BufferedImage create3ByteImage(int[] nBits, int[] bOffs) {
    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    ColorModel colorModel =
        new ComponentColorModel(cs, nBits,
                                false, false,
                                Transparency.OPAQUE,
                                DataBuffer.TYPE_BYTE);
    WritableRaster raster =
        Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                       w, h,
                                       w*3, 3,
                                       bOffs, null);
    return new BufferedImage(colorModel, raster, false, null);
}
 
Example 9
Source File: IncorrectUnmanagedImageSourceOffset.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the custom buffered image, which mostly identical to
 * BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
 * This means that the raster will have gaps, between the rows.
 */
private static BufferedImage makeCustomUnmanagedBI() {
    int w = 511, h = 255;
    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
    int[] nBits = {8, 8, 8};
    int[] bOffs = {2, 1, 0};
    ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
                                                    Transparency.OPAQUE,
                                                    DataBuffer.TYPE_BYTE);
    WritableRaster raster =
            Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
                                           w * 3 + 2, 3, bOffs, null);
    return new BufferedImage(colorModel, raster, true, null);
}
 
Example 10
Source File: OGLSurfaceData.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Note: This should only be called from the QFT under the AWT lock.
 * This method is kept separate from the initSurface() method below just
 * to keep the code a bit cleaner.
 */
private void initSurfaceNow(int width, int height) {
    boolean isOpaque = (getTransparency() == Transparency.OPAQUE);
    boolean success = false;

    switch (type) {
    case PBUFFER:
        success = initPbuffer(getNativeOps(),
                              graphicsConfig.getNativeConfigInfo(),
                              isOpaque,
                              width, height);
        break;

    case TEXTURE:
        success = initTexture(getNativeOps(),
                              isOpaque, isTexNonPow2Available(),
                              isTexRectAvailable(),
                              width, height);
        break;

    case FBOBJECT:
        success = initFBObject(getNativeOps(),
                               isOpaque, isTexNonPow2Available(),
                               isTexRectAvailable(),
                               width, height);
        break;

    case FLIP_BACKBUFFER:
        success = initFlipBackbuffer(getNativeOps());
        break;

    default:
        break;
    }

    if (!success) {
        throw new OutOfMemoryError("can't create offscreen surface");
    }
}
 
Example 11
Source File: PrinterGraphicsConfig.java    From dragonwell8_jdk with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the color model associated with this configuration that
 * supports the specified transparency.
 */
public ColorModel getColorModel(int transparency) {
    switch (transparency) {
    case Transparency.OPAQUE:
        return getColorModel();
    case Transparency.BITMASK:
        return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
    case Transparency.TRANSLUCENT:
        return ColorModel.getRGBdefault();
    default:
        return null;
    }
}
 
Example 12
Source File: D3DGraphicsConfig.java    From TencentKona-8 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * {@inheritDoc}
 *
 * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
 */
@Override
public VolatileImage
    createCompatibleVolatileImage(int width, int height,
                                  int transparency, int type)
{
    if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
        transparency == Transparency.BITMASK)
    {
        return null;
    }
    boolean isOpaque = transparency == Transparency.OPAQUE;
    if (type == RT_TEXTURE) {
        int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA;
        if (!device.isCapPresent(cap)) {
            return null;
        }
    } else if (type == RT_PLAIN) {
        if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) {
            return null;
        }
    }

    SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
                                                      transparency, type);
    Surface sd = vi.getDestSurface();
    if (!(sd instanceof AccelSurface) ||
        ((AccelSurface)sd).getType() != type)
    {
        vi.flush();
        vi = null;
    }

    return vi;
}
 
Example 13
Source File: OGLBlitLoops.java    From dragonwell8_jdk with GNU General Public License v2.0 4 votes vote down vote up
static void Blit(SurfaceData srcData, SurfaceData dstData,
                 Composite comp, Region clip,
                 AffineTransform xform, int hint,
                 int sx1, int sy1,
                 int sx2, int sy2,
                 double dx1, double dy1,
                 double dx2, double dy2,
                 int srctype, boolean texture)
{
    int ctxflags = 0;
    if (srcData.getTransparency() == Transparency.OPAQUE) {
        ctxflags |= OGLContext.SRC_IS_OPAQUE;
    }

    OGLRenderQueue rq = OGLRenderQueue.getInstance();
    rq.lock();
    try {
        // make sure the RenderQueue keeps a hard reference to the
        // source (sysmem) SurfaceData to prevent it from being
        // disposed while the operation is processed on the QFT
        rq.addReference(srcData);

        OGLSurfaceData oglDst = (OGLSurfaceData)dstData;
        if (texture) {
            // make sure we have a current context before uploading
            // the sysmem data to the texture object
            OGLGraphicsConfig gc = oglDst.getOGLGraphicsConfig();
            OGLContext.setScratchSurface(gc);
        } else {
            OGLContext.validateContext(oglDst, oglDst,
                                       clip, comp, xform, null, null,
                                       ctxflags);
        }

        int packedParams = createPackedParams(false, texture,
                                              false, xform != null,
                                              hint, srctype);
        enqueueBlit(rq, srcData, dstData,
                    packedParams,
                    sx1, sy1, sx2, sy2,
                    dx1, dy1, dx2, dy2);

        // always flush immediately, since we (currently) have no means
        // of tracking changes to the system memory surface
        rq.flushNow();
    } finally {
        rq.unlock();
    }
}
 
Example 14
Source File: D3DBlitLoops.java    From TencentKona-8 with GNU General Public License v2.0 4 votes vote down vote up
static void Blit(SurfaceData srcData, SurfaceData dstData,
                 Composite comp, Region clip,
                 AffineTransform xform, int hint,
                 int sx1, int sy1,
                 int sx2, int sy2,
                 double dx1, double dy1,
                 double dx2, double dy2,
                 int srctype, boolean texture)
{
    int ctxflags = 0;
    if (srcData.getTransparency() == Transparency.OPAQUE) {
        ctxflags |= D3DContext.SRC_IS_OPAQUE;
    }

    D3DSurfaceData d3dDst = (D3DSurfaceData)dstData;
    D3DRenderQueue rq = D3DRenderQueue.getInstance();
    rq.lock();
    try {
        // make sure the RenderQueue keeps a hard reference to the
        // source (sysmem) SurfaceData to prevent it from being
        // disposed while the operation is processed on the QFT
        rq.addReference(srcData);

        if (texture) {
            // make sure we have a current context before uploading
            // the sysmem data to the texture object
            D3DContext.setScratchSurface(d3dDst.getContext());
        } else {
            D3DContext.validateContext(d3dDst, d3dDst,
                                       clip, comp, xform, null, null,
                                       ctxflags);
        }

        int packedParams = createPackedParams(false, texture,
                                              false, xform != null,
                                              hint, srctype);
        enqueueBlit(rq, srcData, dstData,
                    packedParams,
                    sx1, sy1, sx2, sy2,
                    dx1, dy1, dx2, dy2);

        // always flush immediately, since we (currently) have no means
        // of tracking changes to the system memory surface
        rq.flushNow();
    } finally {
        rq.unlock();
    }

    if (d3dDst.getType() == D3DSurfaceData.WINDOW) {
        // flush immediately when copying to the screen to improve
        // responsiveness of applications using VI or BI backbuffers
        D3DScreenUpdateManager mgr =
            (D3DScreenUpdateManager)ScreenUpdateManager.getInstance();
        mgr.runUpdateNow();
    }
}
 
Example 15
Source File: JPEGImageWriter.java    From jdk1.8-source-analysis with Apache License 2.0 4 votes vote down vote up
/**
 * Put the scanline y of the source ROI view Raster into the
 * 1-line Raster for writing.  This handles ROI and band
 * rearrangements, and expands indexed images.  Subsampling is
 * done in the native code.
 * This is called by the native code.
 */
private void grabPixels(int y) {

    Raster sourceLine = null;
    if (indexed) {
        sourceLine = srcRas.createChild(sourceXOffset,
                                        sourceYOffset+y,
                                        sourceWidth, 1,
                                        0, 0,
                                        new int [] {0});
        // If the image has BITMASK transparency, we need to make sure
        // it gets converted to 32-bit ARGB, because the JPEG encoder
        // relies upon the full 8-bit alpha channel.
        boolean forceARGB =
            (indexCM.getTransparency() != Transparency.OPAQUE);
        BufferedImage temp = indexCM.convertToIntDiscrete(sourceLine,
                                                          forceARGB);
        sourceLine = temp.getRaster();
    } else {
        sourceLine = srcRas.createChild(sourceXOffset,
                                        sourceYOffset+y,
                                        sourceWidth, 1,
                                        0, 0,
                                        srcBands);
    }
    if (convertTosRGB) {
        if (debug) {
            System.out.println("Converting to sRGB");
        }
        // The first time through, converted is null, so
        // a new raster is allocated.  It is then reused
        // on subsequent lines.
        converted = convertOp.filter(sourceLine, converted);
        sourceLine = converted;
    }
    if (isAlphaPremultiplied) {
        WritableRaster wr = sourceLine.createCompatibleWritableRaster();
        int[] data = null;
        data = sourceLine.getPixels(sourceLine.getMinX(), sourceLine.getMinY(),
                                    sourceLine.getWidth(), sourceLine.getHeight(),
                                    data);
        wr.setPixels(sourceLine.getMinX(), sourceLine.getMinY(),
                     sourceLine.getWidth(), sourceLine.getHeight(),
                     data);
        srcCM.coerceData(wr, false);
        sourceLine = wr.createChild(wr.getMinX(), wr.getMinY(),
                                    wr.getWidth(), wr.getHeight(),
                                    0, 0,
                                    srcBands);
    }
    raster.setRect(sourceLine);
    if ((y > 7) && (y%8 == 0)) {  // Every 8 scanlines
        cbLock.lock();
        try {
            processImageProgress((float) y / (float) sourceHeight * 100.0F);
        } finally {
            cbLock.unlock();
        }
    }
}
 
Example 16
Source File: PaletteBuilder.java    From TencentKona-8 with GNU General Public License v2.0 4 votes vote down vote up
protected void buildPalette() {
    reduceList = new ColorNode[MAXLEVEL + 1];
    for (int i = 0; i < reduceList.length; i++) {
        reduceList[i] = null;
    }

    numNodes = 0;
    maxNodes = 0;
    root = null;
    currSize = 0;
    currLevel = MAXLEVEL;

    /*
      from the book

    */

    int w = src.getWidth();
    int h = src.getHeight();
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {

            Color aColor = getSrcColor(w - x - 1, h - y - 1);
            /*
             * If transparency of given image is not opaque we assume all
             * colors with alpha less than 1.0 as fully transparent.
             */
            if (transparency != Transparency.OPAQUE &&
                aColor.getAlpha() != 0xff)
            {
                if (transColor == null) {
                    this.requiredSize --; // one slot for transparent color

                    transColor = new ColorNode();
                    transColor.isLeaf = true;
                }
                transColor = insertNode(transColor, aColor, 0);
            } else {
                root = insertNode(root, aColor, 0);
            }
            if (currSize > requiredSize) {
                reduceTree();
            }
        }
    }
}
 
Example 17
Source File: AffineTransformOp.java    From dragonwell8_jdk with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Creates a zeroed destination image with the correct size and number of
 * bands.  A <CODE>RasterFormatException</CODE> may be thrown if the
 * transformed width or height is equal to 0.
 * <p>
 * If <CODE>destCM</CODE> is null,
 * an appropriate <CODE>ColorModel</CODE> is used; this
 * <CODE>ColorModel</CODE> may have
 * an alpha channel even if the source <CODE>ColorModel</CODE> is opaque.
 *
 * @param src  The <CODE>BufferedImage</CODE> to be transformed.
 * @param destCM  <CODE>ColorModel</CODE> of the destination.  If null,
 * an appropriate <CODE>ColorModel</CODE> is used.
 *
 * @return The zeroed destination image.
 */
public BufferedImage createCompatibleDestImage (BufferedImage src,
                                                ColorModel destCM) {
    BufferedImage image;
    Rectangle r = getBounds2D(src).getBounds();

    // If r.x (or r.y) is < 0, then we want to only create an image
    // that is in the positive range.
    // If r.x (or r.y) is > 0, then we need to create an image that
    // includes the translation.
    int w = r.x + r.width;
    int h = r.y + r.height;
    if (w <= 0) {
        throw new RasterFormatException("Transformed width ("+w+
                                        ") is less than or equal to 0.");
    }
    if (h <= 0) {
        throw new RasterFormatException("Transformed height ("+h+
                                        ") is less than or equal to 0.");
    }

    if (destCM == null) {
        ColorModel cm = src.getColorModel();
        if (interpolationType != TYPE_NEAREST_NEIGHBOR &&
            (cm instanceof IndexColorModel ||
             cm.getTransparency() == Transparency.OPAQUE))
        {
            image = new BufferedImage(w, h,
                                      BufferedImage.TYPE_INT_ARGB);
        }
        else {
            image = new BufferedImage(cm,
                      src.getRaster().createCompatibleWritableRaster(w,h),
                      cm.isAlphaPremultiplied(), null);
        }
    }
    else {
        image = new BufferedImage(destCM,
                                destCM.createCompatibleWritableRaster(w,h),
                                destCM.isAlphaPremultiplied(), null);
    }

    return image;
}
 
Example 18
Source File: DirectColorModel.java    From TencentKona-8 with GNU General Public License v2.0 3 votes vote down vote up
/**
 * Constructs a <code>DirectColorModel</code> from the specified masks
 * that indicate which bits in an <code>int</code> pixel representation
 * contain the red, green and blue color samples and the alpha sample,
 * if present.  If <code>amask</code> is 0, pixel values do not contain
 * alpha information and all pixels are treated as opaque, which means
 * that alpha&nbsp;=&nbsp;1.0.  All of the bits in each mask must
 * be contiguous and fit in the specified number of least significant bits
 * of an <code>int</code> pixel representation.  Alpha, if present, is not
 * premultiplied.  The <code>ColorSpace</code> is the default sRGB space.
 * The transparency value is Transparency.OPAQUE if no alpha is
 * present, or Transparency.TRANSLUCENT otherwise.  The transfer type
 * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
 * or DataBuffer.TYPE_INT that can hold a single pixel.
 * @param bits the number of bits in the pixel values; for example,
 *         the sum of the number of bits in the masks.
 * @param rmask specifies a mask indicating which bits in an
 *         integer pixel contain the red component
 * @param gmask specifies a mask indicating which bits in an
 *         integer pixel contain the green component
 * @param bmask specifies a mask indicating which bits in an
 *         integer pixel contain the blue component
 * @param amask specifies a mask indicating which bits in an
 *         integer pixel contain the alpha component
 */
public DirectColorModel(int bits, int rmask, int gmask,
                        int bmask, int amask) {
    super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
           bits, rmask, gmask, bmask, amask, false,
           amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
           ColorModel.getDefaultTransferType(bits));
    setFields();
}
 
Example 19
Source File: DirectColorModel.java    From jdk1.8-source-analysis with Apache License 2.0 3 votes vote down vote up
/**
 * Constructs a <code>DirectColorModel</code> from the specified masks
 * that indicate which bits in an <code>int</code> pixel representation
 * contain the red, green and blue color samples and the alpha sample,
 * if present.  If <code>amask</code> is 0, pixel values do not contain
 * alpha information and all pixels are treated as opaque, which means
 * that alpha&nbsp;=&nbsp;1.0.  All of the bits in each mask must
 * be contiguous and fit in the specified number of least significant bits
 * of an <code>int</code> pixel representation.  Alpha, if present, is not
 * premultiplied.  The <code>ColorSpace</code> is the default sRGB space.
 * The transparency value is Transparency.OPAQUE if no alpha is
 * present, or Transparency.TRANSLUCENT otherwise.  The transfer type
 * is the smallest of DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT,
 * or DataBuffer.TYPE_INT that can hold a single pixel.
 * @param bits the number of bits in the pixel values; for example,
 *         the sum of the number of bits in the masks.
 * @param rmask specifies a mask indicating which bits in an
 *         integer pixel contain the red component
 * @param gmask specifies a mask indicating which bits in an
 *         integer pixel contain the green component
 * @param bmask specifies a mask indicating which bits in an
 *         integer pixel contain the blue component
 * @param amask specifies a mask indicating which bits in an
 *         integer pixel contain the alpha component
 */
public DirectColorModel(int bits, int rmask, int gmask,
                        int bmask, int amask) {
    super (ColorSpace.getInstance(ColorSpace.CS_sRGB),
           bits, rmask, gmask, bmask, amask, false,
           amask == 0 ? Transparency.OPAQUE : Transparency.TRANSLUCENT,
           ColorModel.getDefaultTransferType(bits));
    setFields();
}
 
Example 20
Source File: Scalr.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 3 votes vote down vote up
/**
 * Used to create a {@link BufferedImage} with the given dimensions and the
 * most optimal RGB TYPE ( {@link BufferedImage#TYPE_INT_RGB} or
 * {@link BufferedImage#TYPE_INT_ARGB} ) capable of being rendered into from
 * the given <code>src</code>.
 * <p/>
 * This does not perform a copy of the image data from <code>src</code> into
 * the result image; see {@link #copyToOptimalImage(BufferedImage)} for
 * that.
 * <p/>
 * We force all rendering results into one of these two types, avoiding the
 * case where a source image is of an unsupported (or poorly supported)
 * format by Java2D causing the rendering result to end up looking terrible
 * (common with GIFs) or be totally corrupt (e.g. solid black image).
 * <p/>
 * Originally reported by Magnus Kvalheim from Movellas when scaling certain
 * GIF and PNG images.
 *
 * @param src
 *        The source image that will be analyzed to determine the most
 *        optimal image type it can be rendered into.
 * @param width
 *        The width of the newly created resulting image.
 * @param height
 *        The height of the newly created resulting image.
 *
 * @return a new {@link BufferedImage} representing the most optimal target
 *         image type that <code>src</code> can be rendered into.
 *
 * @throws IllegalArgumentException
 *         if <code>width</code> or <code>height</code> are &lt; 0.
 *
 * @see <a
 *      href="http://www.mail-archive.com/[email protected]/msg05621.html">How
 *      Java2D handles poorly supported image types</a>
 * @see <a
 *      href=
 *      "http://code.google.com/p/java-image-scaling/source/browse/trunk/src/main/java/com/mortennobel/imagescaling/MultiStepRescaleOp.java">Thanks
 *      to Morten Nobel for implementation hint</a>
 */
protected static BufferedImage createOptimalImage(BufferedImage src, int width, int height)
    throws IllegalArgumentException {
  if (width <= 0 || height <= 0)
    throw new IllegalArgumentException("width [" + width + "] and height [" + height + "] must be > 0");

  return new BufferedImage(width, height,
      (src.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB));
}