Loading a BufferedImage

Im trying to load a image as a buffered image since I am going to rotate it around and other fun stuff like that.

The problem is I’m not loading it into the buffered image properly. When I try and draw it to my frame, all i get is a suitably sized black box. :stuck_out_tongue:

Anyway, if you’re willing to take a look at my loading code…


    private BufferedImage loadBI(String filename)
    {
        Image img=Toolkit.getDefaultToolkit().getImage(filename); //works
        int w = 512; // img.getWidth(this);
        int h = 384; // img.getHeight(this);
        BufferedImage newbi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);  //variable name gives too much away ;)
        newbi.createGraphics().drawImage(img,0,0,this);
        return newbi;
    }


      private BufferedImage loadBI(String filename) {
            Image img = Toolkit.getDefaultToolkit().getImage(filename); //works
            int w = 512; // img.getWidth(this);
            int h = 384; // img.getHeight(this);
            MediaTracker tracker = new MediaTracker(this);
            tracker.addImage(img,0);
            try { tracker.waitForID(0); } catch(Exception e) { }
            BufferedImage newbi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);  
            newbi.createGraphics().drawImage(img,0,0,this);
            return newbi;
      }

try this, i don’t know is this the right answer or not but i think you create the image from unfinished read image
so wait the image loaded first using mediatracker

Yep, that was it. Thanks a lot!

Okay… maybe not.

I modified my code the get the width and height from thr Just loaded image, but now it gives ma a runtime error that says width and height are -1.

Now, width and height are -1 if they are “not yet known”, or so the API spec says. Is my image loaded or not? I kind of need those values :stuck_out_tongue:

What does your code look like now?
Maybe the tracker.waitForID(0) throws an exception for whatever reason (you could output the exception in the catch block to be sure).

humm :o
i don’t get it
where do you put the get width and get height method?
you should put it after mediatracker, so the image fully loaded before asking its width
so the code must be like this


 private BufferedImage loadBI(String filename) { 
  Image img = Toolkit.getDefaultToolkit().getImage(filename); //works 
  MediaTracker tracker = new MediaTracker(this); 
  tracker.addImage(img,0); 
  try { tracker.waitForID(0); } catch(Exception e) { } 
  int w = img.getWidth(null); 
  int h = img.getHeight(null); 
  BufferedImage newbi = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB);   
  newbi.createGraphics().drawImage(img,0,0,this); 
  return newbi; 
 } 

There’s a much simpler way, if you’re not trying to load images over the network and are just loading them off of a local disk: use javax.imageio.ImageIO.read( File f )


private BufferedImage loadBI(String filename)
{
    BufferedImage img = null;
    try {
                     File f = new File( filename );
                     img = javax.imageio.ImageIO.read( f );
    } catch { IOException ioe) { /* ... */ }

   return img;
}

–Brad

try this code to load an image and make sure it’s accelerated:

// get the graphicsConfig when you create the frame

GraphicsEnvironment graphicsEnvironment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
graphicsDevice = graphicsEnvironment.getDefaultScreenDevice();
graphicsConfiguration = graphicsDevice.getDefaultConfiguration();

        frame = new Frame( "blah", graphicsConfiguration );

// then make some method like this one

public BufferedImage loadImage( String file ) {

// use the Toolkit and MediaTracker to load the image

        Toolkit tk = Toolkit.getDefaultToolkit();
        Image temp = tk.createImage( file );
        MediaTracker mt = new MediaTracker( frame );
        mt.addImage( temp, 0 );
        
        try {
              mt.waitForAll();
        } catch ( Exception e ) {
            System.out.println(e.toString());
        }
        
        BufferedImage image = graphicsConfiguration.createCompatibleImage( temp.getWidth( null ),
                    temp.getHeight( null ), Transparency.BITMASK );

        Graphics g = image.getGraphics();
        g.drawImage( temp, 0, 0, null );
        g.dispose();
        
        return image;
  }

are images loaded with javax.imageio accelerated?

[quote]are images loaded with javax.imageio accelerated?
[/quote]
don’t think so, no.

but, its not hard to create an accelerated image, and copy it over.

This is the code I use, I wrote it using some java tutorial…

public BufferedImage getBufferedImage(Image img) {
BufferedImage bImg = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_ARGB);
Graphics2D biContext = bImg.createGraphics();
biContext.drawImage(img, 0, 0, null);
return bImg;
}

Ok, I think I fixed it. Dumbass me wasn’t passing a proper component. (I told you that variable name was revealing :P)

Is there any way I can do a similar loading without actually having some component to wait on? Or do I at least have to pass through a dummy component to the media tracker?

Thanks for all your help.

the best solution… don’t use MediaTracker!

simply use toolkit.createImage (or getImage)

then, to begin the loading,
toolkit.checkImage (passing in an image observer)
followed by a synchronized wait,
which gets woken by the image observer when the image is loaded completely.

Alternatively, forget about all that crap, and just use ImageIO.
(followed by copying the unaccelerated image into a blank acceleratable image)

If you still want to use toolkit.createImage, perhaps this image loader i wrote a while ago will be helpful.
(be warned, it isn’t bulletproof - having said that, it includes a fix relating to Image.createScaledinstance())

It doesn’t have any facility for handling images that ABORT or ERROR during loading.


import java.awt.*;
import java.awt.image.*;
public class ImageLoader implements      ImageObserver
{
      //THIS CLASS IS NOT THREAD      SAFE
      final      Toolkit toolkit;
      final      GraphicsConfiguration gc;
      final      boolean debug;

      public ImageLoader(Toolkit      toolkit,      GraphicsConfiguration gc)
      {
            this(toolkit,gc,false);
      }

      public ImageLoader(Toolkit      toolkit,      GraphicsConfiguration gc, boolean debug)
      {
            this.toolkit =      toolkit;
            this.gc = gc;
            this.debug = debug;
      }

      public Image[]      loadImages(String[] s, int      transparency)
      {
            Image[] imagesToLoad      = new      Image[s.length];
            for(int i =      0;      i < imagesToLoad.length; i++)
            {
                  imagesToLoad[i] =      loadImage(s[i], transparency);
            }
            return imagesToLoad;
      }

      //      a duplicate      of      the image is made, because      some methods
      //      when called      using      an      Image      obtained      directly      from a file      (i.e.      the Images ImageProducer is a      file)
      //      are very      buggy      (i.e.      Image.getScaledInstance();)
      public Image loadImage(String      s,      int transparency)
      {
            if(debug) System.out.print("loadImage " +      s + "      ");

            //1st, fully load      the source image
            Image      sourceImage      = prepareImage(toolkit.createImage(getClass().getResource(s)));
            //then, create      a replica, that will      have its      ImageObserver as a memoryImage (rather      than a file)
            BufferedImage returnImage = gc.createCompatibleImage(sourceImage.getWidth(null),sourceImage.getHeight(null), transparency);

            //now, copy      the sourceImage into      the memoryImage
            Graphics2D g2d      = returnImage.createGraphics();
            g2d.setComposite(AlphaComposite.Src);
            g2d.drawImage(sourceImage,0,0,null);
            g2d.dispose();

            //and      return the memoryImage (the original image source is lost)
            return returnImage;
      }

      //prepares an [] of precreated Images
      //      blocks until all images      are loaded (or      ERRORed)
      //      each image is 'prepared' sequencially,      so      only 1
      //      image      loading thread      should be active at any      1 time
      //      im      not sure      if      this is better      or      worse      than loading all images      simultaneously
      //      though, looking at the way      MediaTracker does      it      - i think its better
      public Image[]      prepareImages(Image[] imagesToLoad)
      {
            for(int i =      0;      i < imagesToLoad.length; i++)
            {
                  prepareImage(imagesToLoad[i],-1,-1);
            }
            return imagesToLoad;
      }

      //prepares a single image (blocks until it is fully loaded
      public Image prepareImage(Image image)
      {
            return prepareImage(image,      -1,-1);
      }

      volatile      boolean loaded      = false;
      public synchronized Image prepareImage(Image      image, int width,      int height)
      {
            if(debug) System.out.print("prepareImage " +      width      + ","      + height      + " ");
            loaded =      false;
            //prepare image doesn't      always do the loading asynchronously!!
            if(!toolkit.prepareImage(image,width,height,this) && !loaded)
            {
                  //if(debug)      System.out.print("async      load");
                  try
                  {
                        this.wait();
                  }
                  catch(InterruptedException      e){}
            }
            if(!loaded)      System.out.println("ERROR:      Failed to load      image      " + image);
            return image;
      }

      public synchronized boolean imageUpdate(Image img,      int flags, int      x,      int y, int w, int      h)
      {
            if((flags &      ImageObserver.ALLBITS) == ImageObserver.ALLBITS)
            {
                  if(debug) System.out.println(generateDebugData("Complete",x,y,w,h,flags));
                  loaded =      true;
                  this.notifyAll();
                  return false;
            }
            if((flags &      ImageObserver.FRAMEBITS) == ImageObserver.FRAMEBITS)
            {
                  if(debug) System.out.println(generateDebugData("Framebits",x,y,w,h,flags));
                  loaded =      true;
                  this.notifyAll();
                  return false;
            }
            if((flags &      ImageObserver.ERROR)      ==      ImageObserver.ERROR)
            {
                  if(debug) System.out.println(generateDebugData("Error",x,y,w,h,flags));
                  this.notifyAll();
                  return false;
            }
            if((flags &      ImageObserver.ABORT)      ==      ImageObserver.ABORT)
            {
                  if(debug) System.out.println(generateDebugData("Abort",x,y,w,h,flags));
                  this.notifyAll();
                  return false;
            }
            if(debug) System.out.print(".");
            return true;
      }

      private String      generateDebugData(String flagString, int x, int      y,      int w, int h, int      flags)
      {
            StringBuffer sb =      new StringBuffer();
            sb.append(flagString).append(" x=").append(x)
                                                      .append(" y=").append(y)
                                                      .append(" width=").append(w)
                                                      .append(" height=").append(h)
                                                      .append(" flags=").append(flags);
            return sb.toString();
      }
}

and the ImageIO alternative (that avoids all the ImageObserver uglyness)…
(just knocked this together - it compiles but ive not run it :P)


import java.awt.*;
import java.awt.image.*;
public class ImageLoader
{
   final GraphicsConfiguration gc;
   public ImageLoader(GraphicsConfiguration gc)
   {
      this.gc = gc;
   }

   public BufferedImage loadImage(String resource, int transparencyType) throws java.io.IOException
   {
      BufferedImage src = javax.imageio.ImageIO.read(getClass().getResource(resource));
      BufferedImage dst = gc.createCompatibleImage(src.getWidth(),src.getHeight(),transparencyType);
      Graphics2D g2d = dst.createGraphics();
      g2d.setComposite(AlphaComposite.Src);
      g2d.drawImage(src,0,0,null);
      g2d.dispose();
      return dst;
   }
}