I am trying to get a background Image to display on a JFrame for a small game I'm programming. The image is a .jpg and I keep getting these errors:
Exception in thread "main" java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(ImageIcon.java:205)
at web.game.Base.<init>(Base.java:45)
at web.game.Base.main(Base.java:61)
And my code is:
Image myimage;
public Base() {
ImageIcon ii = new ImageIcon(this.getClass().getResource("myimage.jpg"));
myimage = ii.getImage();
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(myimage, 10, 10, null);
There are many reasons you might have problems. The most obvious begin, the image doesn't exist (or at least doesn't exist where you think it does)
private BufferedImage myImage;
public Board() {
try {
myimage = ImageIO.read(this.getClass().getResource("/myimage"));
} catch (IOException exp) {
exp.printStackTrace();
}
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (myImage != null) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(myimage, 10, 10, this);
System.out.println("Background Image");
}
}
You may find Performing Custom Painting and Reading/Loading an Image of some use.
When using getResource you have two (basic) choices. Relative or absolute.
With a relative path, the class loader will start searching based on the context of the class. So if you image is in the root folder of your project, but your class is in sub folder (of packages), then a relative path won't work, because the class loader will start search from where the class resides.
An absolute path will allow you to search from the root of the classpath, which is going to be more helpful, especially in your case.
Try something like this and see what you get..
System.out.println(TestReference.class.getResource("myimage.jpg"));
System.out.println(TestReference.class.getResource("/myimage.jpg"));
Related
I have a function that is drawing an image and then saving it immediately after but the problem is that it seems to be drawing it twice, once for the view on the screen and then once to save it to the disk
public class myFrame {
public static void main(String[] args) {
JFrame lv_frame = new JFrame();
// setup jframe here
lv_frame.add(new image());
lv_frame.setVisible(true);
}
}
class image extends JPanel {
public void paintComponent(Graphics graphic) {
super.paintComponent(graphic);
draw(graphic);
save();
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.fillArc(0, 0, 250, 250, 0, 90);
}
public void save() {
BufferedImage image = new BufferedImage(250, 250, BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics2D graphic2D = image.createGraphics();
try {
File output = new File("file.png");
// is it possible to use the graphic I've already
// drawn here instead of re-drawing?
draw(graphic2D);
ImageIO.write(image, "png", output);
} catch(IOException log) {
System.out.println(log);
}
}
}
I have a function draw which creates the image on the gui screen and another function save which saves it to the disk but the save function is calling draw as well.
Is it possible to save the image that has already been drawn without re-calling the draw function as it is being done in my code?
I was answering your question on Display to GUI and Save to Disk with a Single Object/Variable, however it was closed probably due to the similar nature of your question.
I think there are several issues which you seemed confused with and I would like to write my solution here which also addresses your question in your duplicated post.
Is it possible to save the image that has already been drawn without re-calling the draw function as it is being done in my code?
Don't be confused between drawing an image on the Panel and saving it. The following shows a working example on saving a drawn image.
class DrawingSpace extends JPanel
{
private BufferedImage buf;
public DrawingSpace(){
setPreferredSize(new Dimension(200, 200));
buf = new BufferedImage(200, 200, BufferedImage.TYPE_INT_ARGB);
drawOnBuffer();
}
public void drawOnBuffer(){
Graphics g = buf.createGraphics();
g.setColor(Color.BLUE);
g.fillOval(0,0,200,200);
g.setColor(Color.RED);
g.fillOval(50,50,100,100);
g.dispose();
}
public void saveBufferAsImage(String pathname){
String fmt = "";
if(!(pathname == null || pathname.equals(""))){
fmt = pathname.substring(pathname.lastIndexOf(".")+1);
File outputfile = new File(pathname);
try{
ImageIO.write(buf, fmt, outputfile);
}catch(IOException ioe){System.out.println("Unable to save file");}
}
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(buf, 0, 0, 200, 200, null); //Only for user to see
}
}
To save an image, you not necessarily have to draw and display it in the JPanel first. Note that I created a BufferedImage called buf and I am drawing on buf. Once I have drawn onto a BufferedImage, I can simply save that image as a file (I don't have to draw it to the panel first).
Notice that I did the following:
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.drawImage(buf, 0, 0, 200, 200, null); //Only for user to see
}
g.drawImage(buf, 0, 0, 200, 200, null) will draw whatever on buf onto the JPanel. It can be deleted and the saving will still work. When I draw it on the panel, it is only for the user to see the outcome of the drawing.
To test the program:
class SaveImageRunner{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
JFrame frame = new JFrame("Saving a buffered image");
DrawingSpace ds = new DrawingSpace();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(ds);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
ds.saveBufferAsImage("BlueCircle.png");
}
});
}
}
Saved Image:
Some pointers on drawing:
paintComponent(Graphics) shall only contain codes for drawing and nothing else. Do not implement your codes for saving the image to a file inside here.
Try not to create a new BufferedImage in the paintComponent(Graphics). If not, a new instance of a BufferedImage will be created on every repaint.
Change the place where you create the graphics2D object and reuse it.
Try this out.
public class myFrame {
public static void main(String[] args) {
JFrame lv_frame = new JFrame();
// setup jframe here
lv_frame.add(new image());
lv_frame.setVisible(true);
}
}
class image extends JPanel {
public void paintComponent(Graphics graphic) {
super.paintComponent(graphic);
// Image and graphics are now created here
BufferedImage image = new BufferedImage(250, 250, BufferedImage.TYPE_4BYTE_ABGR_PRE);
Graphics2D graphic2D = image.createGraphics();
draw(graphic2D);
save(image);
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.fillArc(0, 0, 250, 250, 0, 90);
}
public void save(BufferedImage image) {
try {
File output = new File("file.png");
ImageIO.write(image, "png", output);
} catch(IOException log) {
System.out.println(log);
}
}
}
EDIT
I have found the answer in another post. It is not a bad idea to make the drawing twice. What you are doing is, like #Hovercraft says in this post, separating the screen drawing from the writing to files so that you don't see your graphics drawing performance hurt.
I have tried to make the drawing only once but you have no easy method to store the drawing Graphics object. Probably, it is implemented to prevent this. If you see the way the method works, you are given the Graphics object with the only purpose to draw on it. Using it in other ways could impact the performance.
Im try to load image with file chooser,
but when I updated image after loaded, and reload it, image is not change. It just show first time loaded.
(I tryed not use filechooser)
Load-> change image -> Load -> image not change
Load-> change image ->Exit Program ->open program -> Load -> image change
How can I clear it?
Load Image
int ret = chooser.showOpenDialog(null);
if(ret == JFileChooser.APPROVE_OPTION){
String filePath = chooser.getSelectedFile().getPath();
ImageIcon icon = new ImageIcon(filePath);
main.ChangeImage(icon);
}
Change Image
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image.getImage(), 0, 0, this);
}
public void ChangeImage(ImageIcon img) {
image = img;
origin_image = image;
origin_height = image.getIconHeight();
origin_width = image.getIconWidth();
this.setBounds(0, 0, image.getImage().getWidth(null), image.getImage()
.getHeight(null));
repaint();
}
Java tends to cache images.
If the images change during run-time, one way to fool the methods into reloading it is to read the bytes of the file yourself, form an input stream from them (using ByteArrayInputStream) and use the input stream in ImageIO.read(InputStream).
The reason this works is that if an URL or File is used to load the image, the toolkit uses the location as a key to cache it.
Other notes
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// ..
Should be:
public void paintComponent(Graphics g) {
super.paintComponent(g); // paint the border and BG to avoid arttifacts!
Graphics2D g2 = (Graphics2D) g;
// ..
I want to load an image to JPanel. The images that are going to be drawn are images saved from this JPanel.
For example i have this picture that has been capture from the JPanel and later i want to load that image to the same JPanel.
I have tried this but it does not work. This piece of code is inside a class that extends JPanel. Any suggestions?
public void load(String path) throws IOException {
BufferedImage img = ImageIO.read(new File(path));
Graphics2D g2d = img.createGraphics();
g2d.drawImage(img, 0, 0, null);
this.repaint();
}
You draw the image back to itself (?) using a Graphics object derived from the Image itself. Instead store the image to a field, not a local variable, and draw that image within the JPanel's paintComponent method. Most important, have a look at the Swing graphics tutorials
private BufferedImage img;
public void load(String path) throws IOException {
img = ImageIO.read(new File(path));
this.repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, null);
}
}
you can do that by an override
public void paintComponent(Graphics g) {...} for javax.swing components
and public void paint(Graphics g) for java.awt components
I would like to display a DICOM image in my java program. I am using pixelmed. However, I found that i cant correctly display the correct contrast. The contrast is too low.
Here is my code:
(SourceImage is a class provided by PixelMed, chosenImageFile.getPath() is just the path of the DICOM File.)
SourceImage dimg = new SourceImage(chosenImageFile.getPath());
BufferedImage image = dimg.getBufferedImage();
BufferedImage source = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = source.createGraphics();
g2d.drawImage(image, 0, 0, null);
dicomImgDisplayer1.setImage(source);
dicomImgDisplayer1 is an class extend JPanel. setImage() of this JPanel class will call the setImage() of an JFrame class.
The JFrame class's setImage() code:
public void setImage(BufferedImage image) {
this.image = image;
setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
repaint();
revalidate();
}
public void paint(Graphics graphics) {
Graphics2D g2d = (Graphics2D) graphics;
g2d.drawImage(image, null, 0, 0);
}
Is that something wrong with the color model? Please help. Thanks.
Does your image have a prescribed window width / window center? Be sure you set that (or allow the user to adjust it). See SingleImagePanel - there are some static methods to apply windowing to your buffered image.
I want to load an image from my computer into 2D Graphics so that I can edit it afterwards and then I want to add it to JPanel. If you need to see my project I can send it to you.
void loadImage()
{
FileDialog fd = new FileDialog(new Frame(), "Please choose a file:", FileDialog.LOAD);
fd.show();
if (fd.getFile() != null)
{
File fil = new File(fd.getDirectory(), fd.getFile());
strDirectory = fd.getDirectory();
strFileType = fd.getFile();
mainImage.setIcon(new ImageIcon(fil.toString()));
getFileList(strDirectory);
checkFileType(strFileType);
}
}
Thanks in advance
To load your image into the memory, you can use ImageIO.read(File). To edit it afterwards, obtain a Graphics2D instance from it by calling createGraphics():
BufferedImage img = ImageIO.read(yourFile);
Graphics2D g = img.createGraphics();
// Draw here on the graphics
g.dispose();
You can even turn on anti-alias by setting a RenderingHint before drawing:
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIASING_ON);
Then, to add it to a JPanel, create your custom JComponent and add an instance of that component to your JPanel:
public class JImageComponent extends JComponent
{
private BufferedImage img;
public JImageComponent(BufferedImage bi)
{
img = bi;
}
#Override
public void paintComponent(Graphics g)
{
g.drawImg(img, 0, 0, this);
}
}
please read this tutorials about Icon in Swing and your Image/ImageIcon would by placed to the JLabel, this way eliminated all troubles came from paint/paintComponents ...
For image loading you should use ImageIO object with method read(File file) see docs. Then you will get BufferedImage instance of which you can make your changes through Graphics2D instance which you'll obtain by calling createGraphics() on the image instance see docs. Last thing, override method paintComponent() from JPanel or better JComponent see docs and there you can draw your image on Graphics instance which you'll get as parameter in paintComponent(Graphics g) method by calling drawImage(Image img, int x, int y, ImageObserver observer) see docs where ImageObserver set to null.