【问题标题】:How can I edit a BufferedImage after it has been displayed?如何在 BufferedImage 显示后对其进行编辑?
【发布时间】:2018-03-19 21:40:40
【问题描述】:

我正在使用 16 位灰度图像:

BufferedImage bufferedImage = new BufferedImage(320, 240, BufferedImage.TYPE_USHORT_GRAY);

我可以通过获取对其底层存储的引用来编辑该图像。数据存储在一个线性数组中,按行主要顺序:

short[] data = ((DataBufferUShort)bufferedImage.getRaster().getDataBuffer()).getData();

但是,如果bufferedImage 已被渲染到任何屏幕,编辑data 不再有任何效果。我可以在数据显示在屏幕上之前对其进行编辑,但在显示之后就不能再更改了。

我当然尝试过重新绘制 AWT 控件——它没有使用新的像素数据进行更新。我什至尝试过 getDataElements 和 setDataElements。显示图像后似乎没有任何效果。

【问题讨论】:

  • minimal reproducible example 会有很大帮助。
  • 您是否使用新的像素数据更新了 BufferedImage? (即,你有没有在 BufferedImage 上调用 setData(data)
  • @Campbell getRaster().getDataBuffer()).getData() 不返回数据的副本;没有必要打电话给setData
  • @Mr.史密斯值得一试,不是吗?

标签: java awt bufferedimage


【解决方案1】:

我怀疑您在屏幕上绘制图像的方式有问题。

这里有一些最小的代码来演示你正在做什么应该可以工作:

public class Test {
    public static void main(String[] args) throws InterruptedException, InvocationTargetException {
        JFrame frame = new JFrame("Image Test");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY);
        ImageComponent component = new ImageComponent(image);
        frame.add(component);
        frame.pack();
        frame.setVisible(true);

        short gray = 0;
        short[] data = ((DataBufferUShort) image.getRaster().getDataBuffer()).getData();
        while (true) {
            for (int i = 0; i < data.length; i++) {
                data[i] = gray;
            }
            Thread.sleep(20);
            gray += 1000;
            component.repaint();
        }
    }

    static class ImageComponent extends JComponent {
        private BufferedImage image;

        public ImageComponent(BufferedImage image) {
            this.image = image;
            this.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        }

        @Override
        protected void paintComponent(Graphics g) {
            g.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
        }
    }
}

【讨论】:

  • 1.你真的应该打电话给super.paintComponent,因为组件可能比它的首选尺寸大; 2. 您应该覆盖getPreferredSize 而不是setPreferredSize,因为它可以防止其他元素更改它的可能性; 3.Graphics#drawImageImageObserver应该是this; 4.虽然只是一个例子,但修改两个线程之间共享的BufferedImage是一个坏主意,值得注意
  • @MadProgrammer:根据graphics tutorial,在渲染BufferedImage 时不需要图像观察器。
  • 这是真的 - 但这是一个使用的好习惯 - 因为你不会总是知道 ;)
猜你喜欢
  • 1970-01-01
  • 2021-08-03
  • 2010-12-15
  • 2015-10-14
  • 2014-01-05
  • 1970-01-01
  • 2019-07-11
  • 2010-12-10
  • 1970-01-01
相关资源
最近更新 更多