我正在使用Java SWT Images,包含完整的32位颜色和alpha通道(org.eclipse.swt.graphics.Image)。我需要提取图像的矩形区域作为新图像,包括完整的alpha通道信息。
例如,我可能有一个大小为100×100的图像,我需要创建一个新的图像,其中只包含左上角50×50像素的内容,与100×100图像完全相同。(我是在裁剪,而不是重新缩放。)
我最初的尝试是创建一个所需大小的空白图像(在此示例中为50×50),然后获取新图像的GC,然后在新图像上绘制旧图像的正确部分。问题是透明度没有被保留。如果我的新图像开始是不透明的,那么绘制后的结果将完全不透明。如果我的新图像开始是透明的,那么绘制后的结果将完全透明(所有RGB颜色都正确,但因为所有像素的alpha值为零而不可见)。
我的当前解决方案很笨重:我使用GC来绘制图像,然后逐行手动复制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的新手,可能做错了什么。alpha通道对于swt Image类来说真的只是一个附带的考虑吗?肯定有一种更简单和更快速的方法来完成这个任务。我很想直接使用ImageData对象,并完全绕过GC的使用。