Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Opencv
提交
3159bd1a
O
Opencv
项目概览
Greenplum
/
Opencv
11 个月 前同步成功
通知
7
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
O
Opencv
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3159bd1a
编写于
7月 01, 2011
作者:
A
Andrey Pavlenko
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
#863: 'string' args support added
上级
6c8a2b88
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
159 addition
and
128 deletion
+159
-128
modules/java/gen_java.py
modules/java/gen_java.py
+113
-119
modules/java/src/cpp/Mat.cpp
modules/java/src/cpp/Mat.cpp
+33
-9
modules/java/src/java/Mat.java
modules/java/src/java/Mat.java
+10
-0
samples/android/1-java/src/org/opencv/samples/s1/Sample1View.java
...android/1-java/src/org/opencv/samples/s1/Sample1View.java
+3
-0
未找到文件。
modules/java/gen_java.py
浏览文件 @
3159bd1a
...
@@ -6,34 +6,56 @@ try:
...
@@ -6,34 +6,56 @@ try:
except
:
except
:
from
StringIO
import
StringIO
from
StringIO
import
StringIO
ctype2j
=
{
# c_type : { java/jni correspondence }
# c : (j, jn, jni, jni code)
type_dict
=
{
""
:
(
""
,
"long"
,
"jlong"
,
""
),
# c-tor
# "simple" : { j_type : "?", jn_type : "?", jni_type : "?", suffix : "?" },
"void"
:
(
"void"
,
"void"
,
"void"
,
""
),
""
:
{
"j_type"
:
""
,
"jn_type"
:
"long"
,
"jni_type"
:
"jlong"
},
# c-tor ret_type
"bool"
:
(
"boolean"
,
"boolean"
,
"jboolean"
,
"Z"
),
"void"
:
{
"j_type"
:
"void"
,
"jn_type"
:
"void"
,
"jni_type"
:
"void"
},
"int"
:
(
"int"
,
"int"
,
"jint"
,
"I"
),
"env"
:
{
"j_type"
:
""
,
"jn_type"
:
""
,
"jni_type"
:
"JNIEnv*"
},
"long"
:
(
"int"
,
"int"
,
"jint"
,
"I"
),
"cls"
:
{
"j_type"
:
""
,
"jn_type"
:
""
,
"jni_type"
:
"jclass"
},
"float"
:
(
"float"
,
"float"
,
"jfloat"
,
"F"
),
"bool"
:
{
"j_type"
:
"boolean"
,
"jn_type"
:
"boolean"
,
"jni_type"
:
"jboolean"
,
"suffix"
:
"Z"
},
"double"
:
(
"double"
,
"double"
,
"jdouble"
,
"D"
),
"int"
:
{
"j_type"
:
"int"
,
"jn_type"
:
"int"
,
"jni_type"
:
"int"
,
"suffix"
:
"I"
},
"size_t"
:
(
"long"
,
"long"
,
"jlong"
,
"J"
),
"long"
:
{
"j_type"
:
"int"
,
"jn_type"
:
"int"
,
"jni_type"
:
"int"
,
"suffix"
:
"I"
},
"env"
:
(
""
,
""
,
"JNIEnv*"
,
""
),
# dummy 'env'
"float"
:
{
"j_type"
:
"float"
,
"jn_type"
:
"float"
,
"jni_type"
:
"jfloat"
,
"suffix"
:
"F"
},
"cls"
:
(
""
,
""
,
"jclass"
,
""
),
# dummy 'cls'
"double"
:
{
"j_type"
:
"double"
,
"jn_type"
:
"double"
,
"jni_type"
:
"jdouble"
,
"suffix"
:
"D"
},
#
"size_t"
:
{
"j_type"
:
"long"
,
"jn_type"
:
"long"
,
"jni_type"
:
"jlong"
,
"suffix"
:
"J"
},
"Mat"
:
(
"Mat"
,
((
"size_t"
,
".nativeObj"
),),
"*%(n)s"
,
"J"
),
"__int64"
:
{
"j_type"
:
"long"
,
"jn_type"
:
"long"
,
"jni_type"
:
"jlong"
,
"suffix"
:
"J"
},
"Point"
:
(
"Point"
,
((
"double"
,
".x"
),
(
"double"
,
".y"
)),
"cv::Point((int)%(n)s_x, (int)%(n)s_y)"
,
"DD"
),
#"+Mat+" : { "j_type" : "Mat", "jn_type" : "long", "jn_name" : "%s.nativeObj", "jni_type" : "jlong", "suffix" : "J" },
"Point2f"
:
(
"Point"
,
((
"double"
,
".x"
),
(
"double"
,
".y"
)),
"cv::Point2f((float)%(n)s_x, (float)%(n)s_y)"
,
"DD"
),
# "complex" : { j_type : "?", jn_args : (("", ""),), jn_name : "", jni_var : "", jni_name : "", "suffix" : "?" },
"Point2d"
:
(
"Point"
,
((
"double"
,
".x"
),
(
"double"
,
".y"
)),
"cv::Point2d(%(n)s_x, %(n)s_y)"
,
"DD"
),
"Mat"
:
{
"j_type"
:
"Mat"
,
"jn_type"
:
"long"
,
"jn_args"
:
((
"__int64"
,
".nativeObj"
),),
"Point3i"
:
(
"Point"
,
((
"double"
,
".x"
),
(
"double"
,
".y"
),
(
"double"
,
".z"
)),
\
"jni_var"
:
"cv::Mat %(n)s(%(n)s_nativeObj ? *((cv::Mat*)%(n)s_nativeObj) : cv::Mat())"
,
"jni_type"
:
"jlong"
,
"cv::Point3i((int)%(n)s_x, (int)%(n)s_y, (int)%(n)s_z)"
,
"DDD"
),
"suffix"
:
"J"
},
"Point3f"
:
(
"Point"
,
((
"double"
,
".x"
),
(
"double"
,
".y"
),
(
"double"
,
".z"
)),
\
"Point"
:
{
"j_type"
:
"Point"
,
"jn_args"
:
((
"double"
,
".x"
),
(
"double"
,
".y"
)),
"cv::Point3f((float)%(n)s_x, (float)%(n)s_y, (float)%(n)s_z)"
,
"DDD"
),
"jni_var"
:
"cv::Point %(n)s((int)%(n)s_x, (int)%(n)s_y)"
,
"Point3d"
:
(
"Point"
,
((
"double"
,
".x"
),
(
"double"
,
".y"
),
(
"double"
,
".z"
)),
\
"suffix"
:
"DD"
},
"cv::Point3d(%(n)s_x, %(n)s_y, %(n)s_z)"
,
"DDD"
),
"Point2f"
:
{
"j_type"
:
"Point"
,
"jn_args"
:
((
"double"
,
".x"
),
(
"double"
,
".y"
)),
"Rect"
:
(
"Rect"
,
((
"int"
,
".x"
),
(
"int"
,
".y"
),
(
"int"
,
".width"
),
(
"int"
,
".height"
)),
\
"jni_var"
:
"cv::Point2f %(n)s((float)%(n)s_x, (float)%(n)s_y)"
,
"cv::Rect(%(n)s_x, %(n)s_y, %(n)s_width, %(n)s_height)"
,
"IIII"
),
"suffix"
:
"DD"
},
"Size"
:
(
"Size"
,
((
"int"
,
".width"
),
(
"int"
,
".height"
)),
"cv::Size(%(n)s_width, %(n)s_height)"
,
"II"
),
"Point2d"
:
{
"j_type"
:
"Point"
,
"jn_args"
:
((
"double"
,
".x"
),
(
"double"
,
".y"
)),
"Scalar"
:
(
"Scalar"
,
((
"double"
,
".v0"
),
(
"double"
,
".v1"
),
(
"double"
,
".v2"
),
(
"double"
,
".v3"
)),
\
"jni_var"
:
"cv::Point2d %(n)s(%(n)s_x, %(n)s_y)"
,
"cv::Scalar(%(n)s_v0, %(n)s_v1, %(n)s_v2, %(n)s_v3)"
,
"DDDD"
),
"suffix"
:
"DD"
},
"Point3i"
:
{
"j_type"
:
"Point"
,
"jn_args"
:
((
"double"
,
".x"
),
(
"double"
,
".y"
),
(
"double"
,
".z"
)),
"jni_var"
:
"cv::Point3i %(n)s((int)%(n)s_x, (int)%(n)s_y, (int)%(n)s_z)"
,
"suffix"
:
"DDD"
},
"Point3f"
:
{
"j_type"
:
"Point"
,
"jn_args"
:
((
"double"
,
".x"
),
(
"double"
,
".y"
),
(
"double"
,
".z"
)),
"jni_var"
:
"cv::Point3f %(n)s((float)%(n)s_x, (float)%(n)s_y, (float)%(n)s_z)"
,
"suffix"
:
"DDD"
},
"Point3d"
:
{
"j_type"
:
"Point"
,
"jn_args"
:
((
"double"
,
".x"
),
(
"double"
,
".y"
),
(
"double"
,
".z"
)),
"jni_var"
:
"cv::Point3d %(n)s(%(n)s_x, %(n)s_y, %(n)s_z)"
,
"suffix"
:
"DDD"
},
"Rect"
:
{
"j_type"
:
"Rect"
,
"jn_args"
:
((
"int"
,
".x"
),
(
"int"
,
".y"
),
(
"int"
,
".width"
),
(
"int"
,
".height"
)),
"jni_var"
:
"cv::Rect %(n)s(%(n)s_x, %(n)s_y, %(n)s_width, %(n)s_height)"
,
"suffix"
:
"IIII"
},
"Size"
:
{
"j_type"
:
"Size"
,
"jn_args"
:
((
"int"
,
".width"
),
(
"int"
,
".height"
)),
"jni_var"
:
"cv::Size %(n)s(%(n)s_width, %(n)s_height)"
,
"suffix"
:
"II"
},
"Scalar"
:
{
"j_type"
:
"Scalar"
,
"jn_args"
:
((
"double"
,
".v0"
),
(
"double"
,
".v1"
),
(
"double"
,
".v2"
),
(
"double"
,
".v3"
)),
"jni_var"
:
"cv::Scalar %(n)s(%(n)s_v0, %(n)s_v1, %(n)s_v2, %(n)s_v3)"
,
"suffix"
:
"DDDD"
},
"string"
:
{
"j_type"
:
"java.lang.String"
,
"jn_type"
:
"java.lang.String"
,
"jni_type"
:
"jstring"
,
"jni_name"
:
"n_%(n)s"
,
"jni_var"
:
'const char* utf_%(n)s = env->GetStringUTFChars(%(n)s, 0); std::string n_%(n)s( utf_%(n)s ? utf_%(n)s : "" ); env->ReleaseStringUTFChars(%(n)s, utf_%(n)s);'
,
"suffix"
:
"Ljava_lang_String_2"
},
}
}
...
@@ -95,13 +117,13 @@ class FuncInfo(object):
...
@@ -95,13 +117,13 @@ class FuncInfo(object):
self
.
static
=
[
""
,
"static"
][
"/S"
in
decl
[
2
]
]
self
.
static
=
[
""
,
"static"
][
"/S"
in
decl
[
2
]
]
self
.
ctype
=
decl
[
1
]
or
""
self
.
ctype
=
decl
[
1
]
or
""
self
.
args
=
[]
self
.
args
=
[]
self
.
jni_suffix
=
"__"
#
self.jni_suffix = "__"
if
self
.
classname
and
self
.
ctype
and
not
self
.
static
:
# non-static class methods except c-tors
#
if self.classname and self.ctype and not self.static: # non-static class methods except c-tors
self
.
jni_suffix
+=
"J"
# artifical 'self'
#
self.jni_suffix += "J" # artifical 'self'
for
a
in
decl
[
3
]:
for
a
in
decl
[
3
]:
ai
=
ArgInfo
(
a
)
ai
=
ArgInfo
(
a
)
self
.
args
.
append
(
ai
)
self
.
args
.
append
(
ai
)
self
.
jni_suffix
+=
ctype2j
.
get
(
ai
.
ctype
,
[
""
,
""
,
""
,
""
])[
3
]
#
self.jni_suffix += ctype2j.get(ai.ctype, ["","","",""])[3]
...
@@ -139,10 +161,13 @@ class JavaWrapperGenerator(object):
...
@@ -139,10 +161,13 @@ class JavaWrapperGenerator(object):
(
classinfo
.
name
,
classinfo
.
cname
)
(
classinfo
.
name
,
classinfo
.
cname
)
sys
.
exit
(
-
1
)
sys
.
exit
(
-
1
)
self
.
classes
[
classinfo
.
name
]
=
classinfo
self
.
classes
[
classinfo
.
name
]
=
classinfo
if
classinfo
.
name
in
ctype2j
:
if
classinfo
.
name
in
type_dict
:
print
"Duplicated class: "
+
classinfo
.
name
print
"Duplicated class: "
+
classinfo
.
name
sys
.
exit
(
-
1
)
sys
.
exit
(
-
1
)
ctype2j
[
classinfo
.
name
]
=
(
classinfo
.
jname
,
((
"size_t"
,
".nativeObj"
),),
"*%(n)s"
,
"J"
)
type_dict
[
classinfo
.
name
]
=
\
{
"j_type"
:
classinfo
.
name
,
"jn_args"
:
((
"__int64"
,
".nativeObj"
),),
"jni_name"
:
"(*((cv::"
+
classinfo
.
name
+
"*)%s_nativeObj))"
,
"suffix"
:
"J"
}
def
add_const
(
self
,
decl
):
# [ "const cname", val, [], [] ]
def
add_const
(
self
,
decl
):
# [ "const cname", val, [], [] ]
...
@@ -287,87 +312,73 @@ public class %(module)s {
...
@@ -287,87 +312,73 @@ public class %(module)s {
c_decl
=
"%s %s %s(%s)"
%
\
c_decl
=
"%s %s %s(%s)"
%
\
(
fi
.
static
,
fi
.
ctype
,
fi
.
cname
,
\
(
fi
.
static
,
fi
.
ctype
,
fi
.
cname
,
\
", "
.
join
(
a
.
ctype
+
" "
+
a
.
name
+
[
""
,
" = "
+
a
.
defval
][
bool
(
a
.
defval
)]
for
a
in
fi
.
args
)
)
", "
.
join
(
a
.
ctype
+
" "
+
a
.
name
+
[
""
,
" = "
+
a
.
defval
][
bool
(
a
.
defval
)]
for
a
in
fi
.
args
)
)
indent
=
"
"
indent
=
"
"
*
4
if
fi
.
classname
:
if
fi
.
classname
:
indent
=
" "
*
4
indent
+
=
" "
*
4
self
.
java_code
.
write
(
"
\n
%s// %s
\n
"
%
(
indent
,
c_decl
)
)
self
.
java_code
.
write
(
"
\n
%s// %s
\n
"
%
(
indent
,
c_decl
)
)
self
.
cpp_code
.
write
(
"
\n
//
\n
//%s
\n
//
\n
"
%
c_decl
)
self
.
cpp_code
.
write
(
"
\n
//
\n
//%s
\n
//
\n
"
%
c_decl
)
# check if we 'know' all the types
# check if we 'know' all the types
if
fi
.
ctype
and
fi
.
ctype
!=
"Mat"
and
fi
.
ctype
[
0
].
isupper
():
# ret val is class, NYI (TODO!)
type_info
=
type_dict
.
get
(
fi
.
ctype
)
self
.
java_code
.
write
(
" %s// Return type '%s' is not yet supported, skipping the function
\n\n
"
\
if
not
(
type_info
and
type_info
.
get
(
"jn_type"
)):
# unsupported ret type
%
(
indent
,
fi
.
ctype
)
)
msg
=
"// Return type '%s' is not supported, skipping the function
\n\n
"
%
fi
.
ctype
self
.
java_code
.
write
(
indent
+
msg
)
self
.
cpp_code
.
write
(
msg
)
print
"SKIP:"
,
c_decl
,
"
\n\t
due to RET type"
,
fi
.
ctype
print
"SKIP:"
,
c_decl
,
"
\n\t
due to RET type"
,
fi
.
ctype
return
return
types
=
[
fi
.
ctype
]
types
.
extend
([
a
.
ctype
for
a
in
fi
.
args
])
for
t
in
types
:
if
t
not
in
ctype2j
:
self
.
java_code
.
write
(
" %s// Unknown type '%s', skipping the function
\n\n
"
%
(
indent
,
t
)
)
print
"SKIP:"
,
c_decl
,
"
\n\t
due to ARG type"
,
t
return
for
a
in
fi
.
args
:
for
a
in
fi
.
args
:
if
a
.
ctype
[
0
].
isupper
()
and
a
.
ctype
!=
"Mat"
and
a
.
out
:
# C++ reference to a class (gcc disallows temp obj reference)
if
a
.
ctype
not
in
type_dict
:
self
.
java_code
.
write
(
" %s// Unknown type '%s&', skipping the function
\n\n
"
%
(
indent
,
t
)
)
msg
=
"// Unknown type '%s', skipping the function
\n\n
"
%
a
.
ctype
print
"SKIP:"
,
c_decl
,
"
\n\t
due to ARG type"
,
a
.
ctype
+
"&"
self
.
java_code
.
write
(
indent
+
msg
)
self
.
cpp_code
.
write
(
msg
)
print
"SKIP:"
,
c_decl
,
"
\n\t
due to ARG type"
,
a
.
ctype
return
return
if
fi
.
cname
==
"minEnclosingCircle"
:
if
a
.
ctype
!=
"Mat"
and
"jn_args"
in
type_dict
[
a
.
ctype
]
and
a
.
out
:
# complex out args not yet supported
self
.
java_code
.
write
(
" %s// Temporary skipping the function %s
\n\n
"
%
(
indent
,
fi
.
cname
)
)
msg
=
"// Unsupported type '%s&', skipping the function
\n\n
"
%
a
.
ctype
print
"SKIP:"
,
c_decl
,
"
\n\t
due to Temporary filtering"
self
.
java_code
.
write
(
indent
+
msg
)
self
.
cpp_code
.
write
(
msg
)
print
"SKIP:"
,
c_decl
,
"
\n\t
due to OUT ARG of type"
,
a
.
ctype
return
return
self
.
ported_func_counter
+=
1
self
.
ported_func_counter
+=
1
# java args
# java args
args
=
fi
.
args
[:]
args
=
fi
.
args
[:]
# copy
if
args
and
args
[
-
1
].
defval
:
if
args
and
args
[
-
1
].
defval
:
isoverload
=
True
isoverload
=
True
suffix
=
fi
.
jni_suffix
while
True
:
while
True
:
# java native method args
# java native method args
jn_args
=
[]
jn_args
=
[]
if
fi
.
classname
and
fi
.
ctype
and
not
fi
.
static
:
# non-static class method except c-tor
jn_args
.
append
(
ArgInfo
([
"size_t"
,
"nativeObj"
,
""
,
[],
""
]))
# adding 'this'
for
a
in
args
:
if
a
.
ctype
[
0
].
isupper
():
# Point/Rect/...
#"Point" : ("Point", [["int", ".x"], ["int", ".y"]], ...)
fields
=
ctype2j
[
a
.
ctype
][
1
]
for
f
in
fields
:
jn_args
.
append
(
ArgInfo
([
f
[
0
],
a
.
name
+
f
[
1
],
""
,
[],
""
])
)
else
:
jn_args
.
append
(
a
)
# jni (cpp) function args
# jni (cpp) function args
jni_args
=
[
ArgInfo
([
"env"
,
"env"
,
""
,
[],
""
]),
ArgInfo
([
"cls"
,
"cls"
,
""
,
[],
""
])]
jni_args
=
[
ArgInfo
([
"env"
,
"env"
,
""
,
[],
""
]),
ArgInfo
([
"cls"
,
"cls"
,
""
,
[],
""
])]
if
fi
.
classname
and
fi
.
ctype
and
not
fi
.
static
:
suffix
=
"__"
jni_args
.
append
(
ArgInfo
([
"size_t"
,
"self"
,
""
,
[],
""
]))
if
fi
.
classname
and
fi
.
ctype
and
not
fi
.
static
:
# non-static class method except c-tor
# adding 'self'
jn_args
.
append
(
ArgInfo
([
"__int64"
,
"nativeObj"
,
""
,
[],
""
])
)
jni_args
.
append
(
ArgInfo
([
"__int64"
,
"self"
,
""
,
[],
""
])
)
suffix
+=
"J"
for
a
in
args
:
for
a
in
args
:
if
a
.
ctype
[
0
].
isupper
():
# Point/Rect/...
suffix
+=
type_dict
[
a
.
ctype
].
get
(
"suffix"
)
or
""
#"Point" : ("Point", [["int", ".x"], ["int", ".y"]], ...)
fields
=
type_dict
[
a
.
ctype
].
get
(
"jn_args"
)
or
[]
fields
=
ctype2j
[
a
.
ctype
][
1
]
if
fields
:
# complex type
for
f
in
fields
:
for
f
in
fields
:
jn_args
.
append
(
ArgInfo
([
f
[
0
],
a
.
name
+
f
[
1
],
""
,
[],
""
])
)
jni_args
.
append
(
ArgInfo
([
f
[
0
],
a
.
name
+
f
[
1
].
replace
(
"."
,
"_"
),
""
,
[],
""
])
)
jni_args
.
append
(
ArgInfo
([
f
[
0
],
a
.
name
+
f
[
1
].
replace
(
"."
,
"_"
),
""
,
[],
""
])
)
else
:
else
:
jn_args
.
append
(
a
)
jni_args
.
append
(
a
)
jni_args
.
append
(
a
)
# java part:
# java part:
# private java NATIVE method decl
# private java NATIVE method decl
# e.g.
# e.g.
# private static native void n_add(long src1, long src2, long dst, long mask, int dtype);
# private static native void n_add(long src1, long src2, long dst, long mask, int dtype);
jn_type
=
""
if
fi
.
ctype
==
"Mat"
:
jn_type
=
"long"
elif
fi
.
ctype
[
0
].
isupper
():
jn_type
=
"NYI"
# TODO: NYI
else
:
jn_type
=
ctype2j
[
fi
.
ctype
][
1
]
self
.
java_code
.
write
(
Template
(
\
self
.
java_code
.
write
(
Template
(
\
"
${indent}private static native $jn_type $jn_name($jn_args);
\n
"
).
substitute
(
\
"${indent}private static native $jn_type $jn_name($jn_args);
\n
"
).
substitute
(
\
indent
=
indent
,
\
indent
=
indent
,
\
jn_type
=
jn_type
,
\
jn_type
=
type_dict
[
fi
.
ctype
][
"jn_type"
]
,
\
jn_name
=
fi
.
jn_name
,
\
jn_name
=
fi
.
jn_name
,
\
jn_args
=
", "
.
join
([
"%s %s"
%
(
ctype2j
[
a
.
ctype
][
1
],
a
.
name
.
replace
(
"."
,
"_"
))
for
a
in
jn_args
])
jn_args
=
", "
.
join
([
"%s %s"
%
(
type_dict
[
a
.
ctype
][
"jn_type"
],
a
.
name
.
replace
(
"."
,
"_"
))
for
a
in
jn_args
])
)
);
)
);
# java part:
# java part:
...
@@ -375,11 +386,11 @@ public class %(module)s {
...
@@ -375,11 +386,11 @@ public class %(module)s {
# e.g.
# e.g.
# public static void add( Mat src1, Mat src2, Mat dst, Mat mask, int dtype )
# public static void add( Mat src1, Mat src2, Mat dst, Mat mask, int dtype )
# { n_add( src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj, dtype ); }
# { n_add( src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj, dtype ); }
impl_code
=
"
return $jn_name($jn_args_call);
"
impl_code
=
"
return $jn_name($jn_args_call);
"
if
fi
.
ctype
==
"void"
:
if
fi
.
ctype
==
"void"
:
impl_code
=
"
$jn_name($jn_args_call);
"
impl_code
=
"
$jn_name($jn_args_call);
"
elif
fi
.
ctype
==
""
:
# c-tor
elif
fi
.
ctype
==
""
:
# c-tor
impl_code
=
"
nativeObj = $jn_name($jn_args_call);
"
impl_code
=
"
nativeObj = $jn_name($jn_args_call);
"
elif
fi
.
ctype
in
self
.
classes
:
# wrapped class
elif
fi
.
ctype
in
self
.
classes
:
# wrapped class
impl_code
=
" return new %s( $jn_name($jn_args_call) ); "
%
\
impl_code
=
" return new %s( $jn_name($jn_args_call) ); "
%
\
self
.
classes
[
fi
.
ctype
].
jname
self
.
classes
[
fi
.
ctype
].
jname
...
@@ -389,18 +400,18 @@ public class %(module)s {
...
@@ -389,18 +400,18 @@ public class %(module)s {
static
=
fi
.
static
static
=
fi
.
static
self
.
java_code
.
write
(
Template
(
\
self
.
java_code
.
write
(
Template
(
\
"
${indent}public $static $j_type $j_name($j_args)"
).
substitute
(
\
"${indent}public $static $j_type $j_name($j_args)"
).
substitute
(
\
indent
=
indent
,
\
indent
=
indent
,
\
static
=
static
,
\
static
=
static
,
\
j_type
=
ctype2j
[
fi
.
ctype
][
0
],
\
j_type
=
type_dict
[
fi
.
ctype
][
"j_type"
],
\
j_name
=
fi
.
jname
,
\
j_name
=
fi
.
jname
,
\
j_args
=
", "
.
join
([
"%s %s"
%
(
ctype2j
[
a
.
ctype
][
0
],
a
.
name
)
for
a
in
args
])
\
j_args
=
", "
.
join
([
"%s %s"
%
(
type_dict
[
a
.
ctype
][
"j_type"
],
a
.
name
)
for
a
in
args
])
\
)
)
)
)
self
.
java_code
.
write
(
Template
(
"
\n
$indent{ "
+
impl_code
+
" }
\n
"
).
substitute
(
\
self
.
java_code
.
write
(
Template
(
"
\n
$indent{ "
+
impl_code
+
" }
\n
"
).
substitute
(
\
indent
=
indent
,
\
indent
=
indent
,
\
jn_name
=
fi
.
jn_name
,
\
jn_name
=
fi
.
jn_name
,
\
jn_args_call
=
", "
.
join
(
[
a
.
name
+
[
""
,
".nativeObj"
][
ctype2j
[
a
.
ctype
][
0
]
==
"Mat"
]
for
a
in
jn_args
]
)
\
jn_args_call
=
", "
.
join
(
[
a
.
name
for
a
in
jn_args
]
)
\
)
)
)
)
# cpp part:
# cpp part:
...
@@ -408,10 +419,8 @@ public class %(module)s {
...
@@ -408,10 +419,8 @@ public class %(module)s {
ret
=
"return "
ret
=
"return "
if
fi
.
ctype
==
"void"
:
if
fi
.
ctype
==
"void"
:
ret
=
""
ret
=
""
elif
fi
.
ctype
==
"Mat"
:
elif
fi
.
ctype
in
self
.
classes
:
# wrapped class:
ret
=
"return (jlong) new cv::Mat"
ret
=
"return (jlong) new cv::"
+
self
.
classes
[
fi
.
ctype
].
jname
elif
fi
.
ctype
[
0
].
isupper
():
ret
=
NYI
# NYI
cvname
=
"cv::"
+
fi
.
name
cvname
=
"cv::"
+
fi
.
name
j2cvargs
=
[]
j2cvargs
=
[]
...
@@ -421,32 +430,18 @@ public class %(module)s {
...
@@ -421,32 +430,18 @@ public class %(module)s {
elif
fi
.
static
:
elif
fi
.
static
:
cvname
=
"cv::%s::%s"
%
(
fi
.
classname
,
fi
.
name
)
cvname
=
"cv::%s::%s"
%
(
fi
.
classname
,
fi
.
name
)
else
:
else
:
cvname
=
"
%s->%s"
%
(
"me"
,
fi
.
name
)
cvname
=
"
me->"
+
fi
.
name
j2cvargs
.
append
(
\
j2cvargs
.
append
(
\
"cv::%
s* me = (cv::%s*) self; //TODO: check for NULL"
%
\
"cv::%
(cls)s* me = (cv::%(cls)s*) self; //TODO: check for NULL"
\
(
fi
.
classname
,
fi
.
classname
)
\
%
{
"cls"
:
fi
.
classname
}
\
)
)
cvargs
=
[]
cvargs
=
[]
for
a
in
args
:
for
a
in
args
:
cva
=
a
.
name
cvargs
.
append
(
type_dict
[
a
.
ctype
].
get
(
"jni_name"
,
"%(n)s"
)
%
{
"n"
:
a
.
name
})
if
a
.
ctype
[
0
].
isupper
():
# Point/Rect/...
if
"jni_var"
in
type_dict
[
a
.
ctype
]:
# complex type
# "Point" : ("Point", (("int", ".x"), ("int", ".y")), "Point(%(n)s_x, %(n)s_y)", "II")
j2cvargs
.
append
(
type_dict
[
a
.
ctype
][
"jni_var"
]
%
{
"n"
:
a
.
name
}
+
";"
)
# Point(p_x, p_y)
cva
=
ctype2j
[
a
.
ctype
][
2
]
%
{
"n"
:
a
.
name
}
if
a
.
ctype
==
"Mat"
:
j2cvargs
.
append
(
"cv::Mat* %s = (cv::Mat*) %s_nativeObj; //TODO: check for NULL"
\
%
(
a
.
name
,
a
.
name
))
pass
cvargs
.
append
(
cva
)
rtype
=
"NYI"
if
fi
.
ctype
==
"Mat"
:
rtype
=
"jlong"
elif
fi
.
ctype
[
0
].
isupper
():
rtype
=
"NYI"
# TODO: NYI
else
:
rtype
=
ctype2j
[
fi
.
ctype
][
2
]
rtype
=
type_dict
[
fi
.
ctype
][
"jni_type"
]
self
.
cpp_code
.
write
(
Template
(
\
self
.
cpp_code
.
write
(
Template
(
\
"""
"""
#ifdef __cplusplus
#ifdef __cplusplus
...
@@ -471,7 +466,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_$fname
...
@@ -471,7 +466,7 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_$fname
rtype
=
rtype
,
\
rtype
=
rtype
,
\
module
=
self
.
module
,
\
module
=
self
.
module
,
\
fname
=
fi
.
jni_name
+
[
""
,
suffix
][
isoverload
],
\
fname
=
fi
.
jni_name
+
[
""
,
suffix
][
isoverload
],
\
args
=
", "
.
join
([
"%s %s"
%
(
ctype2j
[
a
.
ctype
][
2
]
,
a
.
name
)
for
a
in
jni_args
]),
\
args
=
", "
.
join
([
"%s %s"
%
(
type_dict
[
a
.
ctype
].
get
(
"jni_type"
)
,
a
.
name
)
for
a
in
jni_args
]),
\
j2cv
=
"
\n
"
.
join
([
a
for
a
in
j2cvargs
]),
\
j2cv
=
"
\n
"
.
join
([
a
for
a
in
j2cvargs
]),
\
ret
=
ret
,
\
ret
=
ret
,
\
cvname
=
cvname
,
\
cvname
=
cvname
,
\
...
@@ -481,7 +476,6 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_$fname
...
@@ -481,7 +476,6 @@ JNIEXPORT $rtype JNICALL Java_org_opencv_${module}_$fname
# processing args with default values
# processing args with default values
if
args
and
args
[
-
1
].
defval
:
if
args
and
args
[
-
1
].
defval
:
a
=
args
.
pop
()
a
=
args
.
pop
()
suffix
=
suffix
[
0
:
-
len
(
ctype2j
[
a
.
ctype
][
3
])]
else
:
else
:
break
break
...
...
modules/java/src/cpp/Mat.cpp
浏览文件 @
3159bd1a
...
@@ -292,7 +292,7 @@ JNIEXPORT jlong JNICALL Java_org_opencv_Mat_nClone
...
@@ -292,7 +292,7 @@ JNIEXPORT jlong JNICALL Java_org_opencv_Mat_nClone
}
}
// unlike other nPut()-s this one (with double[]) should convert input values to correct type
// unlike other nPut()-s this one (with double[]) should convert input values to correct type
#define PUT_ITEM(T, R, C) for(int ch=0; ch<me->channels() & count>0; ch++,count--) *((T*)me->ptr(R, C)+ch) = cv::saturate_cast<T>(*(src+ch))
#define PUT_ITEM(T, R, C) for(int ch=0; ch<me->channels() &
&
count>0; ch++,count--) *((T*)me->ptr(R, C)+ch) = cv::saturate_cast<T>(*(src+ch))
JNIEXPORT
jint
JNICALL
Java_org_opencv_Mat_nPutD
JNIEXPORT
jint
JNICALL
Java_org_opencv_Mat_nPutD
(
JNIEnv
*
env
,
jclass
cls
,
jlong
self
,
jint
row
,
jint
col
,
jint
count
,
jdoubleArray
vals
)
(
JNIEnv
*
env
,
jclass
cls
,
jlong
self
,
jint
row
,
jint
col
,
jint
count
,
jdoubleArray
vals
)
{
{
...
@@ -306,7 +306,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nPutD
...
@@ -306,7 +306,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nPutD
double
*
values
=
(
double
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
double
*
values
=
(
double
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
double
*
src
=
values
;
double
*
src
=
values
;
int
r
,
c
;
int
r
,
c
;
for
(
c
=
col
;
c
<
me
->
cols
&
count
>
0
;
c
++
)
for
(
c
=
col
;
c
<
me
->
cols
&
&
count
>
0
;
c
++
)
{
{
switch
(
me
->
depth
())
{
switch
(
me
->
depth
())
{
case
CV_8U
:
PUT_ITEM
(
uchar
,
row
,
c
);
break
;
case
CV_8U
:
PUT_ITEM
(
uchar
,
row
,
c
);
break
;
...
@@ -320,8 +320,8 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nPutD
...
@@ -320,8 +320,8 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nPutD
src
++
;
src
++
;
}
}
for
(
r
=
row
+
1
;
r
<
me
->
rows
&
count
>
0
;
r
++
)
for
(
r
=
row
+
1
;
r
<
me
->
rows
&
&
count
>
0
;
r
++
)
for
(
c
=
0
;
c
<
me
->
cols
&
count
>
0
;
c
++
)
for
(
c
=
0
;
c
<
me
->
cols
&
&
count
>
0
;
c
++
)
{
{
switch
(
me
->
depth
())
{
switch
(
me
->
depth
())
{
case
CV_8U
:
PUT_ITEM
(
uchar
,
r
,
c
);
break
;
case
CV_8U
:
PUT_ITEM
(
uchar
,
r
,
c
);
break
;
...
@@ -475,7 +475,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetS
...
@@ -475,7 +475,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetS
{
{
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
if
(
!
self
)
return
0
;
// no native object behind
if
(
!
self
)
return
0
;
// no native object behind
if
(
me
->
depth
()
!=
CV_
8U
&&
me
->
depth
()
!=
CV_8
S
)
return
0
;
// incompatible type
if
(
me
->
depth
()
!=
CV_
16U
&&
me
->
depth
()
!=
CV_16
S
)
return
0
;
// incompatible type
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
...
@@ -489,7 +489,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetI
...
@@ -489,7 +489,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetI
{
{
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
if
(
!
self
)
return
0
;
// no native object behind
if
(
!
self
)
return
0
;
// no native object behind
if
(
me
->
depth
()
!=
CV_
8U
&&
me
->
depth
()
!=
CV_8
S
)
return
0
;
// incompatible type
if
(
me
->
depth
()
!=
CV_
32
S
)
return
0
;
// incompatible type
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
...
@@ -503,7 +503,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetF
...
@@ -503,7 +503,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetF
{
{
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
if
(
!
self
)
return
0
;
// no native object behind
if
(
!
self
)
return
0
;
// no native object behind
if
(
me
->
depth
()
!=
CV_
8U
&&
me
->
depth
()
!=
CV_8S
)
return
0
;
// incompatible type
if
(
me
->
depth
()
!=
CV_
32F
)
return
0
;
// incompatible type
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
...
@@ -517,7 +517,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetD
...
@@ -517,7 +517,7 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetD
{
{
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
if
(
!
self
)
return
0
;
// no native object behind
if
(
!
self
)
return
0
;
// no native object behind
if
(
me
->
depth
()
!=
CV_
8U
&&
me
->
depth
()
!=
CV_8S
)
return
0
;
// incompatible type
if
(
me
->
depth
()
!=
CV_
64F
)
return
0
;
// incompatible type
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
char
*
values
=
(
char
*
)
env
->
GetPrimitiveArrayCritical
(
vals
,
0
);
...
@@ -526,12 +526,36 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetD
...
@@ -526,12 +526,36 @@ JNIEXPORT jint JNICALL Java_org_opencv_Mat_nGetD
return
res
;
return
res
;
}
}
JNIEXPORT
jdoubleArray
JNICALL
Java_org_opencv_Mat_nGet
(
JNIEnv
*
env
,
jclass
cls
,
jlong
self
,
jint
row
,
jint
col
,
jint
count
)
{
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
if
(
!
self
)
return
0
;
// no native object behind
if
(
me
->
rows
<=
row
||
me
->
cols
<=
col
)
return
0
;
// indexes out of range
jdoubleArray
res
=
env
->
NewDoubleArray
(
me
->
channels
());
if
(
res
){
jdouble
buff
[
me
->
channels
()];
int
i
;
switch
(
me
->
depth
()){
case
CV_8U
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
unsigned
char
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
case
CV_8S
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
signed
char
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
case
CV_16U
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
unsigned
short
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
case
CV_16S
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
signed
short
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
case
CV_32S
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
int
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
case
CV_32F
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
float
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
case
CV_64F
:
for
(
i
=
0
;
i
<
me
->
channels
();
i
++
)
buff
[
i
]
=
*
((
double
*
)
me
->
ptr
(
row
,
col
)
+
i
);
break
;
}
env
->
SetDoubleArrayRegion
(
res
,
0
,
me
->
channels
(),
buff
);
}
return
res
;
}
JNIEXPORT
void
JNICALL
Java_org_opencv_Mat_nSetTo
JNIEXPORT
void
JNICALL
Java_org_opencv_Mat_nSetTo
(
JNIEnv
*
env
,
jclass
cls
,
jlong
self
,
jdouble
v0
,
jdouble
v1
,
jdouble
v2
,
jdouble
v3
)
(
JNIEnv
*
env
,
jclass
cls
,
jlong
self
,
jdouble
v0
,
jdouble
v1
,
jdouble
v2
,
jdouble
v3
)
{
{
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
//TODO: check for NULL
cv
::
Mat
*
me
=
(
cv
::
Mat
*
)
self
;
//TODO: check for NULL
me
->
setTo
(
cv
::
Scalar
(
v0
,
v1
,
v2
,
v3
)
,
cv
::
Mat
()
);
me
->
setTo
(
cv
::
Scalar
(
v0
,
v1
,
v2
,
v3
)
);
}
}
JNIEXPORT
void
JNICALL
Java_org_opencv_Mat_nCopyTo
JNIEXPORT
void
JNICALL
Java_org_opencv_Mat_nCopyTo
...
...
modules/java/src/java/Mat.java
浏览文件 @
3159bd1a
...
@@ -339,6 +339,15 @@ public class Mat {
...
@@ -339,6 +339,15 @@ public class Mat {
throw
new
java
.
lang
.
UnsupportedOperationException
(
"Mat data type is not compatible: "
+
t
);
throw
new
java
.
lang
.
UnsupportedOperationException
(
"Mat data type is not compatible: "
+
t
);
}
}
public
double
[]
get
(
int
row
,
int
col
)
{
checkNull
();
//CvType t = type();
//if(t.depth() == CvType.CV_64F) {
return
nGet
(
nativeObj
,
row
,
col
);
//}
//throw new java.lang.UnsupportedOperationException("Mat data type is not compatible: " + t);
}
public
void
setTo
(
double
v0
,
double
v1
,
double
v2
,
double
v3
)
{
public
void
setTo
(
double
v0
,
double
v1
,
double
v2
,
double
v3
)
{
checkNull
();
checkNull
();
...
@@ -399,6 +408,7 @@ public class Mat {
...
@@ -399,6 +408,7 @@ public class Mat {
private
static
native
int
nGetI
(
long
self
,
int
row
,
int
col
,
int
count
,
int
[]
vals
);
private
static
native
int
nGetI
(
long
self
,
int
row
,
int
col
,
int
count
,
int
[]
vals
);
private
static
native
int
nGetF
(
long
self
,
int
row
,
int
col
,
int
count
,
float
[]
vals
);
private
static
native
int
nGetF
(
long
self
,
int
row
,
int
col
,
int
count
,
float
[]
vals
);
private
static
native
int
nGetD
(
long
self
,
int
row
,
int
col
,
int
count
,
double
[]
vals
);
private
static
native
int
nGetD
(
long
self
,
int
row
,
int
col
,
int
count
,
double
[]
vals
);
private
static
native
double
[]
nGet
(
long
self
,
int
row
,
int
col
);
private
static
native
void
nSetTo
(
long
self
,
double
v0
,
double
v1
,
double
v2
,
double
v3
);
private
static
native
void
nSetTo
(
long
self
,
double
v0
,
double
v1
,
double
v2
,
double
v3
);
private
static
native
void
nCopyTo
(
long
self
,
long
mat
);
private
static
native
void
nCopyTo
(
long
self
,
long
mat
);
private
static
native
double
nDot
(
long
self
,
long
mat
);
private
static
native
double
nDot
(
long
self
,
long
mat
);
...
...
samples/android/1-java/src/org/opencv/samples/s1/Sample1View.java
浏览文件 @
3159bd1a
...
@@ -10,6 +10,8 @@ import android.view.SurfaceHolder;
...
@@ -10,6 +10,8 @@ import android.view.SurfaceHolder;
import
android.view.SurfaceView
;
import
android.view.SurfaceView
;
import
org.opencv.Mat
;
import
org.opencv.Mat
;
import
org.opencv.Point
;
import
org.opencv.Scalar
;
import
org.opencv.Size
;
import
org.opencv.Size
;
import
org.opencv.core
;
import
org.opencv.core
;
import
org.opencv.imgproc
;
import
org.opencv.imgproc
;
...
@@ -142,6 +144,7 @@ class Sample1View extends SurfaceView implements SurfaceHolder.Callback, Runnabl
...
@@ -142,6 +144,7 @@ class Sample1View extends SurfaceView implements SurfaceHolder.Callback, Runnabl
break
;
break
;
case
Sample1Java
.
VIEW_MODE_RGBA
:
case
Sample1Java
.
VIEW_MODE_RGBA
:
imgproc
.
cvtColor
(
mYuv
,
mRgba
,
imgproc
.
CV_YUV420i2RGB
,
4
);
imgproc
.
cvtColor
(
mYuv
,
mRgba
,
imgproc
.
CV_YUV420i2RGB
,
4
);
core
.
putText
(
mRgba
,
"OpenCV + Android"
,
new
Point
(
10
,
100
),
3
/*CV_FONT_HERSHEY_COMPLEX*/
,
2
,
new
Scalar
(
0
,
255
,
0
,
255
),
3
);
break
;
break
;
case
Sample1Java
.
VIEW_MODE_CANNY
:
case
Sample1Java
.
VIEW_MODE_CANNY
:
imgproc
.
Canny
(
mGraySubmat
,
mIntermediateMat
,
80
,
100
);
imgproc
.
Canny
(
mGraySubmat
,
mIntermediateMat
,
80
,
100
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录