Quickly load part of image in java - java

I'm currently working in a map editor for a 2D, tile based game. When I create a new map, the tileset is loaded into memory and displayed in a JPanel that's inside a JScrollPane, so I can choose the tiles I wish to draw.
At first, I was just drawing the full image, but that made scrolling pretty slow, so now I only draw the visible portion of it and that works just fine. What I'm worried about is the memory usage, because the tileset is pretty big. I'm not getting any OutOfMemory erros, but I would like to optimise everything I can.
I tried using ImageReader together with ImageReadParam.setSourceRegion(); and that uses a lot less memory, but the scrolling becomes slower and the image blinks like crazy when scrolling - probably because it takes some time to read the image form disk.
So, is there a good way to quickly load parts of a big image without fully loading it? Or maybe there's a way to fully load it but in a compressed manner?

Related

Implementation of specfical region refresh with Java Swing

The number of models that my swing application needs to display is currently 2000 to 10000 images. After multiple zooming or using for a period of time, the memory continues to increase and will not decrease,How can I optimize it?
It is hard to recommend anything without knowing more about the environment, but I'll list some general tips:
You resize images every time you zoom in/out. This creates new images rapidly, especially if you zoom in using the mouse wheel or some other tool that fires events rapidly. Consider creating the image after the resizing has finished.
Don't hold references to unused images. This means you shouldn't store all the resized images, only the used ones.
Probably you don't need every image in every state of the
application - consider creating a loading screen which is shown while your application loads and resizes the used images, and discards the previous ones. (It does not have to be an actual loading screen or animation)
I've never seen a small or medium-scale project which needed 10k unrelated images. You might be storing animations per-frame, which is way less efficient than using video formats.
If you have many similar images, consider not loading them from file but instead paint them dynamically (you have a base image and paint over it using the component's Graphics).
Call the garbage collector. This should free up any unused space in the memory.

drawing complex generated image in java 2d

I have a very large complicated diagram that needs to be drawn on the fly.
I am already using a double buffered technique to paint the image (from this answer: Using threads to paint panel in java) however, the generated image that is being painted is so large that it cant be painted as a single image (and the multiple images required to paint it cant be stored in memory all at the same time). For this reason, I paint the currently visible area of the view + some margin. As I scroll, I paint the area that is going to come next, and remove from memory the area we just came from. However, if the user then decides to change direction, they need to wait for this area to be painted again. My question is this:
If a single "frame" of the screen being painted is approximately 1000*1000 pixels, in which approximately 5000 lines/circles are drawn (nodes/edges of a graph) is it likely to be more efficient to repaint this image each time, or is there a way to affectively cache the image to hard disk (to avoid java heap limitations).
Ive already optimised the paint method as much as I can think of, but there are still several seconds of delay if a user scrolls to quickly (i.e. moves out of the painted area before the next set of "frames" are painted). So my second question is this: Will moving to OpenGL offer a large improvement, and will it require major changes to the infrastructure of the code? (I tried doing this a couple of days ago, and found it was not as simple as I thought - often led to the computer crashing).
Several things come to mind:
Profile to verify your working hypotheses; self-time the animation budget on your target platform for comparison, as shown in this AnimationTest.
Compare your approach to the example cited here; it scales into the 1000's and accommodates dragging selections into the hundreds.
If your frames have a suitable geometry, consider adopting the flyweight pattern for rendering; JTable rendering is an example; the underlying mechanism using CellRendererPane is examined here.

Needed RAM to display images in java

Another conceptual question..
I am fighting against a java heap space exception.
My problem is, that i have to render/display small but a lot of images.
I exceed maximal ram. (edit vm options does not help) Yet i store all images in one List.
I think about if it may need less ram if i render the images one by one and store it temporary on local hard disk.
Will the images be still all in ram if displayed on screen?
Changes in the code would be significant so i want to ask this before..
If your use case is lots of images/icons in a JList/JTable inside a JScrollPane, I once wrote something similar for a CMS search result display:
I had thumbnails of larger images stored on server/cached on disk. You can exploit the fact that the JList/JTable (or Swing components in general) will only try to paint the components visible on screen, so you don't need to track this yourself. I used a JLabel with ImageIcon as renderer in the list, and a fixed size cache of icons in memory. Whenever the renderer hit an image not in cache, I used a lazy-loading technique with a placeholder icon returned immediately, while loading the icon in the background using a SwingWorker. When loaded, the SwingWorker issued a repaint to JList. The icon would now be in cache, and the list would paint nicely.
Some bonus tips: Make sure your icon cache is larger than the maximum number of items that can be displayed on screen. Also, use a limited (fixed size) thread pool for your SwingWorkers (possibly loading multiple icons at once), to avoid exessive reapint-loops that may cause flickering.

Bitmap size exceeds VM budget when game development

I am developing a game on android.Like tower defense.
I am using surface view.I am using some image as bitmap.(Spritesheets, tilesets, buttons, backgrounds,efects vs.)
Now images are nearly 5-6 mb.And i get this error when i run my game:
Bitmap size exceeds VM budget
19464192-byte external allocation too large for this process.
I call images like that
BitmapFactory.decodeResource(res, id)
and i put it to array.
I can't scale images.I am using all of them.
I tried that
options.inPurgeable=true;
and it work but the image is loading very slowly.I load a spritesheet with that and when it is loading, i get very very low fps.
What can I do?
I've had this problem too; there's really no solution other than to reduce the number/size of bitmaps that you have loaded at once. Some older Android devices only allocate 16MB to the heap for your whole application, and bitmaps are stored in memory uncompressed once you load them, so it's not hard to exceed 16MB with large backgrounds, etc. (An 854x480, 32-bit bitmap is about 1.6MB uncompressed.)
In my game I was able to get around it by only loading bitmaps that I was going to use in the current level (e.g. I have a single Bitmap object for the background that gets reloaded from resources each time it changes, rather than maintaining multiple Bitmaps in memory. I just maintain an int that tracks which resource I have loaded currently.)
Your sprite sheet is huge, so I think you're right that you'll need to reduce the size of your animations. Alternatively, loading from resources is decently fast, so you might be able to get away with doing something like only loading the animation strip for the character's current direction, and have him pause slightly when he turns while you replace it with the new animation strip. That might get complicated though.
Also, I highly recommend testing your app on the emulator with a VM heap set to 16mb, to make sure you've fixed the problem for all devices. (The emulator usually defaults to 24mb, so it's easy for that to go untested and generate some 1-star reviews after release.)
I am not a game dev however I would like to think I know Android enough.
Loading images of the size is almost certain to throw errors. Why are the images that file size?
There is an example at http://p-xr.com/android-tutorial-how-to-paint-animate-loop-and-remove-a-sprite/. If you notice he has an explosion sprite of only ~200Kb. Even a more detailed image would not take much more file space.
OK some suggestions:
Are you loading all your spritesheets onto a single sheet or is
each spritesheet in a seperate file? If they are all on one I would
split them up.
Lower the resolution of the images, an Android device is portable
and some only have a low resolution screen. For example the HTC
Wildfire has a resolution of 240x320 (LDPI device) and is quite a
common device. You have not stated the image dimensions so we can't be sure if this is practical.
Finally; I am not a game programmer but I found this tutorial (part of the same series) quite enlightening - http://p-xr.com/android-tutorial-2d-canvas-graphics/. I wonder if you are applying a pattern that is not appropriate for Android, however without code I cannot say.
Right something a little off topic but worth noting...
People under estimate the power of the View. While there is a certain amount of logic to using a SurfaceView, the standard View will do quite a lot on its own. A SurfaceView more often than not requires an underlying thread to run (that you will have to setup yourself) in order to make it work. A View however calls onDraw(), which can be utilized in a variety of ways including the postinvalidate() method (see What does postInvalidate() do?).
In any case it might be worth checking out this tutorial http://mindtherobot.com/blog/272/android-custom-ui-making-a-vintage-thermometer/. Personally, it was an excellent example of a custom View and what you can do with them. I rewrote a few sections and made a pocket watch app.

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

Categories