What is the best method for using image sprites in processing?

edited July 2014 in Programming Questions

Just wondering what is the best solution for drawing multiple images on screen in terms of memory usage and performance. I can think of three methods and it would be great to get some feedback on what is generally the best way to do it.

1) load a large image and then cut it into various PImages.
2) Load a large image and crop each time it is displayed within the draw method
3) Load in many images and use them as they are

Personally, I am interested in a case where there are about 100 png images being drawn at a high framerate but any feedback is appreciated. thanks

Comments

  • The best way to figure this out is to write a little test program that uses each of these approaches, then see which approach is best.

  • thanks @kev: I do plan to do that but I was hoping to get a little insight here first as it might be helpful when writing the tests

  • (2) is not very good because the draw() method is executed ~60 times a second and any CPU/memory intensive activity is likely to slow it down.

    For an application running in the desktop and the images on the hard drive, there is not likely to be much noticeable difference between (1) and (3)

    If on the other hand it is a web application I would go with (1) because it is much faster to download 1 large image file than a large number of small image files because each each file would be a separate HTTP request.

  • Performance-wise, each sprite element to its own PImage:
    http://processing.org/reference/PImage.html

    Of course, if a set of sprites are always equidistantly together, make a PGraphics to mesh them as 1 PImage:
    http://processing.org/reference/PGraphics.html

  • thanks for the feedback. Does it make any difference to the memory used by PImage if the loaded image is a gif or a png?

  • Only width x height matter! All images end up stored in pixels[]:
    http://processing.org/reference/PImage_pixels.html

  • quark focused on answering precisely the question, but then omitted to mention he made a Sprite library which can be of interest... :-)

  • Also, you don't need to cut one large spritesheet into different PImages. You can use texture coordinates. In fact, you can even use this technique to make animations. See this Texture2DAnimation example and perhaps also check out this DynamicTextures2D example.

  • FYI my Sprite library uses option 1, ie it accepts sprite sheets and chops them up into arrays of PImages. This simplified the library source code especially for sprite animation and pixel level collision detection.

    I should point out that although it works with all the renderers in it does not work in JavaScript mode.

  • edited July 2014

    cool, thanks. I'll take a look at the lib now.

    Just a few more questions on optimisation if you all don't mind.

    Does it make a difference what dimensions the source image or the PImage has? For example I know a lot of 3d software prefers images that are 128px*128px to be used for textures. Does this have any kind of impact on how Processing/Java handles images?

    Also, I know that setting an image to anything other than its original height in HTML can cause a little bit of lag. Does anything like this happen in Processing
    ie: would "image(imageName,10,10,100,100)" run slower than "image(imageName,10,10)"?

    Thanks

  • wouldn't loading a sprite sheet and then cutting it up mean you used twice the memory, once for the original and once for all the bits?

  • but i seem to recall a (really old) bug that meant that images, or something that was created when they were loaded, weren't garbage collected correctly. maybe this has been fixed.

  • edited July 2014

    I believe it would Koogs but only momentarily. Once you have cut the image into sprites you can then discard the original image and then (at some stage) garbage collection will do its job.

    Here is the best solution I have found so far. This was done with highly optimised gif images and seems to work well at the moment (as in it doesn't crash as often) although I haven't done any detailed memory inspection:

    This method loads ten images into sprite arrays.

    public void loadSprites(){
    
            sprites=null;
            int spw = 120;
            int sph=148;
            System.gc();
    
            PImage spriteBlock;
            sprites=new PImage[10][6][5];
            for(int i=1;i<10+1;i++){
            spriteBlock = loadImage("images/sprite"+i+".gif");
    
            for(int x=0;x<6;x++)
                for(int y=0;y<5;y++){
                    sprites[i-1][x][y] = spriteBlock.get(spw*(int)x,sph*(int)y,spw,sph);
    
        }
            spriteBlock=null;
                    System.gc();
        }
        }
    
  • edited July 2014

    I heard that System.gc() shouldn't be used and may not even work. lol

    I have tested it with some of my programs and it didn't seem like it had any effect.

    http://stackoverflow.com/questions/2414105/why-is-it-a-bad-practice-to-call-system-gc

    Also, there is now a library for using animated gifs. I think its called "AnimatedGif"

  • edited July 2014

    Indeed, System.gc() is just a hint for the GC. But the few times I've used it it worked successfully! @-)

    The GC scans and identifies which objects are both orphans (no variable holds a Strong reference to it)
    and got none of its methods running at that moment.
    Once those dead objects are identified, they go to a death line awaiting to be obliterated later!

    What I've found out is that System.gc() is very effective to do away w/ those already queued up! :D
    Like for example, when using WeakHashMap. Those Weak keys, along w/ its values, go away immediately! :))

Sign In or Register to comment.