google-chrome - Canvas 无法在 chrome 中生成 bmp 图像 dataurl

标签 google-chrome canvas html5-canvas

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

<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 中,url 以 bmp 格式生成。

最佳答案

支持

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

User agents must support PNG ("image/png"). User agents may support other types.



任何无法识别的格式 will be saved as default PNG .

The first argument, if provided, controls the type of the image to be returned (e.g. PNG or JPEG). The default is image/png; that type is also used if the given type isn't supported.



要检查是否支持某种格式,请检查返回的 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,您必须从 Canvas 中提取像素数据、格式化文件头、以正确的格式附加数据、创建 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() 一起使用它可以用作图像源和下载目标,并且往往比使用数据 URI 更快,因为它们不需要对 Base-64 进行编码/解码。

它编写支持 alpha 的 32 位 BMP 文件(Firefox 目前忽略 BMP 文件中的 alpha channel )。

无论如何,这里是——

演示和源代码

/*! 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/

相关文章:

c# - Selenium Find by Css 需要帮助。-

javascript - 一页 p5.js 上的两个 Canvas

javascript - canvas.style.display = "block"不工作

javascript - JS从一个圆的边缘到另一个圆的边缘画一条线

javascript - HTML5 canvas 的三种鼠标检测技术,都不够

Android 深层链接和回退到 URL

c# - Selenium:By.Id ("myelement") 和 By.Css ("#myelement") 之间是否存在性能差异?

CSS 动画仅适用于 Chrome

javascript - 是否有 "programming culture"解释为什么 FF 从 measureText 方法返回长分数?

javascript - Canvg 不支持 CSS