使用Java SWT在透明图像上绘制图形

12

如何创建一个完全透明的SWT内存图像,并启用抗锯齿功能在其上绘制一条黑色线条?

由于使用了抗锯齿,期望结果只包含黑色和alpha值从0到255的范围...

我已经尝试了所有谷歌搜索到的方法...这个有可能吗?

4个回答

7
这是我所做的,它是可行的:
    Image src = new Image(null, 16, 16);        
    ImageData imageData = src.getImageData();
    imageData.transparentPixel = imageData.getPixel(0, 0);
    src.dispose();
    Image icon = new Image(null, imageData);
    //draw on the icon with gc

这在标签和工具栏项中都有效,可以轻松地进行泛化,并支持绘图。这应该是被接受的答案。 - hiergiltdiestfu

4

我成功实现了这个功能,但感觉有点麻烦:

Display display = Display.getDefault();

int width = 10;
int height = 10;

Image canvas = new Image(display, width, height);

GC gc = new GC(canvas);

gc.setAntialias(SWT.ON);

// This sets the alpha on the entire canvas to transparent
gc.setAlpha(0);
gc.fillRectangle(0, 0, width, height);

// Reset our alpha and draw a line
gc.setAlpha(255);
gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
gc.drawLine(0, 0, width, height);

// We're done with the GC, so dispose of it
gc.dispose();

ImageData canvasData = canvas.getImageData();
canvasData.alphaData = new byte[width * height];

// This is the hacky bit that is making assumptions about
// the underlying ImageData.  In my case it is 32 bit data
// so every 4th byte in the data array is the alpha for that
// pixel...
for (int idx = 0; idx < (width * height); idx++) {
    int coord = (idx * 4) + 3;
    canvasData.alphaData[idx] = canvasData.data[coord];
}

// Now that we've set the alphaData, we can create our
// final image
Image finalImage = new Image(canvasData);

// And get rid of the canvas
canvas.dispose();

之后,finalImage 可以使用 drawImage 绘制到 GC 中,透明部分将被保留。

gc.setAlpha影响其以下修改,而不是图像的alpha数据。 因此,这些行没有效果。//将整个画布的alpha设置为透明 gc.setAlpha(0); gc.fillRectangle(0,0,宽度,高度); - finejustice
你是因为代码不能工作还是因为你提到的那两行没有任何影响而给它点了踩? - Sean Bright
哦,对不起。我忘记写了一个问题。 如果您使用“finalImage”创建GC,则该GC将具有每个像素的alpha值。因此,绘图将受到每个像素的alpha值的影响。(尽管GC.getAlpha返回255;)这意味着您无法在高级模式下绘制完全不透明的线条(或矩形等)。 我建议使用带有透明像素的图像。请参见:http://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html#Transparency 如果我的错误伤害了您,我真的很抱歉。 - finejustice
没有什么损失,但我仍然不确定我发布的代码有什么问题。在我的测试中,它按照OP的要求工作。此外,在这种情况下,透明像素将无法使用,因为OP想要一条抗锯齿线,这不适用于单个透明像素。 - Sean Bright
抱歉回答晚了,以下是查看我提到的问题的步骤。
  1. 制作一个具有alpha通道的完全透明的32位PNG图像文件。
  2. 使用该文件创建GC和Image实例。
  3. 用GC填充矩形。
  4. 在Canvas(或Composite等)上绘制图像。
注意:我的测试环境为Win32_x86。如果您在不同的环境中测试,则结果可能会有所不同。如果情况如此,请向我报告。
- finejustice

3

我通过分配一个ImageData,使它透明,然后从数据创建Image来实现:

static Image createTransparentImage(Display display, int width, int height) {
    // allocate an image data
    ImageData imData = new ImageData(width, height, 24, new PaletteData(0xff0000,0x00ff00, 0x0000ff));
    imData.setAlpha(0, 0, 0); // just to force alpha array allocation with the right size
    Arrays.fill(imData.alphaData, (byte) 0); // set whole image as transparent

    // Initialize image from transparent image data
    return new Image(display, imData);
}

这对标签(Label)来说很好用,但是对于工具栏项(ToolbarItem),结果是一个纯黑色的图像 :( - hiergiltdiestfu

0
为了实现透明度的缩放,我发现必须手动设置 alpha 字节数组,如下所示。因此,alpha 最终具有最近邻反锯齿效果。
public static Image scaleImage(Device device, Image orig, int scaledWidth, int scaledHeight) {
    Rectangle origBounds = orig.getBounds();
    if (origBounds.width == scaledWidth && origBounds.height == scaledHeight) {
        return orig;
    }

    ImageData origData = orig.getImageData();
    ImageData imData = new ImageData(scaledWidth, scaledHeight, origData.depth, origData.palette);
    if (origData.alphaData != null) {
        imData.alphaData = new byte[imData.width * imData.height];
        for (int row = 0; row < imData.height; row++) {
            for (int col = 0; col < imData.width; col++) {
                int origRow = row * origData.height / imData.height;
                int origCol = col * origData.width / imData.width;
                byte origAlpha = origData.alphaData[origRow * origData.width + origCol];
                imData.alphaData[row * imData.width + col] = origAlpha;
            }
        }
    }
    final Image scaled = new Image(device, imData);
    GC gc = new GC(scaled);
    gc.setAntialias(SWT.ON);
    gc.setInterpolation(SWT.HIGH);
    gc.setBackground(device.getSystemColor(SWT.COLOR_WHITE));
    gc.fillRectangle(0, 0, scaledWidth, scaledHeight);
    gc.drawImage(orig, 0, 0, origBounds.width, origBounds.height, 0, 0, scaledWidth, scaledHeight);
    gc.dispose();
    return scaled;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接