1 #define LOG_TAG "org.opencv.android.Utils"
2 #include "common.h"
3 
4 #include "opencv2/core.hpp"
5 #include "opencv2/imgproc.hpp"
6 
7 #ifdef __ANDROID__
8 #include <android/bitmap.h>
9 
10 using namespace cv;
11 
12 extern "C" {
13 
14 /*
15  * Class:     org_opencv_android_Utils
16  * Method:    void nBitmapToMat2(Bitmap b, long m_addr, boolean unPremultiplyAlpha)
17  */
18 
19 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2
20   (JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha);
21 
Java_org_opencv_android_Utils_nBitmapToMat2(JNIEnv * env,jclass,jobject bitmap,jlong m_addr,jboolean needUnPremultiplyAlpha)22 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2
23   (JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha)
24 {
25     AndroidBitmapInfo  info;
26     void*              pixels = 0;
27     Mat&               dst = *((Mat*)m_addr);
28 
29     try {
30             LOGD("nBitmapToMat");
31             CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 );
32             CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
33                        info.format == ANDROID_BITMAP_FORMAT_RGB_565 );
34             CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 );
35             CV_Assert( pixels );
36             dst.create(info.height, info.width, CV_8UC4);
37             if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 )
38             {
39                 LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4");
40                 Mat tmp(info.height, info.width, CV_8UC4, pixels);
41                 if(needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA);
42                 else tmp.copyTo(dst);
43             } else {
44                 // info.format == ANDROID_BITMAP_FORMAT_RGB_565
45                 LOGD("nBitmapToMat: RGB_565 -> CV_8UC4");
46                 Mat tmp(info.height, info.width, CV_8UC2, pixels);
47                 cvtColor(tmp, dst, COLOR_BGR5652RGBA);
48             }
49             AndroidBitmap_unlockPixels(env, bitmap);
50             return;
51         } catch(const cv::Exception& e) {
52             AndroidBitmap_unlockPixels(env, bitmap);
53             LOGE("nBitmapToMat catched cv::Exception: %s", e.what());
54             jclass je = env->FindClass("org/opencv/core/CvException");
55             if(!je) je = env->FindClass("java/lang/Exception");
56             env->ThrowNew(je, e.what());
57             return;
58         } catch (...) {
59             AndroidBitmap_unlockPixels(env, bitmap);
60             LOGE("nBitmapToMat catched unknown exception (...)");
61             jclass je = env->FindClass("java/lang/Exception");
62             env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}");
63             return;
64         }
65 }
66 
67 // old signature is left for binary compatibility with 2.4.0 & 2.4.1, to removed in 2.5
68 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
69   (JNIEnv * env, jclass, jobject bitmap, jlong m_addr);
70 
Java_org_opencv_android_Utils_nBitmapToMat(JNIEnv * env,jclass,jobject bitmap,jlong m_addr)71 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat
72   (JNIEnv * env, jclass, jobject bitmap, jlong m_addr)
73 {
74     Java_org_opencv_android_Utils_nBitmapToMat2(env, 0, bitmap, m_addr, false);
75 }
76 
77 /*
78  * Class:     org_opencv_android_Utils
79  * Method:    void nMatToBitmap2(long m_addr, Bitmap b, boolean premultiplyAlpha)
80  */
81 
82 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2
83   (JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha);
84 
Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv * env,jclass,jlong m_addr,jobject bitmap,jboolean needPremultiplyAlpha)85 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2
86   (JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha)
87 {
88     AndroidBitmapInfo  info;
89     void*              pixels = 0;
90     Mat&               src = *((Mat*)m_addr);
91 
92     try {
93             LOGD("nMatToBitmap");
94             CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 );
95             CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
96                        info.format == ANDROID_BITMAP_FORMAT_RGB_565 );
97             CV_Assert( src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols );
98             CV_Assert( src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4 );
99             CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 );
100             CV_Assert( pixels );
101             if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 )
102             {
103                 Mat tmp(info.height, info.width, CV_8UC4, pixels);
104                 if(src.type() == CV_8UC1)
105                 {
106                     LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888");
107                     cvtColor(src, tmp, COLOR_GRAY2RGBA);
108                 } else if(src.type() == CV_8UC3){
109                     LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888");
110                     cvtColor(src, tmp, COLOR_RGB2RGBA);
111                 } else if(src.type() == CV_8UC4){
112                     LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888");
113                     if(needPremultiplyAlpha) cvtColor(src, tmp, COLOR_RGBA2mRGBA);
114                     else src.copyTo(tmp);
115                 }
116             } else {
117                 // info.format == ANDROID_BITMAP_FORMAT_RGB_565
118                 Mat tmp(info.height, info.width, CV_8UC2, pixels);
119                 if(src.type() == CV_8UC1)
120                 {
121                     LOGD("nMatToBitmap: CV_8UC1 -> RGB_565");
122                     cvtColor(src, tmp, COLOR_GRAY2BGR565);
123                 } else if(src.type() == CV_8UC3){
124                     LOGD("nMatToBitmap: CV_8UC3 -> RGB_565");
125                     cvtColor(src, tmp, COLOR_RGB2BGR565);
126                 } else if(src.type() == CV_8UC4){
127                     LOGD("nMatToBitmap: CV_8UC4 -> RGB_565");
128                     cvtColor(src, tmp, COLOR_RGBA2BGR565);
129                 }
130             }
131             AndroidBitmap_unlockPixels(env, bitmap);
132             return;
133         } catch(const cv::Exception& e) {
134             AndroidBitmap_unlockPixels(env, bitmap);
135             LOGE("nMatToBitmap catched cv::Exception: %s", e.what());
136             jclass je = env->FindClass("org/opencv/core/CvException");
137             if(!je) je = env->FindClass("java/lang/Exception");
138             env->ThrowNew(je, e.what());
139             return;
140         } catch (...) {
141             AndroidBitmap_unlockPixels(env, bitmap);
142             LOGE("nMatToBitmap catched unknown exception (...)");
143             jclass je = env->FindClass("java/lang/Exception");
144             env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
145             return;
146         }
147 }
148 
149 // old signature is left for binary compatibility with 2.4.0 & 2.4.1, to removed in 2.5
150 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap
151   (JNIEnv * env, jclass, jlong m_addr, jobject bitmap);
152 
Java_org_opencv_android_Utils_nMatToBitmap(JNIEnv * env,jclass,jlong m_addr,jobject bitmap)153 JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap
154   (JNIEnv * env, jclass, jlong m_addr, jobject bitmap)
155 {
156     Java_org_opencv_android_Utils_nMatToBitmap2(env, 0, m_addr, bitmap, false);
157 }
158 
159 } // extern "C"
160 
161 #endif //__ANDROID__
162