在SWT画布上绘制AWT buffereimage



我正在尝试编写一个SWT组件,它能够采取并绘制java.awt.BufferedImage的实例。我的问题是SWT的Image和AWT的BufferedImage不兼容:SWT组件不能绘制java.awt.Image, AWT/Swing组件不能绘制org.eclipse.swt.graphics.Image

有几种方法试图用其他方式解决这个问题(也可能有一些变化,但基本上有这两种):

  1. 转换SWT图像和AWT buffereimage
  2. <
  3. Swing或SWT集成/gh>

他们都有缺点,没有达到我的期望:

  1. 第一种方法,将SWT Image转换为BufferedImage,由于为每个像素创建一个新的RGB实例,导致大图像的性能较差。
  2. 第二种方法在可用性方面有几个缺点。参见链接文章末尾的"变通方法"。

这导致我的结论是,我会尽我最大的努力编写一个组件(基于org.eclipse.swt.widgets.Canvasorg.eclipse.swt.widgets.Composite),允许直接绘制BufferedImage,而无需任何图像转换。

我的方法是逐像素绘制。因此,我只需要获得GC的实例,从左到右逐行遍历源BufferedImage,并使用GC.setForeground(Color color)GC.drawPoint(int x, int y)绘制相应的Color

首先,我为每个像素创建了一个Color的新实例,这使用了相当多的内存并增加了额外的延迟,因为new Color需要获取系统资源,并且为每个像素创建新对象也需要花费时间。

然后我尝试在绘制图像之前将所有可能的(24位)Color s预加载到数组中。这导致内存使用量激增(>= 600 MB),这在我尝试之前就很清楚了,但我必须验证它。

只缓存已使用的颜色也会导致比所需更多的内存消耗。

我认为必须有一个更低级的方法,不需要那么多内存,因为SWT能够在不消耗那么多内存的情况下绘制整个(SWT) Image

我发现有一种方法可以通过使用原始图像的数据缓冲区来"转换"BufferedImageImage,如果它是24位RGB。这是可能的,因为图像格式是兼容的。

final BufferedImage original = ImageIO.read(new File("some-image.jpg");
final PaletteData palette =
        new PaletteData(0x0000FF, 0x00FF00, 0xFF0000);
// the last argument contains the byte[] with the image data
final ImageData data = new ImageData(original.getWidth(), original.getHeight(),
        24, palette, 4,
        ((DataBufferByte) original.getData().getDataBuffer()).getData());
final Image converted = new Image(getDevice(), data);

这样,就不需要创建成千上万的新对象。这种方法的缺点是需要确保原始图像是RGB 24位类型。否则,图像必须转换为此格式。

之后,可以使用以下代码绘制图像:

// get the GC of your component
gc.drawImage(image, 0, 0);

可能其他位深度可以用类似的方式转换,但这是我目前所需要的。

相关内容

  • 没有找到相关文章

最新更新