裁剪保存的图片黑边问题

某些机型上,截图生成的报告,存到手机中会有黑边的问题;不管是设置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());
相关推荐
无限大.1 小时前
前端知识速记:节流与防抖
前端
十八朵郁金香1 小时前
【VUE案例练习】前端vue2+element-ui,后端nodo+express实现‘‘文件上传/删除‘‘功能
前端·javascript·vue.js
学问小小谢1 小时前
第26节课:内容安全策略(CSP)—构建安全网页的防御盾
运维·服务器·前端·网络·学习·安全
LCG元2 小时前
Vue.js组件开发-实现全屏图片文字缩放切换特效
前端·javascript·vue.js
还是鼠鼠3 小时前
图书管理系统 Axios 源码__新增图书
前端·javascript·vscode·ajax·前端框架·node.js·bootstrap
还是鼠鼠6 小时前
图书管理系统 Axios 源码 __删除图书功能
前端·javascript·vscode·ajax·前端框架·node.js·bootstrap
轻口味6 小时前
Vue.js `Suspense` 和异步组件加载
前端·javascript·vue.js
m0_zj7 小时前
8.[前端开发-CSS]Day08-图形-字体-字体图标-元素定位
前端·css
还是鼠鼠7 小时前
图书管理系统 Axios 源码__编辑图书
前端·javascript·vscode·ajax·前端框架
北极象8 小时前
vue3中el-input无法获得焦点的问题
前端·javascript·vue.js