Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (578)
games submitted by our members
Games in WIP (499)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Fastest Way to Load an Image?  (Read 6485 times)
0 Members and 1 Guest are viewing this topic.
Online kappa
« League of Dukes »

JGO Kernel


Medals: 70
Projects: 15


★★★★★


« Posted 2007-05-25 20:59:53 »

Well was experimenting to try find what would be the fastest way to load an image (in an applet for my purposes), as there are several ways to do this, firstly, i tried ImageIO using

1  
image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResource("filename"));


yup sorry about the ugly hack, its from java4k contest, but any how next i decided to try Toolkit using
1  
2  
3  
4  
5  
DataInputStream datainputstream = new DataInputStream(getClass().getResourceAsStream(filename));
            byte abyte0[] = new byte[datainputstream.available()];
            datainputstream.readFully(abyte0);
            datainputstream.close();
            return Toolkit.getDefaultToolkit().createImage(abyte0);


after running a benchmark, found that Toolkit was almost 400x faster, surely this can't be right, any idea's?
Offline tarmo

Innocent Bystander





« Reply #1 - Posted 2007-05-25 21:05:21 »

Thought I'd try it also.

OS: Windows Vista
JAVA: jdk1.6


Testcase: loading 128x128 32 bit png 1k times.
(toolkit testcase also uses mediatracker and converts Image to a BufferedImage to make it a bit more fair Wink)

Results:
Toolkit: 3631 ms
ImageIO: 6503 ms

And here's my code for the test:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
package star.client;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.DataInputStream;
import java.io.IOException;

/**
 * User: tarmo
 * Date: 25.05.2007
 * Time: 21:28:19
 */

public class ImageLoadingTest {

    private static final String IMAGE = "/fonts/LucidaConsole12.png";

    private ImageLoader loader;
    private String name;

    private interface ImageLoader {
        BufferedImage load(String name) throws IOException, InterruptedException;
    }

    public ImageLoadingTest(String name, ImageLoader loader) {
        this.loader = loader;
        this.name = name;
    }

    private void start() throws IOException, InterruptedException {

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000; i++) {
            foo(loader.load(IMAGE));
        }

        System.out.println(String.format(
                "%s: %s", name, System.currentTimeMillis() - start));
    }

    public void foo(Image image) {
    }

    public static void main(String[] args) throws IOException, InterruptedException {

        final MediaTracker tracker = new MediaTracker(new JPanel());

        ImageLoadingTest test1 = new ImageLoadingTest("ImageIO", new ImageLoader() {
            public BufferedImage load(String name) throws IOException {
                return ImageIO.read(Main.class.getResource(name));
            }
        });

        ImageLoadingTest test2 = new ImageLoadingTest("Toolkit", new ImageLoader() {
            public BufferedImage load(String name) throws IOException, InterruptedException {
                DataInputStream datainputstream = new DataInputStream(
                        Main.class.getResourceAsStream(name));

                byte bytes[] = new byte[datainputstream.available()];

                datainputstream.readFully(bytes);
                datainputstream.close();

                Image image = Toolkit.getDefaultToolkit().createImage(bytes);

                tracker.addImage(image, 1);
                tracker.waitForID(1);
                tracker.removeImage(image);

                BufferedImage buffered = new BufferedImage(
                        image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);

                buffered.getGraphics().drawImage(image, 0, 0, null);

                return buffered;
            }
        });

        if (args.length != 1) {
            System.out.println("Usage: ImageLoadingTest <imageio|toolkit>");
            System.exit(1);
        }


        if (args[0].equalsIgnoreCase("imageio")) {
            test1.start();
        } else if (args[0].equalsIgnoreCase("toolkit")) {
            test2.start();
        } else {
            System.out.println("Invalid test.");
        }


    }
}
Offline Eliwood

Junior Member




Stencyl


« Reply #2 - Posted 2007-05-26 02:54:22 »

Well was experimenting to try find what would be the fastest way to load an image (in an applet for my purposes), as there are several ways to do this, firstly, i tried ImageIO using

1  
image = ImageIO.read(Thread.currentThread().getContextClassLoader().getResource("filename"));


yup sorry about the ugly hack, its from java4k contest, but any how next i decided to try Toolkit using
1  
2  
3  
4  
5  
DataInputStream datainputstream = new DataInputStream(getClass().getResourceAsStream(filename));
            byte abyte0[] = new byte[datainputstream.available()];
            datainputstream.readFully(abyte0);
            datainputstream.close();
            return Toolkit.getDefaultToolkit().createImage(abyte0);


after running a benchmark, found that Toolkit was almost 400x faster, surely this can't be right, any idea's?

I hate to make a blanket statement, but the default ImageIO stuff is notoriously slow. It's only there because it's a lot more convenient and clean to use.

If you are just after loading PNG's, Matthias posted up some custom code for loading those really quickly. Ask him about it.

- Jon

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online kappa
« League of Dukes »

JGO Kernel


Medals: 70
Projects: 15


★★★★★


« Reply #3 - Posted 2007-05-26 03:30:38 »

thx, but want to really avoid extra code like a custom png loader as in this case its an applet, and start up time needs to be fast as well as small, so would be better if could rely on just existing jre classes. The thing here was just how much faster Toolkit was than ImageIO, surprising that the don't use the same loader.
Offline noblemaster

JGO Ninja


Medals: 19
Projects: 9


Age of Conquest makes your day!


« Reply #4 - Posted 2007-05-26 07:21:11 »

On another note: Toolkit also loads the image as managed image if possible (i.e. for .gif/.jpg format). The image is stored so it's compatible to the local graphics environment and thus will be drawn faster as well!

Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #5 - Posted 2007-05-26 08:13:43 »

The same is true for ImageIO. Also... doesn't Toolkit use ImageIO under the hood anyways?

弾幕 ☆ @mahonnaiseblog
Offline kevglass

JGO Kernel


Medals: 85
Projects: 25


Coder, Trainee Pixel Artist, Game Reviewer


« Reply #6 - Posted 2007-05-26 08:35:17 »

I said the same thing but it appears not looking at the figures.

Kev

Offline Abuse

JGO Coder


Medals: 10


falling into the abyss of reality


« Reply #7 - Posted 2007-05-26 12:32:47 »

The real frustration is that both loading mechanisms are bugged in different ways, so to ensure you can load all possible png files you have to try one, and then fall back on to the other in the case of a failure. ( I usually try ImageIO, and fall back onto Toolkit.createImage )

Who would have thought writing a png decoder would be so hard  Shocked

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline broumbroum

Junior Member





« Reply #8 - Posted 2007-05-26 14:44:04 »

If you are trying to load images faster and faster the best way I've found is to use the latest nio/JIIO FileChannelImageInputStream/OutputStreams. Include the JAI-core mlib and JIIO clib wrappers in your lib path, set ready your classpath with JAI and JIIO and you're on to use Java Advanced Imaging acceleration for any image format.
Quote
Thought I'd try it also.

OS: Windows Vista
JAVA: jdk1.6


Testcase: loading 128x128 32 bit png 1k times.
(toolkit testcase also uses mediatracker and converts Image to a BufferedImage to make it a bit more fair Wink)

Results:
Toolkit: 3631 ms
ImageIO: 6503 ms

These are really poor timings.  Shocked I get 20 FPS with FileChannelImageInputStreams for loading images. For the moment I don't know if it is worth to convert images before or after loading them, but it is obviously needed to load pictures before using them for painting as well as to decide whether to use BufferedImage or VolatileImage or even the JAI RenderableImage.
I do confirm that loading get really faster with NIO/JIIO Channels for base file loading.It is also true that GraphicsJAI are recommended instead of classical Graphics instances when you want to improve rendering speed and do not pay much attention to Quality.

Finally you can read the Java 2D AWT/SWING improvements sheet for the platform, there you can get more information about painting. Roll Eyes

::::... :..... :::::: ;;;:::™ b23:production 2006 GNU/GPL @ http://b23prodtm.webhop.info
on sf.net: /projects/sf3jswing
Java (1.6u10 plz) Web Start pool
dev' VODcast[/ur
Offline mabraham

Junior Member





« Reply #9 - Posted 2007-05-26 22:30:42 »

These are really poor timings.  I get 20 FPS with FileChannelImageInputStreams for loading images.

BB, you may want to reconsider this.  Surely, the figures stated by tarmo are overall timings.  This means the decoder works at ~6ms per frame, i.e. neglecting I/O this is well over 150fps.  I/O included (say we can do 20MB/sec), assuming the image is 32K large (2:1 compression), and no fancy overlapping I/O, adds another 1..2ms.  In other words, worst case should be around 10ms which is a good 100fps.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline broumbroum

Junior Member





« Reply #10 - Posted 2007-05-26 22:42:25 »

sorry I've made a mistake it was 1000 times the image !!! Wink By the way I've got to apologize for this "poor" statement, but it is also important to be able to cut-off threads asynchronously, so I decided to use the FileChannels for that. Is that correct?

::::... :..... :::::: ;;;:::™ b23:production 2006 GNU/GPL @ http://b23prodtm.webhop.info
on sf.net: /projects/sf3jswing
Java (1.6u10 plz) Web Start pool
dev' VODcast[/ur
Offline mabraham

Junior Member





« Reply #11 - Posted 2007-05-26 23:24:12 »

Certainly not a bad idea! Smiley  Although, personally I wouldn't worry about a 10ms lag in stopping a thread!  Might be a different story though if you're loading larger images...
Offline noblemaster

JGO Ninja


Medals: 19
Projects: 9


Age of Conquest makes your day!


« Reply #12 - Posted 2007-05-27 01:31:06 »

Quote
The same is true for ImageIO. Also... doesn't Toolkit use ImageIO under the hood anyways?

I thought so too, but you are wrong: http://weblogs.java.net/blog/chet/archive/2003/08/bufferedimage_a_1.html

Quote
Images that you get from other key means, such as ImageIO-created images or any image created explicitly through calling new BufferedImage() are not managed, and thus will not benefit from under-the-hood acceleration possibilities.

I tried and I can confirm the statement...

Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #13 - Posted 2007-05-27 02:41:03 »

2003/08...

Managed by default (with ImageIO) exists since 1.5 iirc. With 1.4 you have to copy it over manually.

弾幕 ☆ @mahonnaiseblog
Offline noblemaster

JGO Ninja


Medals: 19
Projects: 9


Age of Conquest makes your day!


« Reply #14 - Posted 2007-05-27 04:00:14 »

Quote
Managed by default (with ImageIO) exists since 1.5 iirc

not with my 1.5... you also got any references to confirm your claim?

Offline oNyx

JGO Coder


Medals: 1


pixels! :x


« Reply #15 - Posted 2007-05-27 04:22:30 »

>you also got any references to confirm your claim?

http://www.java-gaming.org/forums/index.php?topic=4583.msg42005#msg42005 (He's from the Java2D team)

弾幕 ☆ @mahonnaiseblog
Offline JAW

Junior Member





« Reply #16 - Posted 2007-06-05 16:03:53 »

Quote
Testcase: loading 128x128 32 bit png 1k times.
Results:
Toolkit: 3631 ms
ImageIO: 6503 ms

So this makes 3 ms vs 6 ms per Image. Even for 100 images the difference will be less than a half second. Does this really matter? If you load images only once here and there, I wouldnt care about some ms more or less. When you load images on the fly during a game where fps matter, I would use a stream and read only a limited amount of data every frame, and create the image when all data is loaded. I dont know if you can do this with ImageIO.

-JAW
Offline trembovetski

Senior Member




If only I knew what I'm talking about!


« Reply #17 - Posted 2007-06-06 17:52:33 »

Images returned by ImageIO should be managed in 1.5 except for
a few cases due to known bugs.

However, remember that if your images are translucent (as many pngs are)
they won't be accelerated by the default pipelines.

Also, only BufferedImages created with your own raster/data buffer will
not be managed, the rest will be (so images
create with "new BufferedImage(w, h, type)" will be managed).

Thanks,
  Dmitri
Offline broumbroum

Junior Member





« Reply #18 - Posted 2007-06-06 18:01:09 »

seen the 3ms 6ms average, is that a matter of raster or something else to improve Image Memory Storage? I mean to rasterize the image data in buffers px by px in addition to reference them softly is even faster, isn't it?
For the moment I only use softRef 'ed images in my cache/buffers but I don't manage to get the 3-6ms per image since they are quite bigger than usual icons-like pic's, say 150x150 is the pics size I have to load up. What you mean about?

::::... :..... :::::: ;;;:::™ b23:production 2006 GNU/GPL @ http://b23prodtm.webhop.info
on sf.net: /projects/sf3jswing
Java (1.6u10 plz) Web Start pool
dev' VODcast[/ur
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (30 views)
2014-04-15 18:08:23

BurntPizza (27 views)
2014-04-15 03:46:01

UprightPath (42 views)
2014-04-14 17:39:50

UprightPath (24 views)
2014-04-14 17:35:47

Porlus (41 views)
2014-04-14 15:48:38

tom_mai78101 (63 views)
2014-04-10 04:04:31

BurntPizza (123 views)
2014-04-08 23:06:04

tom_mai78101 (222 views)
2014-04-05 13:34:39

trollwarrior1 (189 views)
2014-04-04 12:06:45

CJLetsGame (198 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!