裁剪保存的图片黑边问题

某些机型上,截图生成的报告,存到手机中会有黑边的问题;不管是设置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());
相关推荐
xjt_09013 分钟前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农15 分钟前
Vue 2.3
前端·javascript·vue.js
夜郎king40 分钟前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳1 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵2 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星2 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_2 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
未来龙皇小蓝2 小时前
RBAC前端架构-01:项目初始化
前端·架构
程序员agions2 小时前
2026年,微前端终于“死“了
前端·状态模式
万岳科技系统开发2 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法