Problems using ImageIO

very sorry for the dummy post before !!
you should never have bottles in the radius of your keyboard …

my first try to substitue the old 1.1 method for image-work is not too succesfull.
im very ashamed to have such problems so early :-[

following code written in an applet:


                URL u = getClass().getResource("avatar.jpg");

            BufferedImage img=null;
            
                 try
            {
                  img = ImageIO.read(u);
            }
            catch(IOException e)
            {
                  System.out.println("error");
            }

            g.drawImage(img, 0, 0, this);
}


with that code i get a securityException, java is unable to create a temporary file … (?)

but before i have more problems after getting this one solved i need further tips:
i want to replace the old code which was written to cut a big image into pieces (only for referencing the new pieces, not for writing on disk)
i used a conglomerate of ImageProducer, FilteredImageSource and CropImageFilter.

what is the best way of doing it in javax.imagIO ?

Sometimes ImageIO makes temp files (so it can be sure it is able to rewind the input stream or do other performance enhancements, I think).

You can turn that feature off. Call ImageIO.setUseCache(false)

ok, problem is gone.

but another question:
i just noticed the BufferedImage.getSubImage() methode (perfekt for cutting my images into pieces).
normally i cut the parts and store them as “stand-alone” images in a collection object as tiles.
but the method offers to do the cut-operation just in time so that a animation object hold only the big image and returns a tile on demand. the only reason i see for not using this technique could be that getSubImage is much too slow (?!)

getSubImage is handy, but performance-wise it sucks badly. The returned image isn’t a new, stand alone image but shares the same data as the original. So what you think is a nice cache-friendly 32x32 image is actually a section of a monster 256x256 image (for example).

For best speed I found:

  • load single big image (much faster disk reading).
  • Chop up into lots of sub images (via getSubImage)
  • Copy sub images into their own new images (faster drawing, better image caching).

Chop up and copy can be done at the same time… you can specify a clipping region with drawImage :slight_smile:


chars = new BufferedImage[52];
for(int i=0;i<52;i++)
{
      chars[i] = gc.createCompatibleImage(6,5,Transparency.BITMASK);
      tg = (Graphics2D)chars[i].getGraphics();
      tg.setComposite(AlphaComposite.Src);
      tg.drawImage(cmImg,
            0,0,
            6,5,
            i*6,0,
            i*6+6,5,
            null);
      tg.dispose();
}

After that I have all of these chars in a seperate BufferedImage :slight_smile:

(these cute chars are hand pixelated)

@Orangy Tang

if i get you right, it is ok to do it this way :


BufferedImage img = ImageIO.read(getClass().getResource("animation.png"));
BufferedImage allTiles[] = new BufferedImage[50];
allTiles[i] = img.getSubimage(i*cellWidth, 0, cellWidth, cellHeight);
(...)
img = null

No, you’re making the same mistake. While that apparenly gives you lots of small images they’re actually just referencing the original big image (and nulling the reference to the original doesn’t make any difference). What you need to do after that is create your ‘proper’ animation images as new buffered images, then copy each image in your tiles array into its own new image.

ugh, it was ment to be so. but what you write isnt everytime what youre thinking about …

but now i get the clue, thx

If you don’t have the option to create tiles on beforehand and wan’t to draw a small part of a large image.

I have tried two variants

  1. getSubImage() … which then is drawn
  2. setClip() in combination with AffineTransform and the draw the whole image.

Which is preferred?

Thanks!

/ Peter

It depends on how often the section of the image your want to draw is going to change.

If its the same section every time (i.e. a tile) then producing a seperate image in some way (subImage() is one option) is preferred.

If you’re constantly changing the section of the image your want to draw you might find sectioning the drawing more efficent (i.e. setClip() method).

Kev

Thanks for your quick reply …

The large image is really a part of my world that is painted whenever the world has changed or the view area has moved. The world consists of quad tree of image objects.
I use a scrollbuffer to keep the current viewarea and its surroundings. The scroll buffer is only updated when view area has exceeded the scrollbuffer area.

The process is as follows:

  1. Paint needed part of the world to large image
  2. Paint part of world (in 4 parts) to scroll buffer
  3. Paint shown area of the scroll buffer to canvas

Possibly I shouldn’t use the temporary file at all and instead get the four parts from the world directly. The downside is the quadtree must be searched 4 times instead on one.

Just reading this and its got me wondering,

im just sorting out a scroll bg that uses tiles (32x32) and with seeing this about cutting the tiles into thier own buffers, does that mean that by creating individual buffers for each tile, they blit faster than how I currently do it via:

calculate the tile position in the tile image, then in my g.drawImage i set the destinations x,y width height and also the source width height etc etc.

and that then gets blitted onto the backbuffer screen.

heres the code :
(tilex & tiley are the offsets into the image containing the tiles)
(twidth & theight are the tile sizes (32x32 in this instance)


      int tilex = map[world_X_offset+tx][ty+world_Y_offset]%20;
      int tiley = map[world_X_offset+tx][ty+world_Y_offset]/20;

        int dx = tx*twidth-(int)scroll_X_offset;
        int dy = ty*theight-(int)scroll_Y_offset;
        int dw = tx*twidth+32-(int)scroll_X_offset;
        int dh = ty*theight+32-(int)scroll_Y_offset;
        int sx =tilex*32;
        int sy = tiley*32;
        int sw = sx+32;
        int sh = sy+32;
        g.drawImage(title,dx,dy,dw,dh,sx,sy,sw,sh,null);


it is a long winded way to do it, so was wondering how to streamline it, and it looks like the cut tiles into individual buffers sounds like a good plan. just thought id ask about the difference and what ppl thought.

TIA

I suppose that it would be preferred to divide the tiles in separate buffered images if it is possible. The drawImage() function you use supports scaling of the image and depending on how effective this implementation is the performance may be different. Question is if implementation checks if scaling is performed or not and in this case exclude any transform operation.

Ordinary drawImage(img, x,y, obs) cannot be implemented in too many different ways. Later on I will try all methods and do some profiling but I’m not there yet.

An overview of different graphics drawing operations and its performance would be great but I haven’t found any.

I believe Mark_J’s method is the fastest of all. It’s also good in consideration that it would also be best for use in OpenGL. I’m pretty sure the Graphics2D implementations check for scaling first and if there is none, simply draw the appropriate region.