diff --git a/app/src/main/assets/sample/图片与图色处理/图片处理.js b/app/src/main/assets/sample/图片与图色处理/图片处理.js index 97248d99..67671072 100644 --- a/app/src/main/assets/sample/图片与图色处理/图片处理.js +++ b/app/src/main/assets/sample/图片与图色处理/图片处理.js @@ -2,6 +2,7 @@ var url = "https://www.autojs.org/assets/uploads/profile/3-profileavatar.png"; var logo = null; +var currentImg = null; ui.layout( @@ -18,7 +19,14 @@ ui.layout( //把一张图片设置到图片控件中 function setImage(img) { ui.run(() => { + var curImg = currentImg; + if(oldImg != null){ + ui.post(()=>{ + oldImg.recycle(); + }); + } ui.img.setImageBitmap(img.bitmap); + currentImg = img; }); } @@ -63,20 +71,20 @@ ui.hsv.on("click", () => { ui.blur.on("click", () => { processImg(img => { - //RGB转HSV + //模糊 return images.blur(img, [10, 10]); }); }); ui.medianBlur.on("click", () => { processImg(img => { - //RGB转HSV - return images.medianBlur(img, 10); + //中值滤波 + return images.medianBlur(img, 5); }); }); ui.gaussianBlur.on("click", () => { processImg(img => { - //RGB转HSV + //高斯模糊 return images.gaussianBlur(img, [5, 5]); }); }); \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/App.java b/app/src/main/java/org/autojs/autojs/App.java index 6468b9be..e3601240 100644 --- a/app/src/main/java/org/autojs/autojs/App.java +++ b/app/src/main/java/org/autojs/autojs/App.java @@ -14,7 +14,6 @@ import com.bumptech.glide.request.transition.Transition; import com.flurry.android.FlurryAgent; import com.squareup.leakcanary.LeakCanary; import com.stardust.app.GlobalAppContext; -import com.stardust.autojs.core.image.OpenCVHelper; import com.stardust.autojs.core.ui.inflater.ImageLoader; import com.stardust.autojs.core.ui.inflater.util.Drawables; import com.stardust.theme.ThemeColor; @@ -31,8 +30,6 @@ 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.opencv.android.BaseLoaderCallback; -import org.opencv.android.OpenCVLoader; import java.lang.ref.WeakReference; import java.util.ArrayList; diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.java b/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.java index bf30ee25..04833873 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.java @@ -45,8 +45,7 @@ import static org.autojs.autojs.ui.edit.EditorView.EXTRA_READ_ONLY; * Created by Stardust on 2017/1/29. */ @EActivity(R.layout.activity_edit) -public class -EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, PermissionRequestProxyActivity { +public class EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, PermissionRequestProxyActivity { private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator(); private static final String LOG_TAG = "EditActivity"; diff --git a/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java b/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java index 62411794..c16898a0 100644 --- a/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java +++ b/app/src/main/java/org/autojs/autojs/ui/splash/SplashActivity.java @@ -9,7 +9,7 @@ import android.support.annotation.Nullable; import android.util.Log; import android.view.View; -import com.stardust.autojs.core.image.OpenCVHelper; +import com.stardust.autojs.core.opencv.OpenCVHelper; import com.xcy8.ads.listener.LoadAdListener; import com.xcy8.ads.view.FullScreenAdView; diff --git a/autojs/src/main/assets/modules/__images__.js b/autojs/src/main/assets/modules/__images__.js index ab320ca4..58d4bb4e 100644 --- a/autojs/src/main/assets/modules/__images__.js +++ b/autojs/src/main/assets/modules/__images__.js @@ -283,7 +283,7 @@ module.exports = function (__runtime__, scope) { } function newMat() { - return new org.opencv.core.Mat(); + return new com.stardust.autojs.core.opencv.Mat(); } function matToImage(mat) { diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java b/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java index eb1deb33..dfb364b2 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/ColorFinder.java @@ -4,11 +4,14 @@ import android.graphics.Color; import android.os.Build; import android.support.annotation.RequiresApi; +import com.stardust.autojs.core.opencv.MatOfPoint; +import com.stardust.autojs.core.opencv.OpenCVHelper; import com.stardust.util.ScreenMetrics; import org.opencv.core.Core; -import org.opencv.core.Mat; -import org.opencv.core.MatOfPoint; + +import com.stardust.autojs.core.opencv.Mat; + import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; @@ -48,6 +51,7 @@ public class ColorFinder { point.x = mScreenMetrics.scaleX((int) (point.x + rect.x)); point.y = mScreenMetrics.scaleX((int) (point.y + rect.y)); } + OpenCVHelper.release(matOfPoint); return point; } @@ -86,7 +90,7 @@ public class ColorFinder { if (nonZeroPos.rows() == 0 || nonZeroPos.cols() == 0) { result = null; } else { - result = new MatOfPoint(nonZeroPos); + result = OpenCVHelper.newMatOfPoint(nonZeroPos); } OpenCVHelper.release(bi); OpenCVHelper.release(nonZeroPos); @@ -114,7 +118,7 @@ public class ColorFinder { x += startingPoint.x; y += startingPoint.y; if (x >= image.getWidth() || y >= image.getHeight() - || x < 0 || y < 0) { + || x < 0 || y < 0) { return false; } int c = image.pixel(x, y); diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/ImageWrapper.java b/autojs/src/main/java/com/stardust/autojs/core/image/ImageWrapper.java index df80b86b..1f86003b 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/ImageWrapper.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/ImageWrapper.java @@ -6,10 +6,11 @@ import android.media.Image; import android.os.Build; import android.support.annotation.RequiresApi; +import com.stardust.autojs.core.opencv.OpenCVHelper; import com.stardust.pio.UncheckedIOException; import org.opencv.android.Utils; -import org.opencv.core.Mat; +import com.stardust.autojs.core.opencv.Mat; import org.opencv.highgui.Highgui; import java.io.FileNotFoundException; diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/TemplateMatching.java b/autojs/src/main/java/com/stardust/autojs/core/image/TemplateMatching.java index 461352da..ef9295c3 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/TemplateMatching.java +++ b/autojs/src/main/java/com/stardust/autojs/core/image/TemplateMatching.java @@ -1,14 +1,14 @@ package com.stardust.autojs.core.image; -import android.util.Log; import android.util.Pair; import android.util.TimingLogger; +import com.stardust.autojs.core.opencv.OpenCVHelper; import com.stardust.util.Nath; import org.opencv.core.Core; import org.opencv.core.CvType; -import org.opencv.core.Mat; +import com.stardust.autojs.core.opencv.Mat; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Size; @@ -100,6 +100,7 @@ public class TemplateMatching { } logger.addSplit("result:" + p); logger.dumpToLog(); + OpenCVHelper.release(matchResult); if (similarity < strictThreshold) { return null; } diff --git a/autojs/src/main/java/com/stardust/autojs/core/opencv/Mat.java b/autojs/src/main/java/com/stardust/autojs/core/opencv/Mat.java new file mode 100644 index 00000000..57dd72f1 --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/opencv/Mat.java @@ -0,0 +1,108 @@ +package com.stardust.autojs.core.opencv; + +import com.stardust.util.ResourceMonitor; + +import org.opencv.core.Range; +import org.opencv.core.Rect; +import org.opencv.core.Scalar; +import org.opencv.core.Size; + +import java.lang.reflect.Method; +import java.util.concurrent.atomic.AtomicInteger; + +public class Mat extends org.opencv.core.Mat implements ResourceMonitor.Resource { + + private static Method nClone; + + static { + try { + nClone = org.opencv.core.Mat.class.getDeclaredMethod("n_clone", long.class); + nClone.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + private static final AtomicInteger sResourceId = new AtomicInteger(); + private volatile boolean mReleased = false; + private final int mResourceId = sResourceId.incrementAndGet(); + + public Mat(long addr) { + super(addr); + ResourceMonitor.onOpen(this); + } + + public Mat() { + super(); + ResourceMonitor.onOpen(this); + } + + public Mat(int rows, int cols, int type) { + super(rows, cols, type); + ResourceMonitor.onOpen(this); + } + + public Mat(Size size, int type) { + super(size, type); + ResourceMonitor.onOpen(this); + } + + public Mat(int rows, int cols, int type, Scalar s) { + super(rows, cols, type, s); + ResourceMonitor.onOpen(this); + } + + public Mat(Size size, int type, Scalar s) { + super(size, type, s); + ResourceMonitor.onOpen(this); + } + + public Mat(Mat m, Range rowRange, Range colRange) { + super(m, rowRange, colRange); + ResourceMonitor.onOpen(this); + } + + public Mat(Mat m, Range rowRange) { + super(m, rowRange); + ResourceMonitor.onOpen(this); + } + + public Mat(Mat m, Rect roi) { + super(m, roi); + ResourceMonitor.onOpen(this); + } + + @Override + public Mat clone() { + return new Mat(n_clone(this.nativeObj)); + } + + protected long n_clone(long addr) { + try { + return (long) nClone.invoke(this, addr); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void release() { + super.release(); + mReleased = true; + ResourceMonitor.onClose(this); + } + + @Override + protected void finalize() throws Throwable { + if (!mReleased) { + ResourceMonitor.onFinalize(this); + super.release(); + } + super.finalize(); + } + + @Override + public int getResourceId() { + return mResourceId; + } +} diff --git a/autojs/src/main/java/com/stardust/autojs/core/opencv/MatOfPoint.java b/autojs/src/main/java/com/stardust/autojs/core/opencv/MatOfPoint.java new file mode 100644 index 00000000..1a92051a --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/opencv/MatOfPoint.java @@ -0,0 +1,56 @@ +package com.stardust.autojs.core.opencv; + +import com.stardust.util.ResourceMonitor; + +import org.opencv.core.Mat; +import org.opencv.core.Point; + +import java.util.concurrent.atomic.AtomicInteger; + +public class MatOfPoint extends org.opencv.core.MatOfPoint implements ResourceMonitor.Resource { + + private static final AtomicInteger sResourceId = new AtomicInteger(); + private volatile boolean mReleased = false; + private final int mResourceId = sResourceId.incrementAndGet(); + + public MatOfPoint() { + super(); + ResourceMonitor.onOpen(this); + } + + public MatOfPoint(long addr) { + super(addr); + ResourceMonitor.onOpen(this); + } + + public MatOfPoint(Mat m) { + super(m); + ResourceMonitor.onOpen(this); + } + + public MatOfPoint(Point... a) { + super(a); + ResourceMonitor.onOpen(this); + } + + @Override + public void release() { + super.release(); + mReleased = true; + ResourceMonitor.onClose(this); + } + + @Override + protected void finalize() throws Throwable { + if (!mReleased) { + ResourceMonitor.onFinalize(this); + super.release(); + } + super.finalize(); + } + + @Override + public int getResourceId() { + return mResourceId; + } +} diff --git a/autojs/src/main/java/com/stardust/autojs/core/image/OpenCVHelper.java b/autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java similarity index 94% rename from autojs/src/main/java/com/stardust/autojs/core/image/OpenCVHelper.java rename to autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java index d2c97ca3..ac19c36c 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/image/OpenCVHelper.java +++ b/autojs/src/main/java/com/stardust/autojs/core/opencv/OpenCVHelper.java @@ -1,4 +1,4 @@ -package com.stardust.autojs.core.image; +package com.stardust.autojs.core.opencv; import android.app.Activity; import android.support.annotation.Nullable; @@ -9,7 +9,7 @@ import com.afollestad.materialdialogs.MaterialDialog; import org.opencv.android.InstallCallbackInterface; import org.opencv.android.LoaderCallbackInterface; import org.opencv.android.OpenCVLoader; -import org.opencv.core.Mat; + /** * Created by Stardust on 2018/4/2. @@ -24,6 +24,17 @@ public class OpenCVHelper { private static final String LOG_TAG = "OpenCVHelper"; private static boolean mInitialized = false; + public static MatOfPoint newMatOfPoint(Mat mat){ + return new MatOfPoint(mat); + } + + public static void release(@Nullable MatOfPoint mat) { + if (mat == null) + return; + mat.release(); + } + + public static void release(@Nullable Mat mat) { if (mat == null) return; diff --git a/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java b/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java index e2c70fc5..a9a91e36 100644 --- a/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java +++ b/autojs/src/main/java/com/stardust/autojs/runtime/api/Images.java @@ -12,14 +12,12 @@ import android.os.Handler; import android.support.annotation.RequiresApi; import android.util.Base64; import android.view.Display; -import android.view.Surface; import android.view.WindowManager; -import android.widget.ListView; import com.stardust.autojs.annotation.ScriptVariable; import com.stardust.autojs.core.image.ColorFinder; import com.stardust.autojs.core.image.ImageWrapper; -import com.stardust.autojs.core.image.OpenCVHelper; +import com.stardust.autojs.core.opencv.OpenCVHelper; import com.stardust.autojs.core.image.capture.ScreenCaptureRequester; import com.stardust.autojs.core.image.capture.ScreenCapturer; import com.stardust.autojs.core.image.TemplateMatching; @@ -30,11 +28,9 @@ import com.stardust.concurrent.VolatileDispose; import com.stardust.pio.UncheckedIOException; import com.stardust.util.ScreenMetrics; -import org.opencv.core.Core; -import org.opencv.core.Mat; +import com.stardust.autojs.core.opencv.Mat; import org.opencv.core.Point; import org.opencv.core.Rect; -import org.opencv.imgproc.Imgproc; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; diff --git a/common/src/main/java/com/stardust/util/ResourceMonitor.java b/common/src/main/java/com/stardust/util/ResourceMonitor.java new file mode 100644 index 00000000..5a03979d --- /dev/null +++ b/common/src/main/java/com/stardust/util/ResourceMonitor.java @@ -0,0 +1,96 @@ +// ResourceMonitor$onFinalize$1.java +package com.stardust.util; + +import android.os.Handler; +import android.os.Looper; +import android.util.SparseArray; + +import com.stardust.BuildConfig; + +import java.util.concurrent.ConcurrentHashMap; + + +public final class ResourceMonitor { + + private static final String LOG_TAG = "ResourceTracer"; + private static final ConcurrentHashMap, SparseArray> mResources; + private static Handler mHandler; + private static boolean mEnabled; + + public static void onOpen(ResourceMonitor.Resource resource) { + if (!mEnabled) { + return; + } + SparseArray map = mResources.get(resource.getClass()); + if (map == null) { + map = new SparseArray<>(); + mResources.put(resource.getClass(), map); + } + int resourceId = resource.getResourceId(); + ResourceMonitor.UnclosedResourceException exception = new ResourceMonitor.UnclosedResourceException("id = " + resourceId + ", resource = " + resource); + exception.fillInStackTrace(); + map.put(resourceId, exception); + } + + public static void onClose(ResourceMonitor.Resource resource) { + if (!mEnabled) { + return; + } + SparseArray map = mResources.get(resource.getClass()); + if (map != null) { + map.remove(resource.getResourceId()); + } + } + + public static void onFinalize(ResourceMonitor.Resource resource) { + if (!mEnabled) { + return; + } + SparseArray map = mResources.get(resource.getClass()); + if (map != null) { + int indexOfKey = map.indexOfKey(resource.getResourceId()); + if (indexOfKey >= 0) { + final ResourceMonitor.UnclosedResourceException unclosedResourceException = map.valueAt(indexOfKey); + map.removeAt(indexOfKey); + if (mHandler == null) { + mHandler = new Handler(Looper.getMainLooper()); + } + mHandler.post(new Runnable() { + public final void run() { + throw new UnclosedResourceDetectedException(unclosedResourceException); + } + }); + } + } + } + + static { + mResources = new ConcurrentHashMap<>(); + mEnabled = BuildConfig.DEBUG; + } + + public static boolean isEnabled() { + return mEnabled; + } + + public static void setEnabled(boolean mEnabled) { + ResourceMonitor.mEnabled = mEnabled; + } + + public static final class UnclosedResourceException extends RuntimeException { + public UnclosedResourceException(String message) { + super(message); + } + } + + + public static final class UnclosedResourceDetectedException extends RuntimeException { + public UnclosedResourceDetectedException(ResourceMonitor.UnclosedResourceException cause) { + super(cause); + } + } + + public interface Resource { + int getResourceId(); + } +} diff --git a/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java b/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java index ff6dcc96..3e4f3d4f 100644 --- a/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java +++ b/inrt/src/main/java/com/stardust/auojs/inrt/SplashActivity.java @@ -16,7 +16,7 @@ import android.widget.Toast; import com.stardust.auojs.inrt.autojs.AutoJs; import com.stardust.auojs.inrt.launch.GlobalProjectLauncher; -import com.stardust.autojs.core.image.OpenCVHelper; +import com.stardust.autojs.core.opencv.OpenCVHelper; import java.util.ArrayList; import java.util.List;