When dealing with different screen sizes I use like 3 packs of assets for SD, MD and HD phones / tablets.
But doing this is kinda annoying, and makes the APK bigger.
I want to use just the biggest pack that I want to use, like HD.
But if someone got a 3.2" phone I don't want to render a 1280x768 background on 320x480 phone..
So i'm just wondering..is possible with libGDX to resize a Texture ?
I don't mean resizing like, drawing with a specific size..I mean, in Texture Packer GUI I can add the biggest assets pack and choose to export also HD or MD pack..
Is possible to resize a Texture in runtime?
So if I play my game on a small phone, the textures will be smaller in size.
I hope you guys understand what I'm trying to say.
Using extra storage space on the low-end phones is probably the best bet. The alternatives are less attractive:
Scale the images down when you load them. This will lengthen load times on an already under-powered phone. The scaling will have to be done on the CPU, as the GPU may not support textures that are a multiple of screen size. Plus you'll need to load these large images into memory, which will tax a small phone even more. (You could do this once and cache the results, so you don't penalize every startup but then you might as well just put the files in the .APK) (You could chop the HD image into parts to avoid overwhelming a low-end phone, but that just increases the startup latency even more.) If you still want to try it, with LibGDX you could use a FrameBuffer to create a low-resolution image at run-time from a higher-resolution one.
Scale the images down when you render them. This is unlikely to work reliably, and requires a significant memory footprint to keep the images loaded.
To get a real handle on what you are optimizing here, try building your APK with all the resolutions and then again with just the HD images. I bet the difference isn't that big (the low-end images are, by definition, not that big relatively.)
Related
what is the best practice to set image size for banners and products in E-Commerce/Shopping android application? and what are the ideal image sizes for the product and banners so that it can be responsive for all screen sizes?
Actually there are different ways you can handle this:
Use a high-resolution image file put it into drawable-nodpi and resize that based on your screen density. (I recommend using Glide, but Bitmap and BitmapFactory consist of methods handling resizing and loading bitmaps)
Pro: A single image file can be easily scaled
Con: It can lead to OutOfMemory if not handled correctly.
Put your images into different density buckets MORE INFO. The image files should be based on common pixel densities that phones are manufactured base on e.g. Full-HD (1080x1920) or HD resolution.
Pro: It's less work for OS and even your own coding
Con: It's more work to design image files
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.
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
I'm making an Android live wallpaper using OpenGL.
I would like to let the user pick an image to use for the background. Can someone give me any advice on an easy way to do this?
I know that I need to down sample bitmaps before loading them to avoid using huge amounts of memory for large bitmaps.
I also know OpenGL only supports texture sizes that are powers of two. It looks like messy work having to calculate the down scale factor then calculate the closest good texture size and then scale a quad with that texture appropriately to the screen.
It would also be nice to have the wallpaper panning feature when homescreens change.
Is there any easier way than doing all of the above myself? If not, is there sample code available for what appears to be a very common task?
I'm having a strange problem, basically in Java Graphics.drawImage() is extremely slow on some computers and faster on others. This isn't related to the computers power either, some weaker computers run it fine while some stronger ones seem to choke up at the drawImage call.
It may or may not be related to the width and height, I have a very, very large width and height defined (something like 5000 by 2500). I wouldn't think it's the issue except like I said it runs in real time speed on some computers and slower on others and doesn't seem to be tied to the computers relative power.
Both computers have the same version of Java, both use Vista. One has a 1.83ghz Core 2 Duo with 1gb RAM and onboard graphics (runs everything fine), the other has a 2.53 ghz core 2 duo with a 9600GS (latest nVidia drivers) and 4gb of RAM and it literally chugs on the drawImage call.
Any ideas?
edit: ok this is really wierd, I'm drawing the image to a window in Swing, now when I resize the window and make it really small the image gets scaled down too and it becomes small. Suddenly everything runs smoothly, when I scale it back up to the size it was before it's still running smoothly!
It also has multiple monitor issues, if I do the resize trick to make it run faster on one monitor then scroll it over to another monitor when more than half of the window is in the new monitor it starts chugging again. I have to resize the window again to small then back to its original size to get back the speed.
If I do the resize trick on one monitor, move it over to the other it of course chugs, but if I return it back to the original monitor on which I did the resize trick it works 100%
If I have two swing windows open (displaying the same image) they both run slow, but if I do the resize trick on one window they both start running smoothly (however this isn't always the case).
*when I say resize the window I mean make it as small as possible to the point the image can't actually be seen.
Could this be a bug in Java maybe?
Performance of writing an image to a screen is very much affected by the format in which the image is stored. If the format is the same as the screen memory wants then it can be very fast; if it is not then a conversion must be done, sometimes pixel by pixel, which is very slow.
If you have any control over how the image is stored, you should store it in a format that the screen is looking for. Here is some sample code:
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration config = device.getDefaultConfiguration();
BufferedImage buffy = config.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics g = buffy.getGraphics();
If you are going to draw the image many times it may be worth converting to a compatible format even if it came in some other format.
Drawing an image will also be slower if you are transforming it as you draw, which the 'resizing' part of your description makes me think you might be. Again, do the resize once (when the window is resized) and cache the resized and compatible image so that it can be redrawn quickly.
If you are using sun's Java try some of the following system properties, either as command line parameters or the first lines in main
sun.java2d.opengl=true //force ogl
sun.java2d.ddscale=true //only when using direct3d
sun.java2d.translaccel=true //only when using direct3d
more flags can be viewed at this page
Look at sun.java2d.trace which can allow you to determine the source of less-than-desirable graphics performance.
There are several things that could influence performance here:
Available RAM
CPU speed
Graphic card (onboard or seperate)
Graphic driver
Java version
Used video mode (resolution, bitdepth, acceleration support)
EDIT:
Having a look at the edited question, I'd propose to check if the 9600GS system has the newest NVIDIA drivers installed. I recently installed a driver for an Intel onboard graphics card that replaced the generic Windows driver and made moving windows, watching videos, browsing etc. a lot faster.
All the other specs look good. Perhaps Java doesn't detect the 9600GS and doesn't use hardware acceleration, but I doubt this.
Also check the OS configuration. On Windows, you can turn off hardware acceleration for debugging purposes.
Of course the best way to handle this would be to change your code - resize the image or split it up into chunks as DNS proposed. You'll never be able to see the whole image as it is on the screen.
How are you judging the computers' power? A 50x25 K 32-bit image takes more than 4.5 GB RAM to hold in memory (50000 * 25000 * 4 bytes). If one computer has more RAM than another, that can make a huge difference in speed, because it won't have to swap to disk as often. You should consider grabbing subsections of the image and working with those, instead of the whole thing.
Edit: Are you using the latest Java & graphics drivers? If your image is only 5Kx2.5K, the only thing I can think of is that it's doing it without any hardware acceleration.
Check the screen settings. My bet is that pixel depth is different on the two systems, and that the slow one has an odd pixel depth related to the image object you are trying to display.
Since Java uses OpenGL to do 2D drawing, the performance of your app will be affected by the OpenGL performance of the graphics chip in the respective computer. Support for OpenGL is dwindling in the 3D industry, which means that (ironically) newer chips may be slower at OpenGL rendering than older ones - not only due to hardware but also drivers.
Have you tried Full-Screen Exclusive Mode?
This might help:
http://download.oracle.com/javase/tutorial/extra/fullscreen/index.html