Transparency between SWT & # 8596; AWT Image Conversions

I created a dialog in which the user can view the image, and then see a preview of the image drawn on the canvas . The image is scaled so that its aspect ratio is maintained when installed in the field. I used the resizing method found in this answer , which includes converting the image from SWT to AWT, performing resizing, moving from AWT to SWT, and finally drawing it on canvas. Since this process is very expensive in terms of processing time and power, I choose to skip the resize step if the image matches the exact size and therefore does not need to be converted in any way.

The problem occurs when working with images with alpha transparency. In some cases, images with transparency, which are first converted, are drawn on the canvas with a black background. A copy of the same image, the size of which depends on the exact size of the canvas and, therefore, is not converted, has a white background.

Fluttershy's background is so flaky and inconsistent.

However, this is also not always the case. Some images with a transparent background will always be displayed as white, regardless of whether they were converted or not.

They've seen angrier days.

What makes an image with a transparent background draw one color over another in SWT canvas? How does AWT conversion affect it and how can I make it become consistent if I so desire?

Here is the conversion code taken entirely from another source:

public static BufferedImage convertToAWT (ImageData data) { ColorModel colorModel = null; PaletteData palette = data.palette; if (palette.isDirect) { colorModel = new DirectColorModel(data.depth, palette.redMask, palette.greenMask, palette.blueMask); BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null); WritableRaster raster = bufferedImage.getRaster(); int[] pixelArray = new int[3]; for (int y = 0; y < data.height; y++) { for (int x = 0; x < data.width; x++) { int pixel = data.getPixel(x, y); RGB rgb = palette.getRGB(pixel); pixelArray[0] = rgb.red; pixelArray[1] = rgb.green; pixelArray[2] = rgb.blue; raster.setPixels(x, y, 1, 1, pixelArray); } } return bufferedImage; } else { RGB[] rgbs = palette.getRGBs(); byte[] red = new byte[rgbs.length]; byte[] green = new byte[rgbs.length]; byte[] blue = new byte[rgbs.length]; for (int i = 0; i < rgbs.length; i++) { RGB rgb = rgbs[i]; red[i] = (byte) rgb.red; green[i] = (byte) rgb.green; blue[i] = (byte) rgb.blue; } if (data.transparentPixel != -1) { colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue, data.transparentPixel); } else { colorModel = new IndexColorModel(data.depth, rgbs.length, red, green, blue); } BufferedImage bufferedImage = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(data.width, data.height), false, null); WritableRaster raster = bufferedImage.getRaster(); int[] pixelArray = new int[1]; for (int y = 0; y < data.height; y++) { for (int x = 0; x < data.width; x++) { int pixel = data.getPixel(x, y); pixelArray[0] = pixel; raster.setPixel(x, y, pixelArray); } } return bufferedImage; } } public static ImageData convertToSWT (BufferedImage bufferedImage) { if (bufferedImage.getColorModel() instanceof DirectColorModel) { DirectColorModel colorModel = (DirectColorModel) bufferedImage.getColorModel(); PaletteData palette = new PaletteData(colorModel.getRedMask(), colorModel.getGreenMask(), colorModel.getBlueMask()); ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette); WritableRaster raster = bufferedImage.getRaster(); int[] pixelArray = new int[3]; for (int y = 0; y < data.height; y++) { for (int x = 0; x < data.width; x++) { raster.getPixel(x, y, pixelArray); int pixel = palette.getPixel(new RGB(pixelArray[0], pixelArray[1], pixelArray[2])); data.setPixel(x, y, pixel); } } return data; } else if (bufferedImage.getColorModel() instanceof IndexColorModel) { IndexColorModel colorModel = (IndexColorModel) bufferedImage.getColorModel(); int size = colorModel.getMapSize(); byte[] reds = new byte[size]; byte[] greens = new byte[size]; byte[] blues = new byte[size]; colorModel.getReds(reds); colorModel.getGreens(greens); colorModel.getBlues(blues); RGB[] rgbs = new RGB[size]; for (int i = 0; i < rgbs.length; i++) { rgbs[i] = new RGB(reds[i] & 0xFF, greens[i] & 0xFF, blues[i] & 0xFF); } PaletteData palette = new PaletteData(rgbs); ImageData data = new ImageData(bufferedImage.getWidth(), bufferedImage.getHeight(), colorModel.getPixelSize(), palette); data.transparentPixel = colorModel.getTransparentPixel(); WritableRaster raster = bufferedImage.getRaster(); int[] pixelArray = new int[1]; for (int y = 0; y < data.height; y++) { for (int x = 0; x < data.width; x++) { raster.getPixel(x, y, pixelArray); data.setPixel(x, y, pixelArray[0]); } } return data; } return null; } 
+6
source share
2 answers

Well, since I think I finally understand your requirements, I decided to post an answer. Let me make sure that I understood correctly:

You want to display Image in your application as a Widget that you can modify. The image should be resized with its parent and maintain transparency.

Instead of resizing the image and displaying it in Label or some other Widget you can use Canvas and draw the image to the appropriate size using GC#drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) .

To use this function, you need the Image size, the Canvas size, and the size of the properly scaled (proportional) version of the image.

Here is the code:

 public static void main(String[] args) { Display display = Display.getDefault(); final Shell shell = new Shell(display); shell.setLayout(new GridLayout(1, false)); /* Load the image and calculate size and ratio */ final Image image = new Image(display, "settings.png"); final Rectangle imageSize = image.getBounds(); final double imageRatio = 1.0 * imageSize.width / imageSize.height; /* Define the canvas and set the background color */ final Canvas canvas = new Canvas(shell, SWT.BORDER); canvas.setBackground(display.getSystemColor(SWT.COLOR_DARK_GRAY)); canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); canvas.addListener(SWT.Paint, new Listener() { @Override public void handleEvent(Event e) { Rectangle canvasSize = canvas.getBounds(); double canvasRatio = 1.0 * canvasSize.width / canvasSize.height; int newHeight; int newWidth; /* Determine scaled height and width of the image */ if (canvasRatio > imageRatio) { newWidth = (int) (imageSize.width * (1.0 * canvasSize.height / imageSize.height)); newHeight = (int) (canvasSize.height); } else { newWidth = (int) (canvasSize.width); newHeight = (int) (imageSize.height * (1.0 * canvasSize.width / imageSize.width)); } /* Compute position such that the image is centered in the canvas */ int top = (int) ((canvasSize.height - newHeight) / 2.0); int left = (int) ((canvasSize.width - newWidth) / 2.0); /* Draw the image */ e.gc.drawImage(image, 0, 0, imageSize.width, imageSize.height, left, top, newWidth, newHeight); } }); shell.pack(); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } display.dispose(); /* DISPOSE THE IMAGE !!! */ image.dispose(); } 

And here is what it looks like after launch:

enter image description here

and after resizing:

enter image description here


Note : I did not have time to test it on Windows, but I am sure that it works.

It also works on Windows!


EDIT

Add these lines to enable anti-aliasing:

 e.gc.setAntialias(SWT.ON); e.gc.setAdvanced(true); 
+2
source

A bit late for an answer, but since I just had similar experiences and problems, I thought that my results could help others.

The original problem is the supplied code, which converts SWT-> AWT and AWT-> SWT. When using the direct palette, transparency (alpha) is not served at all, but for an indexed palette and why some images work and some don't.

It’s relatively easy to fix this code to handle transparency, but there are better solutions that you don’t need to get through AWT to get a modified image.

If you do not care about smoothing (smoothness) of the transformed image, then a simple solution:

 Image newImage = new Image(image.getDevice(), image.getImageData().scaledTo(newWidth, newHeight)); 

If you care about smoothness, then the solution is almost as simple:

 Image newImage = new Image(image.getDevice(), newWidth, newHeight); GC gc = new GC(newImage); gc.setAdvanced(true); gc.setAntialias(SWT.ON); gc.drawImage(image, 0, 0, origWidth, origHeight, 0, 0, newWidth, newHeight); gc.dispose(); 
+1
source

Source: https://habr.com/ru/post/955529/


All Articles