Lazily loading images in Java - java

Let us consider this code snippet
Image img=Toolkit.getDefaultToolkit().getImage("1.png");
g.drawImage(img,0,0,null);
What the code does is load the image 1.png and draw it on a graphic context. Now what I observe is drawImagedo not draw any image the first time it is called. Instead it draws the image on further calls. Now I think this behavior is due to asynchronous image load or the lazy behavior of the method.
To correct the problem what I could do is use the javax.swing.ImageIcon class like this.
Image img=new ImageIcon("1.png").getImage();
g.drawImage(img,0,0,null);
I want to know what are the other better ways to perform the same task.

It depends.
If you are loading the image over a "slow" connection (like the internet) or you are loading a sizable image, it's best to use a lazy loading approach.
This allows the application to continue running while the image is begin loaded.
Andrew is correct, you should be using g.drawImage(img,0,0,this), as this allows the component to automatically update itself once the image has completed loading, without you needing to perform any other actions.
If you application relies on the image for some part of it's operation OR you are loading small images locally, it would be sufficent to use something like...
BufferedImage image = ImageIO.read(imageResource);
// Where image resource is either a file or local URL (such as an embedded resource)
I personally, tend to use a background thread to load my images in most cases and use ImageIO. In my paint method, I might use a small placeholder image if required to let the user know that I am loading the image.
You will also need to take into consideration the type of image you are loading as well. While ImageIO has a larger support for image formats, loading animated GIFs is problematic and requires significant more work on you part to achieve.
ps - Don't load images in you component paint methods - paint can be called numerous times and loading images (or other resources) will dramatically slow the repaint process, making your application lag...

Try using ImageIO.read() for loading the images. This will block until the image is fully loaded. Check this page.

Related

Is there a way to proactively load photos with Universal Image Loader?

Is there a way to load the images that will come on the screen soon as opposed to loading the images that are currently in view?
If you're asking how to pre-load images so they are freshly cached, so that when the corresponding ImageView comes on screen the loading is nice and fast, you could use (somewhat untested):
String uri = getUriOfImageAboutToComeOnScreen(...);
ImageLoader.getInstance().loadImage(uri, null /* or use a listener */);
Of course, the magic contained in getUriOfImageAboutToComeOnScreen() is up to you :)

What is the difference between the ways to read an Image file in Java?

There are various ways of reading an image file in java such as BufferedImage and ImageIcon to name a few. I want to know what is the difference between these cases? Are they context dependent that in a particular case only one of them can be used?
What would be the best way of reading a image selected by JFileChooser by the user and separating the color channels of an image?
A good way is to use the different ImageIO.read methods, which return BufferedImage objects.
Image is an abstract class, so I think the real question is which subclass is more efficient for your program. Use VolatileImage if you need hardware acceleration. More on that here.
ImageIcon (and Toolkit#createImage/Toolkit#getImage) use a background loading process. That is, after you call these methods, they will return immediately, having created a background thread to actually load the image data.
These were/are used when loading large images across slow connections, like ye old 28k modems (ah, how I remember the days). This means that your application can continue running while the images are been downloaded.
You'll find in the Graphics class the drawImage methods accept an ImageObserver interface and that java.awt.Component implements this interface, this allows components the ability to automatically update themselves once the image has actually finished loading.
ImageIO on the other hand will not return until the image is fully loaded. It also makes it easier to introduce new readers/writers, making the API far more flexible then the original API. ImageIO also supports a wider range of images out of the box.
BufferedImage is also a far more flexible image class, especially when it comes to apply effects to the image.
Now, I, personally, prefer ImageIO. If I know I'm loading large images or images over a potentially slow connection, I will create my own background thread to load them. While a little more complicated, the trade offs greatly out weight the small amount of extra work -IMHO
What would be the best way of reading a image selected by JFileChooser by the user and separating the color channels of an image?
ImageIO without a doubt. In order to do any serious manipulation of an image loaded using something ImageIcon, you'd have to convert that image to a BufferedImage anyway

Toolkit.getDefaultToolkit().createImage() vs ImageIO.read()

I'm creating a UI using Swing and I want to display an image in a JLabel. The code I use is the following:
JLabel label = new JLabel(new ImageIcon(ImageIO.read(new File("img.jpg"))));
This works fine if I use png images but when it comes to jpg (only some of them), I get a redish image (a different one than the one I see in Paint.NET).
The image I used is this one: img.jpg
So I tried (as an alternative):
Toolkit.getDefaultToolkit().createImage(new File("img.jpg").getAbsolutePath());
Does anyone have an idea of why this happening? Is it a special JPEG format which is not supported?
I've read on this forum that most people recommend to use ImageIO (here for example). Why?
Thanks a lot
As discussed here, your JPEG image may contain spurious transparency information. One simple expedient is to render the image in a buffer having a compatible color model, as shown here.
It looks like you have found a bug in ImageIO.read... (I can reproduce the red tint, and it is definitely not how it should look like).
You can try to
save the JPEG files with other settings
open/re-save the file with other programs (hoping to get a more common JPEG-encoding)
or use the Toolkit method (if you don't control the images).
The only problem with the Toolkit method is that the getImage() method returns immediately after it is invoked and the loading is happening on a background thread, so you cannot start working with the Image object immediately.

Fastest way to load and display a jpeg on a SurfaceView?

This is a bit of a followup to my last question: Canvas is drawing too slowly
Now that I can draw images more quickly, the problem I am faced with is that the actual loading of the images takes far too long.
In the app I am working on, the user is able to play back video frames (jpegs) in succession, as though he is viewing the video in realtime. I have been using BitmapFactory.decodeFile() to load each jpeg in a Bitmap. I'm unable to load all images at once since there are about 240 of them, and that would use up all of my heap space. What I have been doing is preloading up to 6 at a time into an array by way of a separate thread in order to cut down on the time it takes for each image to display.
Unfortunately, it takes somewhere between 50 and 90ms to load an image, and I need to show an image every 42ms. Is there a faster way to load images possibly?
For clarification, these images are in a folder on the SD card, and they are all 720x480 jpegs. I am sampling them at half that size to cut down on memory usage.
I ended up doing this quite a bit differently than I had originally envisioned. There was quite a bit to it, but here's the gist of how I achieved my goal:
All images are stored on SD card and written to one file (each image takes up X bytes in the file)
Use native code to read from and write to the image file
When requesting an image, I pass the index of the image in the list and a bitmap object (RGB_565) to the native code using a JNI wrapper
The native code locks the bitmap surface, writes pixel data (as a uint8_t**) directly to the bitmap, then unlocks it
The image is rendered to the screen
By doing it this way, I only needed to store one image in memory at a time, and I was able to bypass garbage collection (since the bitmap was only created once and then repopulated natively). I hope someone else might find this strategy useful.
Guess you already tried all methods in this tutorial http://www.higherpass.com/Android/Tutorials/Working-With-Images-In-Android/2/ and chosen the fastest. Maybe tweaking resizing can decrease loading time.
Best of all would of course be if you didn't have to resize the images at all. If you have full control of the images maybe you could try to pack them as sprites, see article http://www.droidnova.com/2d-sprite-animation-in-android,471.html

Java2d thumbnails. Can I get thumbnail from OS

I develop an application in which I want to display a grid with a list of images. For each image I create an instance of a class myImage. MyImage class, extends JCompoment and create an thumbnail and after draw it with overide thepaintCompoment(Graphics g).
All is ok, but in big size images I have a lot of delay to create the thumbnail.
Now I think to when I scan the folders for image(to create the list I said above to create an thumbanail of each image and save it to disc. For each image I will have a database record to save the image path and thumbnail path.So is this a good solution of the problem?
Is there a way to get the thumbnails of the system creates for each image, in file manager. Or a more effective solution than I try.
Thank you!!
Your best bet is to use something like imagemagick to convert the image and create the thumbnail. There's a project called JMagick which provides JNI hooks into Imagemagick, but running a process work too.
Imagemagick is heavily optimized C code for manipulating images. It will also be able to handle images that Java won't and with much less memory usage.
I work for a website where we let users upload art and create thumbnails on the fly, and it absolutely needs to be fast, so that's what we use.
The following is Groovy code, but it can modified to Java code pretty easily:
public boolean createThumbnail(InputStream input, OutputStream output){
def cmd = "convert -colorspace RGB -auto-orient -thumbnail 125x125 -[0] jpg:-"
Process p = cmd.execute()
p.consumeProcessErrorStream(System.out)
p.consumeProcessOutputStream(output)
p.out << input
p.out.close()
p.waitForOrKill(8000)
return p.exitValue()==0
}
This creates a thumbnail using pipes without actually writing any data to disk. The outputStream can be to a file if you wanted to immediately write it as well.
One way to avoid OS dependance is to use getScaledInstance(), as shown in this example. See the cited articles for certain limitations. If it's taking too long, use a SwingWorker to do the load and scale in the background.
I haven't used it for the creation of thumbnails, but you may also want to take a look at the ImageIO API.
ImageIO

Categories