我有从视频中绘制图像的代码。这是代码
<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显示为&#34; data:image / png; base64,...&#34;
问题?
为什么dataurl是以png格式生成的?
注意: 这发生在chrome浏览器[41.0.2272.89]中。 在firefox中,url是以bmp格式生成的。
答案 0 :(得分:5)
并非所有浏览器都支持BMP。没有要求支持 other formats than PNG (我强调):
用户代理必须支持PNG(&#34; image / png&#34;)。用户代理可能支持 其他类型。
任何未被识别的格式 will be saved as default PNG 。
第一个参数(如果提供)控制图像的类型 返回(例如PNG或JPEG)。默认为image / png;那种类型 如果不支持给定的类型,也会使用。
要检查是否支持格式,请检查返回数据的第一部分 - 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,您必须从画布中提取像素数据,格式化文件标题,以正确格式附加数据,创建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通道)。
无论如何,这是 -
/*! 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);
&#13;
<h2>Canvas left, BMP from canvas as image right</h2>
<canvas width="299" height="200"></canvas>
&#13;