mirror of
https://github.com/TonyJiangWJ/Auto.js.git
synced 2026-06-12 21:01:32 +08:00
利用opencv处理截图图片,优化截图返回速度30+ms => 10+ms
This commit is contained in:
parent
0ac1d97045
commit
b3d21e8db7
@ -11,6 +11,8 @@ import com.stardust.autojs.core.opencv.OpenCVHelper;
|
||||
import com.stardust.pio.UncheckedIOException;
|
||||
|
||||
import org.opencv.android.Utils;
|
||||
import org.opencv.core.CvType;
|
||||
import org.opencv.core.Rect;
|
||||
import org.opencv.imgcodecs.Imgcodecs;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
@ -61,7 +63,11 @@ public class ImageWrapper {
|
||||
if (image == null) {
|
||||
return null;
|
||||
}
|
||||
return new ImageWrapper(toBitmap(image));
|
||||
if (OpenCVHelper.isInitialized()) {
|
||||
return ofImageByMat(image);
|
||||
} else {
|
||||
return new ImageWrapper(toBitmap(image));
|
||||
}
|
||||
}
|
||||
|
||||
public static ImageWrapper ofMat(Mat mat) {
|
||||
@ -100,6 +106,47 @@ public class ImageWrapper {
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, image.getWidth(), image.getHeight());
|
||||
}
|
||||
|
||||
public static ImageWrapper ofImageByMat(Image image) {
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
// 获取Image的平面
|
||||
Image.Plane[] planes = image.getPlanes();
|
||||
Log.d("ImageWrapper", "ofImageByMat: planes.length: " + planes.length);
|
||||
// 获取Image的宽高
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
|
||||
Log.d("ImageWrapper", "ofImageByMat: width:" + width + " height:" + height);
|
||||
Image.Plane plane = planes[0];
|
||||
// 获取平面的数据缓冲区
|
||||
ByteBuffer buffer = planes[0].getBuffer();
|
||||
// 创建一个byte数组来存储缓冲区的数据
|
||||
byte[] bytes = new byte[buffer.remaining()];
|
||||
buffer.position(0);
|
||||
int pixelStride = plane.getPixelStride();
|
||||
int rowPadding = plane.getRowStride() - pixelStride * image.getWidth();
|
||||
// 将数据从缓冲区拷贝到byte数组
|
||||
buffer.get(bytes);
|
||||
|
||||
// 创建一个Mat对象
|
||||
Mat mat = new Mat(height, width + rowPadding / pixelStride, CvType.CV_8UC4);
|
||||
// 将byte数组拷贝到Mat对象
|
||||
mat.put(0, 0, bytes);
|
||||
if (width != mat.width()) {
|
||||
Log.d("ImageWrapper", "ofImageByMat: mat width is not valid: " + mat.width() + " => " + width);
|
||||
// 定义裁切区域
|
||||
Rect rect = new Rect(0, 0, width, height);
|
||||
// 裁切图像
|
||||
Mat croppedImage = new Mat(mat, rect);
|
||||
mat.release();
|
||||
mat = croppedImage;
|
||||
}
|
||||
Log.d("ImageWrapper", "ofImageByMat: create by mat cost: " + (System.currentTimeMillis() - start) + "ms");
|
||||
return new ImageWrapper(mat);
|
||||
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
ensureNotRecycled();
|
||||
return mWidth;
|
||||
|
||||
@ -29,6 +29,8 @@ import org.mozilla.javascript.ast.Loop;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@ -64,6 +66,10 @@ public class GlobalScreenCapture {
|
||||
private boolean hasPermission;
|
||||
private boolean noRegister;
|
||||
|
||||
private ReentrantLock captureLock = new ReentrantLock();
|
||||
|
||||
private Condition captureComplete = captureLock.newCondition();
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private static volatile GlobalScreenCapture INSTANCE;
|
||||
|
||||
@ -234,11 +240,17 @@ public class GlobalScreenCapture {
|
||||
if (noRegister) {
|
||||
return;
|
||||
}
|
||||
Image oldCacheImage = mCachedImage.getAndSet(null);
|
||||
if (oldCacheImage != null) {
|
||||
oldCacheImage.close();
|
||||
captureLock.lock();
|
||||
try {
|
||||
Image oldCacheImage = mCachedImage.getAndSet(null);
|
||||
if (oldCacheImage != null) {
|
||||
oldCacheImage.close();
|
||||
}
|
||||
mCachedImage.set(reader.acquireLatestImage());
|
||||
captureComplete.signal();
|
||||
} finally {
|
||||
captureLock.unlock();
|
||||
}
|
||||
mCachedImage.set(reader.acquireLatestImage());
|
||||
} catch (Exception e) {
|
||||
mException = e;
|
||||
}
|
||||
@ -257,13 +269,26 @@ public class GlobalScreenCapture {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int retryLimit = 5;
|
||||
while (!thread.isInterrupted()) {
|
||||
Image cachedImage = mCachedImage.getAndSet(null);
|
||||
Image cachedImage = getCachedImage();
|
||||
if (cachedImage != null) {
|
||||
if (mUnderUsingImage != null) {
|
||||
mUnderUsingImage.close();
|
||||
}
|
||||
mUnderUsingImage = cachedImage;
|
||||
return cachedImage;
|
||||
} else {
|
||||
Log.d(TAG, "capture: 加锁等待获取截图");
|
||||
long waitStart = System.currentTimeMillis();
|
||||
captureLock.lock();
|
||||
try {
|
||||
captureComplete.await();
|
||||
Log.d(TAG, "capture: 获取到截图信号,等待耗时:" + (System.currentTimeMillis() - waitStart) + "ms");
|
||||
cachedImage = getCachedImage();
|
||||
if (cachedImage != null) {
|
||||
return cachedImage;
|
||||
}
|
||||
Log.d(TAG, "capture: 获取到截图信号,但是图片已经被其他脚本获取 重新获取");
|
||||
} catch (InterruptedException ex) {
|
||||
throw new ScriptInterruptedException();
|
||||
} finally {
|
||||
captureLock.unlock();
|
||||
}
|
||||
}
|
||||
if (System.currentTimeMillis() - startTime > 1000) {
|
||||
startTime = System.currentTimeMillis();
|
||||
@ -275,10 +300,23 @@ public class GlobalScreenCapture {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
|
||||
private Image getCachedImage() {
|
||||
Image cachedImage = mCachedImage.getAndSet(null);
|
||||
if (cachedImage != null) {
|
||||
if (mUnderUsingImage != null) {
|
||||
mUnderUsingImage.close();
|
||||
}
|
||||
mUnderUsingImage = cachedImage;
|
||||
return cachedImage;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public synchronized void unregister(ScriptRuntime runtime) {
|
||||
Log.d(TAG, "unregister: " + runtime);
|
||||
registeredRuntimes.remove(runtime);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user