base64

  

 (function (){

    window.toTransparentDataUrl=function(srcImage, result) {
        let targetCanvas = toTransparentCanvas(srcImage, null, result);
        if (targetCanvas===null){
            return null;
        }
        return  targetCanvas.toDataURL("image/png");
    }

    window.toTransparentImage=function(srcImage, targetImage, result) {
        let data = toTransparentDataUrl(srcImage, result);
        if (data===null){
            return null;
        }
        if (!targetImage){
            targetImage = new Image();
        }
        targetImage.src = data;
        return targetImage;
    }

    /**
     * 将给定Image对象所引用的图片,转换为背景透明的canvas返回
     * @param {Image} srcImage 源图像元素
     * @param {Element} targetCanvas 目标画布,用于保存转换后的图片. 如果传了这个参数,那么结果将展现在指定画布上; 如果不传这个参数, 那么函数会创建一个canvas对象,并返回
     * @returns 变为背景透明的图像canvas; 如果源图像就是背景透明的,那么返回null.
     */
    window.toTransparentCanvas=function(srcImage, targetCanvas, result) {
        //背景色误差容忍度
        const tolerance = 10;
        //获取图像size
        let width = srcImage.naturalWidth, height = srcImage.naturalHeight;

        //源canvas, 用于获取图像数据
        let sourceCanvas = document.createElement("canvas");
        sourceCanvas.width = width;
        sourceCanvas.height = height;
        //将图像内容绘制到源canvas,并获得数据
        let sourceContext = sourceCanvas.getContext('2d');
        sourceContext.drawImage(srcImage, 0, 0);
        //获取像素数据
        let srcImageData = sourceContext.getImageData(0, 0, width, height)
        let srcImgDataArray = srcImageData.data;
        let length = srcImgDataArray.length;
        //推测可能的背景色
        let possibleBgColor = getPosibleBgColor(srcImageData);
        if (result){
            result.bgColor = colorToHex(possibleBgColor);
        }
        //定义结果像素数据
        let trtImgDataArray = new Uint8ClampedArray(length);
        //将接近背景色的像素都置为全透明,其他的取源像素值
        //但如果本来就有透明像素存在, 就不再处理, 直接返回false
        for (var i = 0; i < length; i += 4) {
            let r = srcImgDataArray[i];
            let g = srcImgDataArray[i + 1];
            let b = srcImgDataArray[i + 2];
            let a = srcImgDataArray[i + 3];
            if (a!=255){
                return null;
            }

            let diffR = r - possibleBgColor.r;
            let diffG = g - possibleBgColor.g;
            let diffB = b - possibleBgColor.b;

            if ( Math.sqrt(
                diffR*diffR + diffG*diffG + diffB*diffB
                ) <= tolerance )
            {
                trtImgDataArray[i] = 0;
                trtImgDataArray[i+1]=0;
                trtImgDataArray[i+2]=0;
                trtImgDataArray[i+3]=0;
            } else {
                trtImgDataArray[i] = r;
                trtImgDataArray[i+1]=g;
                trtImgDataArray[i+2]=b;
                trtImgDataArray[i+3]=a;
            }
        }

        if (!targetCanvas){
            targetCanvas = document.createElement("canvas");
        }
        targetCanvas.width = width;
        targetCanvas.height = height;
        
        let targetContext = targetCanvas.getContext('2d');
        let targetImageData = new ImageData(trtImgDataArray, width, height);
        targetContext.putImageData(targetImageData, 0, 0 );
        //targetContext.drawImage(image, 0, 0);
        // let trtImgData = targetContext.getImageData(0, 0, width, height);
        if (result){
            result.imageData = targetImageData;
            result.canvas = targetCanvas;
        }
        return targetCanvas;
    }

    function numToHex(number){
        let hex = number.toString(16);
        return (hex.length < 2) ? '0' + hex : hex;
    }

    function colorToHex(color){
        return '#'+ numToHex(color.r) + numToHex(color.g) + numToHex(color.b);
    }

    /**
     * 一个存储颜色出现次数的数据结构
     */
    function Frequency(){};
    /**
     * 把颜色存入,如果已经存在,计数+1
     */
    Frequency.prototype.put = function(r,g,b){
        if (this[r]===undefined){
            this[r]={};
            this[r][g]={};
            this[r][g][b]=1;
        }else if (this[r][g]===undefined){
            this[r][g]={};
            this[r][g][b]=1;
        }else if (this[r][g][b]===undefined){
            this[r][g][b]=1;
        }else{
            this[r][g][b] += 1;
        }
    };
    /**
     * 获取数据结构中最频繁出现的颜色
     */
    Frequency.prototype.getMostRgb = function(){
        let most = 0;
        let rIndex,gIndex,bIndex;
        for (let r in this) {
            let ro = this[r];
            for (let g in ro) {
                let rgo = ro[g];
                for (let b in rgo) {
                    if (most<rgo[b]){
                        most=rgo[b];
                        rIndex = r;
                        gIndex = g;
                        bIndex = b;
                    }
                }
            }
        }
        return {r:parseInt(rIndex), g:parseInt(gIndex), b:parseInt(bIndex)};
    };

    /**
     * 获取图片数据中最有可能的背景颜色
     * @param {ImageData} imgData 这个是canvas.getImageData()获取的数据结构,应该有width,height和data三个属性
     */
    function getPosibleBgColor(imgData){
        //定义一个统计频次的对象
        let frequency = new Frequency();

        let dataArray = imgData.data;
        let width = imgData.width, height = imgData.height;
        let length = dataArray.length;
        //统计第一行
        for (let i = 0; i < width*4; i+=4) {
            frequency.put(dataArray[i], dataArray[i+1], dataArray[i+2]);
        }
        //统计最后一行
        let lastLineStart = width*4*(height -1);
        for (let i = lastLineStart; i < length; i+=4) {
            frequency.put(dataArray[i], dataArray[i+1], dataArray[i+2]);
        }
        //统计第一列(除去首行和末行)
        for (let i = width*4; i < lastLineStart; i+=width*4) {
            frequency.put(dataArray[i], dataArray[i+1], dataArray[i+2]);
        }
        //统计最后一列(除去首行和末行)
        for (let i = width*4*2 - 4; i < length - width*4; i+=width*4) {
            frequency.put(dataArray[i], dataArray[i+1], dataArray[i+2]);
        }
        return frequency.getMostRgb();
    }

})();
原文地址:https://www.cnblogs.com/fqh123/p/10600617.html