Drawing on a transparent image using Java SWT

前端 未结 4 1799
天涯浪人
天涯浪人 2021-01-04 12:08

How do I create an in-memory fully transparent SWT image and draw a black line on it with antialias enabled?

I expect the result to include only black color and alph

相关标签:
4条回答
  • 2021-01-04 12:54

    I was able to make this work, although it feels a bit hacky:

    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();
    

    After this, finalImage can be drawn into a GC with drawImage and the transparent parts will be respected.

    0 讨论(0)
  • 2021-01-04 13:03

    This is how I did and it works:

        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
    
    0 讨论(0)
  • 2021-01-04 13:11

    To scale with transparency, I've found that I have to manually set the alpha byte array as shown below. So the alpha ends up with nearest-neighbor anti aliasing.

    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;
    }
    
    0 讨论(0)
  • 2021-01-04 13:14

    I made it by allocating an ImageData, making it transparent then creating the Image from the data :

    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);
    }
    
    0 讨论(0)
提交回复
热议问题