Canvas2Image.js通过元素单击将base64图像保存为png

时间:2012-10-09 16:29:01

标签: javascript html image stream base64

我没有看到canvas2Image.js插件:

/*
 * Canvas2Image v0.1
 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk
 * MIT License [http://www.opensource.org/licenses/mit-license.php]
 */

var Canvas2Image = (function() {

    // check if we have canvas support
    var bHasCanvas = false;
    var oCanvas = document.createElement("canvas");
    if (oCanvas.getContext("2d")) {
        bHasCanvas = true;
    }

    // no canvas, bail out.
    if (!bHasCanvas) {
        return {
            saveAsBMP : function(){},
            saveAsPNG : function(){},
            saveAsJPEG : function(){}
        }
    }

    var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
    var bHasDataURL = !!(oCanvas.toDataURL);
    var bHasBase64 = !!(window.btoa);

    var strDownloadMime = "image/octet-stream";

    // ok, we're good
    var readCanvasData = function(oCanvas) {
        var iWidth = parseInt(oCanvas.width);
        var iHeight = parseInt(oCanvas.height);
        return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
    }

    // base64 encodes either a string or an array of charcodes
    var encodeData = function(data) {
        var strData = "";
        if (typeof data == "string") {
            strData = data;
        } else {
            var aData = data;
            for (var i=0;i<aData.length;i++) {
                strData += String.fromCharCode(aData[i]);
            }
        }
        return btoa(strData);
    }

    // creates a base64 encoded string containing BMP data
    // takes an imagedata object as argument
    /*var createBMP = function(oData) {
        var aHeader = [];

        var iWidth = oData.width;
        var iHeight = oData.height;

        aHeader.push(0x42); // magic 1
        aHeader.push(0x4D); 

        var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes
        aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
        aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
        aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
        aHeader.push(iFileSize % 256);

        aHeader.push(0); // reserved
        aHeader.push(0);
        aHeader.push(0); // reserved
        aHeader.push(0);

        aHeader.push(54); // dataoffset
        aHeader.push(0);
        aHeader.push(0);
        aHeader.push(0);

        var aInfoHeader = [];
        aInfoHeader.push(40); // info header size
        aInfoHeader.push(0);
        aInfoHeader.push(0);
        aInfoHeader.push(0);

        var iImageWidth = iWidth;
        aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
        aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
        aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
        aInfoHeader.push(iImageWidth % 256);

        var iImageHeight = iHeight;
        aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
        aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
        aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
        aInfoHeader.push(iImageHeight % 256);

        aInfoHeader.push(1); // num of planes
        aInfoHeader.push(0);

        aInfoHeader.push(24); // num of bits per pixel
        aInfoHeader.push(0);

        aInfoHeader.push(0); // compression = none
        aInfoHeader.push(0);
        aInfoHeader.push(0);
        aInfoHeader.push(0);

        var iDataSize = iWidth*iHeight*3; 
        aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
        aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
        aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
        aInfoHeader.push(iDataSize % 256); 

        for (var i=0;i<16;i++) {
            aInfoHeader.push(0);    // these bytes not used
        }

        var iPadding = (4 - ((iWidth * 3) % 4)) % 4;

        var aImgData = oData.data;

        var strPixelData = "";
        var y = iHeight;
        do {
            var iOffsetY = iWidth*(y-1)*4;
            var strPixelRow = "";
            for (var x=0;x<iWidth;x++) {
                var iOffsetX = 4*x;

                strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);
                strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);
                strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);
            }
            for (var c=0;c<iPadding;c++) {
                strPixelRow += String.fromCharCode(0);
            }
            strPixelData += strPixelRow;
        } while (--y);

        var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);

        return strEncoded;
    }
*/

    // sends the generated file to the client
    var saveFile = function(strData) {
        document.location.href = strData;
    }

    var makeDataURI = function(strData, strMime) {
        return "data:" + strMime + ";base64," + strData;
    }

    // generates a <img> object containing the imagedata
    var makeImageObject = function(strSource) {
        var oImgElement = document.createElement("img");
        oImgElement.src = strSource;
        return oImgElement;
    }

    var scaleCanvas = function(oCanvas, iWidth, iHeight) {
        if (iWidth && iHeight) {
            var oSaveCanvas = document.createElement("canvas");
            oSaveCanvas.width = iWidth;
            oSaveCanvas.height = iHeight;
            oSaveCanvas.style.width = iWidth+"px";
            oSaveCanvas.style.height = iHeight+"px";

            var oSaveCtx = oSaveCanvas.getContext("2d");

            oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
            return oSaveCanvas;
        }
        return oCanvas;
    }

    return {

        saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
            if (!bHasDataURL) {
                return false;
            }
            var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
            var strData = oScaledCanvas.toDataURL("image/png");
            if (bReturnImg) {
                return makeImageObject(strData);
            } else {
                saveFile(strData.replace("image/png", strDownloadMime));
            }
            return true;
        },

        saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
            if (!bHasDataURL) {
                return false;
            }

            var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
            var strMime = "image/jpeg";
            var strData = oScaledCanvas.toDataURL(strMime);

            // check if browser actually supports jpeg by looking for the mime type in the data uri.
            // if not, return false
            if (strData.indexOf(strMime) != 5) {
                return false;
            }

            if (bReturnImg) {
                return makeImageObject(strData);
            } else {
                saveFile(strData.replace(strMime, strDownloadMime));
            }
            return true;
        },

    /*  saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
            if (!(bHasImageData && bHasBase64)) {
                return false;
            }

            var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);

            var oData = readCanvasData(oScaledCanvas);
            var strImgData = createBMP(oData);
            if (bReturnImg) {
                return makeImageObject(makeDataURI(strImgData, "image/bmp"));
            } else {
                saveFile(makeDataURI(strImgData, strDownloadMime));
            }
            return true;
        }*/
    };

})();

在html中我做:

  <script type="text/javascript">
  $(document).ready(function(){
    var _txt = "hey";
    $('#qrcode').qrcode({
      text  :_txt
    });
    $("#qrcode-canvas").attr("download","file.png");
    var oCanvas = document.getElementById("qrcode-canvas");  
    $("#download-qrcode").on('click',function(){
      Canvas2Image.saveAsPNG(oCanvas);
    })
  });
  </script>

<div id="qrcode" class="" style="" ></div>
 <a class="btn btn-large btn-inverse" id="download-qrcode"><i class="icon icon-download-alt icon-white"></i> download</a>

我遇到问题,我正在使用macosx FF,Chrome Opera和Safari,然后通过元素点击调用saveAsPNG()方法

图像返回没有扩展名的文档进行保存:

data:image/octet-stream;base64,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

我想将其保存为图片,想要png:/

可能吗?

因为我知道我可以使用数据来解决这个问题:image / png;等等。但它会在浏览器中打开新窗口。

1 个答案:

答案 0 :(得分:10)

根据此问题:Name a PNG file saved from Canvas using an "open with" dialog,您可以使用download元素的a属性来指示应使用给定名称下载href。< / p>

更好的是,我们可以将href设置为toDataURL的返回值,这样可以确保将图片下载为PNG。

<a class="btn btn-large btn-inverse" id="download-qrcode" download="my_file.png">
    <i class="icon icon-download-alt icon-white"></i>
    download
</a>

$("#download-qrcode").on('click',function(){
    var dataUrl = oCanvas[0].toDataURL();
    $(this).attr('href', dataUrl);
});

单击链接后,文件将以my_file.png的形式下载。正如该问题中所述,download属性并未得到广泛支持 - 上述代码仅在Chrome中有效,即使Firefox显然支持该属性。

我不确定如何解决此问题,因为您无法在Content-Disposition网址中设置data:,这意味着您无法强制下载服务器端。

您还可以查看以下内容:http://www.joeltrost.com/blog/2012/01/29/html5-canvas-save-a-jpeg-with-extension/,它使用回发方法处理同样的问题。这样做的好处在于它优先考虑服务器指定Content-Disposition的能力,以便您可以强制下载图像。

修改

因此,回发后方法的想法基本上是将数据Url发送回服务器,而服务器基本上将其回送。诀窍是,当这样做时,设置Content-Disposition,强制下载图像。

现在该链接显示了PHP的解决方案,因此您可以重用该脚本来执行相同的操作。