美文网首页
autojs图片回收时img, bitmap和mat三者的关系

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

作者: 牙叔教程 | 来源:发表于2021-11-19 19:02 被阅读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, 来复制图片数据,
    此时你就要自己去回收你复制的图片数据了

    以上代码的测试环境

    手机: Mi 11 Pro
    Android版本: 11
    Autojs版本: 9.0.11

    名人名言

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

    声明

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

    相关文章

      网友评论

          本文标题:autojs图片回收时img, bitmap和mat三者的关系

          本文链接:https://www.haomeiwen.com/subject/qodetrtx.html