BufferedImage

Discussion in 'Java' started by Martijn Mulder, May 31, 2005.

  1. I try to load an image into a BufferdImage instance in the constructor
    of my class. It does not work. However, if I load the image in the
    paint() method, all goes well. How can I fix this?

    The code below should compile readily and illustrate the problem. The file
    "Dog.jpg" is a file I have on my system. The second line in the constructor
    does not do the job. But the same line in the paint()-method (commented out),
    makes the picture appear on the screen.

    Is there a better way to load an image into a BufferedImage instance?



    /*
    DisplayImage.java
    Load an image into a BufferedImage and display it to the screen
    */

    //class DisplayImage
    public class DisplayImage extends javax.swing.JFrame
    {

    //data member image
    java.awt.Image image;

    //data member displayimage
    java.awt.image.BufferedImage displayimage=new
    java.awt.image.BufferedImage(377,233,
    java.awt.image.BufferedImage.TYPE_INT_ARGB);

    //data member graphics2d
    java.awt.Graphics2D graphics2d=displayimage.createGraphics();

    //constructor
    DisplayImage()
    {
    image=java.awt.Toolkit.getDefaultToolkit().getImage("Dog.jpg");
    graphics2d.drawImage(image,0,0,this);
    }

    //paint
    public void paint(java.awt.Graphics a)
    {
    java.awt.Graphics2D b=(java.awt.Graphics2D)a;
    // graphics2d.drawImage(image,0,0,this);//uncommenting this makes it work
    b.drawImage(displayimage,0,0,this);
    }

    static void main(String[]a)
    {
    DisplayImage displayimage=new DisplayImage();
    displayimage.setSize(377,233);
    displayimage.show();
    }
    }
     
    Martijn Mulder, May 31, 2005
    #1
    1. Advertising

  2. Martijn Mulder wrote:
    > I try to load an image into a BufferdImage instance in the constructor
    > of my class. It does not work.


    Wrong, loading works. But then you do the wrong thing with it.

    > //data member graphics2d
    > java.awt.Graphics2D graphics2d=displayimage.createGraphics();


    This is the Graphics context of the Image itself.

    > graphics2d.drawImage(image,0,0,this);


    Here you draw the image on itself by using its own Graphics context.

    Please note, however, that changing to the "right" Graphics context will
    not work. There is no right Graphics context the moment you try to
    paint. The idea of painting ("pushing" graphics onto a component)
    outside of the paint[Component]() method is basically flawed.

    Q3.4 of the comp.lang.java.gui FAQ basically applies to your problem.
    The TCS article about painting in AWT and Swing is also a good read.

    /Thomas

    --
    The comp.lang.java.gui FAQ:
    ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
     
    Thomas Weidenfeller, May 31, 2005
    #2
    1. Advertising

  3. Martijn Mulder

    John McGrath Guest

    On 5/31/2005 at 9:12:11 AM, Thomas Weidenfeller wrote:

    > > //data member graphics2d
    > > java.awt.Graphics2D graphics2d=displayimage.createGraphics();

    >
    > This is the Graphics context of the Image itself.
    >
    > > graphics2d.drawImage(image,0,0,this);

    >
    > Here you draw the image on itself by using its own Graphics context.


    Actually, the "graphics2d" graphics context is associated with the
    BufferedImage "displayimage", so this draws the image referred to by
    "image" onto the BufferedImage "displayImage".

    I do see a number of other problems, though:

    1) Nothing is done to ensure that the image has completely loaded before
    it is drawn onto the BufferedImage. A MediaTracker can do this.

    2) It overrides the paint() method. With Swing components, the
    paintComponent() method should be overridden instead.

    3) It does not call the superclass paint() (or paintComponent()) from the
    overridden method.

    4) It paints on a JFrame, but that will be covered by the content pane.

    5) The class organization is *really* bad. The code that creates and
    loads the BufferedImage is spread across multiple initializers and the
    class constructor, and temporary variables are declared at the class
    level. This should be done in a separate method.

    6) The comments are brain-dead. If you don't have anything useful to say
    in a comment, don't say anything.

    --
    Regards,

    John McGrath
     
    John McGrath, Jun 2, 2005
    #3
  4. > > > //data member graphics2d
    > > > java.awt.Graphics2D graphics2d=displayimage.createGraphics();


    > >
    > > This is the Graphics context of the Image itself.
    > >


    > > > graphics2d.drawImage(image,0,0,this);


    > >
    > > Here you draw the image on itself by using its own Graphics context.


    > Actually, the "graphics2d" graphics context is associated with the
    > BufferedImage "displayimage", so this draws the image referred to by
    > "image" onto the BufferedImage "displayImage".
    >
    > I do see a number of other problems, though:
    >
    > 1) Nothing is done to ensure that the image has completely loaded before
    > it is drawn onto the BufferedImage. A MediaTracker can do this.
    >
    > 2) It overrides the paint() method. With Swing components, the
    > paintComponent() method should be overridden instead.
    >
    > 3) It does not call the superclass paint() (or paintComponent()) from the
    > overridden method.
    >
    > 4) It paints on a JFrame, but that will be covered by the content pane.
    >
    > 5) The class organization is *really* bad. The code that creates and
    > loads the BufferedImage is spread across multiple initializers and the
    > class constructor, and temporary variables are declared at the class
    > level. This should be done in a separate method.
    >
    > 6) The comments are brain-dead. If you don't have anything useful to say
    > in a comment, don't say anything.


    Wow. Thank you, I guess. I'll try to implement your suggestions and see if it
    works
    then.
     
    Martijn Mulder, Jun 2, 2005
    #4
  5. "John McGrath"
    <snip>
    > I do see a number of other problems, though:

    <snip>

    I tried to heed your advice, but... nope :-(



    /*
    ImageBuffer.java. Load an instance of BufferedImage with a file from
    disk before paintComponent() is called. This shouldn't be difficult at
    all. Do I have the wrong books? A blind spot?
    */

    //class ImageBuffer. Extend JComponent and draw a BufferedImage on it
    public class ImageBuffer extends javax.swing.JComponent
    {

    //data member bufferedimage. Java2 image, is to hold "Dog.jpg"
    java.awt.image.BufferedImage bufferedimage=new
    java.awt.image.BufferedImage(233,377,
    java.awt.image.BufferedImage.TYPE_INT_ARGB);

    //constructor. Load image and copy it to bufferedimage
    ImageBuffer(String a)
    {
    java.awt.Image image=java.awt.Toolkit.getDefaultToolkit().getImage(a);
    new java.awt.MediaTracker(this).addImage(image,0);
    bufferedimage.createGraphics().drawImage(image,0,0,this);
    }

    //paintComponent. Draw the pre-stored bufferedimage on the screen
    public void paintComponent(java.awt.Graphics a)
    {
    java.awt.Graphics2D b=(java.awt.Graphics2D)a;
    super.paintComponent(b);
    b.drawImage(bufferedimage,0,0,this);
    }

    //main. Create a JFrame, load an ImageBuffer on it and show(). "Dog.jpg" is a
    local file
    static void main(String[]a)
    {
    javax.swing.JFrame jframe=new javax.swing.JFrame("ImageBuffer");
    jframe.getContentPane().add(new ImageBuffer("Dog.jpg"));
    jframe.setSize(233,377);
    jframe.show();
    }
    }
     
    Martijn Mulder, Jun 2, 2005
    #5
  6. Re: BufferedImage - Fixed

    Fixed!

    //class ImageBuffer. Extend JComponent and draw a BufferedImage on it
    public class ImageBuffer extends javax.swing.JComponent
    {


    //data member bufferedimage. Java2 image, is to hold "Dog.jpg"
    java.awt.image.BufferedImage bufferedimage=new
    java.awt.image.BufferedImage(233,377,
    java.awt.image.BufferedImage.TYPE_INT_ARGB);


    //constructor. Load image and copy it to bufferedimage
    ImageBuffer(String a)
    {
    java.awt.Image image=java.awt.Toolkit.getDefaultToolkit().getImage(a);
    java.awt.MediaTracker mediatracker=new java.awt.MediaTracker(this);
    mediatracker.addImage(image,0);
    try
    {
    mediatracker.waitForID(0);
    }
    catch(java.lang.InterruptedException interruptedexception)
    {
    System.out.println("Image loading interrupted");
    }
    if(mediatracker.isErrorID(0))
    {
    System.out.println("Error loading image");
    }
    bufferedimage.createGraphics().drawImage(image,0,0,this);
    }


    //paintComponent. Draw the pre-stored bufferedimage on the screen
    public void paintComponent(java.awt.Graphics a)
    {
    java.awt.Graphics2D b=(java.awt.Graphics2D)a;
    b.drawImage(bufferedimage,0,0,this);
    super.paintComponent(b);
    }


    //main. Create a JFrame, load an ImageBuffer on it and show()
    static void main(String[]a)
    {
    javax.swing.JFrame jframe=new javax.swing.JFrame("ImageBuffer");
    jframe.getContentPane().add(new ImageBuffer("Dog.jpg"));
    jframe.setSize(233,377);
    jframe.show();
    }
    }
     
    Martijn Mulder, Jun 2, 2005
    #6
  7. Martijn Mulder

    John McGrath Guest

    On 6/2/2005 at 5:31:44 PM, Martijn Mulder wrote:

    > I tried to heed your advice, but... nope :-(


    Check the docs for MediaTracker.

    > static void main(String[]a)


    This should be declared *public*.

    > javax.swing.JFrame jframe=new javax.swing.JFrame("ImageBuffer");


    It would be nice to add this line:

    jframe.setDefaultCloseOperation( javax.swing.JFrame.EXIT_ON_CLOSE );

    --
    Regards,

    John McGrath
     
    John McGrath, Jun 2, 2005
    #7
  8. John McGrath wrote:
    > Actually, the "graphics2d" graphics context is associated with the
    > BufferedImage "displayimage", so this draws the image referred to by
    > "image" onto the BufferedImage "displayImage".


    Ah yes, I didn't see that in the mess of code.

    > 1) Nothing is done to ensure that the image has completely loaded before
    > it is drawn onto the BufferedImage. A MediaTracker can do this.


    That is a good idea yes. Sun is inconclusive if Toolkit.getImage() works
    asynchronously, and better save than sorry.

    /Thomas

    --
    The comp.lang.java.gui FAQ:
    ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq
     
    Thomas Weidenfeller, Jun 3, 2005
    #8
  9. Martijn Mulder

    John McGrath Guest

    On 6/3/2005 at 4:10:09 AM, Thomas Weidenfeller wrote:

    > Ah yes, I didn't see that in the mess of code.


    I had to read through it several times to be sure. This is an excellent
    example of the havoc that can be caused by poorly structured code. :eek:)

    > Sun is inconclusive if Toolkit.getImage() works asynchronously,
    > and better save than sorry.


    My experience has been that Toolkit.getImage() *always* loads the image in
    the background. In fact, it just creates the Image object and does not
    start loading the image data until some of the Image methods are called to
    retrieve the data.

    The JavaDocs for getImage() do not say much about this, but I did find the
    following in a JDC article:

    To load an image in an application, pass the filename or URL to the
    getImage() method, which returns a reference to an Image object that
    is loaded later.

    http://java.sun.com/developer/onlineTraining/new2java/supplements/2004/jan0
    4.html

    --
    Regards,

    John McGrath
     
    John McGrath, Jun 3, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Szymanski
    Replies:
    0
    Views:
    863
    Peter Szymanski
    Jul 9, 2003
  2. Eel

    Copying BufferedImage

    Eel, Jul 9, 2003, in forum: Java
    Replies:
    2
    Views:
    6,976
  3. hz010c1877

    Read PPM images as BufferedImage

    hz010c1877, Aug 14, 2003, in forum: Java
    Replies:
    1
    Views:
    6,912
    John C. Bollinger
    Aug 14, 2003
  4. Morten Nørgaard
    Replies:
    0
    Views:
    3,437
    Morten Nørgaard
    Aug 29, 2003
  5. Mike Westerfield

    Transparent BufferedImage

    Mike Westerfield, Nov 1, 2003, in forum: Java
    Replies:
    1
    Views:
    4,700
    Andrew Thompson
    Nov 1, 2003
Loading...

Share This Page