canvas canvas2image 生成bmp格式的图片

原因:canvas  生成图片,可通过toDataURL()方法。

canvas.toDataURL(type, encoderOptions);

1、type:图片格式,默认为 image/png,可以是其他image/jpeg等

2、encoderOptions:0到1之间的取值,主要用来选定图片的质量,默认值是0.92,超出范围也会选择默认值。

toDataURL()能把画布里的图案转变成base64编码格式的png,,然后返回 Data URL数据。即使把type改为bmp,生成后缀为bmp的文件,文件的本质还是png类型的。这是需要用到canvas2image.js 来进行转换。

大致的逻辑就是把生成base64链接再进行转化。

var oCanvas = document.getElementById("thecanvas");

Canvas2Image.saveAsPNG(oCanvas);  // 这将会提示用户保存PNG图片

Canvas2Image.saveAsJPEG(oCanvas); // 这将会提示用户保存JPG图片

Canvas2Image.saveAsBMP(oCanvas);  // 这将会提示用户保存BMP图片


// 返回一个包含PNG图片的<img>元素
var oImgPNG = Canvas2Image.saveAsPNG(oCanvas, true);   

// 返回一个包含JPG图片的<img>元素
var oImgJPEG = Canvas2Image.saveAsJPEG(oCanvas, true); 
                                                       
// 返回一个包含BMP图片的<img>元素
var oImgBMP = Canvas2Image.saveAsBMP(oCanvas, true); 


// 这些函数都可以接受高度和宽度的参数
// 可以用来调整图片大小

// 把画布保存成100x100的png格式
Canvas2Image.saveAsPNG(oCanvas, false, 100, 100);

以下是测试demo,多余部分自行去除

html:

<!DOCTYPE html>
<html>
<head> 
    <meta charset="utf-8">
    <title>菜鸟教程(runoob.com)</title> 
    <script type="text/javascript"src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script type="text/javascript"src="./canvas2image.js"></script>
    <style>
        .doc {
            width: 604px;
            margin: 0 auto;
        }
        canvas {
            border: 1px solid #888;
        }
    </style>
<body>
<div class="">

    <div style="float: left;">
        <p>
            宽度 : <input type="number" value="1920" id="imgW" /><br/>
            高度 : <input type="number" value="128" id="imgH" /><br/>
            color: <select id="bgColor">
            <option value="white">white</option>
            <option value="black">black</option>
            <option value="gray">gray</option>
            <option value="yellow">yellow</option>
            <option value="blue">blue</option>
            <option value="red">red</option>
        </select><br/>
            <button onclick="setWh()">设置宽高</button>
            <br/>
            <br/>
            文字行1 : <input type="text" value="第一行文字" id="text1" /> <br/>
            X: <input type="text" id="t1X" value="0"/>  <br/>
            Y: <input type="text" id="t1Y" value="30"/><br/>
            font-size: <select id="t1Size">
            <option value="10px">10px</option>
            <option value="15px">15px</option>
            <option value="20px">20px</option>
            <option value="25px">25px</option>
            <option value="30px">30px</option>
            <option value="40px">40px</option>
            <option value="50px">50px</option>
        </select>
            font-style: <select id="t1Font">
            <option value="Georgia">Georgia</option>
            <option value="Verdana">Verdana</option>
            <option value="宋体">宋体</option>
            <option value="微软雅黑">微软雅黑</option>
        </select><br/>
            color: <select id="t1Color">
            <option value="black">black</option>
            <option value="white">white</option>
            <option value="gray">gray</option>
            <option value="yellow">yellow</option>
            <option value="blue">blue</option>
            <option value="red">red</option>
        </select><br/>
            <br/>
            <br/>
            文字行2 : <input type="text" value="" id="text2" /><br/>
            X: <input type="text" id="t2X" value="50"/>  <br/>
            Y: <input type="text" id="t2Y" value="70"/><br/>
            font-size: <select id="t2Size">
            <option value="10px">10px</option>
            <option value="15px">15px</option>
            <option value="20px">20px</option>
            <option value="25px">25px</option>
            <option value="30px">30px</option>
            <option value="40px">40px</option>
            <option value="50px">50px</option>
        </select>
            font-style: <select id="t2Font">
            <option value="Georgia">Georgia</option>
            <option value="Verdana">Verdana</option>
            <option value="宋体">宋体</option>
            <option value="微软雅黑">微软雅黑</option>
        </select><br/>
            <br/>
            <button onclick="setTest()" >显示文字</button>
            <br/>
            保存图片格式:
            <select id="sel">
                <option value="bmp">bmp</option>
                <option value="png">png</option>
                <option value="jpeg">jpeg</option>

            </select>
            <button style="display: none;" id="convert" >转换为   </button>
            <button style="display: none;" id="save">保存</button>

        </p>
        <br/>
        <br/>
        <!--<button onclick="showImg()" >图片</button>-->

    </div>
    <div style="">
        <canvas id="cvs" width="1920px" height="128px" onclick="clickBtn()"></canvas>
    </div>
</div>
<script>
    var canvas, ctx, bMouseIsDown = false, iLastX, iLastY,
        $save, $imgs,
        $convert, $imgW, $imgH,
        $sel;
    function init () {
        $("#text1").css("width",window.innerWidth-100);
        canvas = document.getElementById('cvs');
        ctx = canvas.getContext('2d');
        ctx.fillStyle="white";
        ctx.fillRect(0,0,1920,128);
        $save = document.getElementById('save');
        $convert = document.getElementById('convert');
        $sel = document.getElementById('sel');
        $imgs = document.getElementById('imgs');
        $imgW = document.getElementById('imgW');
        $imgH = document.getElementById('imgH');
        bind();
        draw();
    }
    function bind () {
        canvas.onmousedown = function(e) {
            bMouseIsDown = true;
            iLastX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
            iLastY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
        }
        canvas.onmouseup = function() {
            bMouseIsDown = false;
            iLastX = -1;
            iLastY = -1;
        }
        canvas.onmousemove = function(e) {
            if (bMouseIsDown) {
                var iX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
                var iY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
                ctx.moveTo(iLastX, iLastY);
                ctx.lineTo(iX, iY);
                ctx.stroke();
                iLastX = iX;
                iLastY = iY;
            }
        };

        $save.onclick = function (e) {
            var type = $sel.value,
                w = $imgW.value,
                h = $imgH.value;
            Canvas2Image.saveAsImage(canvas, w, h, type);
        }
        $convert.onclick = function (e) {
            var type = $sel.value,
                w = $imgW.value,
                h = $imgH.value;
            $imgs.appendChild(Canvas2Image.convertToImage(canvas, w, h, type))
        }

    }
    function setWh() {
        var width = $("#imgW").val();
        var height = $("#imgH").val();
        $("#cvs").css("width",width+"px");
        $("#cvs").css("height",height+"px");
        ctx.clearRect(0,0,width,height);
        ctx.fillStyle = $("#bgColor").val();
        ctx.fillRect(0,0,width,height);
    }
    function setTest() {
        var width = $("#imgW").val();
        var height = $("#imgH").val();
        var c=document.getElementById("cvs");
        var ctx=c.getContext("2d");
        ctx.clearRect(0,0,width,height);
        ctx.fillStyle = $("#bgColor").val();
        ctx.fillRect(0,0,width,height);

        if($("#text1").val() != "") {
            ctx.fillStyle = $("#t1Color").val(); // text color
            ctx.font= $("#t1Size").val()+" "+$("#t1Font").val();
            ctx.fillText($("#text1").val(),$("#t1X").val(),$("#t1Y").val());
        }

        if($("#text2").val() != "") {
            ctx.fillStyle="white";
            ctx.font= $("#t2Size").val()+" "+$("#t2Font").val();
            var gradient=ctx.createLinearGradient(0,0,c.width,0);
            gradient.addColorStop("0","magenta");
            gradient.addColorStop("0.5","blue");
            gradient.addColorStop("1.0","red");
            ctx.fillStyle=gradient;
            ctx.fillText($("#text2").val(),$("#t2X").val(),$("#t2Y").val());
        }

    }

    function draw () {
    }

    function clickBtn () {
        var oCanvas = document.getElementById("cvs");
        var width = $("#imgW").val();
        var height = $("#imgH").val();
        var imgDom = Canvas2Image.convertToImage(oCanvas, width, height, $("#sel").val());

       console.log( oCanvas.toDataURL("image/"+$("#sel").val()));
        console.log( imgDom.src);
        var imgUrl =imgDom.src;
        var link = document.createElement("a");
        link.href = imgUrl;
        link.download = "XXXX."+$("#sel").val();
        document.body.appendChild(link);
        link.click();
        URL.revokeObjectURL(link.href); // 释放URL 对象
        document.body.removeChild(link);
    }

    onload = init;
</script>
</body>
</html>

canvas2image.js

/**
 * 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');
        }
    };

}();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值