我有从视频中绘制图像的代码。这是代码
<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/