Using BitmapRegionDecoder to load large images - android

I am trying to load a very large image from the internet in an android tablet application. I know how to load a smaller size sample but have noticed it hampers the resolution of the images. The android docs tell me about the BitmapRegionDecoder to help loading the images in tiles but there does not seem to be much documentation on it.
I am doing something like this:-
BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(inputstream, false);
I understand that i have to loop through the below code as many times as required to get the entire image by passing different rect objects
region = decoder.decodeRegion(new Rect(0, 0, 50, 50), null);
But i fail to understand how to put all these bits in the right position in one imageview. Any example would be really helpful

What you are trying to do sounds like you want to defy the purpose of the region decoder. You could as well try to load the whole huge bitmap instead of pieces and joining them together. In the end you would risk an out of memory error either way. The point of the region decoder is getting just a clip from a huge bitmap. One use case could be a map view that can be panned with swipe gestures. You would calculate only the currently visible clip of the bitmap load that with the region decoder and display that in your map view. What you need to do is in fact loading a scaled version.

Yes you can use a BitmapRegionDecoder to view large Images based on Tiles
This guy here implemented a TileBitmapDrawable Class, that you can hook to your imageview:
https://github.com/diegocarloslima/ByakuGallery

Related

Image scrolling app - bitmap too large to be uploaded into a texture

I am working on a very simple app that shows one jpg, which is scrollable on vertical axis.
I would like this image to be very large(20000x1000 px), however, when I try to run the app on my device, it says that "bitmap too large to be uploaded into a texture".
Is there a way to display the image of such size in an android app?
If not, would it be possible to divide the image into segments, and after I scrolled to the bottom
of one segment, I would proceed to another?
To quote the answer for your question here:
All rendering is based on OpenGL, so no you can't go over this limit.
Note that this would take a huge amount of memory. With such big
images, if you want to zoom in out, and in a mobile environement with
heavy memory constraints, you should setup a system similar to what
you see in google maps for example. With the image split in several
pieces, and several definitions.
You could split the images into let's say 128x128 chunks. Add them to an array, and loop the array to create and fill an ImageView with the image that is currently served.
some pseudocode would be: (excuse me, I've been programming a PHP application the past few days)
Private BitMap[] imageArray = {your bitmaps from internal or external storage};
For(BitMap bm in imageArray) {
// create a new image view here, use the correct layout params or use a parrent grid view.
imageView.setBitMap(bm)
}
now once again, I am 0% sure about that pseudo code, but it should help you along.

how to speed up display for continous images in android

Currently, I am trying an application for receive and display views from another mobile. When views received, I will convert it as a bitmap, and use ImageView to display them like
imageView.setImagebitmap(xxx). However, I found the API performance is not good.
As I need display the continous images (not a video), is there any method to speed up the display?
Thank you
You should consider using SurfaceView instead of ImageView. Every time you call ImageView.setImageBitmap new BitmapDrawable instance is created and view itself is invalidated so this is quite heavy way for switching images rapidly.
Also if you need to scale bitmap before drawing you can dramatically increase framerate by disabling bitmap filtering.

Saving shapes on top of large images

I'm creating somekind of 2D image editor in Android and I have the big problem of big files don't fit in memory.
I need to zoom in/out the image put some shapes and then save it.
My question is:
How can I load the image and save it without getting out of memory?
I've been reading about bitmapregiondecode and the sample technic but there's must be another solution. How can I save the image if I always use regiondecode?
The images need good detail quality because it's architectural images... and the lines must be well defined.
I'm new to this, help me please.
Note two things while dealing with images:
tempBitmap = Bitmap.createBitmap(bit);
clone the bitmap which you are using for zoom and other operations but wont use the original because it looses its clarity when you save;
when done with bitmap give
bit.recycle();
to release the memory space

Merging multiple picture to form one complete picture in Android

i would like to know whether is it possible to merge several images to form one complete image. For my case, is a floor plan that is split in 18 small images and i would like to merge them into one. I had one idea but not sure whether is it workable. My idea is this:
I would first place the top left most image first, with the x and y coordinates as (0,0).
Next for the subsequent images (right/bottom of this first image), using the width and height of the image, i would find out the coordinates where the next image would be placed. Doing this i presume would required 18 ImageView to achieve that.
Btw, these 18 images are .gif format and so do i need to like convert them to Bitmap or something before i can display them using ImageView?
You could merge the images to a bigger images by drawing the small images to a canvas associated with the resulting big bitmap
Canvas c=new Canvas(result_bitmapenter);
and then draw your small images onto the canvas
c.drawBitmap(small,...);
But that might not be the best way as big images eat lots of memory - perhaps you should concider dynamic loading instead of merging then
Yes its possible create a Bitmap object large enough to hold the whole floor plan and use Canvas to paint them into to the large bitmap. Be sure to cache it or you'll be recreating it every time and you'll have to convert it to png for compatibility with older devices.

OutOfMemory error while joining large images

I am joining two images using the code below but it throws an OutOfMemory error my images are around 1MB each.
private Bitmap overlayMark(String first, String second)
{
Bitmap bmp1, bmp2;
bmp1 = BitmapFactory.decodeFile(first);
bmp2 = BitmapFactory.decodeFile(second);
if (bmp1 == null || bmp2 == null)
return bmp1;
int height = bmp1.getHeight();
if (height < bmp2.getHeight())
height = bmp2.getHeight();
Bitmap bmOverlay = Bitmap.createBitmap(bmp1.getWidth() + bmp2.getWidth(), height,
Bitmap.Config.ARGB_8888);// Out of memory
Canvas canvas = new Canvas(bmOverlay);
canvas.drawBitmap(bmp1, 0, 0, null);
canvas.drawBitmap(bmp2, bmp1.getWidth(), 0, null);
bmp1.recycle();
bmp2.recycle();
return bmOverlay;
}
Update: I tried below two answers but it still not allwoing me to create bitmap of such big size the problem is that the resultant bitmap is too large in size around 2400x3200 so its going out of memory.
How can I join large images without running out of memory?
Without loading the image into memory, you CAN get the size of the image, using inJustDecodeBounds. The Bitmap returns null, but all the parameters are set. You can scale down the image accordingly.
If your JPEG images are 1 MiB each, conversion to a BMP will take a lot of memory indeed. You can easily calculate its BMP equivalent by the dimensions of the image. Conversion of such a large image is expected to crash indeed. Android limits its apps to 16 MiB VM only.
Also use RGB_565 instead of ARGB_8888.
So your only solution is:
(a) To use BitmapFactory.Options.inSampleSize to scale down the image
or
(b) Use Android NDK where the 16 MiB limit isn't there.
I use this simple rule of the thumb:
the heavy lifting (both memory/CPU) is done on the server.
So write some servlet that takes the image, resizes it to a specified dimension (probably reduces the pixel depth too) and returns the result.
Piece of cake and it works on any mobile device you need.
Good luck!
I think a solution sort of like Sumon suggests might work.
Figure out the size of the final
image based on what will fit on the
screen.
Get the size of the first image using
the inJustDecodeBounds technique.
Figure out the size of the first
image in the final image. Calculate
re-sizing parameters.
Resize image, loading into memory.
Write resized image back to disk.
Recycle the bitmap. (This will help
when resizing the 2nd image)
Repeat for the second image, only you
can skip the writing to disk part.
Load first image.
If you only need to display, then just do that. If not then you can combine into a single bitmap at this point and write to disk. If this is the case, it may be difficult because you wil have essentially 2x the screen size in memory. In that case I would recommend resizing smaller. If you can't go smaller, then you will have to go the NDK route, thought I'm not sure how much that will help. Here's an amusing intro to the NDK and JNI. Finally, I would highly recommend developing this using a phone running Android 2.3+ since its use of heap-allocated bitmaps will make debugging much easier. More about those here.
It's not necessary that the space taken by in-memory representation of bitmaps correspond closely with file size. So even if you have 3mb memory available to jvm, you might still get OutOfMemoryException.
Your code is creating three in-memory images simultaneously. If you can find the size of both images without reading the complete files, you can modify the code in a way to have only one of the source images in memory at a time. If even that doesn't prove to be sufficient you might need some sort of streaming method of reading the images.
you may get some idea from here.
Are you trying to display this super large image or are you just trying to save it?
If your trying to display it. Cut the images into tiles. Then only display the tiles that are being viewed. If the user zooms out you need to reduce the size of the bitmap before showing the whole thing.
If your trying to save it, try saving it in sections to the same file by cutting the image up.
Loading 2 1m files in memory then creating a 2m file leaves you with 4M in memory for your images alone. Dynamically loading and unloading the memory solves this issue similar to tiles on Google maps or dynamic zooming in other map oriented solutions.
If you need to return that huge 2400x3200 bitmap as your result, there is no way to actually realize this goal. The reason is that 2400*3200*4 bytes ~ 30 Mb! How can you hope to implement this method, when even you can't even fit the return value into your limited heap space (ie 16Mb)?
And even if you used 16-bit color, it would still fail because you would end up using about 15MB, which would not leave you enough space for the language run time.

Categories

Resources