and*_*per 8 c++ java-native-interface android image-manipulation bitmap
在某些应用程序中,处理没有OOM的大型图像以及快速处理这些图像非常重要.
为此,JNI(或令人遗憾地缺乏文档的renderscript)可以是一个很好的解决方案.
在过去,我成功地使用JNI来旋转巨大的位图,同时避免使用OOM(链接在这里,这里和这里).这是一个很好的(但很烦人)经验,但最终它的工作.
android框架有很多处理位图的功能,但我不知道JNI方面的情况如何.
我已经知道如何将位图从android的"java世界"传递到"JNI世界"并返回.
我不知道的是我可以在JNI端使用哪些功能来帮助我使用位图.
我希望能够在JNI上进行所有图像操作(包括解码),这样我在呈现大图像时就不用担心OOM了,在这个过程的最后,我可以将数据转换为Java-位图(显示用户)和/或将其写入文件.
再次,我不想将JNI端的数据转换为java位图,只是为了能够运行这些操作.
事实证明,有一些库提供了许多功能(如JavaCV),但是它们非常大,我不太确定它们的功能,如果它们真的在JNI端进行解码,所以我更喜欢能够通过Android的内置JNI功能知道什么是可能的.
哪些功能可以在Android上的JNI端进行图像处理?
例如,我如何在位图上运行面部检测,应用矩阵,下采样位图,缩放位图等等?
对于某些操作,我已经可以想到一种实现它们的方法(缩放图像非常简单,维基百科可以提供很多帮助),但有些操作非常复杂.
即使我自己实现了这些操作,也许其他人已经提高了效率,想到了C/C++可以拥有的那么多优化.
当我去Android的JNI方面时,我真的是靠自己,我需要从头开始实现每一个方面吗?
为了说清楚,我感兴趣的是:
在java上输入位图 - >纯粹在JNI和C/C++中的图像处理(无论如何都没有转换为java对象) - >在java上输出位图.
"Android的内置JNI功能"是一种矛盾.从技术上讲,许多Android Framework Java类在链中的某个地方使用JNI来调用本机库在技术上是正确的.
但对此声明有三种保留意见.
这些是"实施细节",并且在任何下一版本的Android或任何分支(例如Kindle),甚至是不被视为"分叉"的 OEM版本(例如由三星或Quallcom构建)中如有更改,恕不另行通知SOC).
在核心Java类中实现本机方法的方式与"经典"JNI不同.这些方法由JVM预加载和缓存,因此不会受到JNI调用典型的大部分开销的影响.
您的Java或本机代码无法直接与其他类的JNI方法进行交互,尤其是构成系统框架的类.
所有这些说,您可以自由地学习Android的源代码,找到支持特定类和方法的本机库(例如面部检测),并在您的本机代码中使用这些库,或构建您自己的JNI层使用Java代码中的这些库.
举一个具体的例子,Android中的人脸检测是通过加载的android.media.FaceDetector类实现的libFFTEm.so.您可以查看本机代码,并根据需要使用它.您不应该假设libFFTEm.so设备上存在该设备,或者设备上的库将具有相同的API.
但在这种特殊情况下,这不是问题,因为所有工作neven都完全基于软件.因此,您可以完整复制此代码,或仅复制此相关部分,并使其成为本机库的一部分.请注意,对于许多设备,您可以简单地加载和使用,/system/lib/libFFTEm.so并且永远不会感到不适,直到您遇到一个行为异常的系统.
通过阅读本机代码可以得出一个值得注意的结论,即底层算法会忽略颜色信息.因此,如果要查找面部坐标的图像来自YUV源,则可以在调用时避免大量开销
// run detection
btk_DCR_assignGrayByteImage(hdcr, bwbuffer, width, height);
int numberOfFaces = 0;
if (btk_FaceFinder_putDCR(hfd, hdcr) == btk_STATUS_OK) {
numberOfFaces = btk_FaceFinder_faces(hfd);
} else {
ALOGE("ERROR: Return 0 faces because error exists in btk_FaceFinder_putDCR.\n");
}
Run Code Online (Sandbox Code Playgroud)
直接使用YUV(或Y)字节数组,而不是将其转换为RGB并返回到android.media.FaceDetector.findFaces()中的 YUV .如果您的YUV缓冲区来自Java,您可以构建自己的类YuvFaceDetector,它将是android.media.FaceDetector的副本,唯一的区别是仅YuvFaceDetector.findFaces()采用Y(亮度)值而不是Bitmap,并避免RGB到Y转换.
其他一些情况并不像这样容易.例如,视频编解码器与硬件平台紧密耦合,您不能简单地将libstagefright.so中的代码复制到您的项目中.Jpeg编解码器是一种特殊的野兽.在现代系统中(IIRC,自2.2以来),您可以期待/system/lib/libjpeg.so在场.但是许多平台通过libstagefright.soOpenMAX或者OpenMAX 也有更高效的Jpeg编解码器硬件实现,并且通常用于android.graphics.Bitmap.compress()和android.graphics.BitmapFactory.decode***()方法.
还有一个优化的libjpeg-turbo,它有自己的优势/system/lib/libjpeg.so.
| 归档时间: |
|
| 查看次数: |
4592 次 |
| 最近记录: |