在SWT Canvas上绘制AWT BufferedImage

时间:2014-06-16 09:32:19

标签: java swt awt

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

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

  1. Convert between SWT Image and AWT BufferedImage
  2. Swing/SWT Integration
  3. 他们都有缺点,不符合我的期望:

    1. 将SWT Image转换为BufferedImage的第一种方法是,由于为每个Pixel创建了一个新的RGB实例,导致大型图像的性能下降。
    2. 第二种方法在可用性方面存在一些缺点。请参阅链接文章末尾的“变通办法”。
    3. 这导致我得到的结论是,我会尽力编写一个组件(基于org.eclipse.swt.widgets.Canvasorg.eclipse.swt.widgets.Composite),该组件允许直接绘制BufferedImage而无需任何图像转换

      我的方法是逐个像素地绘制它。因此,我只需要获取GC的实例,逐行,从左到右遍历源BufferedImage并使用Color和{{绘制相应的GC.setForeground(Color color) 1}}。

      首先,我为每个像素创建了一个GC.drawPoint(int x, int y)的新实例,它使用了大量内存并增加了额外的延迟,因为Color获取系统资源并为每个像素创建一个新对象也花时间。

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

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

      我认为必须采用更低级别的方法,不需要太多内存,因为SWT能够在不消耗大量内存的情况下绘制整个(SWT)Color

      我会很感激任何想法或解决方案。

1 个答案:

答案 0 :(得分:4)

我发现在那里可以转换"如果是24位RGB,则使用原始图像的数据缓冲区BufferedImageImage。这是可能的,因为图像格式是兼容的。

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

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