我如何有效地实现java.awt.Composite?
背景:我需要能够创建“禁用”外观的图像。 通常建议的方法是将图像转换为灰度并显示灰度图像。 缺点是它仅适用于图像,因此在显示图形时,如果您无法立即访问处于禁用状态的图像,则会很麻烦。 现在我认为这可以使用java.awt.Composite实现(然后我不需要知道如何实现一个图标来使其禁用)。 只有似乎没有实现转换为灰度,所以我必须创建自己的...
也就是说,我一起攻击了一个实现(并且它呈现了我期望的结果)。 但我不确定它会在所有情况下都能正常工作(对于这样复杂的操作,Composite / CompositeContext的Javadocs显得非常薄)。 正如你从我的实现中可以看到的那样,我会采用迂回的方式逐像素地进行处理,因为似乎没有简单的方式来以非所涉及的栅格规定的格式批量读取/写入像素。
任何指向更广泛的文档/示例/提示的指针都是受欢迎的。
这是SSCCE--它通过DisabledComposite渲染一个(彩色的)GradientPaint,将梯度转换为灰度。 请注意,在现实世界中,你将不知道什么是通过什么调用呈现的。 渐变仅仅是一个例子(对不起,但人们往往不明白这一点,所以这次我会把它弄清楚)。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class CompositeSSCE implements Runnable {
static class DisabledComposite implements Composite {
@Override
public CompositeContext createContext(
final ColorModel srcColorModel,
final ColorModel dstColorModel,
final RenderingHints hints) {
return new DisabledCompositeContext(srcColorModel, dstColorModel);
}
}
static class DisabledCompositeContext implements CompositeContext {
private final ColorModel srcCM;
private final ColorModel dstCM;
final static int PRECBITS = 22;
final static int WEIGHT_R = (int) ((1 << PRECBITS) * 0.299);
final static int WEIGHT_G = (int) ((1 << PRECBITS) * 0.578);
final static int WEIGHT_B = (int) ((1 << PRECBITS) * 0.114);
final static int SRCALPHA = (int) ((1 << PRECBITS) * 0.667);
DisabledCompositeContext(final ColorModel srcCM, final ColorModel dstCM) {
this.srcCM = srcCM;
this.dstCM = dstCM;
}
public void compose(final Raster src, final Raster dstIn, final WritableRaster dstOut) {
final int w = Math.min(src.getWidth(), dstIn.getWidth());
final int h = Math.min(src.getHeight(), dstIn.getHeight());
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
int rgb1 = srcCM.getRGB(src.getDataElements(x, y, null));
int a1 = ((rgb1 >>> 24) * SRCALPHA) >> PRECBITS;
int gray = (
((rgb1 >> 16) & 0xFF) * WEIGHT_R +
((rgb1 >> 8) & 0xFF) * WEIGHT_G +
((rgb1 ) & 0xFF) * WEIGHT_B
) >> PRECBITS;
int rgb2 = dstCM.getRGB(dstIn.getDataElements(x, y, null));
int a2 = rgb2 >>> 24;
int r2 = (rgb2 >> 16) & 0xFF;
int g2 = (rgb2 >> 8) & 0xFF;
int b2 = (rgb2 ) & 0xFF;
// mix the two pixels
gray = gray * a1 / 255;
final int ta = a2 * (255 - a1);
r2 = gray + (r2 * ta / (255*255));
g2 = gray + (g2 * ta / (255*255));
b2 = gray + (b2 * ta / (255*255));
a2 = a1 + (ta / 255);
rgb2 = (a2 << 24) | (r2 << 16) | (g2 << 8) | b2;
Object data = dstCM.getDataElements(rgb2, null);
dstOut.setDataElements(x, y, data);
}
}
}
@Override
public void dispose() {
// nothing for this implementation
}
}
// from here on out its only the fluff to make this a runnable example
public static void main(String[] argv) {
Runnable r = new CompositeSSCE();
SwingUtilities.invokeLater(r);
}
// simple component to use composite to render
static class DemoComponent extends JComponent {
// demonstrate rendering an icon in grayscale with the composite
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
GradientPaint p = new GradientPaint(0, 0, Color.GREEN, 127, 127, Color.BLUE, true);
g2d.setComposite(new DisabledComposite());
g2d.setPaint(p);
g2d.fillRect(0, 0, getWidth(), getHeight());
}
}
// Fluff to use the Composite in Swing
public void run() {
try {
JFrame f = new JFrame("Test grayscale composite");
DemoComponent c = new DemoComponent();
c.setPreferredSize(new Dimension(500, 300));
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new BorderLayout());
f.add(c, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
您始终可以创建一个BufferedImage
,使用bufferedImage.createGraphics()
将任何需要灰度化的Graphics
绘制到该Graphics
对象,然后使用javax.swing.GreyFilter
创建图像的灰度缩放副本。
本页面显示如何使用Filter
。
您可能还想将您的方法与SwingX的BlendComposite
进行比较,我期望您可以做同样的事情。 BlendComposite具有饱和度模式,可以实现灰度。 (它也有更多模式。)
此页面有BlendComposite演示。
关于效率,我期望它们之间没有重要的区别,因为有中间步骤,并且从我所能看到的两个方面完成图像数据的复制。 但是,如果您使用我建议的第一种方法保留灰度图像,则可以防止重新计算非动态控件。
如果你做了以上其中一项,性能将是正确的,我期望这就是你真正想要的。
从你的评论我猜你可能只是想将效果应用到组件。 为此,您可以使用仅在Java 7中提供的JLayer
。从Javadoc中可以看到覆盖半透明绿色的示例。 你可以用灰色代替它。 如果你想在以前的Java版本中使用JXLayer
,你可以使用JXLayer
,这是SwingX项目的一部分。
如果我没有正确理解你的问题,我很抱歉,但这可能会对你有帮助吗? 它使用CSS来制作图像灰度。
这也可以是你在找什么? 它使用jQuery和画布来操纵图像。
链接地址: http://www.djcxy.com/p/11517.html上一篇: How can I implement java.awt.Composite efficiently?
下一篇: Attach existing EBS as root device in spot instance request