1/* 2OpenCV for Android NDK 3Copyright (c) 2006-2009 SIProp Project http://www.siprop.org/ 4 5This software is provided 'as-is', without any express or implied warranty. 6In no event will the authors be held liable for any damages arising from the use of this software. 7Permission is granted to anyone to use this software for any purpose, 8including commercial applications, and to alter it and redistribute it freely, 9subject to the following restrictions: 10 111. 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. 122. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 133. 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 47static const char* fmtSignBmp = "BM"; 48 49CvCapture *m_capture = 0; 50CvHaarClassifierCascade *m_cascade = 0; 51IplImage *m_sourceImage = 0; 52IplImage *m_grayImage = 0; 53IplImage *m_smallImage = 0; 54CvMemStorage *m_storage = 0; 55CvSeq *m_facesFound = 0; 56CvRect m_faceCropArea; 57CvSize m_smallestFaceSize; 58 59 60#ifdef __cplusplus 61extern "C" { 62#endif 63 64JNIEXPORT 65jboolean 66JNICALL 67Java_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 74JNIEXPORT 75void 76JNICALL 77Java_org_siprop_opencv_OpenCV_releaseSocketCapture(JNIEnv* env, 78 jobject thiz); 79 80JNIEXPORT 81jboolean 82JNICALL 83Java_org_siprop_opencv_OpenCV_grabSourceImageFromCapture(JNIEnv* env, 84 jobject thiz); 85 86JNIEXPORT 87jbooleanArray 88JNICALL 89Java_org_siprop_opencv_OpenCV_getSourceImage(JNIEnv* env, 90 jobject thiz); 91 92JNIEXPORT 93jboolean 94JNICALL 95Java_org_siprop_opencv_OpenCV_setSourceImage(JNIEnv* env, 96 jobject thiz, 97 jintArray photo_data, 98 jint width, 99 jint height); 100 101JNIEXPORT 102jbooleanArray 103JNICALL 104Java_org_siprop_opencv_OpenCV_findContours(JNIEnv* env, 105 jobject thiz, 106 jint width, 107 jint height); 108 109JNIEXPORT 110jboolean 111JNICALL 112Java_org_siprop_opencv_OpenCV_initFaceDetection(JNIEnv* env, 113 jobject thiz, 114 jstring cascade_path_str); 115 116JNIEXPORT 117void 118JNICALL 119Java_org_siprop_opencv_OpenCV_releaseFaceDetection(JNIEnv* env, 120 jobject thiz); 121 122JNIEXPORT 123jboolean 124JNICALL 125Java_org_siprop_opencv_OpenCV_highlightFaces(JNIEnv* env, 126 jobject thiz); 127 128JNIEXPORT 129jobjectArray 130JNICALL 131Java_org_siprop_opencv_OpenCV_findAllFaces(JNIEnv* env, 132 jobject thiz); 133 134JNIEXPORT 135jobject 136JNICALL 137Java_org_siprop_opencv_OpenCV_findSingleFace(JNIEnv* env, 138 jobject thiz); 139 140#ifdef __cplusplus 141} 142#endif 143 144 145 146IplImage* 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 166void 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 231bool 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 249bool 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 253bool 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 257bool 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 261bool 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 265bool 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 269bool 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} 272bool 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 279void 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 290int 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 300int 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 311int 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 322float 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 333jobject 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