Fixed java tests build
[profile/ivi/opencv.git] / modules / java / generator / gen_java.py
1 #!/usr/bin/env python
2
3 import sys, re, os.path
4 from string import Template
5
6 try:
7     from cStringIO import StringIO
8 except:
9     from StringIO import StringIO
10
11 class_ignore_list = (
12     #core
13     "FileNode", "FileStorage", "KDTree", "KeyPoint", "DMatch",
14     #videoio
15     "VideoWriter",
16 )
17
18 const_ignore_list = (
19     "CV_CAP_OPENNI",
20     "CV_CAP_PROP_OPENNI_",
21     "CV_CAP_INTELPERC",
22     "CV_CAP_PROP_INTELPERC_"
23     "WINDOW_AUTOSIZE",
24     "CV_WND_PROP_",
25     "CV_WINDOW_",
26     "CV_EVENT_",
27     "CV_GUI_",
28     "CV_PUSH_BUTTON",
29     "CV_CHECKBOX",
30     "CV_RADIOBOX",
31
32     #attention!
33     #the following constants are added to this list using code automatic generation
34     #TODO: should be checked
35     "CV_CAP_ANY",
36     "CV_CAP_MIL",
37     "CV_CAP_VFW",
38     "CV_CAP_V4L",
39     "CV_CAP_V4L2",
40     "CV_CAP_FIREWARE",
41     "CV_CAP_FIREWIRE",
42     "CV_CAP_IEEE1394",
43     "CV_CAP_DC1394",
44     "CV_CAP_CMU1394",
45     "CV_CAP_STEREO",
46     "CV_CAP_TYZX",
47     "CV_TYZX_LEFT",
48     "CV_TYZX_RIGHT",
49     "CV_TYZX_COLOR",
50     "CV_TYZX_Z",
51     "CV_CAP_QT",
52     "CV_CAP_UNICAP",
53     "CV_CAP_DSHOW",
54     "CV_CAP_PVAPI",
55     "CV_CAP_PROP_DC1394_OFF",
56     "CV_CAP_PROP_DC1394_MODE_MANUAL",
57     "CV_CAP_PROP_DC1394_MODE_AUTO",
58     "CV_CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO",
59     "CV_CAP_PROP_POS_MSEC",
60     "CV_CAP_PROP_POS_FRAMES",
61     "CV_CAP_PROP_POS_AVI_RATIO",
62     "CV_CAP_PROP_FPS",
63     "CV_CAP_PROP_FOURCC",
64     "CV_CAP_PROP_FRAME_COUNT",
65     "CV_CAP_PROP_FORMAT",
66     "CV_CAP_PROP_MODE",
67     "CV_CAP_PROP_BRIGHTNESS",
68     "CV_CAP_PROP_CONTRAST",
69     "CV_CAP_PROP_SATURATION",
70     "CV_CAP_PROP_HUE",
71     "CV_CAP_PROP_GAIN",
72     "CV_CAP_PROP_EXPOSURE",
73     "CV_CAP_PROP_CONVERT_RGB",
74     "CV_CAP_PROP_WHITE_BALANCE_BLUE_U",
75     "CV_CAP_PROP_RECTIFICATION",
76     "CV_CAP_PROP_MONOCROME",
77     "CV_CAP_PROP_SHARPNESS",
78     "CV_CAP_PROP_AUTO_EXPOSURE",
79     "CV_CAP_PROP_GAMMA",
80     "CV_CAP_PROP_TEMPERATURE",
81     "CV_CAP_PROP_TRIGGER",
82     "CV_CAP_PROP_TRIGGER_DELAY",
83     "CV_CAP_PROP_WHITE_BALANCE_RED_V",
84     "CV_CAP_PROP_MAX_DC1394",
85     "CV_CAP_GSTREAMER_QUEUE_LENGTH",
86     "CV_CAP_PROP_PVAPI_MULTICASTIP",
87     "CV_CAP_PROP_SUPPORTED_PREVIEW_SIZES_STRING",
88     "EVENT_.*",
89     "CV_L?(BGRA?|RGBA?|GRAY|XYZ|YCrCb|Luv|Lab|HLS|YUV|HSV)\d*2L?(BGRA?|RGBA?|GRAY|XYZ|YCrCb|Luv|Lab|HLS|YUV|HSV).*",
90     "CV_COLORCVT_MAX",
91     "CV_.*Bayer.*",
92     "CV_YUV420(i|sp|p)2.+",
93     "CV_TM_.+",
94     "CV_FLOODFILL_.+",
95     "CV_ADAPTIVE_THRESH_.+",
96     "WINDOW_.+",
97     "WND_PROP_.+",
98 )
99
100 const_private_list = (
101     "CV_MOP_.+",
102     "CV_INTER_.+",
103     "CV_THRESH_.+",
104     "CV_INPAINT_.+",
105     "CV_RETR_.+",
106     "CV_CHAIN_APPROX_.+",
107     "OPPONENTEXTRACTOR",
108     "GRIDDETECTOR",
109     "PYRAMIDDETECTOR",
110     "DYNAMICDETECTOR",
111 )
112
113 # { Module : { public : [[name, val],...], private : [[]...] } }
114 missing_consts = \
115 {
116     'Core' :
117     {
118         'private' :
119         (
120             ('CV_8U',  0 ), ('CV_8S',  1 ),
121             ('CV_16U', 2 ), ('CV_16S', 3 ),
122             ('CV_32S', 4 ),
123             ('CV_32F', 5 ), ('CV_64F', 6 ),
124             ('CV_USRTYPE1', 7 ),
125         ), # private
126         'public' :
127         (
128             ('SVD_MODIFY_A', 1), ('SVD_NO_UV', 2), ('SVD_FULL_UV', 4),
129             ('FILLED', -1),
130             ('REDUCE_SUM', 0), ('REDUCE_AVG', 1), ('REDUCE_MAX', 2), ('REDUCE_MIN', 3),
131         ) #public
132     }, # Core
133
134     "Imgproc":
135     {
136         'private' :
137         (
138             ('IPL_BORDER_CONSTANT',    0 ),
139             ('IPL_BORDER_REPLICATE',   1 ),
140             ('IPL_BORDER_REFLECT',     2 ),
141             ('IPL_BORDER_WRAP',        3 ),
142             ('IPL_BORDER_REFLECT_101', 4 ),
143             ('IPL_BORDER_TRANSPARENT', 5 ),
144         ), # private
145         'public' :
146         (
147             ('LINE_AA', 16), ('LINE_8', 8), ('LINE_4', 4),
148         ) #public
149     }, # Imgproc
150
151     "Calib3d":
152     {
153         'private' :
154         (
155             ('CV_LMEDS',  4),
156             ('CV_RANSAC', 8),
157             ('CV_FM_LMEDS', 'CV_LMEDS'),
158             ('CV_FM_RANSAC','CV_RANSAC'),
159             ('CV_FM_7POINT', 1),
160             ('CV_FM_8POINT', 2),
161             ('CV_CALIB_USE_INTRINSIC_GUESS', 1),
162             ('CV_CALIB_FIX_ASPECT_RATIO',    2),
163             ('CV_CALIB_FIX_PRINCIPAL_POINT', 4),
164             ('CV_CALIB_ZERO_TANGENT_DIST',   8),
165             ('CV_CALIB_FIX_FOCAL_LENGTH',   16),
166             ('CV_CALIB_FIX_K1',             32),
167             ('CV_CALIB_FIX_K2',             64),
168             ('CV_CALIB_FIX_K3',            128),
169             ('CV_CALIB_FIX_K4',           2048),
170             ('CV_CALIB_FIX_K5',           4096),
171             ('CV_CALIB_FIX_K6',           8192),
172             ('CV_CALIB_RATIONAL_MODEL',  16384),
173             ('CV_CALIB_THIN_PRISM_MODEL',32768),
174             ('CV_CALIB_FIX_S1_S2_S3_S4', 65536),
175             ('CV_CALIB_FIX_INTRINSIC',     256),
176             ('CV_CALIB_SAME_FOCAL_LENGTH', 512),
177             ('CV_CALIB_ZERO_DISPARITY',   1024),
178         ) # public
179     }, # Calib3d
180
181     "Video":
182     {
183         'private' :
184         (
185             ('CV_LKFLOW_INITIAL_GUESSES',    4 ),
186             ('CV_LKFLOW_GET_MIN_EIGENVALS',  8 ),
187         ) # private
188     }, # Video
189
190 }
191
192
193 # c_type    : { java/jni correspondence }
194 type_dict = {
195 # "simple"  : { j_type : "?", jn_type : "?", jni_type : "?", suffix : "?" },
196     ""        : { "j_type" : "", "jn_type" : "long", "jni_type" : "jlong" }, # c-tor ret_type
197     "void"    : { "j_type" : "void", "jn_type" : "void", "jni_type" : "void" },
198     "env"     : { "j_type" : "", "jn_type" : "", "jni_type" : "JNIEnv*"},
199     "cls"     : { "j_type" : "", "jn_type" : "", "jni_type" : "jclass"},
200     "bool"    : { "j_type" : "boolean", "jn_type" : "boolean", "jni_type" : "jboolean", "suffix" : "Z" },
201     "int"     : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
202     "long"    : { "j_type" : "int", "jn_type" : "int", "jni_type" : "jint", "suffix" : "I" },
203     "float"   : { "j_type" : "float", "jn_type" : "float", "jni_type" : "jfloat", "suffix" : "F" },
204     "double"  : { "j_type" : "double", "jn_type" : "double", "jni_type" : "jdouble", "suffix" : "D" },
205     "size_t"  : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
206     "__int64" : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
207     "int64"   : { "j_type" : "long", "jn_type" : "long", "jni_type" : "jlong", "suffix" : "J" },
208     "double[]": { "j_type" : "double[]", "jn_type" : "double[]", "jni_type" : "jdoubleArray", "suffix" : "_3D" },
209
210 # "complex" : { j_type : "?", jn_args : (("", ""),), jn_name : "", jni_var : "", jni_name : "", "suffix" : "?" },
211
212     "vector_Point"    : { "j_type" : "MatOfPoint", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Point> %(n)s", "suffix" : "J" },
213     "vector_Point2f"  : { "j_type" : "MatOfPoint2f", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Point2f> %(n)s", "suffix" : "J" },
214     #"vector_Point2d"  : { "j_type" : "MatOfPoint2d", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Point2d> %(n)s", "suffix" : "J" },
215     "vector_Point3i"  : { "j_type" : "MatOfPoint3", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Point3i> %(n)s", "suffix" : "J" },
216     "vector_Point3f"  : { "j_type" : "MatOfPoint3f", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Point3f> %(n)s", "suffix" : "J" },
217     #"vector_Point3d"  : { "j_type" : "MatOfPoint3d", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Point3d> %(n)s", "suffix" : "J" },
218     "vector_KeyPoint" : { "j_type" : "MatOfKeyPoint", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<KeyPoint> %(n)s", "suffix" : "J" },
219     "vector_DMatch"   : { "j_type" : "MatOfDMatch", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<DMatch> %(n)s", "suffix" : "J" },
220     "vector_Rect"     : { "j_type" : "MatOfRect",   "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Rect> %(n)s", "suffix" : "J" },
221     "vector_uchar"    : { "j_type" : "MatOfByte",   "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<uchar> %(n)s", "suffix" : "J" },
222     "vector_char"     : { "j_type" : "MatOfByte",   "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<char> %(n)s", "suffix" : "J" },
223     "vector_int"      : { "j_type" : "MatOfInt",    "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<int> %(n)s", "suffix" : "J" },
224     "vector_float"    : { "j_type" : "MatOfFloat",  "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<float> %(n)s", "suffix" : "J" },
225     "vector_double"   : { "j_type" : "MatOfDouble", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<double> %(n)s", "suffix" : "J" },
226     "vector_Vec4i"    : { "j_type" : "MatOfInt4",    "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Vec4i> %(n)s", "suffix" : "J" },
227     "vector_Vec4f"    : { "j_type" : "MatOfFloat4",  "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Vec4f> %(n)s", "suffix" : "J" },
228     "vector_Vec6f"    : { "j_type" : "MatOfFloat6",  "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Vec6f> %(n)s", "suffix" : "J" },
229
230     "vector_Mat"      : { "j_type" : "List<Mat>",   "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector<Mat> %(n)s", "suffix" : "J" },
231
232     "vector_vector_KeyPoint": { "j_type" : "List<MatOfKeyPoint>", "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector< std::vector<KeyPoint> > %(n)s" },
233     "vector_vector_DMatch"  : { "j_type" : "List<MatOfDMatch>",   "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector< std::vector<DMatch> > %(n)s" },
234     "vector_vector_char"    : { "j_type" : "List<MatOfByte>",     "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector< std::vector<char> > %(n)s" },
235     "vector_vector_Point"   : { "j_type" : "List<MatOfPoint>",    "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector< std::vector<Point> > %(n)s" },
236     "vector_vector_Point2f" : { "j_type" : "List<MatOfPoint2f>",    "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector< std::vector<Point2f> > %(n)s" },
237     "vector_vector_Point3f" : { "j_type" : "List<MatOfPoint3f>",    "jn_type" : "long", "jni_type" : "jlong", "jni_var" : "std::vector< std::vector<Point3f> > %(n)s" },
238
239     "Mat"     : { "j_type" : "Mat", "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
240                   "jni_var" : "Mat& %(n)s = *((Mat*)%(n)s_nativeObj)",
241                   "jni_type" : "jlong", #"jni_name" : "*%(n)s",
242                   "suffix" : "J" },
243
244     "Point"   : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
245                   "jni_var" : "Point %(n)s((int)%(n)s_x, (int)%(n)s_y)", "jni_type" : "jdoubleArray",
246                   "suffix" : "DD"},
247     "Point2f" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
248                   "jni_var" : "Point2f %(n)s((float)%(n)s_x, (float)%(n)s_y)", "jni_type" : "jdoubleArray",
249                   "suffix" : "DD"},
250     "Point2d" : { "j_type" : "Point", "jn_args" : (("double", ".x"), ("double", ".y")),
251                   "jni_var" : "Point2d %(n)s(%(n)s_x, %(n)s_y)", "jni_type" : "jdoubleArray",
252                   "suffix" : "DD"},
253     "Point3i" : { "j_type" : "Point3", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
254                   "jni_var" : "Point3i %(n)s((int)%(n)s_x, (int)%(n)s_y, (int)%(n)s_z)", "jni_type" : "jdoubleArray",
255                   "suffix" : "DDD"},
256     "Point3f" : { "j_type" : "Point3", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
257                   "jni_var" : "Point3f %(n)s((float)%(n)s_x, (float)%(n)s_y, (float)%(n)s_z)", "jni_type" : "jdoubleArray",
258                   "suffix" : "DDD"},
259     "Point3d" : { "j_type" : "Point3", "jn_args" : (("double", ".x"), ("double", ".y"), ("double", ".z")),
260                   "jni_var" : "Point3d %(n)s(%(n)s_x, %(n)s_y, %(n)s_z)", "jni_type" : "jdoubleArray",
261                   "suffix" : "DDD"},
262     "KeyPoint": { "j_type" : "KeyPoint", "jn_args" : (("float", ".x"), ("float", ".y"), ("float", ".size"),
263                     ("float", ".angle"), ("float", ".response"), ("int", ".octave"), ("int", ".class_id")),
264                   "jni_var" : "KeyPoint %(n)s(%(n)s_x, %(n)s_y, %(n)s_size, %(n)s_angle, %(n)s_response, %(n)s_octave, %(n)s_class_id)",
265                   "jni_type" : "jdoubleArray",
266                   "suffix" : "FFFFFII"},
267     "DMatch" :  { "j_type" : "DMatch", "jn_args" : ( ('int', 'queryIdx'), ('int', 'trainIdx'),
268                     ('int', 'imgIdx'), ('float', 'distance'), ),
269                   "jni_var" : "DMatch %(n)s(%(n)s_queryIdx, %(n)s_trainIdx, %(n)s_imgIdx, %(n)s_distance)",
270                   "jni_type" : "jdoubleArray",
271                   "suffix" : "IIIF"},
272     "Rect"    : { "j_type" : "Rect",  "jn_args" : (("int", ".x"), ("int", ".y"), ("int", ".width"), ("int", ".height")),
273                   "jni_var" : "Rect %(n)s(%(n)s_x, %(n)s_y, %(n)s_width, %(n)s_height)", "jni_type" : "jdoubleArray",
274                   "suffix" : "IIII"},
275     "Size"    : { "j_type" : "Size",  "jn_args" : (("double", ".width"), ("double", ".height")),
276                   "jni_var" : "Size %(n)s((int)%(n)s_width, (int)%(n)s_height)", "jni_type" : "jdoubleArray",
277                   "suffix" : "DD"},
278     "Size2f"  : { "j_type" : "Size",  "jn_args" : (("double", ".width"), ("double", ".height")),
279                   "jni_var" : "Size2f %(n)s((float)%(n)s_width, (float)%(n)s_height)", "jni_type" : "jdoubleArray",
280                   "suffix" : "DD"},
281  "RotatedRect": { "j_type" : "RotatedRect",  "jn_args" : (("double", ".center.x"), ("double", ".center.y"), ("double", ".size.width"), ("double", ".size.height"), ("double", ".angle")),
282                   "jni_var" : "RotatedRect %(n)s(cv::Point2f(%(n)s_center_x, %(n)s_center_y), cv::Size2f(%(n)s_size_width, %(n)s_size_height), %(n)s_angle)",
283                   "jni_type" : "jdoubleArray", "suffix" : "DDDDD"},
284     "Scalar"  : { "j_type" : "Scalar",  "jn_args" : (("double", ".val[0]"), ("double", ".val[1]"), ("double", ".val[2]"), ("double", ".val[3]")),
285                   "jni_var" : "Scalar %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2, %(n)s_val3)", "jni_type" : "jdoubleArray",
286                   "suffix" : "DDDD"},
287     "Range"   : { "j_type" : "Range",  "jn_args" : (("int", ".start"), ("int", ".end")),
288                   "jni_var" : "Range %(n)s(%(n)s_start, %(n)s_end)", "jni_type" : "jdoubleArray",
289                   "suffix" : "II"},
290     "CvSlice" : { "j_type" : "Range",  "jn_args" : (("int", ".start"), ("int", ".end")),
291                   "jni_var" : "Range %(n)s(%(n)s_start, %(n)s_end)", "jni_type" : "jdoubleArray",
292                   "suffix" : "II"},
293     "String"  : { "j_type" : "String",  "jn_type" : "String",
294                   "jni_type" : "jstring", "jni_name" : "n_%(n)s",
295                   "jni_var" : 'const char* utf_%(n)s = env->GetStringUTFChars(%(n)s, 0); String n_%(n)s( utf_%(n)s ? utf_%(n)s : "" ); env->ReleaseStringUTFChars(%(n)s, utf_%(n)s)',
296                   "suffix" : "Ljava_lang_String_2"},
297     "c_string": { "j_type" : "String",  "jn_type" : "String",
298                   "jni_type" : "jstring", "jni_name" : "n_%(n)s.c_str()",
299                   "jni_var" : 'const char* utf_%(n)s = env->GetStringUTFChars(%(n)s, 0); String n_%(n)s( utf_%(n)s ? utf_%(n)s : "" ); env->ReleaseStringUTFChars(%(n)s, utf_%(n)s)',
300                   "suffix" : "Ljava_lang_String_2"},
301 "TermCriteria": { "j_type" : "TermCriteria",  "jn_args" : (("int", ".type"), ("int", ".maxCount"), ("double", ".epsilon")),
302                   "jni_var" : "TermCriteria %(n)s(%(n)s_type, %(n)s_maxCount, %(n)s_epsilon)", "jni_type" : "jdoubleArray",
303                   "suffix" : "IID"},
304 "CvTermCriteria": { "j_type" : "TermCriteria",  "jn_args" : (("int", ".type"), ("int", ".maxCount"), ("double", ".epsilon")),
305                   "jni_var" : "TermCriteria %(n)s(%(n)s_type, %(n)s_maxCount, %(n)s_epsilon)", "jni_type" : "jdoubleArray",
306                   "suffix" : "IID"},
307     "Vec2d"   : { "j_type" : "double[]",  "jn_args" : (("double", ".val[0]"), ("double", ".val[1]")),
308                   "jn_type" : "double[]",
309                   "jni_var" : "Vec2d %(n)s(%(n)s_val0, %(n)s_val1)", "jni_type" : "jdoubleArray",
310                   "suffix" : "DD"},
311     "Vec3d"   : { "j_type" : "double[]",  "jn_args" : (("double", ".val[0]"), ("double", ".val[1]"), ("double", ".val[2]")),
312                   "jn_type" : "double[]",
313                   "jni_var" : "Vec3d %(n)s(%(n)s_val0, %(n)s_val1, %(n)s_val2)", "jni_type" : "jdoubleArray",
314                   "suffix" : "DDD"},
315
316 }
317
318 # { class : { func : {j_code, jn_code, cpp_code} } }
319 ManualFuncs = {
320     'Core' :
321     {
322         'minMaxLoc' : {
323             'j_code'   : """
324     // manual port
325     public static class MinMaxLocResult {
326         public double minVal;
327         public double maxVal;
328         public Point minLoc;
329         public Point maxLoc;
330
331         public MinMaxLocResult() {
332             minVal=0; maxVal=0;
333             minLoc=new Point();
334             maxLoc=new Point();
335         }
336     }
337
338     // C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
339
340     //javadoc: minMaxLoc(src, mask)
341     public static MinMaxLocResult minMaxLoc(Mat src, Mat mask) {
342         MinMaxLocResult res = new MinMaxLocResult();
343         long maskNativeObj=0;
344         if (mask != null) {
345             maskNativeObj=mask.nativeObj;
346         }
347         double resarr[] = n_minMaxLocManual(src.nativeObj, maskNativeObj);
348         res.minVal=resarr[0];
349         res.maxVal=resarr[1];
350         res.minLoc.x=resarr[2];
351         res.minLoc.y=resarr[3];
352         res.maxLoc.x=resarr[4];
353         res.maxLoc.y=resarr[5];
354         return res;
355     }
356
357     //javadoc: minMaxLoc(src)
358     public static MinMaxLocResult minMaxLoc(Mat src) {
359         return minMaxLoc(src, null);
360     }
361
362 """,
363             'jn_code'  :
364 """    private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj);\n""",
365             'cpp_code' :
366 """
367 // C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
368 JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1minMaxLocManual (JNIEnv*, jclass, jlong, jlong);
369
370 JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1minMaxLocManual
371   (JNIEnv* env, jclass, jlong src_nativeObj, jlong mask_nativeObj)
372 {
373     try {
374         LOGD("Core::n_1minMaxLoc()");
375         jdoubleArray result;
376         result = env->NewDoubleArray(6);
377         if (result == NULL) {
378             return NULL; /* out of memory error thrown */
379         }
380
381         Mat& src = *((Mat*)src_nativeObj);
382
383         double minVal, maxVal;
384         Point minLoc, maxLoc;
385         if (mask_nativeObj != 0) {
386             Mat& mask = *((Mat*)mask_nativeObj);
387             minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc, mask);
388         } else {
389             minMaxLoc(src, &minVal, &maxVal, &minLoc, &maxLoc);
390         }
391
392         jdouble fill[6];
393         fill[0]=minVal;
394         fill[1]=maxVal;
395         fill[2]=minLoc.x;
396         fill[3]=minLoc.y;
397         fill[4]=maxLoc.x;
398         fill[5]=maxLoc.y;
399
400         env->SetDoubleArrayRegion(result, 0, 6, fill);
401
402     return result;
403
404     } catch(const cv::Exception& e) {
405         LOGD("Core::n_1minMaxLoc() catched cv::Exception: %s", e.what());
406         jclass je = env->FindClass("org/opencv/core/CvException");
407         if(!je) je = env->FindClass("java/lang/Exception");
408         env->ThrowNew(je, e.what());
409         return NULL;
410     } catch (...) {
411         LOGD("Core::n_1minMaxLoc() catched unknown exception (...)");
412         jclass je = env->FindClass("java/lang/Exception");
413         env->ThrowNew(je, "Unknown exception in JNI code {core::minMaxLoc()}");
414         return NULL;
415     }
416 }
417
418 """,
419         }, # minMaxLoc
420
421
422 ##        "checkRange"           : #TBD
423 ##            {'j_code' : '/* TBD: checkRange() */', 'jn_code' : '', 'cpp_code' : '' },
424
425         "checkHardwareSupport" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
426         "setUseOptimized"      : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
427         "useOptimized"         : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
428
429     }, # Core
430
431     'Imgproc' :
432     {
433         'getTextSize' :
434         {
435             'j_code'   :
436     """
437     // C++: Size getTextSize(const String& text, int fontFace, double fontScale, int thickness, int* baseLine);
438     //javadoc:getTextSize(text, fontFace, fontScale, thickness, baseLine)
439     public static Size getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine) {
440         if(baseLine != null && baseLine.length != 1)
441             throw new java.lang.IllegalArgumentException("'baseLine' must be 'int[1]' or 'null'.");
442         Size retVal = new Size(n_getTextSize(text, fontFace, fontScale, thickness, baseLine));
443         return retVal;
444     }
445     """,
446             'jn_code'  :
447     """    private static native double[] n_getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine);\n""",
448             'cpp_code' :
449     """
450     // C++: Size getTextSize(const String& text, int fontFace, double fontScale, int thickness, int* baseLine);
451     JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize (JNIEnv*, jclass, jstring, jint, jdouble, jint, jintArray);
452
453     JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_Core_n_1getTextSize
454     (JNIEnv* env, jclass, jstring text, jint fontFace, jdouble fontScale, jint thickness, jintArray baseLine)
455     {
456     try {
457         LOGD("Core::n_1getTextSize()");
458         jdoubleArray result;
459         result = env->NewDoubleArray(2);
460         if (result == NULL) {
461             return NULL; /* out of memory error thrown */
462         }
463
464         const char* utf_text = env->GetStringUTFChars(text, 0);
465         String n_text( utf_text ? utf_text : "" );
466         env->ReleaseStringUTFChars(text, utf_text);
467
468         int _baseLine;
469         int* pbaseLine = 0;
470
471         if (baseLine != NULL)
472             pbaseLine = &_baseLine;
473
474         cv::Size rsize = cv::getTextSize(n_text, (int)fontFace, (double)fontScale, (int)thickness, pbaseLine);
475
476         jdouble fill[2];
477         fill[0]=rsize.width;
478         fill[1]=rsize.height;
479
480         env->SetDoubleArrayRegion(result, 0, 2, fill);
481
482         if (baseLine != NULL) {
483             jint jbaseLine = (jint)(*pbaseLine);
484             env->SetIntArrayRegion(baseLine, 0, 1, &jbaseLine);
485         }
486
487         return result;
488
489     } catch(const cv::Exception& e) {
490         LOGD("Core::n_1getTextSize() catched cv::Exception: %s", e.what());
491         jclass je = env->FindClass("org/opencv/core/CvException");
492         if(!je) je = env->FindClass("java/lang/Exception");
493         env->ThrowNew(je, e.what());
494         return NULL;
495     } catch (...) {
496         LOGD("Core::n_1getTextSize() catched unknown exception (...)");
497         jclass je = env->FindClass("java/lang/Exception");
498         env->ThrowNew(je, "Unknown exception in JNI code {core::getTextSize()}");
499         return NULL;
500     }
501     }
502     """,
503         }, # getTextSize
504
505     }, # Imgproc
506
507     'Highgui' :
508     {
509         "namedWindow"       : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
510         "destroyWindow"     : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
511         "destroyAllWindows" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
512         "startWindowThread" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
513         "setWindowProperty" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
514         "getWindowProperty" : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
515         "getTrackbarPos"    : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
516         "setTrackbarPos"    : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
517         "imshow"            : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
518         "waitKey"           : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
519         "moveWindow"        : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
520         "resizeWindow"      : {'j_code' : '', 'jn_code' : '', 'cpp_code' : '' },
521     }, # Highgui
522
523     'VideoCapture' :
524     {
525         "getSupportedPreviewSizes" :
526         {
527             'j_code' :
528 """
529     public java.util.List<org.opencv.core.Size> getSupportedPreviewSizes()
530     {
531         String[] sizes_str = getSupportedPreviewSizes_0(nativeObj).split(",");
532         java.util.List<org.opencv.core.Size> sizes = new java.util.ArrayList<org.opencv.core.Size>(sizes_str.length);
533
534         for (String str : sizes_str) {
535             String[] wh = str.split("x");
536             sizes.add(new org.opencv.core.Size(Double.parseDouble(wh[0]), Double.parseDouble(wh[1])));
537         }
538
539         return sizes;
540     }
541
542 """,
543             'jn_code' :
544 """\n    private static native String getSupportedPreviewSizes_0(long nativeObj);\n""",
545             'cpp_code' :
546 """
547 JNIEXPORT jstring JNICALL Java_org_opencv_videoio_VideoCapture_getSupportedPreviewSizes_10
548   (JNIEnv *env, jclass, jlong self);
549
550 JNIEXPORT jstring JNICALL Java_org_opencv_videoio_VideoCapture_getSupportedPreviewSizes_10
551   (JNIEnv *env, jclass, jlong self)
552 {
553     static const char method_name[] = "videoio::VideoCapture_getSupportedPreviewSizes_10()";
554     try {
555         LOGD("%s", method_name);
556         VideoCapture* me = (VideoCapture*) self; //TODO: check for NULL
557         union {double prop; const char* name;} u;
558         u.prop = me->get(CAP_PROP_ANDROID_PREVIEW_SIZES_STRING);
559         return env->NewStringUTF(u.name);
560     } catch(const std::exception &e) {
561         throwJavaException(env, &e, method_name);
562     } catch (...) {
563         throwJavaException(env, 0, method_name);
564     }
565     return env->NewStringUTF("");
566 }
567
568 """,
569         }, # getSupportedPreviewSizes
570     }, # VideoCapture
571 }
572
573 # { class : { func : { arg_name : {"ctype" : ctype, "attrib" : [attrib]} } } }
574 func_arg_fix = {
575     '' : {
576         'randu'    : { 'low'  : {"ctype" : 'double'},
577                        'high' : {"ctype"    : 'double'} },
578         'randn'    : { 'mean'   : {"ctype" : 'double'},
579                        'stddev' : {"ctype"  : 'double'} },
580         'inRange'  : { 'lowerb' : {"ctype" : 'Scalar'},
581                        'upperb' : {"ctype" : 'Scalar'} },
582         'goodFeaturesToTrack' : { 'corners' : {"ctype" : 'vector_Point'} },
583         'findFundamentalMat'  : { 'points1' : {"ctype" : 'vector_Point2f'},
584                                   'points2' : {"ctype" : 'vector_Point2f'} },
585         'cornerSubPix' : { 'corners' : {"ctype" : 'vector_Point2f'} },
586         'minEnclosingCircle' : { 'points' : {"ctype" : 'vector_Point2f'} },
587         'findHomography' : { 'srcPoints' : {"ctype" : 'vector_Point2f'},
588                              'dstPoints' : {"ctype" : 'vector_Point2f'} },
589         'solvePnP' : { 'objectPoints' : {"ctype" : 'vector_Point3f'},
590                       'imagePoints'   : {"ctype" : 'vector_Point2f'},
591                       'distCoeffs'    : {"ctype" : 'vector_double' } },
592         'solvePnPRansac' : { 'objectPoints' : {"ctype" : 'vector_Point3f'},
593                              'imagePoints'  : {"ctype" : 'vector_Point2f'},
594                              'distCoeffs'   : {"ctype" : 'vector_double' } },
595         'calcOpticalFlowPyrLK' : { 'prevPts' : {"ctype" : 'vector_Point2f'},
596                                    'nextPts' : {"ctype" : 'vector_Point2f'},
597                                    'status'  : {"ctype" : 'vector_uchar'},
598                                    'err'     : {"ctype" : 'vector_float'} },
599         'fitEllipse' : { 'points' : {"ctype" : 'vector_Point2f'} },
600         'fillPoly'   : { 'pts' : {"ctype" : 'vector_vector_Point'} },
601         'polylines'  : { 'pts' : {"ctype" : 'vector_vector_Point'} },
602         'fillConvexPoly' : { 'points' : {"ctype" : 'vector_Point'} },
603         'boundingRect'   : { 'points' : {"ctype" : 'vector_Point'} },
604         'approxPolyDP' : { 'curve'       : {"ctype" : 'vector_Point2f'},
605                            'approxCurve' : {"ctype" : 'vector_Point2f'} },
606         'arcLength' : { 'curve' : {"ctype" : 'vector_Point2f'} },
607         'pointPolygonTest' : { 'contour' : {"ctype" : 'vector_Point2f'} },
608         'minAreaRect' : { 'points' : {"ctype" : 'vector_Point2f'} },
609         'getAffineTransform' : { 'src' : {"ctype" : 'vector_Point2f'},
610                                  'dst' : {"ctype" : 'vector_Point2f'} },
611         'hconcat' : { 'src' : {"ctype" : 'vector_Mat'} },
612         'vconcat' : { 'src' : {"ctype" : 'vector_Mat'} },
613         'undistortPoints' : { 'src' : {"ctype" : 'vector_Point2f'},
614                               'dst' : {"ctype" : 'vector_Point2f'} },
615         'checkRange' : {'pos' : {"ctype" : '*'} },
616         'meanStdDev' : { 'mean'   : {"ctype" : 'vector_double'},
617                          'stddev' : {"ctype" : 'vector_double'} },
618         'drawContours' : {'contours' : {"ctype" : 'vector_vector_Point'} },
619         'findContours' : {'contours' : {"ctype" : 'vector_vector_Point'} },
620         'convexityDefects' : { 'contour'          : {"ctype" : 'vector_Point'},
621                                'convexhull'       : {"ctype" : 'vector_int'},
622                                'convexityDefects' : {"ctype" : 'vector_Vec4i'} },
623         'isContourConvex' : { 'contour' : {"ctype" : 'vector_Point'} },
624         'convexHull' : { 'points' : {"ctype" : 'vector_Point'},
625                          'hull'   : {"ctype" : 'vector_int'},
626                          'returnPoints' : {"ctype" : ''} },
627         'projectPoints' : { 'objectPoints' : {"ctype" : 'vector_Point3f'},
628                             'imagePoints'  : {"ctype" : 'vector_Point2f'},
629                             'distCoeffs'   : {"ctype" : 'vector_double' } },
630         'initCameraMatrix2D' : { 'objectPoints' : {"ctype" : 'vector_vector_Point3f'},
631                                  'imagePoints'  : {"ctype" : 'vector_vector_Point2f'} },
632         'findChessboardCorners' : { 'corners' : {"ctype" : 'vector_Point2f'} },
633         'drawChessboardCorners' : { 'corners' : {"ctype" : 'vector_Point2f'} },
634         'mixChannels' : { 'dst' : {"attrib" : []} },
635     }, # '', i.e. no class
636 } # func_arg_fix
637
638
639 def getLibVersion(version_hpp_path):
640     version_file = open(version_hpp_path, "rt").read()
641     major = re.search("^W*#\W*define\W+CV_VERSION_MAJOR\W+(\d+)\W*$", version_file, re.MULTILINE).group(1)
642     minor = re.search("^W*#\W*define\W+CV_VERSION_MINOR\W+(\d+)\W*$", version_file, re.MULTILINE).group(1)
643     revision = re.search("^W*#\W*define\W+CV_VERSION_REVISION\W+(\d+)\W*$", version_file, re.MULTILINE).group(1)
644     status = re.search("^W*#\W*define\W+CV_VERSION_STATUS\W+\"(.*?)\"\W*$", version_file, re.MULTILINE).group(1)
645     return (major, minor, revision, status)
646
647 class ConstInfo(object):
648     def __init__(self, cname, name, val, addedManually=False):
649         self.cname = cname
650         self.name = re.sub(r"^Cv", "", name)
651         self.value = val
652         self.addedManually = addedManually
653
654
655 class ClassPropInfo(object):
656     def __init__(self, decl): # [f_ctype, f_name, '', '/RW']
657         self.ctype = decl[0]
658         self.name = decl[1]
659         self.rw = "/RW" in decl[3]
660
661 class ClassInfo(object):
662     def __init__(self, decl): # [ 'class/struct cname', ': base', [modlist] ]
663         name = decl[0]
664         name = name[name.find(" ")+1:].strip()
665         self.cname = self.name = self.jname = re.sub(r"^cv\.", "", name)
666         self.cname = self.cname.replace(".", "::")
667         self.methods = {}
668         self.methods_suffixes = {}
669         self.consts = [] # using a list to save the occurence order
670         self.private_consts = []
671         self.imports = set()
672         self.props= []
673         self.jname = self.name
674         for m in decl[2]:
675             if m.startswith("="):
676                 self.jname = m[1:]
677         self.base = ''
678         if decl[1]:
679             #self.base = re.sub(r"\b"+self.jname+r"\b", "", decl[1].replace(":", "")).strip()
680             self.base = re.sub(r"^.*:", "", decl[1].split(",")[0]).strip().replace(self.jname, "")
681
682 class ArgInfo(object):
683     def __init__(self, arg_tuple): # [ ctype, name, def val, [mod], argno ]
684         self.pointer = False
685         ctype = arg_tuple[0]
686         if ctype.endswith("*"):
687             ctype = ctype[:-1]
688             self.pointer = True
689         if ctype == 'vector_Point2d':
690             ctype = 'vector_Point2f'
691         elif ctype == 'vector_Point3d':
692             ctype = 'vector_Point3f'
693         self.ctype = ctype
694         self.name = arg_tuple[1]
695         self.defval = arg_tuple[2]
696         self.out = ""
697         if "/O" in arg_tuple[3]:
698             self.out = "O"
699         if "/IO" in arg_tuple[3]:
700             self.out = "IO"
701
702
703 class FuncInfo(object):
704     def __init__(self, decl): # [ funcname, return_ctype, [modifiers], [args] ]
705         name = re.sub(r"^cv\.", "", decl[0])
706         self.cname = name.replace(".", "::")
707         classname = ""
708         dpos = name.rfind(".")
709         if dpos >= 0:
710             classname = name[:dpos]
711             name = name[dpos+1:]
712         self.classname = classname
713         self.jname = self.name = name
714         if "[" in name:
715             self.jname = "getelem"
716         for m in decl[2]:
717             if m.startswith("="):
718                 self.jname = m[1:]
719         self.static = ["","static"][ "/S" in decl[2] ]
720         self.ctype = re.sub(r"^CvTermCriteria", "TermCriteria", decl[1] or "")
721         self.args = []
722         func_fix_map = func_arg_fix.get(classname, {}).get(self.jname, {})
723         for a in decl[3]:
724             arg = a[:]
725             arg_fix_map = func_fix_map.get(arg[1], {})
726             arg[0] = arg_fix_map.get('ctype',  arg[0]) #fixing arg type
727             arg[3] = arg_fix_map.get('attrib', arg[3]) #fixing arg attrib
728             ai = ArgInfo(arg)
729             self.args.append(ai)
730
731
732
733 class FuncFamilyInfo(object):
734     def __init__(self, decl): # [ funcname, return_ctype, [modifiers], [args] ]
735         self.funcs = []
736         self.funcs.append( FuncInfo(decl) )
737         self.jname = self.funcs[0].jname
738         self.isconstructor = self.funcs[0].name == self.funcs[0].classname
739
740
741
742     def add_func(self, fi):
743         self.funcs.append( fi )
744
745
746 class JavaWrapperGenerator(object):
747     def __init__(self):
748         self.clear()
749
750     def clear(self):
751         self.classes = { "Mat" : ClassInfo([ 'class Mat', '', [], [] ]) }
752         self.module = ""
753         self.Module = ""
754         self.java_code= {} # { class : {j_code, jn_code} }
755         self.cpp_code = None
756         self.ported_func_list = []
757         self.skipped_func_list = []
758         self.def_args_hist = {} # { def_args_cnt : funcs_cnt }
759         self.classes_map = []
760         self.classes_simple = []
761
762     def add_class_code_stream(self, class_name, cls_base = ''):
763         jname = self.classes[class_name].jname
764         self.java_code[class_name] = { "j_code" : StringIO(), "jn_code" : StringIO(), }
765         if class_name != self.Module:
766             if cls_base:
767                 self.java_code[class_name]["j_code"].write("""
768 //
769 // This file is auto-generated. Please don't modify it!
770 //
771 package org.opencv.%(m)s;
772
773 $imports
774
775 // C++: class %(c)s
776 //javadoc: %(c)s
777 public class %(jc)s extends %(base)s {
778
779     protected %(jc)s(long addr) { super(addr); }
780
781 """ % { 'm' : self.module, 'c' : class_name, 'jc' : jname, 'base' :  cls_base })
782             else: # not cls_base
783                 self.java_code[class_name]["j_code"].write("""
784 //
785 // This file is auto-generated. Please don't modify it!
786 //
787 package org.opencv.%(m)s;
788
789 $imports
790
791 // C++: class %(c)s
792 //javadoc: %(c)s
793 public class %(jc)s {
794
795     protected final long nativeObj;
796     protected %(jc)s(long addr) { nativeObj = addr; }
797
798 """ % { 'm' : self.module, 'c' : class_name, 'jc' : jname })
799         else: # class_name == self.Module
800             self.java_code[class_name]["j_code"].write("""
801 //
802 // This file is auto-generated. Please don't modify it!
803 //
804 package org.opencv.%(m)s;
805
806 $imports
807
808 public class %(jc)s {
809 """ % { 'm' : self.module, 'jc' : jname } )
810
811         if class_name == 'Core':
812             (major, minor, revision, status) = getLibVersion(
813                 (os.path.dirname(__file__) or '.') + '/../../core/include/opencv2/core/version.hpp')
814             version_str    = '.'.join( (major, minor, revision) ) + status
815             version_suffix =  ''.join( (major, minor, revision) )
816             self.classes[class_name].imports.add("java.lang.String")
817             self.java_code[class_name]["j_code"].write("""
818     // these constants are wrapped inside functions to prevent inlining
819     private static String getVersion() { return "%(v)s"; }
820     private static String getNativeLibraryName() { return "opencv_java%(vs)s"; }
821     private static int getVersionMajor() { return %(ma)s; }
822     private static int getVersionMinor() { return %(mi)s; }
823     private static int getVersionRevision() { return %(re)s; }
824     private static String getVersionStatus() { return "%(st)s"; }
825
826     public static final String VERSION = getVersion();
827     public static final String NATIVE_LIBRARY_NAME = getNativeLibraryName();
828     public static final int VERSION_MAJOR = getVersionMajor();
829     public static final int VERSION_MINOR = getVersionMinor();
830     public static final int VERSION_REVISION = getVersionRevision();
831     public static final String VERSION_STATUS = getVersionStatus();
832 """ % { 'v' : version_str, 'vs' : version_suffix, 'ma' : major, 'mi' : minor, 're' : revision, 'st': status } )
833
834
835     def add_class(self, decl):
836         classinfo = ClassInfo(decl)
837         if classinfo.name in class_ignore_list:
838             return
839         name = classinfo.name
840         if name in self.classes:
841             print "Generator error: class %s (%s) is duplicated" % \
842                     (name, classinfo.cname)
843             return
844         self.classes[name] = classinfo
845         if name in type_dict:
846             print "Duplicated class: " + name
847             return
848         if '/Simple' in decl[2]:
849             self.classes_simple.append(name)
850         if ('/Map' in decl[2]):
851             self.classes_map.append(name)
852             #adding default c-tor
853             ffi = FuncFamilyInfo(['cv.'+name+'.'+name, '', [], []])
854             classinfo.methods[ffi.jname] = ffi
855         type_dict[name] = \
856             { "j_type" : classinfo.jname,
857               "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
858               "jni_name" : "(*("+name+"*)%(n)s_nativeObj)", "jni_type" : "jlong",
859               "suffix" : "J" }
860         type_dict[name+'*'] = \
861             { "j_type" : classinfo.jname,
862               "jn_type" : "long", "jn_args" : (("__int64", ".nativeObj"),),
863               "jni_name" : "("+name+"*)%(n)s_nativeObj", "jni_type" : "jlong",
864               "suffix" : "J" }
865
866         # missing_consts { Module : { public : [[name, val],...], private : [[]...] } }
867         if name in missing_consts:
868             if 'private' in missing_consts[name]:
869                 for (n, val) in missing_consts[name]['private']:
870                     classinfo.private_consts.append( ConstInfo(n, n, val, True) )
871             if 'public' in missing_consts[name]:
872                 for (n, val) in missing_consts[name]['public']:
873                     classinfo.consts.append( ConstInfo(n, n, val, True) )
874
875         # class props
876         for p in decl[3]:
877             if True: #"vector" not in p[0]:
878                 classinfo.props.append( ClassPropInfo(p) )
879             else:
880                 print "Skipped property: [%s]" % name, p
881
882         self.add_class_code_stream(name, classinfo.base)
883         if classinfo.base:
884             self.get_imports(name, classinfo.base)
885
886
887     def add_const(self, decl): # [ "const cname", val, [], [] ]
888         name = decl[0].replace("const ", "").strip()
889         name = re.sub(r"^cv\.", "", name)
890         cname = name.replace(".", "::")
891         for c in const_ignore_list:
892             if re.match(c, name):
893                 return
894         # class member?
895         dpos = name.rfind(".")
896         if dpos >= 0:
897             classname = name[:dpos]
898             name = name[dpos+1:]
899         else:
900             classname = self.Module
901         if classname not in self.classes:
902             # this class isn't wrapped
903             # skipping this const
904             return
905
906         consts = self.classes[classname].consts
907         for c in const_private_list:
908             if re.match(c, name):
909                 consts = self.classes[classname].private_consts
910                 break
911
912         constinfo = ConstInfo(cname, name, decl[1])
913         # checking duplication
914         for list in self.classes[classname].consts, self.classes[classname].private_consts:
915             for c in list:
916                 if c.name == constinfo.name:
917                     if c.addedManually:
918                         return
919                     print "Generator error: constant %s (%s) is duplicated" \
920                             % (constinfo.name, constinfo.cname)
921                     sys.exit(-1)
922
923         consts.append(constinfo)
924
925     def add_func(self, decl):
926         ffi = FuncFamilyInfo(decl)
927         classname = ffi.funcs[0].classname or self.Module
928         if classname in class_ignore_list:
929             return
930         if classname in ManualFuncs and ffi.jname in ManualFuncs[classname]:
931             return
932         if classname not in self.classes:
933             print "Generator error: the class %s for method %s is missing" % \
934                     (classname, ffi.jname)
935             sys.exit(-1)
936         func_map = self.classes[classname].methods
937         if ffi.jname in func_map:
938             func_map[ffi.jname].add_func(ffi.funcs[0])
939         else:
940             func_map[ffi.jname] = ffi
941         # calc args with def val
942         cnt = len([a for a in ffi.funcs[0].args if a.defval])
943         self.def_args_hist[cnt] = self.def_args_hist.get(cnt, 0) + 1
944
945     def save(self, path, buf):
946         f = open(path, "wt")
947         f.write(buf)
948         f.close()
949
950     def gen(self, srcfiles, module, output_path):
951         self.clear()
952         self.module = module
953         self.Module = module.capitalize()
954         parser = hdr_parser.CppHeaderParser()
955
956         self.add_class( ['class ' + self.Module, '', [], []] ) # [ 'class/struct cname', ':bases', [modlist] [props] ]
957
958         # scan the headers and build more descriptive maps of classes, consts, functions
959         for hdr in srcfiles:
960             decls = parser.parse(hdr)
961             for decl in decls:
962                 name = decl[0]
963                 if name.startswith("struct") or name.startswith("class"):
964                     self.add_class(decl)
965                 elif name.startswith("const"):
966                     self.add_const(decl)
967                 else: # function
968                     self.add_func(decl)
969
970         self.cpp_code = StringIO()
971         self.cpp_code.write(Template("""
972 //
973 // This file is auto-generated, please don't edit!
974 //
975
976 #define LOG_TAG "org.opencv.$m"
977
978 #include "common.h"
979
980 #include "opencv2/opencv_modules.hpp"
981 #ifdef HAVE_OPENCV_$M
982
983 #include <string>
984
985 #include "opencv2/$m.hpp"
986
987 using namespace cv;
988
989 /// throw java exception
990 static void throwJavaException(JNIEnv *env, const std::exception *e, const char *method) {
991   std::string what = "unknown exception";
992   jclass je = 0;
993
994   if(e) {
995     std::string exception_type = "std::exception";
996
997     if(dynamic_cast<const cv::Exception*>(e)) {
998       exception_type = "cv::Exception";
999       je = env->FindClass("org/opencv/core/CvException");
1000     }
1001
1002     what = exception_type + ": " + e->what();
1003   }
1004
1005   if(!je) je = env->FindClass("java/lang/Exception");
1006   env->ThrowNew(je, what.c_str());
1007
1008   LOGE("%s caught %s", method, what.c_str());
1009   (void)method;        // avoid "unused" warning
1010 }
1011
1012
1013 extern "C" {
1014
1015 """).substitute( m = module, M = module.upper() ) )
1016
1017         # generate code for the classes
1018         for name in self.classes.keys():
1019             if name == "Mat":
1020                 continue
1021             self.gen_class(name)
1022             # saving code streams
1023             imports = "\n".join([ "import %s;" % c for c in \
1024                 sorted(self.classes[name].imports) if not c.startswith('org.opencv.'+self.module) ])
1025             self.java_code[name]["j_code"].write("\n\n%s\n}\n" % self.java_code[name]["jn_code"].getvalue())
1026             java_code = self.java_code[name]["j_code"].getvalue()
1027             java_code = Template(java_code).substitute(imports = imports)
1028             self.save("%s/%s+%s.java" % (output_path, module, self.classes[name].jname), java_code)
1029
1030         self.cpp_code.write( '\n} // extern "C"\n\n#endif // HAVE_OPENCV_%s\n' % module.upper() )
1031         self.save(output_path+"/"+module+".cpp",  self.cpp_code.getvalue())
1032
1033         # report
1034         report = StringIO()
1035         report.write("PORTED FUNCs LIST (%i of %i):\n\n" % \
1036             (len(self.ported_func_list), len(self.ported_func_list)+ len(self.skipped_func_list))
1037         )
1038         report.write("\n".join(self.ported_func_list))
1039         report.write("\n\nSKIPPED FUNCs LIST (%i of %i):\n\n" % \
1040             (len(self.skipped_func_list), len(self.ported_func_list)+ len(self.skipped_func_list))
1041         )
1042         report.write("".join(self.skipped_func_list))
1043
1044         for i in self.def_args_hist.keys():
1045             report.write("\n%i def args - %i funcs" % (i, self.def_args_hist[i]))
1046
1047         report.write("\n\nclass as MAP:\n\t" + "\n\t".join(self.classes_map))
1048         report.write("\n\nclass SIMPLE:\n\t" + "\n\t".join(self.classes_simple))
1049
1050         self.save(output_path+"/"+module+".txt", report.getvalue())
1051
1052         #print "Done %i of %i funcs." % (len(self.ported_func_list), len(self.ported_func_list)+ len(self.skipped_func_list))
1053
1054
1055
1056     def get_imports(self, scope_classname, ctype):
1057         imports = self.classes[scope_classname or self.Module].imports
1058         if ctype.startswith('vector_vector'):
1059             imports.add("org.opencv.core.Mat")
1060             imports.add("java.util.List")
1061             imports.add("org.opencv.utils.Converters")
1062             self.get_imports(scope_classname, ctype.replace('vector_vector', 'vector'))
1063             return
1064         if ctype.startswith('vector'):
1065             imports.add("org.opencv.core.Mat")
1066             if type_dict[ctype]['j_type'].startswith('MatOf'):
1067                 imports.add("org.opencv.core." + type_dict[ctype]['j_type'])
1068                 return
1069             else:
1070                 imports.add("java.util.List")
1071                 imports.add("org.opencv.utils.Converters")
1072                 self.get_imports(scope_classname, ctype.replace('vector_', ''))
1073                 return
1074         j_type = ''
1075         if ctype in type_dict:
1076             j_type = type_dict[ctype]['j_type']
1077         elif ctype in ("Algorithm"):
1078             j_type = ctype
1079         if j_type in ( "CvType", "Mat", "Point", "Point3", "Range", "Rect", "RotatedRect", "Scalar", "Size", "TermCriteria", "Algorithm" ):
1080             imports.add("org.opencv.core." + j_type)
1081         if j_type == 'String':
1082             imports.add("java.lang.String")
1083         return
1084
1085
1086
1087     def gen_func(self, fi, prop_name=''):
1088         j_code   = self.java_code[fi.classname or self.Module]["j_code"]
1089         jn_code  = self.java_code[fi.classname or self.Module]["jn_code"]
1090         cpp_code = self.cpp_code
1091
1092         # c_decl
1093         # e.g: void add(Mat src1, Mat src2, Mat dst, Mat mask = Mat(), int dtype = -1)
1094         if prop_name:
1095             c_decl = "%s %s::%s" % (fi.ctype, fi.classname, prop_name)
1096         else:
1097             decl_args = []
1098             for a in fi.args:
1099                 s = a.ctype or ' _hidden_ '
1100                 if a.pointer:
1101                     s += "*"
1102                 elif a.out:
1103                     s += "&"
1104                 s += " " + a.name
1105                 if a.defval:
1106                     s += " = "+a.defval
1107                 decl_args.append(s)
1108             c_decl = "%s %s %s(%s)" % ( fi.static, fi.ctype, fi.cname, ", ".join(decl_args) )
1109
1110         # java comment
1111         j_code.write( "\n    //\n    // C++: %s\n    //\n\n" % c_decl )
1112         # check if we 'know' all the types
1113         if fi.ctype not in type_dict: # unsupported ret type
1114             msg = "// Return type '%s' is not supported, skipping the function\n\n" % fi.ctype
1115             self.skipped_func_list.append(c_decl + "\n" + msg)
1116             j_code.write( " "*4 + msg )
1117             print "SKIP:", c_decl.strip(), "\t due to RET type", fi.ctype
1118             return
1119         for a in fi.args:
1120             if a.ctype not in type_dict:
1121                 if not a.defval and a.ctype.endswith("*"):
1122                     a.defval = 0
1123                 if a.defval:
1124                     a.ctype = ''
1125                     continue
1126                 msg = "// Unknown type '%s' (%s), skipping the function\n\n" % (a.ctype, a.out or "I")
1127                 self.skipped_func_list.append(c_decl + "\n" + msg)
1128                 j_code.write( " "*4 + msg )
1129                 print "SKIP:", c_decl.strip(), "\t due to ARG type", a.ctype, "/" + (a.out or "I")
1130                 return
1131
1132         self.ported_func_list.append(c_decl)
1133
1134         # jn & cpp comment
1135         jn_code.write( "\n    // C++: %s\n" % c_decl )
1136         cpp_code.write( "\n//\n// %s\n//\n" % c_decl )
1137
1138         # java args
1139         args = fi.args[:] # copy
1140         suffix_counter = int( self.classes[fi.classname or self.Module].methods_suffixes.get(fi.jname, -1) )
1141         while True:
1142             suffix_counter += 1
1143             self.classes[fi.classname or self.Module].methods_suffixes[fi.jname] = suffix_counter
1144              # java native method args
1145             jn_args = []
1146             # jni (cpp) function args
1147             jni_args = [ArgInfo([ "env", "env", "", [], "" ]), ArgInfo([ "cls", "", "", [], "" ])]
1148             j_prologue = []
1149             j_epilogue = []
1150             c_prologue = []
1151             c_epilogue = []
1152             if type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
1153                 fields = type_dict[fi.ctype]["jn_args"]
1154                 c_epilogue.append( \
1155                     ("jdoubleArray _da_retval_ = env->NewDoubleArray(%(cnt)i);  " +
1156                      "jdouble _tmp_retval_[%(cnt)i] = {%(args)s}; " +
1157                      "env->SetDoubleArrayRegion(_da_retval_, 0, %(cnt)i, _tmp_retval_);") %
1158                     { "cnt" : len(fields), "args" : ", ".join(["_retval_" + f[1] for f in fields]) } )
1159             if fi.classname and fi.ctype and not fi.static: # non-static class method except c-tor
1160                 # adding 'self'
1161                 jn_args.append ( ArgInfo([ "__int64", "nativeObj", "", [], "" ]) )
1162                 jni_args.append( ArgInfo([ "__int64", "self", "", [], "" ]) )
1163             self.get_imports(fi.classname, fi.ctype)
1164             for a in args:
1165                 if not a.ctype: # hidden
1166                     continue
1167                 self.get_imports(fi.classname, a.ctype)
1168                 if "vector" in a.ctype: # pass as Mat
1169                     jn_args.append  ( ArgInfo([ "__int64", "%s_mat.nativeObj" % a.name, "", [], "" ]) )
1170                     jni_args.append ( ArgInfo([ "__int64", "%s_mat_nativeObj" % a.name, "", [], "" ]) )
1171                     c_prologue.append( type_dict[a.ctype]["jni_var"] % {"n" : a.name} + ";" )
1172                     c_prologue.append( "Mat& %(n)s_mat = *((Mat*)%(n)s_mat_nativeObj)" % {"n" : a.name} + ";" )
1173                     if "I" in a.out or not a.out:
1174                         if a.ctype.startswith("vector_vector_"):
1175                             self.classes[fi.classname or self.Module].imports.add("java.util.ArrayList")
1176                             j_prologue.append( "List<Mat> %(n)s_tmplm = new ArrayList<Mat>((%(n)s != null) ? %(n)s.size() : 0);" % {"n" : a.name } )
1177                             j_prologue.append( "Mat %(n)s_mat = Converters.%(t)s_to_Mat(%(n)s, %(n)s_tmplm);" % {"n" : a.name, "t" : a.ctype} )
1178                         else:
1179                             if not type_dict[a.ctype]["j_type"].startswith("MatOf"):
1180                                 j_prologue.append( "Mat %(n)s_mat = Converters.%(t)s_to_Mat(%(n)s);" % {"n" : a.name, "t" : a.ctype} )
1181                             else:
1182                                 j_prologue.append( "Mat %s_mat = %s;" % (a.name, a.name) )
1183                         c_prologue.append( "Mat_to_%(t)s( %(n)s_mat, %(n)s );" % {"n" : a.name, "t" : a.ctype} )
1184                     else:
1185                         if not type_dict[a.ctype]["j_type"].startswith("MatOf"):
1186                             j_prologue.append( "Mat %s_mat = new Mat();" % a.name )
1187                         else:
1188                             j_prologue.append( "Mat %s_mat = %s;" % (a.name, a.name) )
1189                     if "O" in a.out:
1190                         if not type_dict[a.ctype]["j_type"].startswith("MatOf"):
1191                             j_epilogue.append("Converters.Mat_to_%(t)s(%(n)s_mat, %(n)s);" % {"t" : a.ctype, "n" : a.name})
1192                         c_epilogue.append( "%(t)s_to_Mat( %(n)s, %(n)s_mat );" % {"n" : a.name, "t" : a.ctype} )
1193                 else:
1194                     fields = type_dict[a.ctype].get("jn_args", ((a.ctype, ""),))
1195                     if "I" in a.out or not a.out or a.ctype in self.classes: # input arg, pass by primitive fields
1196                         for f in fields:
1197                             jn_args.append ( ArgInfo([ f[0], a.name + f[1], "", [], "" ]) )
1198                             jni_args.append( ArgInfo([ f[0], a.name + f[1].replace(".","_").replace("[","").replace("]",""), "", [], "" ]) )
1199                     if a.out and a.ctype not in self.classes: # out arg, pass as double[]
1200                         jn_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
1201                         jni_args.append ( ArgInfo([ "double[]", "%s_out" % a.name, "", [], "" ]) )
1202                         j_prologue.append( "double[] %s_out = new double[%i];" % (a.name, len(fields)) )
1203                         c_epilogue.append( \
1204                             "jdouble tmp_%(n)s[%(cnt)i] = {%(args)s}; env->SetDoubleArrayRegion(%(n)s_out, 0, %(cnt)i, tmp_%(n)s);" %
1205                             { "n" : a.name, "cnt" : len(fields), "args" : ", ".join([a.name + f[1] for f in fields]) } )
1206                         if a.ctype in ('bool', 'int', 'long', 'float', 'double'):
1207                             j_epilogue.append('if(%(n)s!=null) %(n)s[0] = (%(t)s)%(n)s_out[0];' % {'n':a.name,'t':a.ctype})
1208                         else:
1209                             set_vals = []
1210                             i = 0
1211                             for f in fields:
1212                                 set_vals.append( "%(n)s%(f)s = %(t)s%(n)s_out[%(i)i]" %
1213                                     {"n" : a.name, "t": ("("+type_dict[f[0]]["j_type"]+")", "")[f[0]=="double"], "f" : f[1], "i" : i}
1214                                 )
1215                                 i += 1
1216                             j_epilogue.append( "if("+a.name+"!=null){ " + "; ".join(set_vals) + "; } ")
1217
1218
1219             # java part:
1220             # private java NATIVE method decl
1221             # e.g.
1222             # private static native void add_0(long src1, long src2, long dst, long mask, int dtype);
1223             jn_code.write( Template(\
1224                 "    private static native $type $name($args);\n").substitute(\
1225                 type = type_dict[fi.ctype].get("jn_type", "double[]"), \
1226                 name = fi.jname + '_' + str(suffix_counter), \
1227                 args = ", ".join(["%s %s" % (type_dict[a.ctype]["jn_type"], a.name.replace(".","_").replace("[","").replace("]","")) for a in jn_args])
1228             ) );
1229
1230             # java part:
1231
1232             #java doc comment
1233             f_name = fi.name
1234             if fi.classname:
1235                 f_name = fi.classname + "::" + fi.name
1236             java_doc = "//javadoc: " + f_name + "(%s)" % ", ".join([a.name for a in args if a.ctype])
1237             j_code.write(" "*4 + java_doc + "\n")
1238
1239             # public java wrapper method impl (calling native one above)
1240             # e.g.
1241             # public static void add( Mat src1, Mat src2, Mat dst, Mat mask, int dtype )
1242             # { add_0( src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj, dtype );  }
1243             ret_type = fi.ctype
1244             if fi.ctype.endswith('*'):
1245                 ret_type = ret_type[:-1]
1246             ret_val = type_dict[ret_type]["j_type"] + " retVal = "
1247             tail = ""
1248             ret = "return retVal;"
1249             if ret_type.startswith('vector'):
1250                 tail = ")"
1251                 j_type = type_dict[ret_type]["j_type"]
1252                 if j_type.startswith('MatOf'):
1253                     ret_val += j_type + ".fromNativeAddr("
1254                 else:
1255                     ret_val = "Mat retValMat = new Mat("
1256                     j_prologue.append( j_type + ' retVal = new Array' + j_type+'();')
1257                     self.classes[fi.classname or self.Module].imports.add('java.util.ArrayList')
1258                     j_epilogue.append('Converters.Mat_to_' + ret_type + '(retValMat, retVal);')
1259             elif ret_type == "void":
1260                 ret_val = ""
1261                 ret = "return;"
1262             elif ret_type == "": # c-tor
1263                 if fi.classname and self.classes[fi.classname].base:
1264                     ret_val = "super( "
1265                     tail = " )"
1266                 else:
1267                     ret_val = "nativeObj = "
1268                 ret = "return;"
1269             elif ret_type in self.classes: # wrapped class
1270                 ret_val = type_dict[ret_type]["j_type"] + " retVal = new " + self.classes[ret_type].jname + "("
1271                 tail = ")"
1272             elif "jn_type" not in type_dict[ret_type]:
1273                 ret_val = type_dict[fi.ctype]["j_type"] + " retVal = new " + type_dict[ret_type]["j_type"] + "("
1274                 tail = ")"
1275
1276             static = "static"
1277             if fi.classname:
1278                 static = fi.static
1279
1280             j_args = []
1281             for a in args:
1282                 if not a.ctype: #hidden
1283                     continue
1284                 jt = type_dict[a.ctype]["j_type"]
1285                 if a.out and a.ctype in ('bool', 'int', 'long', 'float', 'double'):
1286                     jt += '[]'
1287                 j_args.append( jt + ' ' + a.name )
1288
1289             j_code.write( Template(\
1290 """    public $static $j_type $j_name($j_args)
1291     {
1292         $prologue
1293         $ret_val$jn_name($jn_args_call)$tail;
1294         $epilogue
1295         $ret
1296     }
1297
1298 """
1299                 ).substitute(\
1300                     ret = ret, \
1301                     ret_val = ret_val, \
1302                     tail = tail, \
1303                     prologue = "\n        ".join(j_prologue), \
1304                     epilogue = "\n        ".join(j_epilogue), \
1305                     static=static, \
1306                     j_type=type_dict[fi.ctype]["j_type"], \
1307                     j_name=fi.jname, \
1308                     j_args=", ".join(j_args), \
1309                     jn_name=fi.jname + '_' + str(suffix_counter), \
1310                     jn_args_call=", ".join( [a.name for a in jn_args] ),\
1311                 )
1312             )
1313
1314
1315             # cpp part:
1316             # jni_func(..) { _retval_ = cv_func(..); return _retval_; }
1317             ret = "return _retval_;"
1318             default = "return 0;"
1319             if fi.ctype == "void":
1320                 ret = "return;"
1321                 default = "return;"
1322             elif not fi.ctype: # c-tor
1323                 ret = "return (jlong) _retval_;"
1324             elif fi.ctype.startswith('vector'): # c-tor
1325                 ret = "return (jlong) _retval_;"
1326             elif fi.ctype == "String":
1327                 ret = "return env->NewStringUTF(_retval_.c_str());"
1328                 default = 'return env->NewStringUTF("");'
1329             elif fi.ctype in self.classes: # wrapped class:
1330                 ret = "return (jlong) new %s(_retval_);" % fi.ctype
1331             elif ret_type in self.classes: # pointer to wrapped class:
1332                 ret = "return (jlong) _retval_;"
1333             elif type_dict[fi.ctype]["jni_type"] == "jdoubleArray":
1334                 ret = "return _da_retval_;"
1335
1336             # hack: replacing func call with property set/get
1337             name = fi.name
1338             if prop_name:
1339                 if args:
1340                     name = prop_name + " = "
1341                 else:
1342                     name = prop_name + ";//"
1343
1344             cvname = "cv::" + name
1345             retval = fi.ctype + " _retval_ = "
1346             if fi.ctype == "void":
1347                 retval = ""
1348             elif fi.ctype == "String":
1349                 retval = "cv::" + retval
1350             elif fi.ctype.startswith('vector'):
1351                 retval = type_dict[fi.ctype]['jni_var'] % {"n" : '_ret_val_vector_'} + " = "
1352                 c_epilogue.append("Mat* _retval_ = new Mat();")
1353                 c_epilogue.append(fi.ctype+"_to_Mat(_ret_val_vector_, *_retval_);")
1354             if fi.classname:
1355                 if not fi.ctype: # c-tor
1356                     retval = fi.classname + "* _retval_ = "
1357                     cvname = "new " + fi.classname
1358                 elif fi.static:
1359                     cvname = "%s::%s" % (fi.classname, name)
1360                 else:
1361                     cvname = "me->" + name
1362                     c_prologue.append(\
1363                         "%(cls)s* me = (%(cls)s*) self; //TODO: check for NULL" \
1364                             % { "cls" : fi.classname} \
1365                     )
1366             cvargs = []
1367             for a in args:
1368                 if a.pointer:
1369                     jni_name = "&%(n)s"
1370                 else:
1371                     jni_name = "%(n)s"
1372                     if not a.out and not "jni_var" in type_dict[a.ctype]:
1373                         # explicit cast to C type to avoid ambiguous call error on platforms (mingw)
1374                         # where jni types are different from native types (e.g. jint is not the same as int)
1375                         jni_name  = "(%s)%s" % (a.ctype, jni_name)
1376                 if not a.ctype: # hidden
1377                     jni_name = a.defval
1378                 cvargs.append( type_dict[a.ctype].get("jni_name", jni_name) % {"n" : a.name})
1379                 if "vector" not in a.ctype :
1380                     if ("I" in a.out or not a.out or a.ctype in self.classes) and "jni_var" in type_dict[a.ctype]: # complex type
1381                         c_prologue.append(type_dict[a.ctype]["jni_var"] % {"n" : a.name} + ";")
1382                     if a.out and "I" not in a.out and a.ctype not in self.classes and a.ctype:
1383                         c_prologue.append("%s %s;" % (a.ctype, a.name))
1384
1385             rtype = type_dict[fi.ctype].get("jni_type", "jdoubleArray")
1386             clazz = self.Module
1387             if fi.classname:
1388                 clazz = self.classes[fi.classname].jname
1389             cpp_code.write ( Template( \
1390 """
1391 JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname ($argst);
1392
1393 JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_${clazz}_$fname
1394   ($args)
1395 {
1396     static const char method_name[] = "$module::$fname()";
1397     try {
1398         LOGD("%s", method_name);
1399         $prologue
1400         $retval$cvname( $cvargs );
1401         $epilogue$ret
1402     } catch(const std::exception &e) {
1403         throwJavaException(env, &e, method_name);
1404     } catch (...) {
1405         throwJavaException(env, 0, method_name);
1406     }
1407     $default
1408 }
1409
1410
1411 """ ).substitute( \
1412         rtype = rtype, \
1413         module = self.module, \
1414         clazz = clazz.replace('_', '_1'), \
1415         fname = (fi.jname + '_' + str(suffix_counter)).replace('_', '_1'), \
1416         args  = ", ".join(["%s %s" % (type_dict[a.ctype].get("jni_type"), a.name) for a in jni_args]), \
1417         argst = ", ".join([type_dict[a.ctype].get("jni_type") for a in jni_args]), \
1418         prologue = "\n        ".join(c_prologue), \
1419         epilogue = "  ".join(c_epilogue) + ("\n        " if c_epilogue else ""), \
1420         ret = ret, \
1421         cvname = cvname, \
1422         cvargs = ", ".join(cvargs), \
1423         default = default, \
1424         retval = retval, \
1425     ) )
1426
1427             # processing args with default values
1428             if not args or not args[-1].defval:
1429                 break
1430             while args and args[-1].defval:
1431                 # 'smart' overloads filtering
1432                 a = args.pop()
1433                 if a.name in ('mask', 'dtype', 'ddepth', 'lineType', 'borderType', 'borderMode', 'criteria'):
1434                     break
1435
1436
1437
1438     def gen_class(self, name):
1439         # generate code for the class
1440         ci = self.classes[name]
1441         # constants
1442         if ci.private_consts:
1443             self.java_code[name]['j_code'].write("""
1444     private static final int
1445             %s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.private_consts])
1446             )
1447         if ci.consts:
1448             self.java_code[name]['j_code'].write("""
1449     public static final int
1450             %s;\n\n""" % (",\n"+" "*12).join(["%s = %s" % (c.name, c.value) for c in ci.consts])
1451             )
1452         # c-tors
1453         fflist = ci.methods.items()
1454         fflist.sort()
1455         for n, ffi in fflist:
1456             if ffi.isconstructor:
1457                 for fi in ffi.funcs:
1458                     fi.jname = ci.jname
1459                     self.gen_func(fi)
1460         # other methods
1461         for n, ffi in fflist:
1462             if not ffi.isconstructor:
1463                 for fi in ffi.funcs:
1464                     self.gen_func(fi)
1465         # props
1466         for pi in ci.props:
1467             # getter
1468             getter_name = name + ".get_" + pi.name
1469             #print getter_name
1470             fi = FuncInfo( [getter_name, pi.ctype, [], []] ) # [ funcname, return_ctype, [modifiers], [args] ]
1471             self.gen_func(fi, pi.name)
1472             if pi.rw:
1473                 #setter
1474                 setter_name = name + ".set_" + pi.name
1475                 #print setter_name
1476                 fi = FuncInfo( [ setter_name, "void", [], [ [pi.ctype, pi.name, "", [], ""] ] ] )
1477                 self.gen_func(fi, pi.name)
1478
1479         # manual ports
1480         if name in ManualFuncs:
1481             for func in ManualFuncs[name].keys():
1482                 self.java_code[name]["j_code"].write ( ManualFuncs[name][func]["j_code"] )
1483                 self.java_code[name]["jn_code"].write( ManualFuncs[name][func]["jn_code"] )
1484                 self.cpp_code.write( ManualFuncs[name][func]["cpp_code"] )
1485
1486         if name != self.Module:
1487             # finalize()
1488             self.java_code[name]["j_code"].write(
1489 """
1490     @Override
1491     protected void finalize() throws Throwable {
1492         delete(nativeObj);
1493     }
1494 """ )
1495
1496             self.java_code[name]["jn_code"].write(
1497 """
1498     // native support for java finalize()
1499     private static native void delete(long nativeObj);
1500 """ )
1501
1502             # native support for java finalize()
1503             self.cpp_code.write( \
1504 """
1505 //
1506 //  native support for java finalize()
1507 //  static void %(cls)s::delete( __int64 self )
1508 //
1509 JNIEXPORT void JNICALL Java_org_opencv_%(module)s_%(j_cls)s_delete(JNIEnv*, jclass, jlong);
1510
1511 JNIEXPORT void JNICALL Java_org_opencv_%(module)s_%(j_cls)s_delete
1512   (JNIEnv*, jclass, jlong self)
1513 {
1514     delete (%(cls)s*) self;
1515 }
1516
1517 """ % {"module" : module, "cls" : name, "j_cls" : ci.jname.replace('_', '_1')}
1518             )
1519
1520
1521 if __name__ == "__main__":
1522     if len(sys.argv) < 4:
1523         print "Usage:\n", \
1524             os.path.basename(sys.argv[0]), \
1525             "<full path to hdr_parser.py> <module name> <C++ header> [<C++ header>...]"
1526         print "Current args are: ", ", ".join(["'"+a+"'" for a in sys.argv])
1527         exit(0)
1528
1529     dstdir = "."
1530     hdr_parser_path = os.path.abspath(sys.argv[1])
1531     if hdr_parser_path.endswith(".py"):
1532         hdr_parser_path = os.path.dirname(hdr_parser_path)
1533     sys.path.append(hdr_parser_path)
1534     import hdr_parser
1535     module = sys.argv[2]
1536     srcfiles = sys.argv[3:]
1537     #print "Generating module '" + module + "' from headers:\n\t" + "\n\t".join(srcfiles)
1538     generator = JavaWrapperGenerator()
1539     generator.gen(srcfiles, module, dstdir)