裁剪保存的图片黑边问题

某些机型上,截图生成的报告,存到手机中会有黑边的问题;不管是设置scale缩放比为1,画布的宽高为截取内容的width、height,都没有办法解决;

解决方式

获取图片的像素信息

我们创建一个canvas,渲染图片,然后通过 getImageData 方法拿到图片信息。 drawImage: 绘制图像,将图片绘制到画布上 getImageData: 返回一个ImageData对象,获取像素数据

javascript 复制代码
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");

const image = new Image();
image.onload = draw;
image.src = url;
// image.src = dom.toDataURL(); // 导出图片
image.crossOrigin = "Anonymous";

function draw() {
    canvas.width = image.width;
    canvas.height = image.height;

    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
    const { data, width, height } = imageData;
}

打印出来的图片信息为:

  • width: 图片宽度;
  • height: 图片高度;
  • colorSpace: 色彩模式,这里是srgb;
    • ps: 颜色范围的色域标准,sRGB色域应用广泛,包括Windows、Photoshop、大部分浏览器、显示屏等的默认配置都是sRGB
  • data: 色彩信息,可以被使用作为查看初始像素数据。每个像素用 4 个 1bytes 值 (按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。;

我们重点来看看data:

  • data是个数组;
  • 每4个元素构成一个RGBA像素块;
  • 每个元素的值范围都是0-255;
  • RGB代表红绿蓝三原色;
  • A代表透明度(0是完全透明,255是不透明);

假如存在两个,都是黑色的像素点,宽度为2, 高度为1,值为[0, 0, 0, 255, 0, 0, 0, 255]。 那么他的格式就是:

javascript 复制代码
{r: 0, g: 0, b: 0, a: 255}, {r: 0, g: 0, b: 0, a: 255}

获取像素块索引

我们已知widthheight,col为列,row为行,两层循环构造每一个网格,便利所有网格的像素,如果有色彩则设置裁剪的起点和终点。

像素操作

索引值从 0 到 (高度× 宽度 ×4)-1 例如,要读取图片中位于第 50 行,第 200 列的像素的蓝色部份,你会写以下代码: (50 * (imageData.width * 4)) + (200 * 4)) + 2 根据行、列读取某像素点的 R/G/B/A 值的公式: ((50 * (imageData.width * 4)) + (200 * 4)) + 0/1/2/3;

javascript 复制代码
for (let col = 0; col < width; col++) {
    for (let row = 0; row < height; row++) {
        // 当前像素块相对于图片的索引位置
        const pxIndex = (row * width + col) * 4;
    }
}

获取每个像素块的RGBA信息

javascript 复制代码
const pxStartIndex = pxIndex;
const pxData = {
    r: data[pxStartIndex],
    g: data[pxStartIndex + 1],
    b: data[pxStartIndex + 2],
    a: data[pxStartIndex + 3]
};

计算裁剪的起点和终点坐标

我们需要将png图片周围的透明区域去掉。所以先判断是否存在色彩:

javascript 复制代码
// 不透明
const colorExist = pxData.a !== 0;

起点和终点初始化值一定要先设置成极限值,也就是两点互换位置,

javascript 复制代码
let startX = width,
    startY = height,
    endX = 0,
    endY = 0;
  • startX坐标取当前col和startX的最小值;
  • endX坐标取当前col和endX的最大值;
  • startY坐标取当前row和startY的最小值;
  • endY坐标取当前row和endY的最大值;

如果之前初始化的时候没有取极限,使用Math.min判断的时候一直会是0;

javascript 复制代码
if (colorExist) {
    startX = Math.min(col, startX);
    endX = Math.max(col, startX);
    startY = Math.min(row, startY);
    endY = Math.max(row, endY);
}

根据计算的起点终点进行裁剪

javascript 复制代码
const cropCanvas = document.createElement("canvas");
const cropCtx = cropCanvas.getContext("2d");
cropCanvas.width = endX - startX;
cropCanvas.height = endY - startY;
cropCtx.drawImage(
    image,
    startX,
    startY,
    cropCanvas.width,
    cropCanvas.height,
    0,
    0,
    cropCanvas.width,
    cropCanvas.height
);

// 裁剪后的图像字符串
console.log(cropCanvas.toDataURL());
相关推荐
撸猫7913 分钟前
HttpSession 的运行原理
前端·后端·cookie·httpsession
亦世凡华、22 分钟前
Rollup入门与进阶:为现代Web应用构建超小的打包文件
前端·经验分享·rollup·配置项目·前端分享
Bl_a_ck1 小时前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架
为美好的生活献上中指1 小时前
java每日精进 5.11【WebSocket】
java·javascript·css·网络·sql·websocket·网络协议
augenstern4162 小时前
webpack重构优化
前端·webpack·重构
海拥✘2 小时前
CodeBuddy终极测评:中国版Cursor的开发革命(含安装指南+HTML游戏实战)
前端·游戏·html
寧笙(Lycode)2 小时前
React系列——HOC高阶组件的封装与使用
前端·react.js·前端框架
asqq82 小时前
CSS 中的 ::before 和 ::after 伪元素
前端·css
拖孩3 小时前
【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
前端·javascript·css·vue.js·ui组件库
苹果电脑的鑫鑫3 小时前
element中表格文字剧中可以使用的属性
javascript·vue.js·elementui