1 /* 2 OpenCV for Android NDK 3 Copyright (c) 2006-2009 SIProp Project http://www.siprop.org/ 4 5 This software is provided 'as-is', without any express or implied warranty. 6 In no event will the authors be held liable for any damages arising from the use of this software. 7 Permission is granted to anyone to use this software for any purpose, 8 including commercial applications, and to alter it and redistribute it freely, 9 subject to the following restrictions: 10 11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 13 3. This notice may not be removed or altered from any source distribution. 14 */ 15 #include <stdlib.h> 16 #include <string.h> 17 #include <jni.h> 18 #include <android/log.h> 19 20 #include "cv.h" 21 #include "cxcore.h" 22 #include "cvaux.h" 23 #include "highgui.h" 24 #include "ml.h" 25 #include "utils.h" 26 #include "WLNonFileByteStream.h" 27 #include "grfmt_bmp.h" 28 29 #define LOGV(...) __android_log_print(ANDROID_LOG_SILENT, LOG_TAG, __VA_ARGS__) 30 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 31 //ANDROID_LOG_UNKNOWN, ANDROID_LOG_DEFAULT, ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_SILENT 32 //LOGV(ANDROID_LOG_DEBUG, "JNI", ""); 33 34 #define ANDROID_LOG_VERBOSE ANDROID_LOG_DEBUG 35 #define LOG_TAG "CVJNI" 36 #define INVALID_ARGUMENT -18456 37 38 #define SAFE_DELETE(p) { if(p){ delete (p); (p)=0; } } 39 #define SAFE_DELETE_ARRAY(p) { if(p){ delete [](p); (p)=0; } } 40 41 42 #define IMAGE( i, x, y, n ) *(( unsigned char * )(( i )->imageData \ 43 + ( x ) * sizeof( unsigned char ) * 3 \ 44 + ( y ) * ( i )->widthStep ) + ( n )) 45 46 // CV Objects 47 static const char* fmtSignBmp = "BM"; 48 49 CvCapture *m_capture = 0; 50 CvHaarClassifierCascade *m_cascade = 0; 51 IplImage *m_sourceImage = 0; 52 IplImage *m_grayImage = 0; 53 IplImage *m_smallImage = 0; 54 CvMemStorage *m_storage = 0; 55 CvSeq *m_facesFound = 0; 56 CvRect m_faceCropArea; 57 CvSize m_smallestFaceSize; 58 59 60 #ifdef __cplusplus 61 extern "C" { 62 #endif 63 64 JNIEXPORT 65 jboolean 66 JNICALL 67 Java_org_siprop_opencv_OpenCV_createSocketCapture(JNIEnv* env, 68 jobject thiz, 69 jstring address_str, 70 jstring port_str, 71 jint width, 72 jint height); 73 74 JNIEXPORT 75 void 76 JNICALL 77 Java_org_siprop_opencv_OpenCV_releaseSocketCapture(JNIEnv* env, 78 jobject thiz); 79 80 JNIEXPORT 81 jboolean 82 JNICALL 83 Java_org_siprop_opencv_OpenCV_grabSourceImageFromCapture(JNIEnv* env, 84 jobject thiz); 85 86 JNIEXPORT 87 jbooleanArray 88 JNICALL 89 Java_org_siprop_opencv_OpenCV_getSourceImage(JNIEnv* env, 90 jobject thiz); 91 92 JNIEXPORT 93 jboolean 94 JNICALL 95 Java_org_siprop_opencv_OpenCV_setSourceImage(JNIEnv* env, 96 jobject thiz, 97 jintArray photo_data, 98 jint width, 99 jint height); 100 101 JNIEXPORT 102 jbooleanArray 103 JNICALL 104 Java_org_siprop_opencv_OpenCV_findContours(JNIEnv* env, 105 jobject thiz, 106 jint width, 107 jint height); 108 109 JNIEXPORT 110 jboolean 111 JNICALL 112 Java_org_siprop_opencv_OpenCV_initFaceDetection(JNIEnv* env, 113 jobject thiz, 114 jstring cascade_path_str); 115 116 JNIEXPORT 117 void 118 JNICALL 119 Java_org_siprop_opencv_OpenCV_releaseFaceDetection(JNIEnv* env, 120 jobject thiz); 121 122 JNIEXPORT 123 jboolean 124 JNICALL 125 Java_org_siprop_opencv_OpenCV_highlightFaces(JNIEnv* env, 126 jobject thiz); 127 128 JNIEXPORT 129 jobjectArray 130 JNICALL 131 Java_org_siprop_opencv_OpenCV_findAllFaces(JNIEnv* env, 132 jobject thiz); 133 134 JNIEXPORT 135 jobject 136 JNICALL 137 Java_org_siprop_opencv_OpenCV_findSingleFace(JNIEnv* env, 138 jobject thiz); 139 140 #ifdef __cplusplus 141 } 142 #endif 143 144 145 146 IplImage* loadPixels(int* pixels, int width, int height) { 147 148 int x, y; 149 IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); 150 151 for ( y = 0; y < height; y++ ) { 152 for ( x = 0; x < width; x++ ) { 153 // blue 154 IMAGE( img, x, y, 0 ) = pixels[x+y*width] & 0xFF; 155 // green 156 IMAGE( img, x, y, 1 ) = pixels[x+y*width] >> 8 & 0xFF; 157 // red 158 IMAGE( img, x, y, 2 ) = pixels[x+y*width] >> 16 & 0xFF; 159 } 160 } 161 162 return img; 163 } 164 165 166 void loadImageBytes(const uchar* data, 167 int step, 168 int width, 169 int height, 170 int depth, 171 int channels, 172 WLNonFileByteStream* m_strm) { 173 174 int fileStep = (width*channels + 3) & -4; 175 uchar zeropad[] = "\0\0\0\0"; 176 char log_str[100]; 177 178 179 assert( data && width > 0 && height > 0 && step >= fileStep ); 180 181 int bitmapHeaderSize = 40; 182 int paletteSize = channels > 1 ? 0 : 1024; 183 int headerSize = 14 /* fileheader */ + bitmapHeaderSize + paletteSize; 184 PaletteEntry palette[256]; 185 186 int testSize = fileStep*height + headerSize; 187 m_strm->Open(testSize); 188 sprintf(log_str, "fileStep*height + headerSize=%i", testSize); 189 LOGV(log_str); 190 191 // write signature 'BM' 192 m_strm->PutBytes( fmtSignBmp, (int)strlen(fmtSignBmp) ); 193 194 // write file header 195 m_strm->PutDWord( fileStep*height + headerSize ); // file size 196 m_strm->PutDWord( 0 ); 197 m_strm->PutDWord( headerSize ); 198 199 // write bitmap header 200 m_strm->PutDWord( bitmapHeaderSize ); 201 m_strm->PutDWord( width ); 202 m_strm->PutDWord( height ); 203 m_strm->PutWord( 1 ); 204 m_strm->PutWord( channels << 3 ); 205 m_strm->PutDWord( BMP_RGB ); 206 m_strm->PutDWord( 0 ); 207 m_strm->PutDWord( 0 ); 208 m_strm->PutDWord( 0 ); 209 m_strm->PutDWord( 0 ); 210 m_strm->PutDWord( 0 ); 211 212 if( channels == 1 ) 213 { 214 FillGrayPalette( palette, 8 ); 215 m_strm->PutBytes( palette, sizeof(palette)); 216 } 217 218 width *= channels; 219 data += step*(height - 1); 220 for( ; height--; data -= step ) 221 { 222 m_strm->PutBytes( data, width ); 223 if( fileStep > width ) 224 m_strm->PutBytes( zeropad, fileStep - width ); 225 } 226 } 227 228 229 230 231 bool is_NULL_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name, const char* field_type) { 232 233 234 LOGV("in is_NULL_field_JavaObj!"); 235 jclass clazz = env->GetObjectClass(java_obj); 236 237 238 // get field 239 jfieldID fid = env->GetFieldID(clazz, field_name, field_type); 240 241 jobject obj = env->GetObjectField(java_obj, fid); 242 if(obj == 0) { 243 LOGV("Object is NULL!"); 244 return true; 245 } 246 return false; 247 } 248 249 bool is_NULL_vec_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 250 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Vector3;"); 251 } 252 253 bool is_NULL_point_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 254 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Point3;"); 255 } 256 257 bool is_NULL_axis_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 258 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Axis;"); 259 } 260 261 bool is_NULL_pivot_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 262 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Pivot3;"); 263 } 264 265 bool is_NULL_quat_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 266 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Quaternion;"); 267 } 268 269 bool is_NULL_mat3x3_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 270 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Matrix3x3;"); 271 } 272 bool is_NULL_mat3x1_field_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 273 return is_NULL_field_JavaObj(env, java_obj, field_name, "Lorg/siprop/opencv/util/Matrix3x1;"); 274 } 275 276 277 278 279 void set_JavaObj_int(JNIEnv* env, jobject java_obj, const char* field_name, jint val) { 280 281 LOGV("in set_JavaObj_int!"); 282 283 jclass clazz = env->GetObjectClass(java_obj); 284 jfieldID fid = env->GetFieldID(clazz, field_name, "I"); 285 286 env->SetIntField(java_obj, fid, val); 287 288 } 289 290 int get_id_by_JavaObj(JNIEnv* env, jobject java_obj) { 291 292 LOGV("in get_id_by_JavaObj!"); 293 294 jclass method_clazz = env->GetObjectClass(java_obj); 295 jmethodID get_type_mid = env->GetMethodID(method_clazz, "getID", "()I"); 296 return env->CallIntMethod(java_obj, get_type_mid); 297 298 } 299 300 int get_type_by_JavaObj(JNIEnv* env, jobject java_obj) { 301 302 LOGV("in get_type_by_JavaObj!"); 303 304 jclass method_clazz = env->GetObjectClass(java_obj); 305 jmethodID get_type_mid = env->GetMethodID(method_clazz, "getType", "()I"); 306 return env->CallIntMethod(java_obj, get_type_mid); 307 308 } 309 310 311 int get_int_by_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 312 313 LOGV("in get_int_by_JavaObj!"); 314 315 jclass clazz = env->GetObjectClass(java_obj); 316 jfieldID int_fid = env->GetFieldID(clazz, field_name, "I"); 317 return env->GetIntField(java_obj, int_fid); 318 319 } 320 321 322 float get_float_by_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name) { 323 324 LOGV("in get_float_by_JavaObj!"); 325 326 jclass clazz = env->GetObjectClass(java_obj); 327 jfieldID float_fid = env->GetFieldID(clazz, field_name, "F"); 328 return env->GetFloatField(java_obj, float_fid); 329 330 } 331 332 333 jobject get_obj_by_JavaObj(JNIEnv* env, jobject java_obj, const char* field_name, const char* obj_type) { 334 335 LOGV("in get_obj_by_JavaObj!"); 336 337 jclass clazz = env->GetObjectClass(java_obj); 338 jfieldID obj_fid = env->GetFieldID(clazz, field_name, obj_type); 339 return env->GetObjectField(java_obj, obj_fid); 340 341 } 342 343