I am trying to draw on a buffered image. I am able to get the picture on the frame but it doesnt seem to draw on the image. If I use
BufferedImage bufferedImage = new BufferedImage(1280, 800,BufferedImage.TYPE_INT_RGB);
then it seems to draw the string but I would like to ideally draw on the image as I need to plot some coordinates on the image for a project. Any guidance would be highly appreciated. Excuse the bad indentation
import java.awt.Dimension;import java.awt.Graphics;import java.awt.Image;import java.awt.Toolkit;import java.awt.image.BufferedImage;import java.io.IOException;import javax.imageio.ImageIO;import javax.swing.JFrame;import javax.swing.JPanel;public class drawTest extends JPanel {public void paint(Graphics g) {Image img = createImageWithText();g.drawImage(img, 20,20,this);}private Image createImageWithText(){BufferedImage bufferedImage = new BufferedImage(1280, 800,BufferedImage.TYPE_INT_RGB);// BufferedImage bufferedImage = new BufferedImage()Graphics g = bufferedImage.getGraphics();try {bufferedImage = ImageIO.read(getClass().getResource("Unknown.jpg"));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}g.drawString("Point is here", 20,20);return bufferedImage;}public static void main(String[] args) {JFrame frame = new JFrame();Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();double width = screenSize.getWidth();double height = screenSize.getHeight();frame.getContentPane().add(new drawTest());frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// frame.setSize(200, 200);frame.setExtendedState(JFrame.MAXIMIZED_BOTH);System.out.println(height + " " + width); frame.setVisible(true);}}
Best Answer
You're creating two BufferedImage objects -- one that you get the Graphics context from and draw text on, and the other that holds the picture obtained via ImageIO, that you don't draw text on. You return the latter, so it makes sense that the picture holds no new text.
// BufferedImage Object ONEBufferedImage bufferedImage = new BufferedImage(1280, 800, BufferedImage.TYPE_INT_RGB); Graphics g = bufferedImage.getGraphics(); // Graphics for the first object onlytry {// BufferedImage object TWObufferedImage = ImageIO.read(getClass().getResource("Unknown.jpg"));} catch (IOException e) {e.printStackTrace();}// draw with the graphics context for the first objectg.drawString("Point is here", 20, 20);return bufferedImage; // but return the second
Solution: don't do this, create one BufferedImage only, say via ImageIO, get its Graphics context, draw with it, dispose the Graphics when done, and return it.
e.g.,
// have method accept the image path and // have it throw an exception if the path is badprivate Image createImageWithText2(String resourcePath) throws IOException {// create one and only one BufferedImage object. // If this fails, the exception will bubble up the call chainBufferedImage bufferedImage = ImageIO.read(getClass().getResource(resourcePath));// get the Graphics context for this single BufferedImage object Graphics g = bufferedImage.getGraphics(); g.drawString("Point is here", 20, 20);g.dispose(); // get rid of the Graphics context to save resourcesreturn bufferedImage;}
Other problems with your code is here:
public void paint(Graphics g) {Image img = createImageWithText();g.drawImage(img, 20,20,this);}
Problems include:
- You're overriding the wrong painting method. You should override paintComponent, not paint, and in fact your question mentions paintComponent, so I'm not sure why you're doing this.
- You're overriding a painting method but not calling the super's method, breaking the painting chain.
- You're doing file I/O unnecessarily repeatedly within a painting method, a method that has the greatest effect on the perceived responsiveness of your GUI, and so something you don't want to do. Read the image in once store it to a variable, use the variable within paintComponent, and never do file I/O within a painting method.
- You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
When working with Java, you may come across the need to draw on an image. Drawing on an image can be useful for various purposes, such as adding annotations, highlighting specific areas, or creating custom graphics. Fortunately, Java provides libraries and APIs that allow you to achieve this.
One popular library for image manipulation in Java is Java Advanced Imaging (JAI). JAI provides an extensive set of classes and methods for working with images. To draw on an image using JAI, you can create a Graphics object and use its methods to add drawings.
Another option for drawing on images in Java is using the Java 2D API. The Java 2D API provides a powerful set of tools for creating 2D graphics, including drawing on images. You can use the Graphics2D class to draw on an image by creating a Graphics2D object and calling its drawing methods.
To get started with drawing on an image in Java, you'll need to first load the image into your program. You can use classes like BufferedImage or ImageIO to read an image file into a BufferedImage object. Once you have the image loaded, you can create a Graphics or Graphics2D object and use its drawing methods to add your custom drawings.
Overall, drawing on an image in Java can be accomplished using libraries like JAI or the Java 2D API. By leveraging these libraries and their drawing methods, you can easily modify images by adding custom drawings to suit your specific needs.