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 
loadPixels(int * pixels,int width,int height)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 
loadImageBytes(const uchar * data,int step,int width,int height,int depth,int channels,WLNonFileByteStream * m_strm)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 
is_NULL_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name,const char * field_type)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 
is_NULL_vec_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
is_NULL_point_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
is_NULL_axis_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
is_NULL_pivot_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
is_NULL_quat_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
is_NULL_mat3x3_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 }
is_NULL_mat3x1_field_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
set_JavaObj_int(JNIEnv * env,jobject java_obj,const char * field_name,jint val)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 
get_id_by_JavaObj(JNIEnv * env,jobject java_obj)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 
get_type_by_JavaObj(JNIEnv * env,jobject java_obj)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 
get_int_by_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
get_float_by_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name)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 
get_obj_by_JavaObj(JNIEnv * env,jobject java_obj,const char * field_name,const char * obj_type)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