Open AndroidDeveloperLB opened 10 years ago
It's true that this library doesn't contain kind descriptions about features and apis it provides. I'll work on it gradually.
To answer your questions:
1.cool. thanks.
2.FaceDetector works on the java side. if you add it on the JNI side (C/C++) , this could allow you to detect faces without the worry of OOM (for too large images). This way, if an app wishes to crop a huge image based on the faces within it, it could do it all on the JNI side, and after cropping, it could show it on the Java side.
I verified your question and the problem on stackoverflow, and I solved it by creating a new input stream class with buffering feature. It'll be updated soon.
I don't know whether large memory can be held in JNI context. This library decodes bitmap line by line, so that it could handle large image without OOM.
And I think face detection is not suitable for this. It will require OpenCV or something to be implemented, but that will make the binary fat and it seems not so efficient. But it will be good to provide some interfaces that enable developers to manipulate image data line by line, so that they can implement their own detection routines.
about the inputStream, you should try to check some websites and on some old android devices. as i've reported, what i've made doesn't always work.
about large memory, you can just try it out. take a huge image on the Internet and see if an "old" device can handle it. i've tested it on my SGS3 , and I can easily cause OOM if I want to . remember that a bitmap takes at least 4_width_height bytes , so if the heap is of size 64MB, you can use an image that is of size 6000*6000 (which is ~144MB) .
about face detection, ok, it was just a suggestion in case it is possible to harness what googe has inside of its source code.
Updated. The code below should work now.
mImageView = (ImageView) findViewById(R.id.image_view);
new AsyncTask<Object, Object, Bitmap>() {
@Override
protected Bitmap doInBackground(Object... params) {
try {
InputStream in = new URL("http://farm6.staticflickr.com/5172/5588953445_51dcf922aa_o.jpg")
.openConnection()
.getInputStream();
return BitmapDecoder.from(in).scaleBy(1 / 8f).decode();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Bitmap result) {
if (result == null) {
Log.e(LOG_TAG, "Couldn't load an image.");
} else {
mImageView.setImageBitmap(result);
}
}
}.execute();
This wasn't my intention of the question, but it's good to have too. what you've shown can be done on java side without any JNI involved: either download the file and then use it, or use the inputStream twice (once for getting resolution and once for real downsampling). for the part of downsampling, you could use this: http://stackoverflow.com/a/17773344/878126 , which allows you to downsample even by values that are not power of 2 .
What I asked is whether we can do a full decode of the image on the JNI side, and add a function there to play with it (for example setting all pixels to be only of blue colors), and when finished, you could either export the bitmap to a file (as-is) or downsample it for Java-bitmap instead (or both).
BTW, about scaling, wouldn't it be better to use two parameters instead - nominator and denominator ?
You know, neither inDensity nor inTargetDensity are intended to do that. The method you did is not different from scaling image after full decoding. I didn't test it but it will not work with large images.
And now I understand what you really want to do. It may be a nice feature dealing large bitmap which cannot be handled usually, but it is not a good idea to occupy big memory in any way. We should keep design principles Android provides. This feature may be implemented using file that keeps whole decoded data and caching only partial data when it's necessary at the moment.
Yes, I know I made a trick, and also wrote about it. I also wrote a merged method that uses both my way and Google's way, since their method uses less memory and is faster (but it doesn't support downsampling of all possible values).
If a Java-based app needs to handle a large image (even rotate it), it cannot do it in case the heap is too small since the current ways create 2 huge bitmaps in the process. That's why I made a library that handles at least the part of having 2 bitmaps at the same time (though the initial one will still be huge) : http://github.com/AndroidDeveloperLB/AndroidJniBitmapOperations
It's a very basic library, and all it does it holding a large bitmap within the "JNI-world" , while allowing you to do all the work on the "JNI-world", and only when you are done, you continue to the "Java-world". Sadly, it misses the part of decoding, so that's why I'm searching for this solution too. I've also asked about it here: http://blog.translucentcomputing.com/2012/05/jni-android.html
I hope I will find the way (and time) to also add this to my tiny library.
I would like to know better about this library. Are there any JavaDocs ? any list of available features (besides the wiki page) ?
For example, I would like to know if it supports WebP encoding/decoding, if it can have face detection, if it supports direct downsampling of an internet image link (instead of creating 2 input streams or download the file and then check it out),...
Also, I would like to know if using this library ensures that the bitmap isn't held in the heap till you tell it to.