【问题标题】:Drawing AWT BufferedImage on SWT Canvas在 SWT Canvas 上绘制 AWT BufferedImage
【发布时间】:2014-08-06 02:13:48
【问题描述】:

我正在尝试编写一个 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

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

  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 位)Colors 预加载到一个数组中。这导致内存使用量激增 (>= 600 MB),这在我尝试之前很清楚,但我必须验证它。

只缓存使用过的颜色也会导致比原本需要的更多的内存消耗。

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

如果有任何想法或解决方案,我将不胜感激。

【问题讨论】:

  • 第一个参考文献中描述的使用 RGB 的方法看起来会快很多 - 你真的尝试过吗?
  • 我想有这样的方法。但是,AWT 和 SWT 都依赖本机代码来实现低级图形。因此,您的低级桥接很可能涉及一些在 AWT 和 SWT 案例中使用的本机数据结构上运行的粗糙本机代码。这将需要跨多个硬件和操作系统平台实现代码。不漂亮。
  • @greg-449 是的,但我对每个像素的new RGB 调用并不满意。这确实比我自己的方法快得多。
  • @StephenC 可能是的。但也许有人知道更好的方法。

标签: java swt awt


【解决方案1】:

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

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

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

【讨论】:

  • 只是好奇,但是你为什么不直接用 SWT 加载图像呢? Swing/AWT 是否有理由使用绕道?
  • 我从我使用的另一个库中获取了图像,并希望解决将其保存为临时文件并使用 SWT 重新加载它的麻烦。这将花费额外的不必要的时间。
  • 我以这种方式调整了您的代码以处理单色图像:RGB[] colors = new RGB[]{new RGB(0,0,0), new RGB(255,255,255)};调色板数据调色板 = 新调色板数据(颜色); ImageData data = new ImageData(original.getWidth(), original.getHeight(), 1, palette, 4, ((DataBufferByte) original.getData().getDataBuffer()).getData());
猜你喜欢
  • 1970-01-01
  • 2014-11-18
  • 2015-05-06
  • 1970-01-01
  • 2012-11-07
  • 2014-09-07
  • 2020-11-20
  • 1970-01-01
  • 2012-07-23
相关资源
最近更新 更多