美文网首页
文件处理-图片

文件处理-图片

作者: 阿飞_1217 | 来源:发表于2020-12-03 15:23 被阅读0次
    文件图片关系图 图片转换.png

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

    1. 图片获取DataURL
    • dataURL是一种特殊格式的URL。它的前缀是{\color{red}{data}}
    // 格式
    data:[<mediatype>][,base64],<data>
    // 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
    }
    

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

    相关文章

      网友评论

          本文标题:文件处理-图片

          本文链接:https://www.haomeiwen.com/subject/malswktx.html