为什么 Java 加入小缓冲图像的代码不起作用?

Why Java code to join small buffered images does not work?

我创建了 4 个缓冲图像对象并用不同的颜色填充它们。然后创建一个更大的 bufferedimage 对象并将之前创建的所有四个 buff.images 绘制到其中以创建更大的图像。然后我将大图像保存到一个扩展名为 gif 的文件中。虽然大小正确,但 gif 文件不包含颜色。为什么 ?我的错误在哪里?

import java.awt.HeadlessException;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class MainFrame extends JFrame implements Runnable{

    public MainFrame() throws HeadlessException {
        ImagePanel ip=new ImagePanel(this);
        add(ip,"Center");
    }
    
    public static void main(String[] args) {
        MainFrame mf=new MainFrame();
        mf.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        mf.setSize(new Dimension(800,600));
        mf.setLocationRelativeTo(null);
        mf.setVisible(true);

    }

}

class ImagePanel extends JPanel {

    public ImagePanel(MainFrame jf) {
        ImageJoiner imj=new ImageJoiner();
    }
}




class ImageJoiner {
    
    // this will joing four buffered images together to construct bigger image as buffered image and save it as gif file
    
    public ImageJoiner() {
        createImages();
    }
    
    public void createImages() {
            
    imtl=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    imtr=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    imbl=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    imbr=new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    
    bigW=PW*2;
    bigH=PH*2;
    
    bigmap=new BufferedImage(bigW, bigH, BufferedImage.TYPE_INT_RGB); 
    
    imtl.createGraphics().setColor(Color.blue);
    imtl.createGraphics().fillRect(0,0, PW, PH);

    imtr.getGraphics().setColor(Color.red);
    imtr.getGraphics().fillRect(0, 0, PW, PH);

    imbl.getGraphics().setColor(Color.green);
    imbl.getGraphics().fillRect(0, 0, PW, PH);
    
    imbr.getGraphics().setColor(Color.yellow);
    imbr.getGraphics().fillRect(0, 0, PW, PH);
            
    bigmap.getGraphics().drawImage(imtl, 0, 0,PW,PH,null);
    bigmap.getGraphics().drawImage(imtr, PW, 0,PW,PH,null);
    bigmap.getGraphics().drawImage(imbl, 0, PH, PW,PH,null);
    bigmap.getGraphics().drawImage(imbr, PW, PH,PW,PH,null);
    
    writeBufferedImageToFile(bigmap);
        
    }
    
    private void writeBufferedImageToFile(BufferedImage bim) {
        File file = new File("images/out.gif");
        try {
            ImageIO.write(bim, "gif", file);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    static final int PW =1000;
    static final int PH =1000;
    static int bigW,bigH;
    BufferedImage imtl,imtr,imbl,imbr;
    BufferedImage bigmap;

}

您正在随意创建 Graphics 对象,设置其中一个的颜色,用另一个绘制,这可能行不通。创建 并以更好的方式使用 您的 Graphics 对象,例如:

public static void createImages() {
            
    imtl = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    imtr = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    imbl = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    imbr = new BufferedImage(PW, PH, BufferedImage.TYPE_INT_RGB);
    
    int bigW = PW * 2;
    int bigH = PH * 2;
    
    BufferedImage bigmap = new BufferedImage(bigW, bigH, BufferedImage.TYPE_INT_RGB); 
    
    Graphics2D g2d = imtl.createGraphics();
    g2d.setColor(Color.BLUE);
    g2d.fillRect(0,0, PW, PH);
    g2d.dispose();

    g2d = imtr.createGraphics();
    g2d.setColor(Color.RED);
    g2d.fillRect(0,0, PW, PH);
    g2d.dispose();
    
    g2d = imbl.createGraphics();
    g2d.setColor(Color.GREEN);
    g2d.fillRect(0,0, PW, PH);
    g2d.dispose();

    g2d = imbr.createGraphics();
    g2d.setColor(Color.YELLOW);
    g2d.fillRect(0,0, PW, PH);
    g2d.dispose();
    
    g2d = bigmap.createGraphics();
    g2d.drawImage(imtl, 0, 0,PW,PH,null);
    g2d.drawImage(imtr, PW, 0,PW,PH,null);
    g2d.drawImage(imbl, 0, PH, PW,PH,null);
    g2d.drawImage(imbr, PW, PH,PW,PH,null);
    g2d.dispose();
    
    writeBufferedImageToFile(bigmap);
}

代码经过测试,有效


您还问过:

i am still curious that, why BufferedImage#getGraphics().fillRect() does not work? It worked only you define a graphics object and then assign it ? Why can't I use it directly?

BufferedImage#getGraphics()BufferedImage#createGraphics() 创建一个 new Graphics2D 实例时,该实例与之前创建的任何实例都没有关系。

例如,您可以通过调用进行测试:

BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
Graphics ga = img.getGraphics();
Graphics gb = img.getGraphics();

System.out.println("ga: " + ga.hashCode());
System.out.println("gb: " + gb.hashCode());

ga.dispose();  // always dispose of resources that *you* create
gb.dispose();

运行这个程序,你会看到打印出两个不同的hashCode,证明ga和gb实例是不同的。如果您调用 .createGraphics().

,则会出现相同的相对输出

所以,当你这样做时:

imtl.createGraphics().setColor(Color.blue);
imtl.createGraphics().fillRect(0,0, PW, PH);

您正在设置一个 Graphics 实例的颜色,然后使用另一个独特的新实例进行绘制。由于第2个实例的Color没有设置,所以会使用默认的Color绘制,所有图片都保持黑色。