user13887828
user13887828

Reputation:

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

I created 4 bufferedimage objects and fill them with different colors. Then create a bigger bufferedimage object and draw all previously created four buff.images into it to create bigger image. Then I saved big image to a file with gif extension. Although size is correct, gif file contains no color. Why ? Where is my mistake?

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;

}

Upvotes: 1

Views: 70

Answers (1)

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285405

You're creating Graphics objects willy-nilly, setting the color of one, drawing with the other, and this likely won't work. Create and use your Graphics objects in a better fashion, something like:

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);
}

Code tested, and it works


You have also asked:

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?

When either BufferedImage#getGraphics() or BufferedImage#createGraphics() a new Graphics2D instance is created, one that has no relationship to any that have been created previously.

For example, you can test this by calling:

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();

Run this program and you will see two different hashCodes being printed out, proving that the ga and gb instances are different. The same relative output will occur if you called .createGraphics().

So, when you do this:

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

You are setting the Color of one Graphics instance, and then drawing with another unique and new instance. Since the Color of the 2nd instance has not been set, it will draw with the default Color, and all images will remain black.

Upvotes: 2

Related Questions