当前位置: 首页 > news >正文

canvas.toDataURL返回 Base64 编码黑色图片的检测方法

canvas.toDataURL() 用于将 Canvas 画布内容转换为 Base64 编码的图片数据 URL。

如果 canvas 绘制工作比较复杂,执行 toDataURL() 可能会失败,返回黑色图片Base64 编码数据。

这里根据转换结果检测是否为黑图,参考:

/** 
 * 根据 Base64 编码的图片数据判断是否为黑色图片
 * @param {string} base64Data - `canvas.toDataURL()` 返回的 Base64 字符串
 * @param {Object} [options] - 配置选项
 * @param {number} [options.threshold=0.95] - 黑色像素占比阈值(默认 95%)
 * @param {number} [options.maxColorValue=10] - RGB 通道最大值(小于此值视为黑色)
 * @param {number} [options.sampleStep=1] - 抽样步长(1=全检测,2=隔1像素检测,以此类推)
 * @returns {Promise<boolean>} - Promise 返回检测结果(true 表示是黑色图片)
 */
function isBase64ImageBlack(base64Data, options = {}) {
  const { 
    threshold = 0.95,
    maxColorValue = 10,
    sampleStep = 1 
  } = options;

  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => {
      try {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0);

        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const data = imageData.data;
        let blackPixelCount = 0;
        const step = sampleStep <= 0 ? 1 : sampleStep;

        // 按步长抽样检测
        for (let y = 0; y < canvas.height; y += step) {
          for (let x = 0; x < canvas.width; x += step) {
            const i = (y * canvas.width + x) * 4;
            const r = data[i];
            const g = data[i + 1];
            const b = data[i + 2];
            if (r <= maxColorValue && g <= maxColorValue && b <= maxColorValue) {
              blackPixelCount++;
            }
          }
        }

        // 计算抽样后的有效像素总数
        const sampledWidth = Math.ceil(canvas.width / step);
        const sampledHeight = Math.ceil(canvas.height / step);
        const totalSampledPixels = sampledWidth * sampledHeight;
        const blackRatio = blackPixelCount / totalSampledPixels;
        resolve(blackRatio >= threshold);
      } catch (error) {
        reject(error);
      }
    };
    img.onerror = (err) => reject(new Error('图片加载失败: ' + err.message));
    img.src = base64Data;
  });
}

关于返回黑图的原因非常多,比如浏览器兼容性、canvas 上下文复杂度等,而且还有些概率性。遇到这种情况,没必要重试 toDataURL() ,结果一般还是不对,而是要重新绘制 canvas

介绍一种必现的方法:当执行canvas.toDataURL()时,把当前浏览器页签切至后台

主要因浏览器对后台标签页的资源限制:后台页面的渲染管线会被暂停或降级,导致 Canvas 内容未更新;同时,浏览器可能主动释放 GPU 资源或清除帧缓冲区,且出于安全隐私考虑,会强制返回黑色图片以避免后台窃取敏感内容。

参考该方法,以便测试和定位实际业务问题。

相关文章:

  • cs231n-图像分类:kNN与线性分类器
  • 【遥感小目标数据集】【AI-TOD】Tiny Object Detection in Aerial Images
  • Java多线程与JConsole实践:从线程状态到性能优化!!!
  • LeetCode Hot100 刷题笔记(4)—— 二叉树、图论
  • PyTorch实现Transformer模型
  • 输出输入练习
  • 《数字图像处理》第四章 频率域滤波简要学习笔记以及频率域滤波与空间域滤波的区别
  • 构建稳健的机器学习系统:应对数据偏移挑战
  • Leetcode 交错字符串
  • [FPGA基础学习]加法器、三八译码器及DE2-115基本使用方法和数码管显示
  • (C语言)动态分配的动态通讯录(静态通讯录Plus)(C语言小项目)
  • 关于跨域问题(本地前端访问服务器端接口跨域出错)
  • Notepad++ 替换 换行符 为 逗号
  • 关于服务器只能访问localhost:8111地址,局域网不能访问的问题
  • AWE直击:萤石RX30 Max的吸泡面战争,一场清洁技术的范式革命
  • 分布式服务的熔断和降级
  • Unity Shader 学习17:合批渲染
  • Spring Boot 连接 MySQL 配置参数详解
  • 维创智脑(WIC)项目观察:技术集成的理想模型与现实难题
  • Containerd+Kubernetes搭建k8s集群
  • 篮球培训机构东方启明星被指停摆,家长称已登记未退费用超百万
  • 媒体评欧阳娜娜遭民进党当局威胁:艺人表达国家认同是民族大义
  • 一图读懂丨创新创业人才最高补贴500万元!临港新片区发布创客新政“十二条”
  • 国税总局上海市税务局通报:收到王某对刘某某及相关企业涉税问题举报,正依法依规办理
  • “AD365特应性皮炎疾病教育项目”启动,助力提升认知与规范诊疗
  • 上海高院与上海妇联签协议,建立反家暴常态化联动协作机制