Image.getScaledInstance()更改灰度级别

时间:2013-07-02 22:00:31

标签: java image graphics

我有一个JTable,需要非常频繁地重新绘制每个单元格,其中表格的单元格显示灰度图像。通常需要缩放图像以进行绘画以适合绘制区域。我在JComponent的方法paintComponent(Graphics g)中有两个实现:

  1. 创建缩放图像Image.getScaledInstance(),然后使用图形绘制它。
  2. 让图形“动态”缩放图像;
  3. 第一种方法工作得更快,并且需要更少的CPU。但它改变了图像的颜色(灰度)。下图说明了这个问题。第一种方法(错误的颜色)在左边,第二种方法(真彩色)在右边。

    问题:为什么会发生这种情况以及如何解决?或者,我们非常感谢任何其他解决方案。

    enter image description here

    注意:在此代码示例中,我实际上并未缩放图像,但调用Image.getScaledInstance()仍会更改图像值。

    代码:

    class CellImage extends JComponent {
    
        final boolean rescale_img;
        final byte value;
    
        CellImage(boolean flag, byte v) {
            rescale_img = flag;
            value = v;
        }
    
        @Override
        public void paintComponent(Graphics g) {
            Rectangle r = g.getClipBounds();
            BufferedImage image = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_GRAY);
            byte[] bytes = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            Arrays.fill(bytes, value);
            if (rescale_img){
                Image scaled = image.getScaledInstance(r.width, r.height, Image.SCALE_REPLICATE);
                g.drawImage(scaled, 0, 0, null);
            } else {
                g.drawImage(image, 0, 0, null);
            }
        }
    }
    

    如果需要,请参阅以下整个SSCCE:

    package book_test_paint;
    
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Image;
    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.awt.image.DataBufferByte;
    import java.util.Arrays;
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTable;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.JTableHeader;
    import javax.swing.table.TableCellRenderer;
    
    class CellImage extends JComponent {
    
        final boolean rescale_img;
        final byte value;
    
        CellImage(boolean flag, byte v) {
            rescale_img = flag;
            value = v;
        }
    
        @Override
        public void paintComponent(Graphics g) {
            Rectangle r = g.getClipBounds();
            BufferedImage image = new BufferedImage(r.width, r.height, BufferedImage.TYPE_BYTE_GRAY);
            byte[] bytes = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
            Arrays.fill(bytes, value);
            if (rescale_img){
                Image scaled = image.getScaledInstance(r.width, r.height, Image.SCALE_REPLICATE);
                g.drawImage(scaled, 0, 0, null);
            } else {
                g.drawImage(image, 0, 0, null);
            }
        }
    }
    
    class CellText extends JComponent {
    
        final String str;
    
        CellText(String s){
            str = s;
        }
    
        @Override
        public void paintComponent(Graphics g) {
            Rectangle r = g.getClipBounds();
            g.setColor(Color.BLACK);
            g.fill3DRect(0, 0, r.width, r.height, true);
            g.setColor(Color.WHITE);
            ((Graphics2D) g).drawString(str, 0.1f * r.width, 0.9f * r.height);
        }
    }
    
    class MyTableModel extends DefaultTableModel {
    
        final int nrows = 17;
    
        @Override
        public int getRowCount() {
            return nrows;
        }
    
        @Override
        public int getColumnCount() {
            return 3;
        }
    
        @Override
        public Object getValueAt(int row, int column) {
            Object obj = null;
            // The value below represents the desired 
            // gray scale of the image in range [0, 255]
            int val = (int)Math.min(255, row * 256.0 / (nrows - 1));
            switch (column) {
                case 0:
                    obj = new CellImage(true, (byte)val);
                    break;
                case 1:
                    obj = new CellText("" + val);
                    break;
                case 2:
                    obj = new CellImage(false, (byte)val);
                    break;
            }
            return obj;
        }
    }
    
    public class Image_Scaling extends JTable {
    
        public Image_Scaling(JPanel panel) {
            setModel(new MyTableModel());
            setRowHeight(25);
            getColumnModel().getColumn(0).setPreferredWidth(200);
            getColumnModel().getColumn(1).setPreferredWidth(40);
            getColumnModel().getColumn(2).setPreferredWidth(200);
            JTableHeader header = getTableHeader();
            header.getColumnModel().getColumn(0).setHeaderValue("with getScaledInstance()");
            header.getColumnModel().getColumn(1).setHeaderValue("gray");
            header.getColumnModel().getColumn(2).setHeaderValue("without getScaledInstance()");
            panel.setLayout(new BorderLayout());
            panel.add(header, BorderLayout.NORTH);
            panel.add(this, BorderLayout.CENTER);
        }
    
        @Override
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            return (Component) dataModel.getValueAt(row, column);
        }
    
        public static void main(String[] args) {
            JPanel panel = new JPanel(new BorderLayout());
            final Image_Scaling table = new Image_Scaling(panel);
    
            final JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(panel, BorderLayout.CENTER);
            frame.pack();
    
            java.awt.EventQueue.invokeLater(new Runnable() {
    
                public void run() {
                    frame.setVisible(true);
                }
            });
        }
    }
    

0 个答案:

没有答案