Given a JPEG Encoded byte array taken from a camera, I need to decode it and display its image (bitmap) in my application. From searching around, I've found that there are two primary ways to go about this: use NDK Jpeg Decoding library or use BitmapFactory.decodeByteArray. This is for an experimental embedded device being developed that runs on Android with a built-in camera.
I would greatly prefer to develop the application in SDK not NDK if possible at all, but many people seemed to handle this problem by going straight to NDK, which bugged me a bit.
Is there some sort of inherent limitation in BitmapFactory.decodeByteArray that forces you to handle this problem by using libjpeg in NDK (Perhaps speed? Incompatibility?)
Performance isn't a big consideration unless if it takes say more than 45 seconds to decode the image and display it.
This is an important decision I need to make upfront, so I'd appreciate any thoughtful answers. Thank you so much.
Here is a really good example / explanation how you can decode images on device efficiently without using NDK : Displaying Bitmap Efficiently. You have an option to decode bitmap from stream or file so it depends on your needs. But in most of my applications I am using the same method and it's working great. So I suggest you to take a look at the SDK example.
Hope it will helps you.
Related
I am currently working on an HDR application that requires the use of Camera2 to be able to customize HDR settings.
I have developed a customized algorithm to retrieve certain data from Raw DNG images and I would like to implement it on Android.
I am unfortunately not an expert in Java/Android, so I taught myself how to code. Using other formats, I have usually worked with bitmaps to retrieve pixel data. ( which was relatively an easy task concerning the existing methods )
Concerning DNG files, I have found no documentation showing me how to retrieve the pixels data. I thought of bufferizing the image, however the DNG file format contains many information other than pixels and I'm afraid I am unable to find an extraction strategy using bufferstream. (I just want to store the pixels inside an array)
Anyone has an idea ? Would highly appreciate some tips.
Best regards
Camera2 does not produce DNGs directly - it produces plain RAW buffers, which you can then save to a DNG via DngCreator.
Are you operating on the initial RAW buffers, or saving DNGs and then loading them back?
In general, DNGs are not full baked images, so quite a bit of code is needed to render them completely - see for example Adobe's DNG SDK.
I need to get the pixels info from a Jpeg image without instanciating a Bitmap and then pass it to the JNI.
It is impossible with android to get anything else than a jpeg image from camera (except if you need a low resolution in which case you can use thePreviewCallback), so I got the byte[] from the jpegCallback.
Is it possible to get pixels info in an int[] without using Bitmap.getPixels() ?
If you don't want to construct a Bitmap, your only option is to decode the JPEG buffer yourself; this means either finding another Java JPEG decompression library, or using JNI and a C JPEG library such as libjpeg. Or, you can write one from scratch, which I don't recommend unless you're already pretty conversant with image compression routines, and you have plenty of time for implementation and debugging.
As Scott asked, why is using Bitmap unacceptable? No matter what route you take, you'll have to call something to decompress the image data, and using BitmapFactory.decodeByteArray is a straightforward, known-to-work option.
I do not see how this is possible with the standard Android APIs. I'm sure there are 3rd party JPEG libraries you could use (Googling finds may possibilities). Why are you trying to avoid Bitmaps? If it is a memory constraint, you might want to decode small horizontal chunks with BitmapRegionDecoder
I am writing a program to manipulate images,ie change its color,brightness,contrast etc...
The DVM doesn't support the manipulation of images of size beyond a limit...Can any one tell me whether using Open CV will solve the issue(as this seems to be a better option than NDK)?
Or will I have to use NDK?
I have done a lot of search and was not able to find answer..
First of all, there are different options for Image processing in Android, see here for a comparison of the most popular options: see Android Computer Vision JavaCV OpenCV FastCV comparison and Image processing library for Android and Java
Coming back to your question: If the images you deal are really very large so that they do not fit into the memory of the device, you need to process the images in small chunks called tiles.
If your images are not that big, I recommend you to use OpenCv, if you have to do anything more than very simple tasks such as brightness/contrast adjustment.
I'm currently writing Bitmaps to a png file and also reading them back to a Bitmap. I'm looking for ways to improve the speed at which writing and reading happens. The images need to be lossless since I'm reading them back to edit them.
The place where I see the worst performance is the actual BitmapFactory.decode(...).
Few questions:
1. Is there a faster solution to read/write from file to a Bitmap using NDK?
2. Is there a better library to decode a Bitmap faster?
3. What is the best way to store and read a Bitmap?
Trying to resolve the best/fastest possible way to read/write image to file came down to using plain old BitmapFactory. I have tried using NDK to do the encoding/decoding but that really didn't make a difference.
Essentially the format to use was lossless PNG since I didn't want to loose any quality after editing an image.
The main concept from all this was that I needed to understand was how long encoding took versus decoding. The encoding numbers where in the upper 300-600ms, depending on image size, and decoding was just fast, around 10-23ms.
After understanding all that I just created a worker thread that I passed images needing encoding and let it do the work without affecting the user experience. The image was kept cached in memory just in case it was needed right away before it was completely encoded and saved to file.
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?
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
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?