autojs图片回收时img, bitmap和mat三者的关系

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 牙叔教程 简单易懂

牙叔教程 简单易懂


autojs图片的数据表现形式, 一共有三种

  • img: com.stardust.autojs.core.image.ImageWrapper
  • bitmap
  • mat


三种图片数据格式互相转换

img转bitmap和mat

img.bitmap
img.mat


bitmap转img

com.stardust.autojs.core.image.ImageWrapper.ofMat(bitmap)


mat转img

com.stardust.autojs.core.image.ImageWrapper.ofMat(mat)


bitmap转mat

org.opencv.android.Utils.bitmapToMat(bitmap, mat);


mat转bitmap

org.opencv.android.Utils.matToBitmap(mat, bitmap);


img回收时, 会影响bitmap和mat吗

公共函数

// 打印图片信息
function printInfo(tag, img, bitmap, mat) {
  let arr = ["\n"];
  arr.push("tag = " + tag);
  try {
    arr.push(java.lang.String.format("%1$-9s: width = %2$s, height = %3$s", "img", img.width, img.height));
  } catch (e) {
    arr.push(java.lang.String.format("%1$-9s: %2$ss", "img", e));
  }
  arr.push(
    java.lang.String.format(
      "%1$-9s: width = %2$s, height = %3$s, allocationByteCount = %4$s",
      "bitmap",
      bitmap.width,
      bitmap.height,
      bitmap.allocationByteCount
    )
  );
  arr.push(java.lang.String.format("%1$-9s: width = %2$s, height = %3$s", "mat", mat.width(), mat.height()));
  log(arr.join("\n"));
}
// 查看img
function viewImg(img) {
  images.save(img, "/sdcard/1.jpg", "jpg", 50);
  app.viewFile("/sdcard/1.jpg");
}
// 查看mat
function viewMat(mat) {
  let mat2 = mat.clone();
  Imgproc.cvtColor(mat, mat2, Imgproc.COLOR_BGRA2RGBA);
  let tempFilePath = files.join(files.getSdcardPath(), "脚本", "mat.png");
  Imgcodecs.imwrite(tempFilePath, mat2);
  mat2.release();
  app.viewFile(tempFilePath);
}


测试代码

let imgPath = files.path("./牙叔正方形.png");
let img = images.read(imgPath);
let bitmap = img.bitmap;
let mat = img.mat;
printInfo("原始图片信息", img, bitmap, mat);
img.recycle();
printInfo("释放了img后的图片信息", img, bitmap, mat);


日志

tag = 原始图片信息
img      : width = 564.0, height = 564.0
bitmap   : width = 564.0, height = 564.0, allocationByteCount = 1272384.0
mat      : width = 564.0, height = 564.0
11-19 17:56:54.150 Script-56 Main [remote://789216b9dbb2c184ad7efa6ee6d2c830/main.js]/D:
tag = 释放了img后的图片信息
img      : JavaException: java.lang.IllegalStateException: image has been recycleds
bitmap   : width = 564.0, height = 564.0, allocationByteCount = 0.0
mat      : width = 0.0, height = 0.0


从日志可以看出, bitmap的大小归零了, 那么img还能用吗? 我们用图色命令来测试一下

比如获取某个点的颜色

images.pixel(img, 100, 200)


代码报错

Wrapped java.lang.IllegalStateException: Can't call getPixel() on a recycled bitmap


mg不能正常使用了,

那么此时img算回收了吗?

至少mat还是存在的, mat可以正常使用, 所以img也不算回收,


我们用代码来判断一下图片是否回收

log(img.isRecycled()); // false


代码说图片并没有回收, 那么此时把mat也释放掉, img算不算回收了呢?

mat.release();
log(img.isRecycled()); // false

还是false, img并没有被标记为已回收


autojs的img回收方法具体代码

public synchronized void recycle() {
    Bitmap bitmap = this.mBitmap;
    if (bitmap != null) {
        bitmap.recycle();
    }
    this.mBitmap = null;
    Mat mat = this.mMat;
    if (mat != null) {
        OpenCVHelper.release(mat);
    }
    this.mMat = null;
    Image image = this.mediaImage;
    if (image != null) {
        image.close();
    }
    this.mediaImage = null;
    Debug.INSTANCE.noMemoryLeak(this.id);
    d<b> dVar = this.ref;
    if (dVar != null) {
        dVar.b = 0;
    }
    this.isRecycled = true;
}


看着还是有点复杂, mediaImage是个啥? 我都没用过, 也不管用管它了, 知道有这么个东西就行


mat回收时, 会影响img和bitmap吗

测试代码

let imgPath = files.path("./牙叔正方形.png");
let img = images.read(imgPath);
let bitmap = img.bitmap;
let mat = img.mat;
printInfo("原始图片信息", img, bitmap, mat);
mat.release();
printInfo("释放了mat后的图片信息", img, bitmap, mat);


日志

tag = 原始图片信息
img      : width = 564.0, height = 564.0
bitmap   : width = 564.0, height = 564.0, allocationByteCount = 1272384.0
mat      : width = 564.0, height = 564.0
11-19 18:24:44.707 Script-81 Main [remote://789216b9dbb2c184ad7efa6ee6d2c830/main.js]/D:
tag = 释放了mat后的图片信息
img      : width = 564.0, height = 564.0
bitmap   : width = 564.0, height = 564.0, allocationByteCount = 1272384.0
mat      : width = 0.0, height = 0.0


从日志可以看出, mat已经归零了, bitmap没有变化, img此时能用吗? 我们用代码测一下
比如获取某个点的颜色

images.pixel(img, 100, 200); // -16777212


总结

图片回收一律用img, 只要img回收了, 那么bitmap和mat也就回收了;

除非你用了bitmap.copy或者mat.clone, 来复制图片数据,

此时你就要自己去回收你复制的图片数据了


以上代码的测试环境

手机: Mi 11 Pro

Android版本: 11

Autojs版本: 9.0.11

名人名言


思路是最重要的, 其他的百度, bing, stackoverflow, github, 安卓文档, autojs文档, 最后才是群里问问
--- 牙叔教程


声明


部分内容来自网络
本教程仅用于学习, 禁止用于其他用途



相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
8月前
|
XML 算法 Java
Android App开发之位图加工Bitmap中转换位图的像素色彩、裁剪内部区域、利用矩阵变换位图的讲解及实战(附源码和演示)
Android App开发之位图加工Bitmap中转换位图的像素色彩、裁剪内部区域、利用矩阵变换位图的讲解及实战(附源码和演示)
128 0
|
iOS开发
使用AutoLayout约束, 为啥图片的大小(Image size)却还以实际大小显示?
问题 给一个 UIImageView 设置一张图片时,使用 AutoLayout 给 UIImageView 约束宽高,但是实际显示的大小,图片以实际的大小显示出来,代码也没有设置 frame,设置contentMode为UIViewContentModeScaleAspectFit 也不起作用。
1116 0
SwiftUI—使用Image图像视图显示项目中的图片
SwiftUI—使用Image图像视图显示项目中的图片
657 0
SwiftUI—使用Image图像视图显示项目中的图片
|
Android开发
【Android 应用开发】Paint 渲染 之 BitmapShader 位图渲染 ( 渲染流程 | CLAMP 拉伸最后像素 | REPEAT 重复绘制图片 | MIRROR 绘制反向图片 )(二)
【Android 应用开发】Paint 渲染 之 BitmapShader 位图渲染 ( 渲染流程 | CLAMP 拉伸最后像素 | REPEAT 重复绘制图片 | MIRROR 绘制反向图片 )(二)
319 0
【Android 应用开发】Paint 渲染 之 BitmapShader 位图渲染 ( 渲染流程 | CLAMP 拉伸最后像素 | REPEAT 重复绘制图片 | MIRROR 绘制反向图片 )(二)
|
自然语言处理 算法 计算机视觉
举例Halcon,简述数字图像处理之Blob分析和纹理分析texture_laws
举例Halcon,简述数字图像处理之Blob分析和纹理分析texture_laws
949 0
|
前端开发 Android开发
【Android 应用开发】Paint 渲染 之 BitmapShader 位图渲染 ( 渲染流程 | CLAMP 拉伸最后像素 | REPEAT 重复绘制图片 | MIRROR 绘制反向图片 )(一)
【Android 应用开发】Paint 渲染 之 BitmapShader 位图渲染 ( 渲染流程 | CLAMP 拉伸最后像素 | REPEAT 重复绘制图片 | MIRROR 绘制反向图片 )(一)
431 0
|
程序员
好程序员分享该如何选择background-image和img标签
  好程序员分享该如何选择background-image和img标签,用img标签  如果你希望别人打印页面时候包含这张图片请使用img标签  当这张图片有非常有意义的语义,比如警告图标,请使用img标签及它的alt属性。
6820 0
|
Windows
[UWP]使用Writeable?Bitmap创建HSV色轮
原文:[UWP]使用Writeable?Bitmap创建HSV色轮 1. HSV 1.1 HSV的定义 HSV都是一种将RGB色彩模型中的点在圆柱坐标系中的表示法,这种表示法试图做到比RGB基于笛卡尔坐标系的几何结构更加直观。
1485 0

热门文章

最新文章