Several large images needed for animation causing memory error - android

I have created a frame animation comprised of 12 images in an XML file. Do I need to scale each image before adding to the animation, to avoid the Out of Memory error? If I make the images smaller, I do not get the out of error. How can I scale the images to build the animation or is that necessary? I also tried to set scaling in the imageview.

//Firstly add Scale Bitmap code and after that use animation.
photoBitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, true);
imageView.setImageBitmap(photoBitmap);
// Animation code

Related

Crop big images in android

I'm displaying big images in my app and want to crop them. The user can rotate and scale the images and select a region he wants to crop.
How can I crop out a 10000x10000 region, starting at point (1000, 1000) for example from a 20000x20000 image? For loading parts of an image I would use BitmapRegionDecoder but I don't know how to combine them to a new image again. Any ideas?
Rotation is another problem, this won't work with the BitmapRegionDecoder , but I would already be glad to have a solution without rotation...
I would need a memory friendly way that is more than just following:
Bitmap bitmap = loadFullBitmapIntoMemory();
Bitmap cropped = Bitmap.createBitmap(bitmap, 1000, 1000, 10000, 10000);
I want to avoid to load the full image into memory...

Large bitmap not being drawn

I'm in the works of a game and I'm loading a large image that is 5120 wide and 116 high. When I try to draw it to the screen using
canvas.drawBitmap(land, 0, 0, paint);
nothing gets drawn. However when I use a smaller file (512x116) with the same method call, it gets drawn. Is there a image size limit? My image is 750 KB. Also the max canvas width and height is 8192. Thanks in advance!
EDIT:
I noticed this in the log:
Bitmap too large to be uploaded into a texture (20480x464, max=8192x8192)
as if my bitmap is 4 times larger than its actual size. Why would that be?
EDIT 2: Found the issue. Bitmapfactory is returning a larger file because is multiplies the dimensions by my screen density. So the file ends up being too large.
I haven't used Canvas layout but try using largeHeap = "true" in your Manifest

Android loading of large bitmaps

I'm making an Android app and I need to load an image (bitmap) in a cavas and resize it using the "pinch zoom" gesture. When the image is over a certain size, however, the application crashes (OutOfMemory exception). How do I optimize the loading and manipulation of the image?
To load the image I use:
BitmapFactory.decodeResource (ctx.getResources (), R.drawable.image)
To draw it:
imgCanvas.drawBitmap (image, posX, posY, null),
To change its size:
Bitmap.createScaledBitmap (originalBitmap, neww, NEWH, true);
This is not trivial.
Based on the current scale of the image and the currently visible part of the image, only load a part of that image at the appropriate resolution:
https://developer.android.com/reference/android/graphics/BitmapRegionDecoder.html
When zoomed-out and you want to show the entire image scaled down, use the methods from this BitmapRegionDecoder class that take a BitmapFactory.Options parameter and set it inSampleSize to a value larger than 1 (preferably a value that is a power of 2):
https://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize
When zooming in, first zoom in the lower resolution that is already shown (where you used a value of inSampleSize > 1) and lazily load a higher resolution version (where inSampleSize is smaller than the previous value you used) using the BitmapRegionDecoder and fade in the higher resolution version gradually.
When the user zooms in, keep doing this until your inSampleSize is 1.

Speeding Up Bitmap Animation

I'm making a game, while a friend of mine is designing all the graphics. All graphics are PNG files, and drawn and animated using Bitmaps and Canvas in SurfaceView.
One piece of animation involves the main character moving around during the menu, which uses 35 large PNG files. It's too big to have it all loaded in memory, and loading each file when needed is too slow for what he wants. So, what can I do to make this work?
OPTIONS THAT DON'T WORK
Making the image smaller. Making the image smaller than what he wanted won't fly. Anything less than original quality won't fly either.
OPTIONS WE'RE LOOKING INTO
Making the animation a video. However, I don't know how to take a video and turn it into an interface.
My code:
Matrix matrix = new Matrix();
matrix.postScale(scaleFactorX, scaleFactorY);
penguin = BitmapFactory.decodeResource(getResources(), R.drawable.fish_01);
penguin = Bitmap.createBitmap(penguin, 0, 0, penguin.getWidth(), penguin.getHeight(), matrix, true);
canvas.drawBitmap(penguin, canvasWidth - penguin.getWidth(), canvasHeight*0.02f, null);

Is there a way to load and draw partially a bitmap from file in Android?

Say I have a somewhat large (i.e. not fit in most phones' memory) bitmap on disk. I want to draw only parts of it on the screen in a way that isn't scaled (i.e. inSampleSize == 1)
Is there a way to load/draw just the part I want given a Rect specifying the area without loading the entire bitmap content?
I'm quite confident this is possible since you can load a really large bitmap file into an ImageView without problems so there must be some sort of a built-in way to handle large bitmaps... and after a few attempts, I've found a solution:
Instead of loading the entire bitmap and manually draw it yourself, load it as a Drawable instead:
InputStream mapInput = getResources().openRawResource(
R.drawable.transit_map);
_map = Drawable.createFromStream(mapInput, "transit_map");
_map.setBounds(0, 0, _mapDimension.width(), _mapDimension.height());
I'm using a resource file but since you can use Drawable.createFromStream to load image from any InputStream, it should works with arbitrary bitmap.
Then, use the Drawable.draw method to draw it onto the desired canvas like so:
int left = -(int) contentOffset.x;
int top = -(int) contentOffset.y;
int right = (int) (zoom * _mapDimension.width() - contentOffset.x);
int bottom = (int) (zoom * _mapDimension.height() - contentOffset.y);
_map.setBounds(left, top, right, bottom);
_map.draw(canvas);
As in the above case, You can also scale and translate the bitmap as well by manipulating the drawable's bounds and only the relevant parts of the bitmap will be loaded and drawn onto the Canvas.
The result is a pinch-zoomable view from just one single 200KB bitmap file. I've also tested this with a 22MB PNG file and it still works without any OutOfMemoryError including when screen orientation changes.
Now it's very relevant: BitmapRegionDecoder.
Note: available since Android SDK 10
It can easily be done by using RapidDecoder.
import rapid.decoder.BitmapDecoder;
Rect bounds = new Rect(10, 20, 30, 40);
Bitmap bitmap = BitmapDecoder.from("your-file.png")
.region(bounds)
.decode();
imageView.setImageBitmap(bitmap);
It supports down to Android 2.2 (API Level 8).
Generally speaking, that isn't possible, particularly since most image formats are compressed, so you don't even know which bytes to read until you've extracted the uncompressed form.
Break your image up into small tiles and load just the tiles you need to cover the region you want to display at runtime. To avoid jittery scrolling, you might also want to preload tiles that are just out of sight (the ones that border the visible tiles) on a background thread.

Categories

Resources