一张bmp格式的图,图的一部分颜色为 255 0 255(紫红色)
如何实现 画这张图的时候 紫红色不画出来?
类似 DirectDraw 的MaskColor功能。BufferedImage Img = ImageIO.read (url);
//
应该是在这部分实现 mask color功能吧? 如何实现?//
BG.drawImage(Img, null, 0, 0);
以前一直是用c++的 所以java不熟悉。请高手指教。非常感谢
如何实现 画这张图的时候 紫红色不画出来?
类似 DirectDraw 的MaskColor功能。BufferedImage Img = ImageIO.read (url);
//
应该是在这部分实现 mask color功能吧? 如何实现?//
BG.drawImage(Img, null, 0, 0);
以前一直是用c++的 所以java不熟悉。请高手指教。非常感谢
可以参考AffineTransformOp, ColorConvertOp
Graphics2D g2 = img.getGraphics2D();
g2.drawImage(BufferedImage img, BufferedImageOp op, int x, int y);
g2.drawImage(Image img, AffineTransform xform, ImageObserver obs)
//看看怎么去设置参数
或者直接用ColorConvertOp颜色转换
Color clr = new Color(255, 0, 255);
int rgb = clr.getRGB();
ColorSpace srcCs = ColorSpace.getInstance(ColorSpace.CS_sRGB); //LZ可以自己查看doc,看看哪个参数合适
ColorSpace destCs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
ColorConvertOp ccop = new ColorConvertOp(srcCs, destCs, new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_DEFAULT)); //自己看看怎么设置参数
ColorModel cm = new ColorModel(rgb);
//ColorModel cm = img.getColorModel();
BufferedImage img2 = ccop.createCompatibleDestImage(img, cm);//
BG.drawImage(img2, null, 0, 0); 以上代码纯属瞎写的,仅供参考。
但是以我做DirectDraw的经验来看 mask color 功能是硬件级别的。也就是说 显卡就提供了 mask color的功能。所以应该不用去定义 颜色索引,我接触过的一些图象处理方式 也都是直接对 定义 mask color, 然后在blit时直接将颜色忽略。 这样处理能达到较高的性能。
查了下AffineTransform应该帮不了lz
都是些几何转换
自己写个Filter类继承于RGBImageFilter,然后实现filterRGB方法,然后通过原有的Image资源重新生成一个被颜色过滤的Image对象,然后调用Graphics的drawImage方法画出Image就可以了。 不过重新生成的Image对象并不是BufferedImage的实例,所以LZ如果确实需要BufferedImage实例的话,可以再想办法转换。出于学习研究,做了个小sample测试,LZ可以参考
以下代码是个完整的测试source,LZ只需要参考RGBImageFilterImpl类的filterRGB方法和测试用的按钮事件里重新生成过滤Image的doRGBFilter方法就可以了。
测试时请自行准备一张图片,然后修改代码里的imgFile的路径import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.RGBImageFilter;
import java.io.FileInputStream;import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;import sun.awt.image.ToolkitImage;public class ImgTest extends JFrame implements ActionListener {
ImagePane imgPane;
JButton btn;
Image image;
RGBImageFilterImpl filter;
final String imgFile = "./img/00x.jpg";
public static void main(String[] args) {
new ImgTest();
}
public ImgTest () {
super("Image Test");
setSize(400, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
c.setLayout(null);
image = getDefaultImage();
imgPane = new ImagePane(image);
imgPane.setBounds(10, 10, 280, 280);
c.add(imgPane);
btn = new JButton("do filter");
btn.setBounds(300, 220, 80, 20);
btn.addActionListener(this);
c.add(btn);
filter = new RGBImageFilterImpl(); //生成过滤器
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int)((screen.getWidth()-getWidth())/2);
int y = (int)((screen.getHeight()-getHeight())/2);
setLocation(x, y);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == btn) {
doFilterAction();
}
}
protected void doFilterAction() {
Color c = JColorChooser.showDialog(this, "", Color.black);
int rgb = c.getRGB();
filter.setFilterRGB(rgb);//设置过滤颜色
image = doRGBFilter(image, filter); //通过过滤器生成新的Image对象
//System.out.println(image.getClass());
if (image instanceof ToolkitImage) {
ToolkitImage timg = (ToolkitImage)image;
if (timg.getBufferedImage() != null) {
image = timg.getBufferedImage();
System.out.println(image.getClass());
}
}
imgPane.setImage(image);//重新显示被过滤的Image,以查看测试结果
imgPane.repaint();
}
protected Image getDefaultImage() {
try {
return ImageIO.read(new FileInputStream(imgFile));
} catch (Throwable e) {
e.printStackTrace();
}
return Toolkit.getDefaultToolkit().getImage(imgFile);
}
protected void doPaint(Graphics g, Image img) {
if (img instanceof BufferedImage) {
Graphics2D g2 = (Graphics2D)g;
g2.drawImage((BufferedImage)img, null, 0, 0);
//System.out.println("doPaint bufferedimage");
return;
}
g.drawImage(img, 0, 0, imgPane);
//System.out.println("doPaint image");
}
protected Image doRGBFilter(Image img, RGBImageFilter filter) {
FilteredImageSource fis = new FilteredImageSource(img.getSource(), filter); //用设定的过滤器生成要过滤颜色的Filter源
//System.out.println("doRGBFilter");
return Toolkit.getDefaultToolkit().createImage(fis); //生成被过滤的Image实例
}
class RGBImageFilterImpl extends RGBImageFilter {
private int rgb; //可以声明要过滤的颜色
public RGBImageFilterImpl() {
canFilterIndexColorModel = true;
rgb = Color.black.getRGB();//缺省要过滤的颜色为黑色
}
public RGBImageFilterImpl(int rgb) {
canFilterIndexColorModel = true;
this.rgb = rgb;
} public int filterRGB(int x, int y, int rgb) {
if (this.rgb == rgb) {//事先设置好的要过滤的颜色如果和被过滤的颜色相同则过滤
//System.out.println("do filter");
return Color.white.getRGB();//过滤后返回的颜色,可以自己根据需要定义,这里是返回白色
}
return rgb;//不需要过滤的颜色保持原样返回
}
public void setFilterRGB(int rgb) {
this.rgb = rgb; //设置要过滤的颜色
}
}
class ImagePane extends JPanel {
private Image img;
public ImagePane() {
img = getDefaultImage();
}
public ImagePane(Image img) {
this.img = img;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
doPaint(g, img);
}
public void setImage(Image img) {
this.img = img;
}
public Image getImage() {
return img;
}
}
}
我现在用的方法 类似于你的方法。实质就是 将bmp的图存成gif格式,将特定颜色指定为透明色。
做法就是
BufferedImage image1 = ImageIO.read (url);
BufferedImage image2 = GC.createCompatibleImage(image1.getWidth(), image1.getHeight(),Transparency.BITMASK);
然后将 image1 画到 image2 上 期间不画指定的透明色。
(以其这样做 不如直接把原图用gif图)这样做的缺点是 image2 多了个Alpha通道 在画image2时多了Alpha运算 这是非常耗时的。
(以我现在的代码 有Alpha 则屏幕可以稳定在每秒 25帧 没Alpha则达到 35帧 )mask color 是现今大部分显卡中提供的功能 这是实现精灵动画的基本操作之一,所以我觉得应该有方法直接
在blit 也就是画的时候 过滤掉特定颜色。
再次感谢你的回复,帖子再挂几天,要是还没办法就直接把份给你了。
考虑到不同平台的使用所以也不能用Dirctor dll也不能和平台有关,这样做很麻烦。
算了 看来没什么人研究这块,毕竟用java写底层的东西不太实用。
结贴了 谢谢你多次的回复。