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