6.7.0 - Alpha2 - 修复 images 部分相关方法可能引发内存泄露的问题 (issue #372)
This commit is contained in:
@@ -290,8 +290,8 @@
|
||||
android:name="org.autojs.autojs.ui.settings.DeveloperOptionsActivity"
|
||||
android:theme="@style/AppTheme.Settings" />
|
||||
|
||||
<!-- <activity android:name="org.autojs.autojs.ui.error.ErrorReportActivity" android:process=":crash_report"/> -->
|
||||
<activity android:name="org.autojs.autojs.ui.error.ErrorReportActivity" />
|
||||
<!-- <activity android:name="org.autojs.autojs.ui.error.CrashReportActivity" android:process=":crash_report"/> -->
|
||||
<activity android:name="org.autojs.autojs.ui.error.CrashReportActivity" />
|
||||
|
||||
<activity
|
||||
android:name="org.autojs.autojs.external.tasker.TaskerScriptEditActivity"
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.autojs.autojs.pluginclient.DevPluginService
|
||||
import org.autojs.autojs.timing.TimedTaskManager
|
||||
import org.autojs.autojs.timing.TimedTaskScheduler
|
||||
import org.autojs.autojs.tool.CrashHandler
|
||||
import org.autojs.autojs.ui.error.ErrorReportActivity
|
||||
import org.autojs.autojs.ui.error.CrashReportActivity
|
||||
import org.autojs.autojs.ui.floating.FloatyWindowManger
|
||||
import org.autojs.autojs.util.ViewUtils
|
||||
import org.autojs.autojs6.BuildConfig
|
||||
@@ -89,7 +89,7 @@ class App : MultiDexApplication() {
|
||||
|
||||
private fun setUpDebugEnvironment() {
|
||||
Bugly.isDev = false
|
||||
val crashHandler = CrashHandler(ErrorReportActivity::class.java)
|
||||
val crashHandler = CrashHandler(CrashReportActivity::class.java)
|
||||
|
||||
val strategy = CrashReport.UserStrategy(applicationContext)
|
||||
strategy.setCrashHandleCallback(crashHandler)
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package org.autojs.autojs.core.cleaner;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.autojs.autojs.core.ref.MonitorResource;
|
||||
import org.autojs.autojs.core.ref.NativeObjectReference;
|
||||
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Created by SuperMonster003 on Dec 22, 2023.
|
||||
*/
|
||||
// @Reference to Auto.js Pro 9.3.11 by SuperMonster003 on Dec 22, 2023.
|
||||
public final class Cleaner {
|
||||
|
||||
public static final Cleaner instance = new Cleaner();
|
||||
public static final AtomicInteger pointer = new AtomicInteger();
|
||||
public static final ReferenceQueue<Object> 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<MonitorResource> resourceNativeCleaner = new NativeObjectReference<>(resource, referenceQueue, cleaner);
|
||||
resourceNativeCleaner.pointer = resource.getPointer();
|
||||
resource.setNativeObjectReference(resourceNativeCleaner);
|
||||
RegisteredCleaners.registeredCleaners.add(resourceNativeCleaner);
|
||||
pointer.incrementAndGet();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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<NativeObjectReference<MonitorResource>> registeredCleaners = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||
|
||||
}
|
||||
@@ -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<ImageWrapper>, MonitorResource {
|
||||
open class ImageWrapper : Shootable<ImageWrapper> {
|
||||
|
||||
private var mScriptRuntime: ScriptRuntime
|
||||
|
||||
private var mMat: Mat? = null
|
||||
private var mBgrMat: Mat? = null
|
||||
private var mBitmap: Bitmap? = null
|
||||
private var mRef: NativeObjectReference<MonitorResource>? = null
|
||||
private var mMediaImage: Image? = null
|
||||
private var mPlane: Image.Plane? = null
|
||||
|
||||
private var mWidth = 0
|
||||
@@ -47,12 +44,6 @@ open class ImageWrapper : Shootable<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, 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<ImageWrapper>, MonitorResource {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPointer() = mId
|
||||
|
||||
override fun setNativeObjectReference(reference: NativeObjectReference<MonitorResource>) {
|
||||
mRef = reference
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val imageList = ArrayList<WeakReference<Any>>()
|
||||
|
||||
@@ -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<Match> 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<Match> 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();
|
||||
|
||||
@@ -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<MonitorResource> 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<MonitorResource> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<MonitorResource> 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<MonitorResource> reference) {
|
||||
mReference = reference;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<MonitorResource> reference);
|
||||
|
||||
}
|
||||
@@ -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<T> extends PhantomReference<T> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<MonitorResource> 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<MonitorResource> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,14 +760,15 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun concat(scriptRuntime: ScriptRuntime, args: Array<out Any?>): ImageWrapper = ensureArgumentsLengthInRange(args, 2..3) {
|
||||
val (oA, oB, direction) = it
|
||||
val imageA = if (oA.isJsString()) read(scriptRuntime, arrayOf<Any>(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<Any>(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<Any>(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<Any>(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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 4..6) {
|
||||
val (o, color, x, y, threshold, algorithm) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 4..6) { argList ->
|
||||
detectColorRhino(scriptRuntime, argList, ::detectColor.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun detectColorRhino(scriptRuntime: ScriptRuntime, args: Array<out Any?>, funcName: String): Boolean {
|
||||
val (o, color, x, y, threshold, algorithm) = args
|
||||
var imageRef: ImageWrapper? = null
|
||||
try {
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 4..6) {
|
||||
val (o) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): 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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 5..6) {
|
||||
val (o, x, y, firstColor, paths, options) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 5..6) { argList ->
|
||||
detectMultiColorsRhino(scriptRuntime, argList, ::detectMultiColors.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun detectMultiColorsRhino(scriptRuntime: ScriptRuntime, args: Array<out Any?>, funcName: String): Boolean {
|
||||
val (o, x, y, firstColor, paths, options) = args
|
||||
var imageRef: ImageWrapper? = null
|
||||
try {
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 5..6) {
|
||||
val (o, _, _, _, paths) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): Boolean = ensureArgumentsLengthInRange(args, 5..6) { argList ->
|
||||
@Suppress("DEPRECATION")
|
||||
detectMultiColorsRhino(scriptRuntime, argList, ::detectsMultiColors.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun findPointByColor(scriptRuntime: ScriptRuntime, args: Array<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
|
||||
val (o, color, xOrOptions, y, width, height, threshold) = argList
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>, 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<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..3) {
|
||||
val (o, color, options) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): 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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) {
|
||||
val (o) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
|
||||
@Suppress("DEPRECATION")
|
||||
findPointByColorRhino(scriptRuntime, argList, ::findColorInRegion.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun findPointByColorExactly(scriptRuntime: ScriptRuntime, args: Array<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) {
|
||||
val (o) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) { argList ->
|
||||
findPointByColorExactlyRhino(scriptRuntime, argList, ::findPointByColorExactly.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun findPointByColorExactlyRhino(scriptRuntime: ScriptRuntime, args: Array<out Any?>, 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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) {
|
||||
val (o) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..6) { argList ->
|
||||
@Suppress("DEPRECATION")
|
||||
findPointByColorExactlyRhino(scriptRuntime, argList, ::findColorEquals.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun findPointsByColor(scriptRuntime: ScriptRuntime, args: Array<out Any?>): NativeArray = ensureArgumentsLengthInRange(args, 2..3) {
|
||||
val (o, color, options) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): NativeArray = ensureArgumentsLengthInRange(args, 2..3) { argList ->
|
||||
findPointsByColorRhino(scriptRuntime, argList, ::findPointsByColor.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun findPointsByColorRhino(scriptRuntime: ScriptRuntime, args: Array<out Any?>, funcName: String): NativeArray {
|
||||
val (o, color, options) = args
|
||||
var imageRef: ImageWrapper? = null
|
||||
try {
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): NativeArray = ensureArgumentsLengthInRange(args, 2..3) {
|
||||
val (o) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): NativeArray = ensureArgumentsLengthInRange(args, 2..3) { argList ->
|
||||
@Suppress("DEPRECATION")
|
||||
findPointsByColorRhino(scriptRuntime, argList, ::findAllPointsForColor.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun findPointByColors(scriptRuntime: ScriptRuntime, args: Array<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) {
|
||||
val (o, firstColor, paths, options) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) { argList ->
|
||||
findPointByColorsRhino(scriptRuntime, argList, ::findPointByColors.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun findPointByColorsRhino(scriptRuntime: ScriptRuntime, args: Array<out Any?>, funcName: String): OpencvPoint? {
|
||||
val (o, firstColor, paths, options) = args
|
||||
var imageRef: ImageWrapper? = null
|
||||
try {
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 3..4) {
|
||||
val (o, _, paths) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): 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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
|
||||
val (o, template, xOrOptions, y, width, height, thresholdArg) = argList
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>, 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<Any>(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<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..3) {
|
||||
val (o, template) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): 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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) {
|
||||
val (o, template) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<out Any?>): OpencvPoint? = ensureArgumentsLengthInRange(args, 2..7) { argList ->
|
||||
@Suppress("DEPRECATION")
|
||||
findPointByImageRhino(scriptRuntime, argList, ::findImageInRegion.name)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@RhinoRuntimeFunctionInterface
|
||||
fun matchTemplate(scriptRuntime: ScriptRuntime, args: Array<out Any?>): MatchingResult = ensureArgumentsLengthInRange(args, 2..3) {
|
||||
val (o, template, options) = it
|
||||
val image = if (o.isJsString()) read(scriptRuntime, arrayOf<Any>(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<Any>(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<Any>(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<out Any?>): Boolean = ensureArgumentsLength(args, 2) { argList ->
|
||||
val (oA, oB) = argList
|
||||
val imageA = if (oA.isJsString()) read(scriptRuntime, arrayOf<Any>(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<Any>(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<Any>(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<Any>(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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user