我正在尝试编写一个SWT组件,它能够获取并绘制java.awt.BufferedImage
的实例。我的问题是SWT的Image
和AWT的BufferedImage
不兼容:SWT组件无法绘制java.awt.Image
,AWT / Swing组件无法绘制org.eclipse.swt.graphics.Image
。
有几种方法试图以其他方式解决这个问题(也可能有一些变化,但基本上有这两种):
他们都有缺点,不符合我的期望:
Image
转换为BufferedImage
的第一种方法是,由于为每个Pixel创建了一个新的RGB
实例,导致大型图像的性能下降。这导致我得到的结论是,我会尽力编写一个组件(基于org.eclipse.swt.widgets.Canvas
或org.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
。
我会很感激任何想法或解决方案。
答案 0 :(得分:4)
我发现在那里可以转换"如果是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);
可能其他位深度可以以类似的方式转换,但这是我目前所需要的。