文件处理-图片

文件图片关系图
图片转换.png

图中的几个对象包括 canvas、image、DataURL、ObjectURL、Blob、ArrayBuffer

  1. 图片获取DataURL
  • dataURL是一种特殊格式的URL。它的前缀是
// 格式
data:[][,base64],
// eg
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAhAAAAIwCAYAAADXrFK...

从本地选择图片获取DataURL

const reader = new FileReader();
reader.onload = function () {
    const output = document.querySelector("img");
    output.src = reader.result;
};
// 这里传入的参数是一个文件File 而上面图片中是blob。 因为File继承Blob
reader.readAsDataURL(event.target.files[0]);

// 补充  reader.readAsText()  可以获取文本的内容
  1. 图片加载ObjectURL
    通过 URL.createObjectURL(blob)创建
// 格式
blob:null/ab24c171-1c5f-4de1-a44e-568bc1f77d7b
// eg
fetch("https://avatars3.githubusercontent.com/u/4220799")
.then((response) => response.blob())
.then((blob) => {
    const objectURL = URL.createObjectURL(blob);
    image.src = objectURL;
});
// 仅作示例 实际不这么使用

//补充  下载为文件
//  const blob = new Blob([res.data], { type: "application/vnd.ms-excel" });
const link = document.createElement('a');
link.download ='test.excel';
link.style.display = 'none';
link.href = URL.createObjectURL(blob);
document.body.appendChild(link);
link.click();
// 这里需要释放掉,否则会一直占用内存
URL.revokeObjectURL(link.href); // 释放URL 对象
document.body.removeChild(link);
  1. Canvas中的图片处理
  • drawImage(image) 根据已有的图片对象 绘制图片
  • getImageData(x,y, w,h) 获取画布某一个区域内的图像数据(像素数据)
  • putImageData() 将图像数据绘制在画布上
    3.1 图片压缩
1. 绘制图片
context.drawImage(img, dx, dy, dWidth, dHeight)
2. 压缩
const dataUrl = canvas.toDataURL(mimeType, qualityArgument);
const blob = canvas.toBlob(callback, mimeType, qualityArgument)

3.2 图片灰度化

1 获取图像的像素数据
const imageData = ctx.getImageData(x, y, W, H);
const data = imageData.data;
2. 处理图像的像素数据
for (let i = 0; i < data.length; i += 4) {
    const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
    data[i] = avg; // red
    data[i + 1] = avg; // green
    data[i + 2] = avg; // blue
}
3. 处理后的数据重新绘制
ctx.putImageData(imageData, x, y);

3.3 图片打码

1. 获取图像的像素
const imageData = ctx.getImageData(x, y, w, h).data;
// option defaults
2. 设置马赛克块的像素大小 
const res = 4
const size = res
const alpha = 1
const cols = w / res + 1
const rows = h / res + 1
const halfSize = size / 2
3. 双循环行和列
for (let row = 0; row < rows; row++) {
    let y = (row - 0.5) * res
    // normalize y so shapes around edges get color
    let pixelY = Math.max(Math.min(y, h - 1), 0)

    for (let col = 0; col < cols; col++) {
        let x = (col - 0.5) * res
        // normalize y so shapes around edges get color
        let pixelX = Math.max(Math.min(x, w - 1), 0)
        let pixelIndex = (pixelX + pixelY * w) * 4
        const red = imageData[pixelIndex + 0]
        const green = imageData[pixelIndex + 1]
        const blue = imageData[pixelIndex + 2]
        const pixelAlpha = alpha * (imageData[pixelIndex + 3] / 255)
        4 绘制马赛克方块  square
        ctx.fillStyle = `rgba(${red},${green},${blue},${pixelAlpha})`
        ctx.fillRect(x - halfSize, y - halfSize, size, size)
    } // col
} // row

3.4 取色器

1. 获取位置
const {x, y} = event;
2. 获取位置后的一个像素
const imageData = ctx.getImageData(x, y, 1, 1).data;
const colorValue = imageData.join(',');
const colorValueEl = document.querySelector('#colorValue');
colorValueEl.innerText = colorValue;

const bgColorEl = document.querySelector('#bgColor');
bgColorEl.style.backgroundColor = `rgba(${colorValue})`

3.4 边缘检测

1. 像素黑白化
const grayData = blackWhitePixel(imageData);
2. 检测边缘
const edgeData = contourDIB(grayData, w, h);
_imageData.data = imageData;
ctx.putImageData(_imageData, 0, 0);

function contourDIB(data, lWidth, lHeight) {
    // 保存原始数据
    const dataInit = [];
    for (let i = 0, len = data.length; i < len; i++) {
        dataInit[i] = data[i];
    }
    for (let j = 1; j < lHeight - 1; j++) {
        for (let i = 1; i < lWidth - 1; i++) {
            const lpSrc = j * lWidth + i;
            const pixel = dataInit[lpSrc * 4];
            if (pixel === 0) {
                const surroundArr = [lpSrc + lWidth - 1, lpSrc + lWidth,
                lpSrc + lWidth + 1, lpSrc - 1, lpSrc + 1,
                lpSrc - lWidth - 1, lpSrc - lWidth, lpSrc - lWidth + 1];
                let value = 0;
                for (let m = 0, len = surroundArr.length; m < len; m++) {
                    value += dataInit[surroundArr[m] * 4];
                }
                // 如果相邻对八个点都是黑点 说明不是边缘
                if (value === 0) {
                    for (let k = 0; k < 3; k++) {
                        data[lpSrc * 4 + k] = 255;
                    }
                }
            }
        }
    }
    return data
}

参考
玩转前端二进制
数字图像处理-前端实现

你可能感兴趣的:(文件处理-图片)