Paint BufferedImage on JFrame and write to File

2019-07-29 23:25发布

问题:

I'm trying to code a program, that reads an Image into a BufferedImage, paint it on the JFrame, paint circles in it, and writes it to a File.

The following code will do all of it except the content of the saved file. The saved image only contains the untouched BufferedImage. No Circles ;) I already treid to figure it out by changing and adding some code, but it didn't help a lot.

public class PaintImage extends Component {

BufferedImage img;
private int pngWidth, pngHeight;

public int getPngWidth() {
    return pngWidth;
}

public int getPngHeight() {
    return pngHeight;
}

public void paint(Graphics g) {
    super.paint(g);

 //g = img.createGraphics();
 g.drawImage(img, 0, 0, 809, 1080, null);
 g.drawOval(33, 33, 444, 444);
}

public PaintImage() {
try {
    img = ImageIO.read(new File("C:\\karte_vorlage.png"));
    pngWidth = img.getWidth();
    pngHeight = img.getHeight();

} catch (IOException e) {
}
}

public void writeImage () {
    try {
     img.getGraphics();
        ImageIO.write(img, "png", new File("C:\\save.png"));
    } catch (IOException e1) {
        e1.printStackTrace();
    }
}


}

Uncommenting g = img.createGraphics(); causes a disorted image.

Please help me. thank you all in advance.

edit: 1. The method paint(Graphics g) is called twice. In case of minimizing it will be called twice again.

回答1:

You could just simple paint the component directly to the BufferedImage

BufferedImage tempImage = new BufferedImage(imagePane.getWidth(), imagePane.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g = tempImage.createGraphics();

imagePane.printAll(g);

ImageIO.write(tempImage, "png", new File("C:\\save.png"));

You may want to play around with the width & height to better meet your requirements though

UPDATED

Keep thinking about this.

Another idea would be to create some kind of "paint manager" or "paintable" interface, that given a Graphics content could paint it self (obviously you'd like to know some more info, like width & height)

This would mean that it wouldn't matter where it was painted.

The other thing is you might like to provide hints back to the renderer about how the paintable would like to be painted (something like preferred size)

Just an idea



回答2:

Draw the circle to the image in another method. You can call this other method whenever you want to. Then in the paint method you just draw the image to the component and nothing else.

public void paint(Graphics g) {
    super.paint(g);
    g.drawImage(img, 0, 0, 809, 1080, null);
}

public void drawCircle() {
    Graphics g = img.getGraphics();
    g.drawOval(33, 33, 444, 444);
}

You can also remove img.getGraphics(); from the writeImage method, as it is not needed there.



回答3:

You should change your design. Try this way:

  1. read the png file and save it to a bufferedImage.
  2. change your paint() method(this is very important because you want is a new Image with an addtional element, but your code mean to first draw a png and then draw an oval on the UI). it does not modify the bufferedImage. add your own event to change the bufferedImage. For example, when your click a button run a method like this:

void foo(bufferedImage) {

    g = bufferedImage.getGraphis();
    g.drawSomething();
}
public void paint(Graphics g) {
    g.drawImage(bufferedImage);
}