canvas保存为data:image扩展功能的实现
【已知】
canvas提供了toDataURL的接口,可以方便的将canvas画布转化成base64编码的image。目前支持的最好的是png格式,jpeg格式的现代浏览器基本也支持,但是支持的不是很好。
【想要的】
往往这么简单直接的接口通常都满足不了需求。我想要的不仅是简单的通过画布生成一个png,我不想新开一个tab,然后还要右键另存为...
我还需要更方便的自由的配置生成的图片的大小,比例等。
另外如果我还要别的图片格式,比如位图bmp,gif等怎么办...
【解决办法】
a)想直接把图片生成后download到本地,其实办法也很简单。直接改图片的mimeType,强制改成steam流类型的。比如‘image/octet-stream’,浏览器就会自动帮我们另存为..
b)图片大小,及比例的可控倒也好办,我们新建一个我们想要大小的canvas,把之前的canvas画布重新按照所要的比例,及大小draw到新的canvas上,然后用新的canvas来toDataURL即可。
c)想要bmp位图会麻烦些... 没有直接的接口,需要我们自己来生成。生成图片的响应头和响应体有一定的规则,略显麻烦。不过还能接受。剩下的就是性能问题,按像素级别来操作,对于一个大图来说计算量很有压力。
【实现】
/*** covert canvas to image* and save the image file*/var Canvas2Image = function () {// check if support sth.var $support = function () {var canvas = document.createElement('canvas'),ctx = canvas.getContext('2d');return {canvas: !!ctx,imageData: !!ctx.getImageData,dataURL: !!canvas.toDataURL,btoa: !!window.btoa};}();var downloadMime = 'image/octet-stream';function scaleCanvas (canvas, width, height) {var w = canvas.width,h = canvas.height;if (width == undefined) {width = w;}if (height == undefined) {height = h;}var retCanvas = document.createElement('canvas');var retCtx = retCanvas.getContext('2d');retCanvas.width = width;retCanvas.height = height;retCtx.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);return retCanvas;}function getDataURL (canvas, type, width, height) {canvas = scaleCanvas(canvas, width, height);return canvas.toDataURL(type);}function saveFile (strData) {document.location.href = strData;}function genImage(strData) {var img = document.createElement('img');img.src = strData;return img;}function fixType (type) {type = type.toLowerCase().replace(/jpg/i, 'jpeg');var r = type.match(/png|jpeg|bmp|gif/)[0];return 'image/' + r;}function encodeData (data) {if (!window.btoa) { throw 'btoa undefined' }var str = '';if (typeof data == 'string') {str = data;} else {for (var i = 0; i < data.length; i ++) {str += String.fromCharCode(data[i]);}}return btoa(str);}function getImageData (canvas) {var w = canvas.width,h = canvas.height;return canvas.getContext('2d').getImageData(0, 0, w, h);}function makeURI (strData, type) {return 'data:' + type + ';base64,' + strData;}/*** create bitmap image* 按照规则生成图片响应头和响应体*/var genBitmapImage = function (data) {var imgHeader = [],imgInfoHeader = [];var width = data.width,height = data.height;imgHeader.push(0x42); // 66 -> BimgHeader.push(0x4d); // 77 -> Mvar fsize = width * height * 3 + 54; // header size:54 bytesimgHeader.push(fsize % 256); // rfsize = Math.floor(fsize / 256);imgHeader.push(fsize % 256); // gfsize = Math.floor(fsize / 256);imgHeader.push(fsize % 256); // bfsize = Math.floor(fsize / 256);imgHeader.push(fsize % 256); // aimgHeader.push(0);imgHeader.push(0);imgHeader.push(0);imgHeader.push(0);imgHeader.push(54); // offset -> 6imgHeader.push(0);imgHeader.push(0);imgHeader.push(0);// info headerimgInfoHeader.push(40); // info header sizeimgInfoHeader.push(0);imgInfoHeader.push(0);imgInfoHeader.push(0);// 横向infovar _width = width;imgInfoHeader.push(_width % 256);_width = Math.floor(_width / 256);imgInfoHeader.push(_width % 256);_width = Math.floor(_width / 256);imgInfoHeader.push(_width % 256);_width = Math.floor(_width / 256);imgInfoHeader.push(_width % 256);// 纵向infovar _height = height;imgInfoHeader.push(_height % 256);_height = Math.floor(_height / 256);imgInfoHeader.push(_height % 256);_height = Math.floor(_height / 256);imgInfoHeader.push(_height % 256);_height = Math.floor(_height / 256);imgInfoHeader.push(_height % 256);imgInfoHeader.push(1);imgInfoHeader.push(0);imgInfoHeader.push(24); // 24位bitmapimgInfoHeader.push(0);// no compressionimgInfoHeader.push(0);imgInfoHeader.push(0);imgInfoHeader.push(0);imgInfoHeader.push(0);// pixel datavar dataSize = width * height * 3;imgInfoHeader.push(dataSize % 256);dataSize = Math.floor(dataSize / 256);imgInfoHeader.push(dataSize % 256);dataSize = Math.floor(dataSize / 256);imgInfoHeader.push(dataSize % 256);dataSize = Math.floor(dataSize / 256);imgInfoHeader.push(dataSize % 256);// blank spacefor (var i = 0; i < 16; i ++) {imgInfoHeader.push(0);}var padding = (4 - ((width * 3) % 4)) % 4;var imgData = data.data;var strPixelData = '';var y = height;do {var offsetY = width * (y - 1) * 4;var strPixelRow = '';for (var x = 0; x < width; x ++) {var offsetX = 4 * x;strPixelRow += String.fromCharCode(imgData[offsetY + offsetX + 2]);strPixelRow += String.fromCharCode(imgData[offsetY + offsetX + 1]);strPixelRow += String.fromCharCode(imgData[offsetY + offsetX]);}for (var n = 0; n < padding; n ++) {strPixelRow += String.fromCharCode(0);}strPixelData += strPixelRow;} while(-- y);return (encodeData(imgHeader.concat(imgInfoHeader)) + encodeData(strPixelData));};/*** saveAsImage* @param canvasElement* @param {String} image type* @param {Number} [optional] png width* @param {Number} [optional] png height*/var saveAsImage = function (canvas, width, height, type) {if ($support.canvas && $support.dataURL) {if (type == undefined) { type = 'png'; }type = fixType(type);if (/bmp/.test(type)) {var data = getImageData(scaleCanvas(canvas, width, height));var strData = genBitmapImage(data);saveFile(makeURI(strData, downloadMime));} else {var strData = getDataURL(canvas, type, width, height);saveFile(strData.replace(type, downloadMime));}}}var convertToImage = function (canvas, width, height, type) {if ($support.canvas && $support.dataURL) {if (type == undefined) { type = 'png'; }type = fixType(type);if (/bmp/.test(type)) {var data = getImageData(scaleCanvas(canvas, width, height));var strData = genBitmapImage(data);return genImage(makeURI(strData, 'image/bmp'));} else {var strData = getDataURL(canvas, type, width, height);return genImage(strData);}}}return {saveAsImage: saveAsImage,saveAsPNG: function (canvas, width, height) {return saveAsImage(canvas, width, height, 'png');},saveAsJPEG: function (canvas, width, height) {return saveAsImage(canvas, width, height, 'jpeg'); },saveAsGIF: function (canvas, width, height) {return saveAsImage(canvas, width, height, 'gif') },saveAsBMP: function (canvas, width, height) {return saveAsImage(canvas, width, height, 'bmp'); },convertToImage: convertToImage,convertToPNG: function (canvas, width, height) {return convertToImage(canvas, width, height, 'png');},convertToJPEG: function (canvas, width, height) {return convertToImage(canvas, width, height, 'jpeg'); },convertToGIF: function (canvas, width, height) {return convertToImage(canvas, width, height, 'gif'); },convertToBMP: function (canvas, width, height) {return convertToImage(canvas, width, height, 'bmp'); }};}();
【Demo】
http://hongru.github.com/proj/canvas2image/index.html
可以试着在canvas上涂涂画画,然后保存看看。如果用bmp格式的话,需要支持 btoa 的base64编码,关于base64编码规则可看上一篇博文
【不完美的地方】
1)jpeg接口本身就不完善,当canvas没有填充颜色或图片时,保存的jpeg由于是直接由png的alpha通道强制转换过来的,所以在png的透明部分在jpeg里面就是黑色的。
2)gif的限制太多。且可用性不大,有png就够了
3)bmp位图生成,计算量稍显大了。
4)由于是强制改mimeType来实现的自动下载,所以下载的时候文件类型不会自动识别。
原文:http://www.cnblogs.com/hongru/archive/2012/01/14/2322540.html
index.html
<!doctype html>
<html>
<meta charset="utf-8" />
<script src="canvas2image.js"></script>
<style>.doc {width: 604px;margin: 0 auto;}canvas {display: block;border: 2px solid #888;}
</style>
<body>
<div class="doc"><canvas width="600" height="400" id="cvs"></canvas><div><p><button id="save">save</button> or <button id="convert">convert to</button> as: <select id="sel"><option value="png">png</option><option value="jpeg">jpeg</option><option value="bmp">bmp</option></select><br/>width : <input type="number" value="300" id="imgW" /><br/>height : <input type="number" value="200" id="imgH" /></p></div><div id="imgs"></div>
</div>
<script>var canvas, ctx, bMouseIsDown = false, iLastX, iLastY,$save, $imgs,$convert, $imgW, $imgH,$sel;function init () {canvas = document.getElementById('cvs');ctx = canvas.getContext('2d');$save = document.getElementById('save');$convert = document.getElementById('convert');$sel = document.getElementById('sel');$imgs = document.getElementById('imgs');$imgW = document.getElementById('imgW');$imgH = document.getElementById('imgH');bind();draw();}function bind () {canvas.onmousedown = function(e) {bMouseIsDown = true;iLastX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);iLastY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);}canvas.onmouseup = function() {bMouseIsDown = false;iLastX = -1;iLastY = -1;}canvas.onmousemove = function(e) {if (bMouseIsDown) {var iX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);var iY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);ctx.moveTo(iLastX, iLastY);ctx.lineTo(iX, iY);ctx.stroke();iLastX = iX;iLastY = iY;}};$save.onclick = function (e) {var type = $sel.value,w = $imgW.value,h = $imgH.value;Canvas2Image.saveAsImage(canvas, w, h, type);}$convert.onclick = function (e) {var type = $sel.value,w = $imgW.value,h = $imgH.value;$imgs.appendChild(Canvas2Image.convertToImage(canvas, w, h, type))}}function draw () {ctx.fillStyle = '#ffffff';ctx.fillRect(0, 0, 600, 400);ctx.fillStyle = 'red';ctx.fillRect(100, 100, 50, 50);}onload = init;
</script>
</body>
</html>
canvas保存为data:image扩展功能的实现相关推荐
- uniapp 小程序 APP 实现手写板 签名 画图 canvas 保存为图片格式
文章目录 uniapp 小程序 APP 实现手写板 签名 画图 canvas 保存为图片格式 一.手写板 1.H5代码 2.JS代码 总结 uniapp 小程序 APP 实现手写板 签名 画图 can ...
- canvas保存到本地图片三种方法
canvas保存到本地图片三种方法 canvas保存本地图片 第一种方法(修改图片的媒体类型,window.open直接下载) 第二种方法(创建a标签,通过自己触发点击来下载) 第三种方法(将图片数据 ...
- js将canvas保存成图片并下载
<canvas id="canvas" width="400" height="400"></canvas> < ...
- js大屏导出图片_js将canvas保存成图片并下载
保存 var arr = [ {locations:[[0,0],[200,200],[0,400]],color:"red"}, {locations:[[0,0],[400,0 ...
- 图片在canvas中显示,给canvas添加文字,文字描边,将canvas保存成图片下载到本地
Canvas简介 HTML5新增标签 Canvas API(画布)是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitma ...
- Web开发之用canvas2image.js将canvas保存为图片(实现页面截图下载功能)
关于实现页面截图常用的几个js插件库 canvas2image.js html2canvas.js convertImgToBase64.js 废话不多说,直接上demo代码 index.html: ...
- html canvas保存为图片,在HTML5 Canvas中放入图片和保存为图片的方法
第一种方式 如果是使用的图片的话,就会涉及到canvas的图片跨域问题,因为canvas是禁止跨域的,如果图像来自其他域,调用toDataURL()会抛出一个错误 需要添加"img.cros ...
- js实现将canvas保存成图片并下载到本地
//图片导出为 png 格式 var type = 'png'; var imgData = canvas.toDataURL(type);/*** 获取mimeType* @param {Strin ...
- vue使用canvas保存页面为图片,得到图片url
bug:后台返的网络图片路径保存不下来,返回base64格式即可 保存图片的方式 import html2canvas from "html2canvas"; // 点击上传,获取 ...
最新文章
- 通讯系统经验谈【一】TCP连接状态分析:SYNC_RECV,CLOSE_WAIT,TIME_WAIT
- c语言equal,C ++中的ratio_equal()示例
- spring整合ehcache2.5.2缓存异常-- net.sf.ehcache.CacheException
- go reflect 取指针_Go之如何操作结构体的非导出字段
- gulp-cli命令安装出错_一个牛逼的数据库操作命令行工具:mycli
- vue 设置背景图地址_vue-生成自动铺满的背景图
- python进程数上限_在多处理python中限制进程数
- 新人如何适应自己的领导
- 2020还有必要学JSP吗?
- gms认证流程_GMS测试认证的具体操作流程
- mysql命令行备份数据库
- Pycharm Debug调试(纯干货)
- Tomcat启动报Exception in thread “main“ java.lang.UnsatisfiedLinkError: no secure-tomcat in java.library
- uvalive 6657 GCD XOR
- python+selenium高级教程
- B - 爆零(×)大力出奇迹(√) HDU - 2093
- 古城南京,加“数”前进——CDEC2021中国数字智能生态大会走进南京
- 用python制作微信机器人程序编写_Python制作微信聊天机器人
- 许家印的中秋行程单,恒大造车的“全球化”
- CSS3:图片的高斯模糊效果