裁剪保存的图片黑边问题

某些机型上,截图生成的报告,存到手机中会有黑边的问题;不管是设置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());
相关推荐
龙雨LongYu1210 分钟前
vue3+ts 我写了一个跟swagger.yml生成请求和响应实体(接口)
前端·vue.js·typescript
Stanford_11061 小时前
关于IDE的相关知识之一【使用技巧】
前端·ide·windows·微信小程序·微信公众平台·twitter·微信开放平台
_志哥_1 小时前
web开发环境下启动HTTPS服务访问
前端·javascript·https
爱健身的小刘同学1 小时前
安装 electron 依赖报错
前端·javascript·electron
耶啵奶膘1 小时前
uniapp+vue2+uview2.0导航栏组件二次封装
前端·javascript·uni-app
布兰妮甜1 小时前
如何使用 Tailwind CSS 构建响应式网站:详细指南
前端·css·tailwind css
MavenTalk1 小时前
前端技术选型之uniapp
android·前端·flutter·ios·uni-app·前端开发
雨中奔跑的小孩1 小时前
electron打包部署vue项目
javascript·vue.js·electron
ZZZCY20031 小时前
路由策略与路由控制实验
前端·网络
shawya_void1 小时前
javaweb-day01-html和css初识
前端·css·html