autojs图片回收时img, bitmap和mat三者的关系 - 小众知识

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

2023-08-08 17:35:50 苏内容
  标签: 图片
阅读:2630
01:32:23.980/E: Can't find method com.stardust.autojs.core.graphics.ScriptCanvas.drawBitmap(com.stardust.autojs.core.image.ImageWrapper,number,number,android.graphics.Paint). ([remote]testFindImage.js#166)
Can't find method com.stardust.autojs.core.graphics.ScriptCanvas.drawBitmap(com.stardust.autojs.core.image.ImageWrapper,number,number,android.graphics.Paint).
    at WriteImg ([remote]testFindImage.js:166:0)
    at [remote]testFindImage.js:179:0

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


从日志可以看出, img回收之后, bitmap虽然宽高还是原来的, 但是大小已经变成了0, mat的宽高是0,

也就是说, img回收以后, bitmap和mat必然也回收了


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

测试代码

let imgPath = files.path("./牙叔正方形.png");
let img = images.read(imgPath);
let bitmap = img.bitmap;
let mat = img.mat;
printInfo("原始图片信息", img, bitmap, mat);
bitmap.recycle();
// mat.release();
printInfo("释放了bitmap后的图片信息", 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:00:35.347 Script-58 Main [remote://789216b9dbb2c184ad7efa6ee6d2c830/main.js]/D:

tag = 释放了bitmap后的图片信息
img      : width = 564.0, height = 564.0
bitmap   : width = 564.0, height = 564.0, allocationByteCount = 0.0
mat      : width = 564.0, height = 564.0


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

比如获取某个点的颜色

images.pixel(img, 100, 200)


代码报错

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


img不能正常使用了,

那么此时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

颜色正常获取, 说明这个取色方法能用, 至于其他方法能不能用, 要看有没有用到mat,


如果用到了mat, mat已经回收, 自然就会报错.


总结

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


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

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



正文.

chatGPT1.1.8更新了, 加了一个换头功能, 比如传说中的 狗头蛇

先选择一张蛇的图片网址:yii666.com

autojs写一个画板实现AI换头狗头蛇

涂抹蛇头

autojs写一个画板实现AI换头狗头蛇

AI 就会生成 狗头蛇

autojs写一个画板实现AI换头狗头蛇文章来源地址:https://www.yii666.com/blog/313800.html

这里面使用的就是canvas功能

写画板的步骤

第一步: 布局中添加canvas

<canvas id="imageEditCanvas" />

第二步: 编写draw事件

canvasView.on("draw", (canvas) => {})

技巧, 在编写draw事件的时候, 可能会用到canvasView的宽高, 我们可以延迟一下再添加draw事件, 也就是先让界面生成完毕, 再执行我们的操作

const { delay } = require("lang");
delay(1).then(() => {
  let canvasWidth = canvasView.getWidth();
  let canvasHeight = canvasView.getHeight();
  canvasView.on("draw", (canvas) => {})
})

第三步: 画图, 也就是画蛇的图片

画哪张图片是由用户决定的, 因此要让用户选择图片, 增加一个按钮, 让用户选择图片

let intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
context.startActivityForResult(Intent.createChooser(intent, "选择图片"), requestCode);

用户选好图片以后, 我们绘制图片文章来源地址https://www.yii666.com/blog/313800.html文章地址https://www.yii666.com/blog/313800.html

canvas.drawBitmap(maskBitmap512, matrix, null);

这里使用了matrix让图片居中, 在之前的教程已经讲过了

autojs怎么把长宽不定的图片, 放到正方形图片的中间

第四步: 涂抹蛇头

这个随意, 不管画点, 画圆, 画Path, 都可以, 我选择的是Path

canvas.drawPath(path, paint);

第五步: 提交给AI处理, 展示处理后的图片

res = await axios.post(url, form, {
  headers: {
    "Content-Type": "multipart/form-data",
    Authorization: key,
  },
});

AI 返回的是url, 直接给imgView设置src即可

<img id='content' w='*' h='*' scaleType='fitCenter'></img>
this.content.attr("src", url);


扩展阅读
相关阅读
© CopyRight 2010-2021, PREDREAM.ORG, Inc.All Rights Reserved. 京ICP备13045924号-1