一张bmp格式的图,图的一部分颜色为 255 0 255(紫红色)
如何实现 画这张图的时候 紫红色不画出来?
类似 DirectDraw 的MaskColor功能。BufferedImage Img = ImageIO.read (url);
//
应该是在这部分实现 mask color功能吧? 如何实现?//
BG.drawImage(Img, null, 0, 0);
以前一直是用c++的 所以java不熟悉。请高手指教。非常感谢

解决方案 »

  1.   

    没做过这样的处理,不过查了一下jdkdoc,看看能不能这样
    可以参考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); 以上代码纯属瞎写的,仅供参考。
      

  2.   

    谢谢楼上2位。qybao 阿宝 你的方法是不是自定义了 img2 的颜色索引啊? 这个方法我会实验一下。
    但是以我做DirectDraw的经验来看 mask color 功能是硬件级别的。也就是说 显卡就提供了 mask color的功能。所以应该不用去定义 颜色索引,我接触过的一些图象处理方式 也都是直接对 定义 mask color, 然后在blit时直接将颜色忽略。 这样处理能达到较高的性能。
      

  3.   


    查了下AffineTransform应该帮不了lz
    都是些几何转换
      

  4.   

    其实不用那么复杂,用ImageFilter就可以做到了
    自己写个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;
            }
        }
    }
      

  5.   

    qybao 阿宝
    我现在用的方法 类似于你的方法。实质就是 将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 也就是画的时候 过滤掉特定颜色。
    再次感谢你的回复,帖子再挂几天,要是还没办法就直接把份给你了。
      

  6.   

    我对java的图形图像处理了解也不多,java直接调显卡的接口应该做不到,估计要用到JNI。LZ的要求好像是要做动画,那样的话可以下载一个java3d包看看,里面也许有你想要的。
      

  7.   

    java3d 肯定可以的。只是我现在做的这个没必要用到3d的功能。
      

  8.   

    java3d有for openGL和Dirctor两种,估计底层有封装好的对显卡的一些操作,你可以参考调用相应的方法,并非要你一定要用3d效果。或者你用其他语言写一个 mask color的功能的dll,然后在java里调用。
      

  9.   

    不用java3d是因为资料少了点,而且都英文的。没什么时间去研究。
    考虑到不同平台的使用所以也不能用Dirctor dll也不能和平台有关,这样做很麻烦。
    算了 看来没什么人研究这块,毕竟用java写底层的东西不太实用。
    结贴了 谢谢你多次的回复。