如何编辑 BufferedImage 中的像素?

Posted

技术标签:

【中文标题】如何编辑 BufferedImage 中的像素?【英文标题】:How to edit the pixels in a BufferedImage? 【发布时间】:2014-06-07 16:42:48 【问题描述】:

在网上搜索了几天后,我发现了一个似乎可以解决我的目标的问题。 (我正在尝试绘制/编辑图像中的单个像素,并对其进行渲染。)在上述问题中,提问者请求了 Black BufferedImage 的代码。最佳答案提供了该代码,并且看起来运行良好,直到您尝试将其更改为黑色以外的其他内容。这是代码:

package myProjectPackage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.*;

public class Copypasta 

public static JFrame frame;
BufferedImage img;
public static int WIDTH = 500;
public static int HEIGHT = 500;

public Copypasta() 


public static void main(String[] a)

    Copypasta t=new Copypasta();

    frame = new JFrame("WINDOW");
    frame.setVisible(true);

    t.start();
    frame.add(new JLabel(new ImageIcon(t.getImage())));

    frame.pack();
    // Better to DISPOSE than EXIT
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);


public Image getImage() 
    return img;


public void start()

    img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
    int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
    boolean running=true;
    while(running)
        BufferStrategy bs=frame.getBufferStrategy();
        if(bs==null)
            frame.createBufferStrategy(4);
            return;
        
        for (int i = 0; i < WIDTH * HEIGHT; i++)
            pixels[i] = 0; //This is what i've been trying to change.

        Graphics g= bs.getDrawGraphics();
        g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
        g.dispose();
        bs.show();

    


我为缩进错误道歉。我保证它在编辑器中看起来不错。

当设置为 BufferedImage 类型 ARGB 时,黑色背景消失,让我相信 start 函数根本没有绘制到 Image,或者绘制的图像没有绘制在屏幕上。不管怎样,有一些我不明白的地方。如果您有时间,我会很感激一些帮助确定出了什么问题,如果不是解释原因的话。谢谢你们, -导航。

原始问题链接:drawing your own buffered image on frame

【问题讨论】:

我“认为”问题是因为JFrame 上已经有“东西”,这会阻止绘制到BufferStrategy 的任何内容可见。您能解释一下为什么需要使用BufferStrategy 来执行此操作吗...另外,pixels 数组不是像素数据的“实时”副本,这意味着修改不会更改底层图像...一些有关您实际尝试实现的目标的更多信息可能使我们能够为您提供其他解决方案 非常感谢。我根本不需要使用 Bufferstrategy,这只是示例中的内容。我对 java 比较陌生,我在 unity3d 中使用过 javascript,但我决定要提高一个水平。我目前的目标是编辑窗口中的像素。如果您有任何提示/技巧,任何方法都会很棒。 【参考方案1】:

有几件事跳出来,BufferStrategy 的使用可能是矫枉过正。除非你绝对必须控制油漆过程,否则你真的不需要它。使用BufferStrategy 也排除了使用基于 Swing 的组件,这可能是也可能不是问题。

尝试直接操作像素数据可能也有点矫枉过正,相反你可以使用BufferedImage.setRGB(int, int, int),它允许你在指定的x/y位置设置像素的颜色,例如...

img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < img.getWidth(); x++) 
    for (int y = 0; y < img.getHeight(); y++) 
        img.setRGB(x, y, Color.RED.getRGB());
    

但是,即使这有点矫枉过正,同样的事情可以通过使用提供的 2D 图形 API 来实现...

Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.dispose();

您可能会发现它更快(不仅仅是从编码的角度来看)。

看看:

Performing Custom Painting Painting in AWT and Swing 2D Graphics

更多详情...

工作示例...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestImage1 

    public static void main(String[] args) 
        new TestImage1();
    

    public TestImage1() 
        EventQueue.invokeLater(new Runnable() 
            @Override
            public void run() 
                try 
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                 catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) 
                

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            
        );
    

    public class TestPane extends JPanel 

        private BufferedImage img;

        public TestPane() 
            img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
            //for (int x = 0; x < img.getWidth(); x++) 
            //    for (int y = 0; y < img.getHeight(); y++) 
            //        img.setRGB(x, y, Color.RED.getRGB());
            //    
            //

            Graphics2D g2d = img.createGraphics();
            g2d.setColor(Color.RED);
            g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
            g2d.dispose();
        

        @Override
        public Dimension getPreferredSize() 
            return new Dimension(200, 200);
        

        @Override
        protected void paintComponent(Graphics g) 
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.drawImage(img, 0, 0, this);
            g2d.dispose();
        
    


【讨论】:

很好的答案,谢谢。我相信我记得在某处读过有关速度和 setRGB 的文章,但我确信它不会让我慢下来那么糟糕。我试图编辑像素以便最终绘制一些 3d 图形,我拥有 3d 图形的所有公式,但无法将这些数据放在屏幕上。这就是为什么我问如何编辑像素。 2d 图形 API 是一个很好的想法。我现在去看看它是否可以绘制三角形......再次感谢!

以上是关于如何编辑 BufferedImage 中的像素?的主要内容,如果未能解决你的问题,请参考以下文章

Java——BufferedImage对象

Java BufferedImage,写入底层光栅,像素在最终图像中出现偏移

e671. 在缓冲图像中存取像素

int像素数组到java中的bmp

了解 BufferedImage.getRGB 输出值

BufferedImage为什么会这样?