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