diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json
index 86f36165..b430fd8a 100644
--- a/.changelog/lang_zh-Hans.json
+++ b/.changelog/lang_zh-Hans.json
@@ -11,17 +11,18 @@
"使用 XML 语法将 JavaScript 表达式作为属性值时, this 对象可能出现指向错误的问题",
"调用 images.requestScreenCapture 时用户取消授权可能导致应用崩溃的问题",
"images 部分相关方法出现异常时 oneShot 标记功能失效的问题 _[`issue #372`](http://issues.autojs6.com/372)_",
+ "images 部分相关方法可能引发内存泄露的问题 _[`issue #372`](http://issues.autojs6.com/372)_",
"Android 10 UiObject#child 方法可能出现 ArrayIndexOutOfBoundsException 异常的问题 _[`issue #416`](http://issues.autojs6.com/416)_",
"打包应用无法正常使用 Paddle OCR 与 Rapid OCR 功能的问题",
"版本历史页面部分系统因字体差别导致统计数据显示不完整的问题",
"ErrorDialogActivity 可能无法正常启动的问题 _[`issue #414`](http://issues.autojs6.com/414)_ _[`issue #340`](http://issues.autojs6.com/340#issuecomment-2973485826)_",
- "错误报告页面复制详细信息功能失效的问题"
+ "崩溃报告页面复制详细信息功能失效的问题"
],
"improvement": [
"http 模块相关方法支持不安全选项参数 (isInsecure/insecure), 用于忽略证书相关异常 _[`issue #417`](http://issues.autojs6.com/417)_",
"android.graphics.Paint#setColor 支持正常解析 ColorInt/ColorHex/ColorName 等颜色参数",
"内置模块相关方法实参类型的异常消息增加类型摘要信息",
- "错误报告页面支持双指缩放调整字体大小并添加常用功能按钮"
+ "崩溃报告页面支持双指缩放调整字体大小并添加常用功能按钮"
],
"dependency": [
"附加 Androidx Core (KTX) 版本 1.16.0",
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index aab3828d..151b7a5b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -290,8 +290,8 @@
android:name="org.autojs.autojs.ui.settings.DeveloperOptionsActivity"
android:theme="@style/AppTheme.Settings" />
-
-
+
+
referenceQueue = new ReferenceQueue<>();
-
- static {
- Executors.newFixedThreadPool(1).execute(() -> {
- while (true) {
- try {
- NativeObjectReference> nativeObjectReference = (NativeObjectReference>) Cleaner.referenceQueue.remove();
- if (nativeObjectReference == null) {
- continue;
- }
- instance.cleanup(nativeObjectReference);
- } catch (InterruptedException e) {
- /* Ignored. */
- }
- break;
- }
- });
- }
-
- public void cleanup(NativeObjectReference> nativeObjectReference) {
- try {
- pointer.decrementAndGet();
- RegisteredCleaners.registeredCleaners.remove(nativeObjectReference);
- long pointer = nativeObjectReference.pointer;
- if (pointer == 0L) return;
- nativeObjectReference.cleaner.cleanup(pointer);
- nativeObjectReference.pointer = 0L;
- } catch (Throwable throwable) {
- Log.w(Cleaner.class.getSimpleName(), "cleanup error: " + nativeObjectReference.pointer, throwable);
- }
- }
-
- public void cleanup(MonitorResource resource, ICleaner cleaner) {
- resource.getPointer();
- NativeObjectReference resourceNativeCleaner = new NativeObjectReference<>(resource, referenceQueue, cleaner);
- resourceNativeCleaner.pointer = resource.getPointer();
- resource.setNativeObjectReference(resourceNativeCleaner);
- RegisteredCleaners.registeredCleaners.add(resourceNativeCleaner);
- pointer.incrementAndGet();
- }
-
-}
diff --git a/app/src/main/java/org/autojs/autojs/core/cleaner/ICleaner.java b/app/src/main/java/org/autojs/autojs/core/cleaner/ICleaner.java
deleted file mode 100644
index c4ca8c7c..00000000
--- a/app/src/main/java/org/autojs/autojs/core/cleaner/ICleaner.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.autojs.autojs.core.cleaner;
-
-/**
- * Created by SuperMonster003 on Dec 22, 2023.
- */
-// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 22, 2023.
-public interface ICleaner {
-
- void cleanup(final long pointer);
-
-}
diff --git a/app/src/main/java/org/autojs/autojs/core/cleaner/RegisteredCleaners.java b/app/src/main/java/org/autojs/autojs/core/cleaner/RegisteredCleaners.java
deleted file mode 100644
index 2349ecb0..00000000
--- a/app/src/main/java/org/autojs/autojs/core/cleaner/RegisteredCleaners.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.autojs.autojs.core.cleaner;
-
-import org.autojs.autojs.core.ref.MonitorResource;
-import org.autojs.autojs.core.ref.NativeObjectReference;
-
-import java.util.Collections;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Created by SuperMonster003 on Dec 22, 2023.
- */
-// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 22, 2023.
-public final class RegisteredCleaners {
-
- public static final Set> registeredCleaners = Collections.newSetFromMap(new ConcurrentHashMap<>());
-
-}
diff --git a/app/src/main/java/org/autojs/autojs/core/image/ImageWrapper.kt b/app/src/main/java/org/autojs/autojs/core/image/ImageWrapper.kt
index 854bacf2..a68c90db 100644
--- a/app/src/main/java/org/autojs/autojs/core/image/ImageWrapper.kt
+++ b/app/src/main/java/org/autojs/autojs/core/image/ImageWrapper.kt
@@ -9,8 +9,6 @@ import androidx.core.graphics.get
import org.autojs.autojs.annotation.ScriptInterface
import org.autojs.autojs.core.opencv.Mat
import org.autojs.autojs.core.opencv.OpenCVHelper
-import org.autojs.autojs.core.ref.MonitorResource
-import org.autojs.autojs.core.ref.NativeObjectReference
import org.autojs.autojs.pio.UncheckedIOException
import org.autojs.autojs.runtime.ScriptRuntime
import org.autojs.autojs.runtime.api.Images
@@ -24,7 +22,6 @@ import org.opencv.imgproc.Imgproc
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.lang.ref.WeakReference
-import java.util.concurrent.atomic.AtomicLong
/**
* Created by Stardust on Nov 25, 2017.
@@ -32,14 +29,14 @@ import java.util.concurrent.atomic.AtomicLong
* Transformed by SuperMonster003 on May 16, 2023.
*/
// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 20, 2023.
-open class ImageWrapper : Shootable, MonitorResource {
+open class ImageWrapper : Shootable {
private var mScriptRuntime: ScriptRuntime
private var mMat: Mat? = null
private var mBgrMat: Mat? = null
private var mBitmap: Bitmap? = null
- private var mRef: NativeObjectReference? = null
+ private var mMediaImage: Image? = null
private var mPlane: Image.Plane? = null
private var mWidth = 0
@@ -47,12 +44,6 @@ open class ImageWrapper : Shootable, MonitorResource {
private var mIsRecycled = false
private var mIsOneShot = false
- private var mId = 0L
- private val mNextId = AtomicLong()
-
- var mediaImage: Image? = null
- private set
-
val width
get() = mWidth.also { ensureNotRecycled() }
@@ -71,10 +62,7 @@ open class ImageWrapper : Shootable, MonitorResource {
val bitmap = createBitmap(mat.width(), mat.height()).also { mBitmap = it }
Utils.matToBitmap(mat, bitmap)
} else {
- val mediaImage = mediaImage
- if (mediaImage != null) {
- mBitmap = toBitmap(mediaImage)
- }
+ mMediaImage?.let { mBitmap = toBitmap(it) }
}
}
return mBitmap ?: throw Exception("Bitmap of ImageWrapper should never be null")
@@ -93,7 +81,7 @@ open class ImageWrapper : Shootable, MonitorResource {
Utils.bitmapToMat(bitmap, newMat)
return newMat
}
- if (mediaImage != null) {
+ if (mMediaImage != null) {
val plane = plane ?: throw AssertionError("Image plain is null")
plane.buffer.position(0)
return Mat(mHeight, mWidth, CvType.CV_8UC4, plane.buffer, plane.rowStride.toLong()).also { mMat = it }
@@ -111,13 +99,12 @@ open class ImageWrapper : Shootable, MonitorResource {
private set(plane) {
mPlane = plane
}
- get() = mPlane ?: mediaImage?.planes?.get(0)
+ get() = mPlane ?: mMediaImage?.planes?.get(0)
constructor(scriptRuntime: ScriptRuntime, width: Int, height: Int) : this(scriptRuntime, createBitmap(width, height))
constructor(scriptRuntime: ScriptRuntime, bitmap: Bitmap) {
mScriptRuntime = scriptRuntime
- mId = mNextId.incrementAndGet()
mBitmap = bitmap.also { addToList(it) }
mWidth = bitmap.width
mHeight = bitmap.height
@@ -125,7 +112,6 @@ open class ImageWrapper : Shootable, MonitorResource {
constructor(scriptRuntime: ScriptRuntime, mat: Mat) {
mScriptRuntime = scriptRuntime
- mId = mNextId.incrementAndGet()
mMat = mat.also { addToList(it) }
mWidth = mat.cols()
mHeight = mat.rows()
@@ -133,7 +119,6 @@ open class ImageWrapper : Shootable, MonitorResource {
constructor(scriptRuntime: ScriptRuntime, mat: org.opencv.core.Mat) {
mScriptRuntime = scriptRuntime
- mId = mNextId.incrementAndGet()
mMat = when (mat.nativeObj != 0L) {
true -> Mat(mat.nativeObj)
else -> Mat(mat.rows(), mat.cols(), mat.type())
@@ -144,7 +129,6 @@ open class ImageWrapper : Shootable, MonitorResource {
constructor(scriptRuntime: ScriptRuntime, bitmap: Bitmap, mat: Mat?) {
mScriptRuntime = scriptRuntime
- mId = mNextId.incrementAndGet()
mMat = mat?.also { addToList(it) }
mBitmap = bitmap.also { addToList(it) }
mWidth = bitmap.width
@@ -153,8 +137,7 @@ open class ImageWrapper : Shootable, MonitorResource {
constructor(scriptRuntime: ScriptRuntime, mediaImage: Image) {
mScriptRuntime = scriptRuntime
- mId = mNextId.incrementAndGet()
- this.mediaImage = mediaImage.also { addToList(it) }
+ mMediaImage = mediaImage.also { addToList(it) }
mWidth = mediaImage.width
mHeight = mediaImage.height
}
@@ -269,12 +252,10 @@ open class ImageWrapper : Shootable, MonitorResource {
OpenCVHelper.release(it)
mBgrMat = null
}
- mediaImage?.let {
+ mMediaImage?.let {
it.close()
- mediaImage = null
- }
- mRef?.let {
- it.pointer = 0L
+ mMediaImage = null
+ mPlane = null
}
mIsRecycled = true
}
@@ -301,12 +282,6 @@ open class ImageWrapper : Shootable, MonitorResource {
}
}
- override fun getPointer() = mId
-
- override fun setNativeObjectReference(reference: NativeObjectReference) {
- mRef = reference
- }
-
companion object {
private val imageList = ArrayList>()
diff --git a/app/src/main/java/org/autojs/autojs/core/image/TemplateMatching.java b/app/src/main/java/org/autojs/autojs/core/image/TemplateMatching.java
index c24c0284..c6ecd0ca 100644
--- a/app/src/main/java/org/autojs/autojs/core/image/TemplateMatching.java
+++ b/app/src/main/java/org/autojs/autojs/core/image/TemplateMatching.java
@@ -158,32 +158,28 @@ public class TemplateMatching {
Mat currentTemplate = getPyramidDownAtLevel(template, level);
Mat transparentMask = useTransparentMask ? createTransparentMask(currentTemplate) : null;
- boolean shouldStop;
-
- Label_Check_Should_Stop:
- {
- // 如果在上一轮中没有匹配到图片, 则考虑是否退出匹配
- if (previousMatchResult.isEmpty()) {
- // 如果不是第一次匹配, 并且不满足shouldContinueMatching的条件, 则直接退出匹配
- if (!isFirstMatching && !shouldContinueMatching(level, selectPyramidLevel)) {
- shouldStop = true;
- break Label_Check_Should_Stop;
- }
- Mat matchResult = matchTemplate(src, currentTemplate, matchingMethod, transparentMask);
- getBestMatched(matchResult, currentTemplate, matchingMethod, weakThreshold, currentMatchResult, limit, level, null, finalMatchResult);
- OpenCVHelper.release(matchResult);
- } else {
- for (Match match : previousMatchResult) {
- // 根据上一轮的匹配点, 计算本次匹配的区域
- Rect roi = getROI(match.point, src, currentTemplate);
- Mat m = new Mat(src, roi);
- Mat matchResult = matchTemplate(m, currentTemplate, matchingMethod, transparentMask);
- getBestMatched(matchResult, currentTemplate, matchingMethod, weakThreshold, currentMatchResult, limit, level, roi, finalMatchResult);
- OpenCVHelper.release(m);
- OpenCVHelper.release(matchResult);
- }
+ // 如果在上一轮中没有匹配到图片, 则考虑是否退出匹配
+ if (previousMatchResult.isEmpty()) {
+ // 如果不是第一次匹配, 并且不满足shouldContinueMatching的条件, 则直接退出匹配
+ if (!isFirstMatching && !shouldContinueMatching(level, selectPyramidLevel)) {
+ releaseIfNeeded(src, img);
+ releaseIfNeeded(currentTemplate, template);
+ OpenCVHelper.release(transparentMask);
+ break;
+ }
+ Mat matchResult = matchTemplate(src, currentTemplate, matchingMethod, transparentMask);
+ getBestMatched(matchResult, currentTemplate, matchingMethod, weakThreshold, currentMatchResult, limit, level, null, finalMatchResult);
+ OpenCVHelper.release(matchResult);
+ } else {
+ for (Match match : previousMatchResult) {
+ // 根据上一轮的匹配点, 计算本次匹配的区域
+ Rect roi = getROI(match.point, src, currentTemplate);
+ Mat m = new Mat(src, roi);
+ Mat matchResult = matchTemplate(m, currentTemplate, matchingMethod, transparentMask);
+ getBestMatched(matchResult, currentTemplate, matchingMethod, weakThreshold, currentMatchResult, limit, level, roi, finalMatchResult);
+ OpenCVHelper.release(m);
+ OpenCVHelper.release(matchResult);
}
- shouldStop = false;
}
releaseIfNeeded(src, img);
releaseIfNeeded(currentTemplate, template);
@@ -191,26 +187,24 @@ public class TemplateMatching {
logger.addSplit("level:" + level + ", result:" + previousMatchResult);
- if (!shouldStop) {
- // 把满足强阈值的点找出来, 加到最终结果列表
- if (!currentMatchResult.isEmpty()) {
- Iterator iterator = currentMatchResult.iterator();
- while (iterator.hasNext()) {
- Match match = iterator.next();
- if (match.similarity >= strictThreshold) {
- pyrUp(match.point, level);
- finalMatchResult.add(match);
- iterator.remove();
- }
- }
- // 如果所有结果都满足强阈值, 则退出循环, 返回最终结果
- if (currentMatchResult.isEmpty()) {
- break;
+ // 把满足强阈值的点找出来, 加到最终结果列表
+ if (!currentMatchResult.isEmpty()) {
+ Iterator iterator = currentMatchResult.iterator();
+ while (iterator.hasNext()) {
+ Match match = iterator.next();
+ if (match.similarity >= strictThreshold) {
+ pyrUp(match.point, level);
+ finalMatchResult.add(match);
+ iterator.remove();
}
}
- previousMatchResult = currentMatchResult;
- isFirstMatching = false;
+ // 如果所有结果都满足强阈值, 则退出循环, 返回最终结果
+ if (currentMatchResult.isEmpty()) {
+ break;
+ }
}
+ isFirstMatching = false;
+ previousMatchResult = currentMatchResult;
}
logger.addSplit("result:" + finalMatchResult);
logger.dumpToLog();
diff --git a/app/src/main/java/org/autojs/autojs/core/opencv/Mat.java b/app/src/main/java/org/autojs/autojs/core/opencv/Mat.java
index 1740f703..ce344112 100644
--- a/app/src/main/java/org/autojs/autojs/core/opencv/Mat.java
+++ b/app/src/main/java/org/autojs/autojs/core/opencv/Mat.java
@@ -1,10 +1,6 @@
package org.autojs.autojs.core.opencv;
import androidx.annotation.NonNull;
-import org.autojs.autojs.core.cleaner.Cleaner;
-import org.autojs.autojs.core.cleaner.ICleaner;
-import org.autojs.autojs.core.ref.MonitorResource;
-import org.autojs.autojs.core.ref.NativeObjectReference;
import org.opencv.core.CvType;
import org.opencv.core.Range;
import org.opencv.core.Rect;
@@ -15,105 +11,80 @@ import org.opencv.imgproc.Imgproc;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
-public class Mat extends org.opencv.core.Mat implements MonitorResource {
-
- public static final ICleaner MAT_CLEANER = new MatCleaner(null);
+public class Mat extends org.opencv.core.Mat {
private volatile boolean mReleased;
-
+
private static final Method nClone = findMethod("n_clone", Long.TYPE);
private static final Method nOnes = findMethod("n_ones", Integer.TYPE, Integer.TYPE, Integer.TYPE);
private static final Method nRelease = findMethod("n_release", Long.TYPE);
-
- private NativeObjectReference mReference;
public Mat() {
super();
- init();
}
public Mat(long addr) {
super(addr);
- init();
}
public Mat(int rows, int cols, int type) {
super(rows, cols, type);
- init();
}
public Mat(Size size, int type) {
super(size, type);
- init();
}
public Mat(int rows, int cols, int type, Scalar s) {
super(rows, cols, type, s);
- init();
}
public Mat(Size size, int type, Scalar s) {
super(size, type, s);
- init();
}
public Mat(Mat m, Range rowRange, Range colRange) {
super(m, rowRange, colRange);
- init();
}
public Mat(Mat m, Range rowRange) {
super(m, rowRange);
- init();
}
public Mat(Mat m, Rect roi) {
super(m, roi);
- init();
}
public Mat(int rows, int cols, int type, ByteBuffer data) {
super(rows, cols, type, data);
- init();
}
public Mat(int rows, int cols, int type, ByteBuffer data, long step) {
super(rows, cols, type, data, step);
- init();
}
public Mat(org.opencv.core.Mat opencvMat, Range rowRange) {
super(opencvMat, rowRange);
- init();
}
public Mat(org.opencv.core.Mat opencvMat, Range rowRange, Range colRange) {
super(opencvMat, rowRange, colRange);
- init();
}
public Mat(org.opencv.core.Mat opencvMat, Rect rect) {
super(opencvMat, rect);
- init();
}
public Mat(org.opencv.core.Mat opencvMat, Range[] ranges) {
super(opencvMat, ranges);
- init();
}
public Mat(int[] sizes, int type) {
super(sizes, type);
- init();
}
public Mat(int[] sizes, int type, Scalar scalar) {
super(sizes, type, scalar);
- init();
- }
-
- private void init() {
- Cleaner.instance.cleanup(this, MAT_CLEANER);
}
private static Method findMethod(final String s, final Class>... array) {
@@ -179,34 +150,19 @@ public class Mat extends org.opencv.core.Mat implements MonitorResource {
return nRelease;
}
- @Override
- public long getPointer() {
- return super.nativeObj;
- }
-
- @Override
- public void setNativeObjectReference(final NativeObjectReference reference) {
- mReference = reference;
- }
-
- public String getPointerString() {
- return Long.toString(super.nativeObj);
- }
-
public boolean isReleased() {
- return mReleased || mReference != null && mReference.pointer == 0L;
+ return mReleased;
}
@Override
public void release() {
- if (mReleased) return;
- synchronized (this) {
- if (mReleased) return;
- mReleased = true;
- if (mReference != null) {
- mReference.pointer = 0L;
+ if (!mReleased) {
+ synchronized (this) {
+ if (!mReleased) {
+ super.release();
+ mReleased = true;
+ }
}
- super.release();
}
}
diff --git a/app/src/main/java/org/autojs/autojs/core/opencv/MatCleaner.java b/app/src/main/java/org/autojs/autojs/core/opencv/MatCleaner.java
deleted file mode 100644
index 345e1ced..00000000
--- a/app/src/main/java/org/autojs/autojs/core/opencv/MatCleaner.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.autojs.autojs.core.opencv;
-
-import org.autojs.autojs.core.cleaner.ICleaner;
-import org.autojs.autojs.runtime.api.Images;
-
-/**
- * Created by SuperMonster003 on Jan 5, 2024.
- */
-// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Jan 5, 2024.
-public class MatCleaner implements ICleaner {
-
- private MatCleaner() {
- /* Empty body. */
- }
-
- public MatCleaner(Object object) {
- this();
- }
-
- @Override
- public void cleanup(long pointer) {
- try {
- Images.initOpenCvIfNeeded();
- Mat.n_release().invoke(null, pointer);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/app/src/main/java/org/autojs/autojs/core/opencv/MatOfPoint.java b/app/src/main/java/org/autojs/autojs/core/opencv/MatOfPoint.java
index 5272f4c0..550d2b1c 100644
--- a/app/src/main/java/org/autojs/autojs/core/opencv/MatOfPoint.java
+++ b/app/src/main/java/org/autojs/autojs/core/opencv/MatOfPoint.java
@@ -1,62 +1,41 @@
package org.autojs.autojs.core.opencv;
-import org.autojs.autojs.core.cleaner.Cleaner;
-import org.autojs.autojs.core.ref.MonitorResource;
-import org.autojs.autojs.core.ref.NativeObjectReference;
import org.opencv.core.Point;
/**
* Modified by SuperMonster003 as of Jan 21, 2023.
*/
// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 18, 2023.
-public class MatOfPoint extends org.opencv.core.MatOfPoint implements MonitorResource {
+public class MatOfPoint extends org.opencv.core.MatOfPoint {
private volatile boolean mReleased = false;
- private NativeObjectReference mReference;
-
public MatOfPoint() {
- init();
+ super();
}
public MatOfPoint(long l) {
super(l);
- init();
}
public MatOfPoint(org.opencv.core.Mat mat) {
super(mat);
- init();
}
public MatOfPoint(Point... pointArray) {
super(pointArray);
- init();
- }
-
- private void init() {
- Cleaner.instance.cleanup(this, Mat.MAT_CLEANER);
}
@Override
public void release() {
- if (mReleased) return;
- synchronized (this) {
- if (mReleased) return;
- mReleased = true;
- if (mReference != null) {
- mReference.pointer = 0L;
+ if (!mReleased) {
+ synchronized (this) {
+ if (!mReleased) {
+ super.release();
+ mReleased = true;
+ }
}
- super.release();
}
}
- public long getPointer() {
- return nativeObj;
- }
-
- public void setNativeObjectReference(NativeObjectReference reference) {
- mReference = reference;
- }
-
}
diff --git a/app/src/main/java/org/autojs/autojs/core/ref/MonitorResource.java b/app/src/main/java/org/autojs/autojs/core/ref/MonitorResource.java
deleted file mode 100644
index a2e5f559..00000000
--- a/app/src/main/java/org/autojs/autojs/core/ref/MonitorResource.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.autojs.autojs.core.ref;
-
-/**
- * Created by SuperMonster003 on Dec 20, 2023.
- */
-// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 20, 2023.
-public interface MonitorResource {
-
- long getPointer();
-
- void setNativeObjectReference(final NativeObjectReference reference);
-
-}
diff --git a/app/src/main/java/org/autojs/autojs/core/ref/NativeObjectReference.java b/app/src/main/java/org/autojs/autojs/core/ref/NativeObjectReference.java
deleted file mode 100644
index 61cff521..00000000
--- a/app/src/main/java/org/autojs/autojs/core/ref/NativeObjectReference.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.autojs.autojs.core.ref;
-
-import org.autojs.autojs.core.cleaner.ICleaner;
-
-import java.lang.ref.*;
-
-/**
- * Created by SuperMonster003 on Dec 15, 2023.
- */
-// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 15, 2023.
-public final class NativeObjectReference extends PhantomReference {
-
- public final ICleaner cleaner;
- public volatile long pointer;
-
- public NativeObjectReference(final T referent, final ReferenceQueue super T> referenceQueue, final ICleaner cleaner) {
- super(referent, referenceQueue);
- this.cleaner = cleaner;
- }
-
-}
diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/ImageFeatureMatching.java b/app/src/main/java/org/autojs/autojs/runtime/api/ImageFeatureMatching.java
index a893bc43..d96cdeda 100644
--- a/app/src/main/java/org/autojs/autojs/runtime/api/ImageFeatureMatching.java
+++ b/app/src/main/java/org/autojs/autojs/runtime/api/ImageFeatureMatching.java
@@ -4,10 +4,6 @@ import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.autojs.autojs.annotation.ScriptInterface;
-import org.autojs.autojs.core.cleaner.Cleaner;
-import org.autojs.autojs.core.cleaner.ICleaner;
-import org.autojs.autojs.core.ref.MonitorResource;
-import org.autojs.autojs.core.ref.NativeObjectReference;
import org.autojs.autojs.util.ImageUtils;
import org.opencv.calib3d.Calib3d;
import org.opencv.core.Core;
@@ -314,11 +310,10 @@ public final class ImageFeatureMatching {
* A reusable bundle of feature-extraction results for a single image.
* zh-CN: 单张图片的特征提取结果集合.
*/
- public static class FeatureMatchingDescriptor implements MonitorResource {
+ public static class FeatureMatchingDescriptor {
private final Mat mDescriptors;
private long mNativePtr;
- private NativeObjectReference mRef;
private final MatOfKeyPoint mKeyPoint;
private final MatOfPoint2f mCorners;
@@ -344,18 +339,12 @@ public final class ImageFeatureMatching {
mNativePtr = descriptors.nativeObj;
mKeyPoint = keyPoint;
mCorners = corners;
- Cleaner.instance.cleanup(this, SelfCleaner.INSTANCE);
}
public long getNativePtr() {
return mNativePtr;
}
- @Override
- public long getPointer() {
- return mNativePtr;
- }
-
public MatOfKeyPoint getKeyPoint() {
return mKeyPoint;
}
@@ -367,20 +356,12 @@ public final class ImageFeatureMatching {
public void release() {
synchronized (this) {
if (mNativePtr != 0L) {
- SelfCleaner.INSTANCE.cleanup(mNativePtr);
+ releaseFeatureMatchingDescriptor(mNativePtr);
mNativePtr = 0L;
- if (mRef != null) {
- mRef.pointer = 0L;
- }
}
}
}
- @Override
- public void setNativeObjectReference(NativeObjectReference ref) {
- mRef = ref;
- }
-
public void setNativePtr(long nativePtr) {
mNativePtr = nativePtr;
}
@@ -389,23 +370,6 @@ public final class ImageFeatureMatching {
return mCorners;
}
- public static class SelfCleaner implements ICleaner {
-
- public static SelfCleaner INSTANCE;
-
- static {
- INSTANCE = new SelfCleaner();
- }
-
- private SelfCleaner() {
- /* Empty body. */
- }
-
- @Override
- public void cleanup(long pointer) {
- releaseFeatureMatchingDescriptor(pointer);
- }
- }
}
/**
diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/Images.java b/app/src/main/java/org/autojs/autojs/runtime/api/Images.java
index 4df737de..97624d6a 100644
--- a/app/src/main/java/org/autojs/autojs/runtime/api/Images.java
+++ b/app/src/main/java/org/autojs/autojs/runtime/api/Images.java
@@ -628,7 +628,6 @@ public class Images {
throw new NullPointerException(mContext.getString(R.string.error_method_called_with_null_argument, "Images.findImage", "template"));
}
Mat src = image.getMat();
- boolean shouldReleaseMat = false;
if (rect != null) {
if (template.getWidth() > rect.width) {
throw new Exception(mContext.getString(R.string.error_excessive_width_for_template_n_region, template.getWidth(), rect.width));
@@ -637,7 +636,6 @@ public class Images {
throw new Exception(mContext.getString(R.string.error_excessive_height_for_template_n_region, template.getHeight(), rect.height));
}
src = new Mat(src, rect);
- shouldReleaseMat = true;
}
@Nullable
org.opencv.core.Point point;
@@ -645,10 +643,10 @@ public class Images {
point = TemplateMatching.singleTemplateMatching(
src,
template.getMat(),
- new TemplateMatching.Options(-1, weakThreshold, strictThreshold, maxLevel)
+ new TemplateMatching.Options(TemplateMatching.MATCHING_METHOD_NONE, weakThreshold, strictThreshold, maxLevel)
);
} finally {
- if (shouldReleaseMat) {
+ if (src != image.getMat()) {
OpenCVHelper.release(src);
}
}
diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt
index 8ca2ef8d..388fcfda 100644
--- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt
+++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt
@@ -760,14 +760,15 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
@RhinoRuntimeFunctionInterface
fun concat(scriptRuntime: ScriptRuntime, args: Array): ImageWrapper = ensureArgumentsLengthInRange(args, 2..3) {
val (oA, oB, direction) = it
- val imageA = if (oA.isJsString()) read(scriptRuntime, arrayOf(coerceString(oA), true))?.oneShot() else oA
- require(imageA is ImageWrapper) { "Argument \"imageA\" ${imageA.jsBrief()} for images.concat must be a ImageWrapper" }
- val imageB = if (oB.isJsString()) read(scriptRuntime, arrayOf(coerceString(oB), true))?.oneShot() else oB
- require(imageB is ImageWrapper) {
- imageA.shoot()
- "Argument \"imageB\" ${imageB.jsBrief()} for images.concat must be a ImageWrapper"
- }
+ var imageA: ImageWrapper? = null
+ var imageB: ImageWrapper? = null
try {
+ val imageARaw = if (oA.isJsString()) read(scriptRuntime, arrayOf(coerceString(oA), true))?.oneShot() else oA
+ require(imageARaw is ImageWrapper) { "Argument \"imageA\" ${imageARaw.jsBrief()} for images.concat must be a ImageWrapper" }
+ imageA = imageARaw
+ val imageBRaw = if (oB.isJsString()) read(scriptRuntime, arrayOf(coerceString(oB), true))?.oneShot() else oB
+ require(imageBRaw is ImageWrapper) { "Argument \"imageB\" ${imageBRaw.jsBrief()} for images.concat must be a ImageWrapper" }
+ imageB = imageBRaw
initOpenCvIfNeeded()
ApiImages.concat(scriptRuntime, imageA, imageB, directionToGravityToConcat(direction))
} finally {
@@ -777,48 +778,55 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun detectColor(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 4..6) {
- val (o, color, x, y, threshold, algorithm) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.detectColor must be a ImageWrapper" }
+ fun detectColor(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 4..6) { argList ->
+ detectColorRhino(scriptRuntime, argList, ::detectColor.name)
+ }
+
+ @JvmStatic
+ fun detectColorRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String): Boolean {
+ val (o, color, x, y, threshold, algorithm) = args
+ var imageRef: ImageWrapper? = null
try {
+ val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.detectColor must be a ImageWrapper" }
+ imageRef = image
initOpenCvIfNeeded()
val pixel = pixel(scriptRuntime, arrayOf(image, coerceIntNumber(x), coerceIntNumber(y)))
- ColorDetector
+ return ColorDetector
.get(Colors.toIntRhino(color), coerceString(algorithm, DEFAULT_COLOR_ALGORITHM), parseNumber(threshold, DEFAULT_COLOR_THRESHOLD))
.detectColor(Colors.redRhino(pixel).roundToInt(), Colors.greenRhino(pixel).roundToInt(), Colors.blueRhino(pixel).roundToInt())
} finally {
- image.shoot()
+ ApiImages.shoot(imageRef)
}
}
@Deprecated("Deprecated in Java", ReplaceWith("detectColor(image, color, x, y, threshold, algorithm)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun detectsColor(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 4..6) {
- val (o) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.detectsColor must be a ImageWrapper" }
- try {
- initOpenCvIfNeeded()
- detectColor(scriptRuntime, it)
- } finally {
- image.shoot()
- }
+ fun detectsColor(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 4..6) { argList ->
+ @Suppress("DEPRECATION")
+ detectColorRhino(scriptRuntime, argList, ::detectsColor.name)
}
// @Reference to module __images__.js from Auto.js Pro 9.3.11 by SuperMonster003 on May 10, 2025.
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun detectMultiColors(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 5..6) {
- val (o, x, y, firstColor, paths, options) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.detectMultiColors must be a ImageWrapper" }
+ fun detectMultiColors(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 5..6) { argList ->
+ detectMultiColorsRhino(scriptRuntime, argList, ::detectMultiColors.name)
+ }
+
+ @JvmStatic
+ fun detectMultiColorsRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String): Boolean {
+ val (o, x, y, firstColor, paths, options) = args
+ var imageRef: ImageWrapper? = null
try {
+ val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.detectMultiColors must be a ImageWrapper" }
+ imageRef = image
require(paths is NativeArray) { "Argument \"paths\" ${paths.jsBrief()} for images.detectMultiColors must be a JavaScript Array" }
initOpenCvIfNeeded()
val opt = options as? NativeObject ?: newNativeObject()
- scriptRuntime.images.colorFinder.detectMultiColors(
+ return scriptRuntime.images.colorFinder.detectMultiColors(
image,
coerceIntNumber(x),
coerceIntNumber(y),
@@ -831,133 +839,140 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
}.toIntArray(),
)
} finally {
- image.shoot()
+ ApiImages.shoot(imageRef)
}
}
@Deprecated("Deprecated in Java", ReplaceWith("detectMultiColors(image, x, y, firstColor, paths, options)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun detectsMultiColors(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 5..6) {
- val (o, _, _, _, paths) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.detectMultiColors must be a ImageWrapper" }
- try {
- require(paths is NativeArray) { "Argument \"paths\" ${paths.jsBrief()} for images.detectMultiColors must be a JavaScript Array" }
- initOpenCvIfNeeded()
- detectMultiColors(scriptRuntime, it)
- } finally {
- image.shoot()
- }
+ fun detectsMultiColors(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLengthInRange(args, 5..6) { argList ->
+ @Suppress("DEPRECATION")
+ detectMultiColorsRhino(scriptRuntime, argList, ::detectsMultiColors.name)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun findPointByColor(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
- val (o, color, xOrOptions, y, width, height, threshold) = argList
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointByColor must be a ImageWrapper" }
+ findPointByColorRhino(scriptRuntime, argList, ::findPointByColor.name)
+ }
+
+ @JvmStatic
+ fun findPointByColorRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String, overriddenThreshold: Int? = null): OpencvPoint? {
+ val (o, color, xOrOptions, y, width, height, threshold) = args
+ var imageRef: ImageWrapper? = null
try {
+ val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointByColor must be a ImageWrapper" }
+ imageRef = image
initOpenCvIfNeeded()
val opt = when {
- argList.size < 3 -> newNativeObject()
- argList.size == 3 -> when {
+ args.size < 3 -> newNativeObject()
+ args.size == 3 -> when {
xOrOptions.isJsNullish() -> newNativeObject()
else -> xOrOptions as? NativeObject
}
else -> null
}
- scriptRuntime.images.colorFinder.findPointByColor(
+ return scriptRuntime.images.colorFinder.findPointByColor(
image,
Colors.toIntRhino(color),
- opt?.let { parseThreshold(it).roundToInt() } ?: coerceIntNumber(threshold, DEFAULT_COLOR_THRESHOLD),
+ overriddenThreshold ?: opt?.let { parseThreshold(it).roundToInt() } ?: coerceIntNumber(threshold, DEFAULT_COLOR_THRESHOLD),
buildRegionInternal(image, opt?.prop("region")?.takeUnless { it.isJsNullish() } ?: listOf(/* x = */ xOrOptions, y, width, height))
).also { image.shoot() }
} finally {
- image.shoot()
+ ApiImages.shoot(imageRef)
}
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointByColor(image, color, options)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findColor(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..3) {
- val (o, color, options) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findColor must be a ImageWrapper" }
- findPointByColor(scriptRuntime, arrayOf(image, color, options))
+ fun findColor(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..3) { argList ->
+ @Suppress("DEPRECATION")
+ findPointByColorRhino(scriptRuntime, argList, ::findColor.name)
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointByColor(image, color, options)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findColorInRegion(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) {
- val (o) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findColorInRegion must be a ImageWrapper" }
- findPointByColor(scriptRuntime, it)
+ fun findColorInRegion(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
+ @Suppress("DEPRECATION")
+ findPointByColorRhino(scriptRuntime, argList, ::findColorInRegion.name)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findPointByColorExactly(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) {
- val (o) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointByColorExactly must be a ImageWrapper" }
- findPointByColor(scriptRuntime, it + /* threshold = */ 0)
+ fun findPointByColorExactly(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) { argList ->
+ findPointByColorExactlyRhino(scriptRuntime, argList, ::findPointByColorExactly.name)
+ }
+
+ @JvmStatic
+ fun findPointByColorExactlyRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String): OpencvPoint? {
+ return findPointByColorRhino(scriptRuntime, args, funcName, 0)
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointByColorExactly(image, color, x, y, width, height)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findColorEquals(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) {
- val (o) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findColorEquals must be a ImageWrapper" }
- findPointByColorExactly(scriptRuntime, it)
+ fun findColorEquals(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) { argList ->
+ @Suppress("DEPRECATION")
+ findPointByColorExactlyRhino(scriptRuntime, argList, ::findColorEquals.name)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findPointsByColor(scriptRuntime: ScriptRuntime, args: Array): NativeArray = ensureArgumentsLengthInRange(args, 2..3) {
- val (o, color, options) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointsByColor must be a ImageWrapper" }
+ fun findPointsByColor(scriptRuntime: ScriptRuntime, args: Array): NativeArray = ensureArgumentsLengthInRange(args, 2..3) { argList ->
+ findPointsByColorRhino(scriptRuntime, argList, ::findPointsByColor.name)
+ }
+
+ @JvmStatic
+ fun findPointsByColorRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String): NativeArray {
+ val (o, color, options) = args
+ var imageRef: ImageWrapper? = null
try {
+ val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointsByColor must be a ImageWrapper" }
+ imageRef = image
initOpenCvIfNeeded()
val opt = options as? NativeObject ?: newNativeObject()
- scriptRuntime.images.colorFinder.findPointsByColor(
+ return scriptRuntime.images.colorFinder.findPointsByColor(
image,
Colors.toIntRhino(color),
parseThreshold(opt).roundToInt(),
opt.inquire("region") { region -> buildRegionInternal(image, region) },
).toNativeArray()
} finally {
- image.shoot()
+ ApiImages.shoot(imageRef)
}
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointsByColor(image, color, options)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findAllPointsForColor(scriptRuntime: ScriptRuntime, args: Array): NativeArray = ensureArgumentsLengthInRange(args, 2..3) {
- val (o) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findAllPointsForColor must be a ImageWrapper" }
- findPointsByColor(scriptRuntime, it)
+ fun findAllPointsForColor(scriptRuntime: ScriptRuntime, args: Array): NativeArray = ensureArgumentsLengthInRange(args, 2..3) { argList ->
+ @Suppress("DEPRECATION")
+ findPointsByColorRhino(scriptRuntime, argList, ::findAllPointsForColor.name)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findPointByColors(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) {
- val (o, firstColor, paths, options) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointByColors must be a ImageWrapper" }
+ fun findPointByColors(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) { argList ->
+ findPointByColorsRhino(scriptRuntime, argList, ::findPointByColors.name)
+ }
+
+ @JvmStatic
+ fun findPointByColorsRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String): OpencvPoint? {
+ val (o, firstColor, paths, options) = args
+ var imageRef: ImageWrapper? = null
try {
+ val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointByColors must be a ImageWrapper" }
+ imageRef = image
require(paths is NativeArray) { "Argument \"paths\" ${paths.jsBrief()} for images.findPointByColors must be a JavaScript Array" }
initOpenCvIfNeeded()
val opt = options as? NativeObject ?: newNativeObject()
- scriptRuntime.images.colorFinder.findPointByColors(
+ return scriptRuntime.images.colorFinder.findPointByColors(
image,
Colors.toIntRhino(firstColor),
parseThreshold(opt).roundToInt(),
@@ -968,22 +983,16 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
}.toIntArray(),
)
} finally {
- image.shoot()
+ ApiImages.shoot(imageRef)
}
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointByColors(image, firstColor, paths, options)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findMultiColors(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) {
- val (o, _, paths) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findMultiColors must be a ImageWrapper" }
- require(paths is NativeArray) {
- image.shoot()
- "Argument \"paths\" ${paths.jsBrief()} for images.findMultiColors must be a JavaScript Array"
- }
- findPointByColors(scriptRuntime, it)
+ fun findMultiColors(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) { argList ->
+ @Suppress("DEPRECATION")
+ findPointByColorsRhino(scriptRuntime, argList, ::findMultiColors.name)
}
@JvmStatic
@@ -1014,26 +1023,33 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
@JvmStatic
@RhinoRuntimeFunctionInterface
fun findPointByImage(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
- val (o, template, xOrOptions, y, width, height, thresholdArg) = argList
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findPointByImage must be a ImageWrapper" }
- require(template is ImageWrapper) {
- image.shoot()
- "Argument \"template\" ${template.jsBrief()} for images.findPointByImage must be a ImageWrapper"
- }
+ findPointByImageRhino(scriptRuntime, argList, ::findPointByImage.name)
+ }
+
+ @JvmStatic
+ fun findPointByImageRhino(scriptRuntime: ScriptRuntime, args: Array, funcName: String): OpencvPoint? {
+ val (oA, oB, xOrOptions, y, width, height, thresholdArg) = args
+ var imageA: ImageWrapper? = null
+ var imageB: ImageWrapper? = null
try {
+ val image = if (oA.isJsString()) read(scriptRuntime, arrayOf(coerceString(oA), true))?.oneShot() else oA
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.$funcName must be a ImageWrapper" }
+ imageA = image
+ val template = if (oB.isJsString()) read(scriptRuntime, arrayOf(coerceString(oB), true))?.oneShot() else oB
+ require(template is ImageWrapper) { "Argument \"template\" ${oB.jsBrief()} for images.$funcName must be a ImageWrapper" }
+ imageB = template
initOpenCvIfNeeded()
- when {
- argList.size > 2 && xOrOptions !is NativeObject -> {
+ return when {
+ args.size > 2 && xOrOptions !is NativeObject -> {
val options = mapOf(
"region" to listOf(/* x = */ xOrOptions, y, width, height),
"threshold" to thresholdArg,
).toNativeObject()
- findPointByImage(scriptRuntime, arrayOf(image, template, options))
+ findPointByImageRhino(scriptRuntime, arrayOf(image, template, options), funcName)
}
else -> {
val opt = when {
- argList.size > 2 -> xOrOptions as? NativeObject
+ args.size > 2 -> xOrOptions as? NativeObject
else -> null
} ?: newNativeObject()
val weakThreshold = parseWeakThreshold(opt, 0.6).toFloat()
@@ -1044,49 +1060,39 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
}
}
} finally {
- ApiImages.shoot(image, template)
+ ApiImages.shoot(imageA, imageB)
}
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointByImage(image, template, options)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findImage(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..3) {
- val (o, template) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findImage must be a ImageWrapper" }
- require(template is ImageWrapper) {
- image.shoot()
- "Argument \"template\" ${template.jsBrief()} for images.findImage must be a ImageWrapper"
- }
- findPointByImage(scriptRuntime, it)
+ fun findImage(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
+ @Suppress("DEPRECATION")
+ findPointByImageRhino(scriptRuntime, argList, ::findImage.name)
}
@Deprecated("Deprecated in Java", ReplaceWith("findPointByImage(image, template, x, y, width, height, threshold)"))
@JvmStatic
@RhinoRuntimeFunctionInterface
- fun findImageInRegion(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) {
- val (o, template) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.findImageInRegion must be a ImageWrapper" }
- require(template is ImageWrapper) {
- image.shoot()
- "Argument \"template\" ${template.jsBrief()} for images.findImageInRegion must be a ImageWrapper"
- }
- findPointByImage(scriptRuntime, it)
+ fun findImageInRegion(scriptRuntime: ScriptRuntime, args: Array): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
+ @Suppress("DEPRECATION")
+ findPointByImageRhino(scriptRuntime, argList, ::findImageInRegion.name)
}
@JvmStatic
@RhinoRuntimeFunctionInterface
fun matchTemplate(scriptRuntime: ScriptRuntime, args: Array): MatchingResult = ensureArgumentsLengthInRange(args, 2..3) {
- val (o, template, options) = it
- val image = if (o.isJsString()) read(scriptRuntime, arrayOf(coerceString(o), true))?.oneShot() else o
- require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.matchTemplate must be a ImageWrapper" }
- require(template is ImageWrapper) {
- image.shoot()
- "Argument \"template\" ${template.jsBrief()} for images.matchTemplate must be a ImageWrapper"
- }
+ val (oA, oB, options) = it
+ var imageA: ImageWrapper? = null
+ var imageB: ImageWrapper? = null
try {
+ val image = if (oA.isJsString()) read(scriptRuntime, arrayOf(coerceString(oA), true))?.oneShot() else oA
+ require(image is ImageWrapper) { "Argument \"image\" ${image.jsBrief()} for images.matchTemplate must be a ImageWrapper" }
+ imageA = image
+ val template = if (oB.isJsString()) read(scriptRuntime, arrayOf(coerceString(oB), true))?.oneShot() else oB
+ require(template is ImageWrapper) { "Argument \"template\" ${template.jsBrief()} for images.matchTemplate must be a ImageWrapper" }
+ imageB = template
initOpenCvIfNeeded()
val opt = options as? NativeObject ?: newNativeObject()
val weakThreshold = parseWeakThreshold(opt, 0.6).toFloat()
@@ -1101,7 +1107,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
}
MatchingResult(scriptRuntime.images.matchTemplate(image, template, weakThreshold, threshold, region, level, max, useTransparentMask))
} finally {
- ApiImages.shoot(image, template)
+ ApiImages.shoot(imageA, imageB)
}
}
@@ -1452,17 +1458,18 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
@RhinoRuntimeFunctionInterface
fun isEqual(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLength(args, 2) { argList ->
val (oA, oB) = argList
- val imageA = if (oA.isJsString()) read(scriptRuntime, arrayOf(coerceString(oA), true))?.oneShot() else oA
- require(imageA is ImageWrapper) { "Argument \"imageA\" ${imageA.jsBrief()} for images.isEqual must be a ImageWrapper}" }
- val imageB = if (oB.isJsString()) read(scriptRuntime, arrayOf(coerceString(oB), true))?.oneShot() else oB
- require(imageB is ImageWrapper) {
- imageA.shoot()
- "Argument \"imageB\" ${imageB.jsBrief()} for images.isEqual must be a ImageWrapper"
- }
+ var imageARef: ImageWrapper? = null
+ var imageBRef: ImageWrapper? = null
try {
+ val imageA = if (oA.isJsString()) read(scriptRuntime, arrayOf(coerceString(oA), true))?.oneShot() else oA
+ require(imageA is ImageWrapper) { "Argument \"imageA\" ${imageA.jsBrief()} for images.isEqual must be a ImageWrapper}" }
+ imageARef = imageA
+ val imageB = if (oB.isJsString()) read(scriptRuntime, arrayOf(coerceString(oB), true))?.oneShot() else oB
+ require(imageB is ImageWrapper) { "Argument \"imageB\" ${imageB.jsBrief()} for images.isEqual must be a ImageWrapper" }
+ imageBRef = imageB
ImageSimilarity.isEqual(imageA.mat, imageB.mat)
} finally {
- ApiImages.shoot(imageA, imageB)
+ ApiImages.shoot(imageARef, imageBRef)
}
}
diff --git a/app/src/main/java/org/autojs/autojs/tool/CrashHandler.kt b/app/src/main/java/org/autojs/autojs/tool/CrashHandler.kt
index f9c7d97f..c2538f3e 100644
--- a/app/src/main/java/org/autojs/autojs/tool/CrashHandler.kt
+++ b/app/src/main/java/org/autojs/autojs/tool/CrashHandler.kt
@@ -37,7 +37,7 @@ class CrashHandler(private val errorReportClass: Class<*>) : CrashHandleCallback
if (crashTooManyTimes()) {
return super.onCrashHandleStart(crashType, errorType, errorMessage, errorStack)
}
- startErrorReportActivity("$errorType: $errorMessage", errorStack ?: "[ No stack message ]")
+ startCrashReportActivity("$errorType: $errorMessage", errorStack ?: "[ No stack message ]")
} catch (e: Throwable) {
e.printStackTrace()
}
@@ -79,7 +79,7 @@ class CrashHandler(private val errorReportClass: Class<*>) : CrashHandleCallback
mBuglyHandler = buglyHandler
}
- private fun startErrorReportActivity(msg: String, detail: String) {
+ private fun startCrashReportActivity(msg: String, detail: String) {
Intent(GlobalAppContext.get(), errorReportClass).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
putExtra("message", msg)
diff --git a/app/src/main/java/org/autojs/autojs/ui/error/ErrorReportActivity.kt b/app/src/main/java/org/autojs/autojs/ui/error/CrashReportActivity.kt
similarity index 93%
rename from app/src/main/java/org/autojs/autojs/ui/error/ErrorReportActivity.kt
rename to app/src/main/java/org/autojs/autojs/ui/error/CrashReportActivity.kt
index e9ec7080..e3c3f893 100644
--- a/app/src/main/java/org/autojs/autojs/ui/error/ErrorReportActivity.kt
+++ b/app/src/main/java/org/autojs/autojs/ui/error/CrashReportActivity.kt
@@ -16,9 +16,9 @@ import org.autojs.autojs6.databinding.ActivityErrorReportBinding
* Created by Stardust on Feb 2, 2017.
* Transformed by SuperMonster003 on Mar 10, 2025.
*/
-class ErrorReportActivity : BaseActivity() {
+class CrashReportActivity : BaseActivity() {
- private lateinit var errorMessage: String
+ private lateinit var crashMessage: String
@SuppressLint("ClickableViewAccessibility")
override fun onCreate(savedInstanceState: Bundle?) {
@@ -29,7 +29,7 @@ class ErrorReportActivity : BaseActivity() {
appendLine(briefOfCurrentVersionInt(true))
intent.getStringExtra("message")?.let { appendLine().appendLine(it.trimEnd()) }
intent.getStringExtra("error")?.let { appendLine().appendLine(it.trimEnd()) }
- }.also { errorMessage = it }
+ }.also { crashMessage = it }
val binding = ActivityErrorReportBinding.inflate(layoutInflater).also {
setContentView(it.root)
@@ -62,7 +62,7 @@ class ErrorReportActivity : BaseActivity() {
@SuppressLint("MissingSuperCall")
override fun onBackPressed() = exit()
- private fun copy() = ClipboardUtils.setClip(this, errorMessage)
+ private fun copy() = ClipboardUtils.setClip(this, crashMessage)
private fun exit() = finishAffinity()
diff --git a/version.properties b/version.properties
index a48d3bda..40710897 100644
--- a/version.properties
+++ b/version.properties
@@ -1,5 +1,5 @@
-#Sat Jun 28 19:48:58 CST 2025
-BUILD_TIME=1751111338507
+#Tue Jul 01 00:19:56 CST 2025
+BUILD_TIME=1751300396808
COMPILE_SDK_VERSION=35
IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -19,6 +19,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=35
TARGET_SDK_VERSION_INRT=29
-VERSION_BUILD=3308
+VERSION_BUILD=3312
VERSION_NAME=6.7.0 Alpha2
VSCODE_EXT_REQUIRED_VERSION=1.0.8