我有代码从视频中绘制图像。这是代码

<script type="text/javascript">

function capture() {

    var video  = document.getElementById("videoId");
    var canvas = capture(video, 1);
    var dataURL = canvas.toDataURL("image/bmp", 1.0);
    console.log("dataurl: "+dataURL);

}

</script>


<body>
 <input type="button" value="Capture" onClick="capture()"/>
 <video id="videoId" width="640" height="480"/>
</body>

在控制台上,dataurl显示为“data:image / png; base64,...”

题?

为什么dataurl以png格式生成?

注意:
这是在Chrome浏览器中发生的[41.0.2272.89]。
在firefox中,网址以bmp格式生成。

最佳答案

支持

并非所有浏览器都支持BMP。不需要支持 other formats than PNG (我的重点):

用户代理必须支持PNG(“image / png”)。用户代理可以支持
其他类型。

不能识别的任何格式 will be saved as default PNG

第一个参数(如果提供)控制图片的类型为
传回(例如PNG或JPEG)。默认值为image / png;该类型是
如果不支持给定类型,也可以使用。

要检查是否支持格式,请检查返回的data-uri的第一部分:

 var wantType = "image/bmp";
 var dataUri = canvas.toDataURL(wantType);
 if (dataUri.indexOf(wantType) < 0) {  // or use substr etc. data: + mime
      // Format NOT supported - provide workaround/inform user
      // See update below for workaround (or replacement)
 }

解决方法:手动生成低级BMP

要将其另存为BMP,您将必须从画布中提取像素数据,格式化文件头,以正确的格式附加数据,创建一个Blob,然后通过objectURL将其提供给用户。

用法:
var bmpDataUri = CanvasToBMP.toDataURL(canvas);     // returns an data-URI

还可以选择将BMP图像获取为原始ArrayBuffer:
var bmpBuffer = CanvasToBMP.toArrayBuffer(canvas);

Blob:
var bmpBlob = CanvasToBMP.toBlob(canvas);
var url = URL.createObjectURL(bmpBlob);             // example objectURL
Blobs当然可以与createObjectURL()一起使用,它可以用作图像源以及下载目标,并且比使用data-URI更快,因为它们不需要对Base-64进行编码/解码。

它写入支持alpha的32位BMP文件(Firefox当前忽略BMP文件中的alpha通道)。

无论如何,这是-

演示和来源

/*! canvas-to-bmp version 1.0 ALPHA
    (c) 2015 Ken "Epistemex" Fyrstenberg
    MIT License (this header required)
*/

var CanvasToBMP = {

  /**
   * Convert a canvas element to ArrayBuffer containing a BMP file
   * with support for 32-bit (alpha).
   *
   * Note that CORS requirement must be fulfilled.
   *
   * @param {HTMLCanvasElement} canvas - the canvas element to convert
   * @return {ArrayBuffer}
   */
  toArrayBuffer: function(canvas) {

    var w = canvas.width,
        h = canvas.height,
        w4 = w * 4,
        idata = canvas.getContext("2d").getImageData(0, 0, w, h),
        data32 = new Uint32Array(idata.data.buffer), // 32-bit representation of canvas

        stride = Math.floor((32 * w + 31) / 32) * 4, // row length incl. padding
        pixelArraySize = stride * h,                 // total bitmap size
        fileLength = 122 + pixelArraySize,           // header size is known + bitmap

        file = new ArrayBuffer(fileLength),          // raw byte buffer (returned)
        view = new DataView(file),                   // handle endian, reg. width etc.
        pos = 0, x, y = 0, p, s = 0, a, v;

    // write file header
    setU16(0x4d42);          // BM
    setU32(fileLength);      // total length
    pos += 4;                // skip unused fields
    setU32(0x7a);            // offset to pixels

    // DIB header
    setU32(108);             // header size
    setU32(w);
    setU32(-h >>> 0);        // negative = top-to-bottom
    setU16(1);               // 1 plane
    setU16(32);              // 32-bits (RGBA)
    setU32(3);               // no compression (BI_BITFIELDS, 3)
    setU32(pixelArraySize);  // bitmap size incl. padding (stride x height)
    setU32(2835);            // pixels/meter h (~72 DPI x 39.3701 inch/m)
    setU32(2835);            // pixels/meter v
    pos += 8;                // skip color/important colors
    setU32(0xff0000);        // red channel mask
    setU32(0xff00);          // green channel mask
    setU32(0xff);            // blue channel mask
    setU32(0xff000000);      // alpha channel mask
    setU32(0x57696e20);      // " win" color space

    // bitmap data, change order of ABGR to BGRA
    while (y < h) {
      p = 0x7a + y * stride; // offset + stride x height
      x = 0;
      while (x < w4) {
        v = data32[s++];                     // get ABGR
        a = v >>> 24;                        // alpha channel
        view.setUint32(p + x, (v << 8) | a); // set BGRA
        x += 4;
      }
      y++
    }

    return file;

    // helper method to move current buffer position
    function setU16(data) {view.setUint16(pos, data, true); pos += 2}
    function setU32(data) {view.setUint32(pos, data, true); pos += 4}
  },

  /**
   * Converts a canvas to BMP file, returns a Blob representing the
   * file. This can be used with URL.createObjectURL().
   * Note that CORS requirement must be fulfilled.
   *
   * @param {HTMLCanvasElement} canvas - the canvas element to convert
   * @return {Blob}
   */
  toBlob: function(canvas) {
    return new Blob([this.toArrayBuffer(canvas)], {
      type: "image/bmp"
    });
  },

  /**
   * Converts the canvas to a data-URI representing a BMP file.
   * Note that CORS requirement must be fulfilled.
   *
   * @param canvas
   * @return {string}
   */
  toDataURL: function(canvas) {
    var buffer = new Uint8Array(this.toArrayBuffer(canvas)),
        bs = "", i = 0, l = buffer.length;
    while (i < l) bs += String.fromCharCode(buffer[i++]);
    return "data:image/bmp;base64," + btoa(bs);
  }
};


// -------- DEMO CODE -------------

var canvas = document.querySelector("canvas"),
  w = canvas.width,
  h = canvas.height,
  ctx = canvas.getContext("2d"),
  gr = ctx.createLinearGradient(0, 0, w, h),
  img = new Image();

gr.addColorStop(0, "hsl(" + (Math.random() * 360) + ", 90%, 70%)");
gr.addColorStop(1, "hsl(" + (Math.random() * 360) + ", 100%, 30%)");
ctx.fillStyle = gr;
ctx.fillRect(0, 0, w, h);

// append image from the data-uri returned by the CanvasToBMP code below:
img.src = CanvasToBMP.toDataURL(canvas);
document.body.appendChild(img);
<h2>Canvas left, BMP from canvas as image right</h2>
<canvas width="299" height="200"></canvas>

关于google-chrome - Canvas 无法在Chrome中生成bmp图像dataurl,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29652307/

10-09 05:55
查看更多