0

I've got an app where the main viewing area is a WebView.

It's a service where a user can also upload a photo. However, with the WebView, and photo uploads, I'm getting some OutOfMemoryErrors.

Usually all it takes is a page loaded in the WebView, and then simply trying to open an image with something like this:

Bitmap bmp = BitmapFactory.decodeFile(path);

The only reason I need to open the file at all is so that I can scale it down so that it fits in a max width/max height dimensions before uploading it.

I've even tried opening it in a sampled fashion, similar to what's mentioned here:

Strange out of memory issue while loading an image to a Bitmap object

However, with a complex webpage loaded in the WebView, I still get OutOfMemoryError when trying to open the image.

Is there a way to scale it, maybe using another process or something, that's more memory efficient?

Community
  • 1
  • 1
synic
  • 26,359
  • 20
  • 111
  • 149
  • OK, I should have followed that link before answering, as I've just described the method you previously tried! What file format are you working with? If it's a frequency-based format like JPEG scaling is fairly simple (in theory, not tried) – Phil Lello Apr 14 '11 at 18:58
  • Yeah, jpeg from the device's own camera – synic Apr 14 '11 at 19:03
  • See my edited answer (can't format enough in comments!) – Phil Lello Apr 14 '11 at 20:12
  • What size & res is the downsized image, and how are you opening it? I note that you're talking about opening within WebView, so it may not be the source image size that's a problem. – Phil Lello Apr 14 '11 at 20:18
  • The WebView is completely unrelated, except that it consumes a lot of the memory budget. I'm not displaying the images in there or anything else. Scaling is also not the issue at the moment. Simply opening the images with BitmapFactory.decode is currently causing an OutOfMemoryError, before I even attempt scaling. The images I'm trying to open are of variable resolution, depending on the device that took them. – synic Apr 14 '11 at 22:52

2 Answers2

2

I'm glad you asked, I was about to investigate this for my own project.

It looks like BitmapFactory.Options is your friend here, specifically BitmapFactory.Options.inSampleSize enter link description here. You can use BitmapFactory.decodeStream to get the image dimensions without creating a Bitmap.

Googling revealed the com.bristle.javalib.awt ImgUtil classes; these appear to be open source (don't know the license), and are AWT based, so may work on Android. The interesting method is ImgUtil.scalueImageToOutputStreamAsJPEG, which works with InputSteam/OutputStream, so may be memory efficient.

UPDATE

An alternative is to write a JNI wrapper around /system/lib/libjpeg.so, which appears to be standard on Android devices. This library works with scanlines, so can be memory friendly. Another plus is that using JNI should be faster than pure java.

Hope this helps,

Phil Lello

Phil Lello
  • 8,377
  • 2
  • 25
  • 34
  • Looks promising, though Android doesn't include anything from AWT, and specifically, Image and BufferedImage do not exist. – synic Apr 14 '11 at 22:55
0

I had a similar problem and found a workable solution using BitmapFactory.Option.inScale. You can find details here: How do I scale a streaming bitmap in-place without reading the whole image first?

Community
  • 1
  • 1
emmby
  • 99,783
  • 65
  • 191
  • 249