SOURCE

console 命令行工具 X clear

                    
>
console
/**
 * covert canvas to image
 * and save the image file
 */
 
var Canvas2Image = function () {
    // check if support sth.
    var $support = function () {
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d');
        return {
            canvas: !!ctx,
            imageData: !!ctx.getImageData,
            dataURL: !!canvas.toDataURL,
            btoa: !!window.btoa
        };
    }();
 
    var downloadMime = 'image/octet-stream';
 
    function scaleCanvas (canvas, width, height) {
        var w = canvas.width,
            h = canvas.height;
        if (width == undefined) {
            width = w;
        }
        if (height == undefined) {
            height = h;
        }
 
        var retCanvas = document.createElement('canvas');
        var retCtx = retCanvas.getContext('2d');
        retCanvas.width = width;
        retCanvas.height = height;
        retCtx.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);
        return retCanvas;
    }
 
    function getDataURL (canvas, type, width, height) {
        canvas = scaleCanvas(canvas, width, height);
        return canvas.toDataURL(type);
    }
 
    function saveFile (strData) {
        document.location.href = strData;
    }
 
    function genImage(strData) {
        var img = document.createElement('img');
        img.src = strData;
        return img;
    }
    function fixType (type) {
        type = type.toLowerCase().replace(/jpg/i, 'jpeg');
        var r = type.match(/png|jpeg|bmp|gif/)[0];
        return 'image/' + r;
    }
    function encodeData (data) {
        if (!window.btoa) { throw 'btoa undefined' }
        var str = '';
        if (typeof data == 'string') {
            str = data;
        } else {
            for (var i = 0; i < data.length; i ++) {
                str += String.fromCharCode(data[i]);
            }
        }
 
        return btoa(str);
    }
    function getImageData (canvas) {
        var w = canvas.width,
            h = canvas.height;
        return canvas.getContext('2d').getImageData(0, 0, w, h);
    }
    function makeURI (strData, type) {
        return 'data:' + type + ';base64,' + strData;
    }
    /**
     * create bitmap image
     * 按照规则生成图片响应头和响应体
     */
    var genBitmapImage = function (oData) {
 
        //
        // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
        // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
        //
 
        var biWidth  = oData.width;
        var biHeight	= oData.height;
        var biSizeImage = biWidth * biHeight * 3;
        var bfSize  = biSizeImage + 54; // total header size = 54 bytes
 
        //
        //  typedef struct tagBITMAPFILEHEADER {
        //  	WORD bfType;
        //  	DWORD bfSize;
        //  	WORD bfReserved1;
        //  	WORD bfReserved2;
        //  	DWORD bfOffBits;
        //  } BITMAPFILEHEADER;
        //
        var BITMAPFILEHEADER = [
            // WORD bfType -- The file type signature; must be "BM"
            0x42, 0x4D,
            // DWORD bfSize -- The size, in bytes, of the bitmap file
            bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
            // WORD bfReserved1 -- Reserved; must be zero
            0, 0,
            // WORD bfReserved2 -- Reserved; must be zero
            0, 0,
            // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
            54, 0, 0, 0
        ];
        //
        //  typedef struct tagBITMAPINFOHEADER {
        //  	DWORD biSize;
        //  	LONG  biWidth;
        //  	LONG  biHeight;
        //  	WORD  biPlanes;
        //  	WORD  biBitCount;
        //  	DWORD biCompression;
        //  	DWORD biSizeImage;
        //  	LONG  biXPelsPerMeter;
        //  	LONG  biYPelsPerMeter;
        //  	DWORD biClrUsed;
        //  	DWORD biClrImportant;
        //  } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
        //
        var BITMAPINFOHEADER = [
            // DWORD biSize -- The number of bytes required by the structure
            40, 0, 0, 0,
            // LONG biWidth -- The width of the bitmap, in pixels
            biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
            // LONG biHeight -- The height of the bitmap, in pixels
            biHeight & 0xff, biHeight >> 8  & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
            // WORD biPlanes -- The number of planes for the target device. This value must be set to 1
            1, 0,
            // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
            // has a maximum of 2^24 colors (16777216, Truecolor)
            24, 0,
            // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
            0, 0, 0, 0,
            // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
            biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
            // LONG biXPelsPerMeter, unused
            0,0,0,0,
            // LONG biYPelsPerMeter, unused
            0,0,0,0,
            // DWORD biClrUsed, the number of color indexes of palette, unused
            0,0,0,0,
            // DWORD biClrImportant, unused
            0,0,0,0
        ];
 
        var iPadding = (4 - ((biWidth * 3) % 4)) % 4;
 
        var aImgData = oData.data;
 
        var strPixelData = '';
        var biWidth4 = biWidth<<2;
        var y = biHeight;
        var fromCharCode = String.fromCharCode;
 
        do {
            var iOffsetY = biWidth4*(y-1);
            var strPixelRow = '';
            for (var x = 0; x < biWidth; x++) {
                var iOffsetX = x<<2;
                strPixelRow += fromCharCode(aImgData[iOffsetY+iOffsetX+2]) +
                    fromCharCode(aImgData[iOffsetY+iOffsetX+1]) +
                    fromCharCode(aImgData[iOffsetY+iOffsetX]);
            }
 
            for (var c = 0; c < iPadding; c++) {
                strPixelRow += String.fromCharCode(0);
            }
 
            strPixelData += strPixelRow;
        } while (--y);
 
        var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData);
 
        return strEncoded;
    };
    /**
     * saveAsImage
     * @param canvasElement
     * @param {String} image type
     * @param {Number} [optional] png width
     * @param {Number} [optional] png height
     */
    var saveAsImage = function (canvas, width, height, type) {
        if ($support.canvas && $support.dataURL) {
            if (typeof canvas == "string") { canvas = document.getElementById(canvas); }
            if (type == undefined) { type = 'png'; }
            type = fixType(type);
            if (/bmp/.test(type)) {
                var data = getImageData(scaleCanvas(canvas, width, height));
                var strData = genBitmapImage(data);
                saveFile(makeURI(strData, downloadMime));
            } else {
                var strData = getDataURL(canvas, type, width, height);
                saveFile(strData.replace(type, downloadMime));
            }
        }
    };
    var convertToImage = function (canvas, width, height, type) {
        if ($support.canvas && $support.dataURL) {
            if (typeof canvas == "string") { canvas = document.getElementById(canvas); }
            if (type == undefined) { type = 'png'; }
            type = fixType(type);
 
            if (/bmp/.test(type)) {
                var data = getImageData(scaleCanvas(canvas, width, height));
                var strData = genBitmapImage(data);
                return genImage(makeURI(strData, 'image/bmp'));
            } else {
                var strData = getDataURL(canvas, type, width, height);
                return genImage(strData);
            }
        }
    };
    return {
        saveAsImage: saveAsImage,
        saveAsPNG: function (canvas, width, height) {
            return saveAsImage(canvas, width, height, 'png');
        },
        saveAsJPEG: function (canvas, width, height) {
            return saveAsImage(canvas, width, height, 'jpeg');
        },
        saveAsGIF: function (canvas, width, height) {
            return saveAsImage(canvas, width, height, 'gif');
        },
        saveAsBMP: function (canvas, width, height) {
            return saveAsImage(canvas, width, height, 'bmp');
        },
 
        convertToImage: convertToImage,
        convertToPNG: function (canvas, width, height) {
            return convertToImage(canvas, width, height, 'png');
        },
        convertToJPEG: function (canvas, width, height) {
            return convertToImage(canvas, width, height, 'jpeg');
        },
        convertToGIF: function (canvas, width, height) {
            return convertToImage(canvas, width, height, 'gif');
        },
        convertToBMP: function (canvas, width, height) {
            return convertToImage(canvas, width, height, 'bmp');
        }
    };
}();
function hexToRgb(hex) {
    // 检查输入是否为有效的十六进制颜色代码
    if (!/^#([A-Fa-f0-9]{3,6})$/.test(hex)) { return "Invalid hex color code"; }
	hex = hex.length == 4 ? (hex + hex.slice(1)) : hex;
    const rHex = hex.slice(1, 3),gHex = hex.slice(3, 5),bHex = hex.slice(5, 7);// 提取红、绿和蓝十六进制值
    const r = parseInt(rHex, 16),g = parseInt(gHex, 16),b = parseInt(bHex, 16);// 十六进制转十进制
    return {r: r, g: g, b: b, s: `rgb(${r}, ${g}, ${b})`};// 返回RGB格式的字符串
}
//上传
$('#imageUpload').on('change', function(e) {
    const file = e.target.files[0], oig = $('#originalImage');
    if (file) {
        const reader = new FileReader();
        reader.onload = function(event) {
            const img = new Image();
            img.onload = function() { oig.attr('src',event.target.result).css('display','') };
            img.src = event.target.result;
        };
        reader.readAsDataURL(file);
        $('#fileName').val(file.name);
    }
});
//png2bmp
$('#bmpButton').on('click', function() {
    const oig = document.getElementById('originalImage');
    if (oig.src) {
        const canvas = document.getElementById('imgCanvas');
        const ctx = canvas.getContext('2d'), h = oig.height, w = oig.width;
        canvas.width = w;
        canvas.height = h;
        ctx.drawImage(oig, 0, 0, w, h);
        // 将canvas内容转换为BMP格式
        const bmpData = Canvas2Image.convertToBMP(canvas);
        $('#processedImage').attr('src',bmpData.src).css('display','');
    }
});
$('#colorsButton').on('click', function() {
    const oig = document.getElementById('originalImage');
    if (oig.src) {
		// 获取图像的主导颜色
        const colorThief = new ColorThief();
        //主要色\调色板
        let mc = colorThief.getColor(oig), pc = colorThief.getPalette(oig, 10);
        let cls = $('#colorLs').html(''), m = '#'+mc[0].toString(16)+mc[1].toString(16)+mc[2].toString(16);
        cls.append($('<div data="'+m+'">主</div>')
            .css('background-color',"rgba("+mc[0]+","+mc[1]+","+mc[2]+")"));
        pc.sort((a,b)=>(a[0]+a[1]+a[2])-(b[0]+b[1]+b[2]));
        pc.forEach((v,i)=>{
            let c = '#' + v[0].toString(16) + v[1].toString(16) + v[2].toString(16);
            cls.append(`<div style="background-color:${c}" data="${c}"></div>`);
        })
        $('#colorLs div').on('click',function(){
            $('#colorPick').val($(this).attr('data'))
        })
    }
});
//处理图片
$('processButton').on('click', function() {
    const oig = document.getElementById('originalImage'), h = 314, w = 314;
    if (oig.src) {
        const canvas = document.getElementById('imgCanvas'),ctx = canvas.getContext('2d');
        canvas.width = w; canvas.height = h;
        ctx.drawImage(oig, 0, 0, w, h);
        // 处理图片,将非颜色设置为透明
        const imageData = ctx.getImageData(0, 0, w, h), data = imageData.data;
        // 假设颜色为红色,这里可以根据实际情况调整
        const tc = hexToRgb($('#colorPick').val()),
            bc = hexToRgb($('#colorBg').val()),mc = hexToRgb($('#colorMain').val());
        for (let i = 0; i < data.length; i += 4) {
            const r = data[i],g = data[i + 1],b = data[i + 2];
            // 如果当前像素颜色与目标颜色相差较大,则设置为透明
            if (Math.abs(r - tc.r) > 50 || Math.abs(g - tc.g) > 50 || Math.abs(b - tc.b) > 50) {
                //data[i + 3] = 0; // 设置alpha通道为0,即透明
                data[i] = bc.r; data[i+1] = bc.g; data[i+2] = bc.b;
            }else{
                data[i] = mc.r; data[i+1] = mc.g; data[i+2] = mc.b;
            }
        }
        ctx.putImageData(imageData, 0, 0);
        // 将canvas内容转换为BMP格式
        const bmpData = Canvas2Image.convertToBMP(canvas);
        //const blob = new Blob([bmpData], { type: 'image/bmp' }),url = URL.createObjectURL(blob);
        $('#processedImage').attr('src',bmpData.src).css('display','');
    }
});
//下载
$('#downloadButton').on('click', function() {
    const pi = $('#processedImage');
    if (pi[0].src) {
        //let l = document.createElement('a'); l.href = pi.src; l.download = 'processed_stamp.bmp'; l.click();
        $('<a>').attr({href: pi[0].src, download: 'processed_stamp.bmp'}).click();
    }
})
//黑白效果-待验证
function blackEffect(){
    const canvas = document.getElementById('imgCanvas'),ctx = canvas.getContext('2d');
    var imageData = ctx.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var pixelData = imageData.data
    for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){
        let r = pixelData[i*4+0],g = pixelData[i*4+1],b = pixelData[i*4+2];
        pv = (r*0.3+g*0.59+b*0.11) > 125 ? 255:0;
        pixelData[i*4+0] = pv;
        pixelData[i*4+1] = pv;
        pixelData[i*4+2] = pv;
    }
    contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height )
}
<div class="container">
    <div class="left">
        <h2>原始图片(PNG)</h2>
        <div class="controls">
            <input type="file" id="imageUpload" accept="image/png">
            <input type="hidden" id="fileName">
        </div>
        <div class="image-container">
            <img id="originalImage" src="" alt="原始图片" style="display:none">
        </div>
        <div class="controls">
            <button id="colorsButton">提取颜色</button>
			处理基础色<input type="color" id="colorPick" value="#FF0000"/>
        </div>
        <div class="image-container" id="colorLs" style="display: flex;">
            <div style="background-color:red"></div>
        </div>
    </div>
    <div class="right">
        <h2>处理后的图片(BMP)</h2>
        <div class="controls">
            <button id="bmpButton">png2bmp</button>
            <button id="processButton">处理图片</button>
            <button id="downloadButton">下载BMP图片</button>
        </div>
        <div class="image-container">
            <img id="processedImage" src="" alt="处理后的图片" style="display:none"/>
        </div>
        <div class="controls">
			背景 <input type="color" id="colorBg" value="#FFFFFF"/>
			主色 <input type="color" id="colorMain" value="#FF0000"/>
        </div>
        <div class="image-container">
            <canvas id="imgCanvas" width="100" height="100"></canvas>
        </div>
    </div>
</div>
body {
    display: flex;
    justify-content: space-between;
    padding: 20px;
}
.container {
    display: flex;
    width: 100%;
}
.left, .right {
    width: 45%;
    text-align: center;
}
.image-container {
    margin-top: 20px;
    min-height: 50px;
    border: 1px solid #000;
}
.image-container div{
    width: 20px;
    height: 50px;
    border-width: 1px;
    border-style: dotted; 
}
#originalImage, #processedImage {
    max-width: 100%;
    max-height: 300px;
}
.controls {
    margin-top: 20px;
}

本项目引用的自定义外部资源