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