使用alpha复制Java swt图像的部分

时间:2012-02-20 18:51:43

标签: java swt

我正在使用具有完整32位颜色和alpha通道的Java swt Images(org.eclipse.swt.graphics.Image)。我需要提取图像的矩形作为新图像,包括完整的alpha通道信息。

例如,我的图像大小可能是100×100,我需要创建一个新图像,其左上角50×50像素与100×100图像完全相同。 (我正在砍,没有重新缩放。)

我最初的尝试是创建一个我需要的空白图像(在此示例中为50×50),然后获取新图像的GC,然后在新图像上绘制旧图像的正确部分。问题是没有保持透明度。如果我的新图像开始不透明,那么绘制后的结果将完全不透明。如果我的新图像开始透明,那么绘制后的结果将是完全透明的(所有RGB颜色都是正确的,但是不可见,因为对于所有像素,alpha将为零)。

我目前的解决方案很笨重:我使用GC绘制图像,然后逐行手动复制alpha通道。

/**
 * Returns a sub-rectangle from the image, preserving alpha transparency.
 * @param source The image from which to copy a portion
 * @param sourceData The ImageData of the source image
 * @param xInSource The x-coordinate in the source image from which to start copying
 * @param yInSource The y-coordinate in the source image from which to start copying
 * @param widthInSource The width (in pixels) of the copied image portion
 * @param heightInSource The height (in pixels) of the copied image portion
 * @param disp The display to use for the new image, or null for the current display
 * @return New image copied from a portion of the source.
 */
private static Image getRectHelper(final Image source, final ImageData sourceData,
        final int xInSource, final int yInSource, final int widthInSource, final int heightInSource, final Display disp)
{
    // In cases like extracting multiple frames at once, we need both the Image and its ImageData without
    // having to extract the ImageData over and over. That’s why this helper takes both parameters.

    // New up an image of the appropriate size
    final Display d = disp==null ? Display.getDefault() : disp;
    final Image dest = new Image(d, widthInSource, heightInSource);

    // This draws the colors from the original image, but does not set the destination alphas
    // (For the  Image class, alpha transparency doesn’t work well – it seems to have been tacked on as an afterthought.)
    final GC g = new GC(dest);
    g.drawImage(source, xInSource, yInSource, widthInSource, heightInSource, 0, 0, widthInSource, heightInSource);
    g.dispose();

    // Get a copy of the dest image data, then sets the destination alphas from the source image
    final ImageData destData = dest.getImageData();
    copyAlpha(sourceData, destData, xInSource, yInSource, widthInSource, heightInSource, 0, 0);

    // Construct a new image with the modified image data
    final Image ret = new Image(d, destData);
    dest.dispose();

    return ret;
}

/**
 * Copies a block of alpha channel information from the sourceData to the destaData. 
 * 
 * @param sourceData The source image data from which to copy alpha information
 * @param destData The destination image data to modify with new alpha information
 * @param xInSource The x-coordinate from which the alpha information should be copied
 * @param yInSource The y-coordinate from which the alpha information should be copied
 * @param width The width (in pixels) of the alpha information to copy
 * @param height The height (in pixels) of the alpha information to copy
 * @param xInDest The x-coordinate to which the alpha information should be copied 
 * @param yInDest The y-coordinate to which the alpha information should be copied
 */
private static void copyAlpha(final ImageData sourceData, final ImageData destData,
        final int xInSource, final int yInSource, final int width, final int height,
        final int xInDest, final int yInDest)
{
    final byte[] alphas = new byte[width];
    for (int ySrc = yInSource, yDst = yInDest; ySrc < yInSource+height; ++ySrc, ++yDst) {
        sourceData.getAlphas(xInSource, ySrc, width, alphas, 0);
        destData.setAlphas(xInDest, yDst, width, alphas, 0);
    }
}

我在这里缺少什么?我是Java新手,所以我可能做错了。对于swt Image类,alpha通道真的是事后的想法吗?当然,有一种更简单,更快捷的方法。我很想直接使用ImageData对象,完全绕过GC使用。

1 个答案:

答案 0 :(得分:0)

因此,您可能缺少的一件事是图像有多种透明度类型。 http://help.eclipse.org/kepler/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/ImageData.html#getTransparencyType()

在我们用于SWT图像的调整大小代码中,我们首先创建一个新的Image并获取其ImageData。然后根据原始Image的ImageData的透明度类型,我们执行以下操作之一:

  • 如果SWT.TRANSPARENCY_ALPHA,那么在您的示例中应用alpha就应该这样做。
  • 如果是SWT.TRANSPARENCY_PIXEL,那么我们设置ImageData的transparentPixel属性以匹配原始图像的ImageData。
  • 如果是SWT.TRANSPARENCY_MASK,那么我们设置新ImageData的maskData和maskPad属性以匹配原始图像的ImageData。

然后我们使用ImageData创建一个新的Image(处理第一个)并使用GC绘制它。

希望以上内容可以帮助您更接近解决问题。