Progressive Image Loading on Android - java

I have a ViewPager that I'm using to page through several ImageViews (around 1000) which each load a full-screen Bitmap. I'm subsampling the images using options.inSampleSize and using a memcache for performance but this is still not fast enough. What I'm trying to avoid is the user seeing blank ImageViews when they page through the views quickly.
I'm wondering if there is a way to serve a partially rendered image (or low quality) while the requested image loads.
I've noticed the Android gallery incorporates something like this (especially noticeable when zooming in and out, loading looks similar to loading of a progressive JPEG on the web), but I haven't been able to find any related information.

Android does not currently provide a way to get intermediate images during decoding (e.g. a progressive JPEG). You only get one final image.
You are already using inSampleSize to get more coarse versions of the image. This makes the decode hopefully quicker, although there are no time guarantees: it uses libjpeg under the hood. Have you measured how long each image decode takes? Have you tried setting inPreferQualityOverSpeed to false? Are you reusing the same bitmap (also may speed up decode). You can also check if inSampleSize makes a different in speed.
In any case, any work of getting low-quality images quickly gets lost if you then want a more detailed version of the same image, as you have to start the decode from the beginning. Therefore, you want to limit decoding to the visible images plus its near neighbors so that you can scroll without blank images.

Related

Activity with transparent background and blur-filter

I'm currently working on an application where I at one point want to open an Activity that has a transparent background so that I can see the activity below it. This was simple enough and I solved it quick. However, now I want to also add some kind of blur filter so that the activity below my activity seems blurred out.
I have searched around and tried several different solutions but with no luck so I'm trying to add this as a question. Does anyone know of any good way to solve this?
Thanks
There are plenty of libraries that do this. Here's one list of them. Personally I've used BlurView (I hope linking to one of the libraries is not against site rules) but I've had to patch the library a bit, see this issue - the pull request is not in yet. I've also had performance issues with animations.
Basically all the libraries do the same things:
Create Canvas for a Bitmap, with scaled down dimensions (e.g. 4 times smaller), set the transformation matrix to apply this scaling
Render the background of the window to Canvas
Render the root view of the Activity to the Canvas
Blur the Canvas's Bitmap using ScriptIntrinsicBlur
Draw the Bitmap as the background of a View, scaled back up e.g. 4 times
Why the scaling? For performance reasons. It's much faster to draw everything 4 times smaller, and also the blur effect becomes "stronger" due to the upscaling - there's a limit how much ScriptIntrinsicBlur can blur with one pass, and multiple passes slow things down again.
For API < 14, you could use the flag WindowManager.LayoutParams.FLAG_BLUR_BEHIND.
For higher APIS this is no longer supported.
However, you could do this with a view.
Create a Bitmap from your activity's overall layout and Blur that bitmap with whatever method you want. Add(or unhide) a View in your layout that covers everything and you have your problem solved.

Need to obtain standard output size from Android camera pics

I am working on a photobooth type app for iPhone and Android. On iPhone, I know the exact resolution of the front camera, and am able to always output 4 mini pics predictably and make a photostrip from them. But for Android, I need a way to resize 4 images I have taken to a width of 48px and height of 320px per image. This way, I can build the same size photostrip I built for the iPhone version, and easily display the photostrips in a consistent manner on a website (I don't want the size of them to vary depending on platform). On Android, how can I resize to that resolution (48x320), even if the Android camera doesn't output that aspect ratio? Basically, I'd like to resize on Android, and have it automatically zoom as necessary until 48x320 is reached and it doesn't look stretched/distorted...I'm ok with part of the image (like the outside border) being lost in favor of getting a 48x320 image. Maybe this is just a straight Java question...
Thanks so much!

Is there a memory limit available for widgets?

I have a widget with ViewFlipper that flips between X number of images. I aim for 10 images to be flipped, and I can do this if I load very small images. My widget is size 4x2 and I want to display images with good quality, but I can't achieve this. Everything loads fine, no exceptions, but the widget never displays them. If I load very small image sizes (100x100 px), it starts flipping them. If I load larger image size (300x300), it won't start flipping the images until I reduce the number of images (flips) to 4.
This suggests a memory limitation to me, but I would expect an exception to be thrown somewhere after I do appWidgetManager.updateWidget(widgetId, remoteViewFlipper).
Going through the logs, I don't see anything nearly related to this.
I think it depends on concrete implementation of launcher - widget stuff is hosted and processsed there. You updtes are send as parcelables, so there soule be data size limit as well:
http://groups.google.com/group/android-developers/browse_thread/thread/26ce74534024f41a?pli=1

Crop Bitmap without reading entire Bitmap first

I have a very large image and I only want to display a section the size of the display (no scaling), and the section should just be the center of the image. Because the image is very large I cannot read the entire image into memory and then crop it. This is what I have so far but it will give OutOfMemory for large images. Also I don't think inSampleSize applies because I want to crop the image, not lower the resolution.
Uri data = getIntent().getData();
InputStream is = getContentResolver().openInputStream(data);
Bitmap bitmap = BitmapFactory.decodeStream(is, null, null);
Any help would be great?
You can do this in 2 steps:
get the size of the bitmap, by using inJustDecodeBounds=true .
use BitmapRegionDecoder to decode just the part you want to .
The downside ? it works only from API 10 (but it's already the majority...).
I agree that the easiest way is to break the image up into many smaller tiled images and to just load the appropriate ones to make the image you are after.
However, if you do not want to do that, you may be forced to look into the encoding of the jpeg itself.
What you could do is something along the lines of copying the header from the file into a new file, and then extracting just the pixels you want in order to create a new file. Then reloading the new file will allow you to have just the subset of the image you are looking to work with, and all the regular java functionality and classes will be equally available for you to use.
I know it isn't necessarily an elegant or simple solution, however it does guarantee that you will be able to use the original java functionality which you expect to be able to use.
I think you're approaching the problem from the wrong direction.
If the bitmap is already so large it can't be loaded as a single continuous image, why store it as a single image? Slice it into tiles then load the center tile/tiles and act upon those.

How to make a thumb from a big image file in J2ME?

I'm trying to display a big image file in a J2ME application. But I found that when the image file is too big I can not even create the Image instance and get a OutOfMemory exception.
I suppose I can read the image file in small chunks and create a thumbnail to show to the user?
Is there a way to do this? Or is there any other method to display the image file in the application?
Thanks.
There are a number of things to try, depending on exactly what you are trying to do and what handset you want your application to run on.
If your image is packaged inside your MIDlet JAR file, You have less control over what the MIDP runtime does because the data needs to be unzipped before it can be loaded as an Image. In that case, I would suggest simply packaging a smaller image. Either reduce the number of pixels or the number of bytes used to encode each pixel.
If you can read the image bytes from a GCF-based InputStream (file, network...), You need to understand the image format (BMP is straightforward, JPEG less so...) so you can scale it down into a mutable Image object that would take less memory, one chunk at a time.
In that case, you also need to decide what your scaling algorithm should be. Turning 32 bits pixels in a file into 8 bits pixels in memory might not actually work as expected if the LCDUI implementation on your mobile phone was badly written.
Depending on the content of the image, simply removing half of the pixel columns and half of the pixel lines may be either exactly what you need or way too naive an approach. You may want to look at existing image scaling algorithms and write one into your application.
Remember that basic LCDUI may not be the only way to display an image on the screen. JSR-184, JSR-239, JSR-226 and eSWT could all allow you to do that in a way that may be totally independant from your handset LCDUI implementation.
Finally, let's face it, if your phone MIDP runtime doesn't allow you to create at least 2 images the size of your screen at full color depth at the same time, then it might be time to decide to not support that specific handset.

Categories

Resources