277 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
		
		
			
		
	
	
			277 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * 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,filename) {
							 | 
						||
| 
								 | 
							
										var save_link = document.createElement('a');
							 | 
						||
| 
								 | 
							
										save_link.href = strData;
							 | 
						||
| 
								 | 
							
										save_link.download = filename;
							 | 
						||
| 
								 | 
							
										var event = new MouseEvent('click',{"bubbles":false, "cancelable":false});
							 | 
						||
| 
								 | 
							
										save_link.dispatchEvent(event);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									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 (oData) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										// BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
							 | 
						||
| 
								 | 
							
										// BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var biWidth  = oData.width;
							 | 
						||
| 
								 | 
							
										var biHeight	= oData.height;
							 | 
						||
| 
								 | 
							
										var biSizeImage = biWidth * biHeight * 3;
							 | 
						||
| 
								 | 
							
										var bfSize  = biSizeImage + 54; // total header size = 54 bytes
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										//  typedef struct tagBITMAPFILEHEADER {
							 | 
						||
| 
								 | 
							
										//  	WORD bfType;
							 | 
						||
| 
								 | 
							
										//  	DWORD bfSize;
							 | 
						||
| 
								 | 
							
										//  	WORD bfReserved1;
							 | 
						||
| 
								 | 
							
										//  	WORD bfReserved2;
							 | 
						||
| 
								 | 
							
										//  	DWORD bfOffBits;
							 | 
						||
| 
								 | 
							
										//  } BITMAPFILEHEADER;
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										var BITMAPFILEHEADER = [
							 | 
						||
| 
								 | 
							
											// WORD bfType -- The file type signature; must be "BM"
							 | 
						||
| 
								 | 
							
											0x42, 0x4D,
							 | 
						||
| 
								 | 
							
											// DWORD bfSize -- The size, in bytes, of the bitmap file
							 | 
						||
| 
								 | 
							
											bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
							 | 
						||
| 
								 | 
							
											// WORD bfReserved1 -- Reserved; must be zero
							 | 
						||
| 
								 | 
							
											0, 0,
							 | 
						||
| 
								 | 
							
											// WORD bfReserved2 -- Reserved; must be zero
							 | 
						||
| 
								 | 
							
											0, 0,
							 | 
						||
| 
								 | 
							
											// DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
							 | 
						||
| 
								 | 
							
											54, 0, 0, 0
							 | 
						||
| 
								 | 
							
										];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										//  typedef struct tagBITMAPINFOHEADER {
							 | 
						||
| 
								 | 
							
										//  	DWORD biSize;
							 | 
						||
| 
								 | 
							
										//  	LONG  biWidth;
							 | 
						||
| 
								 | 
							
										//  	LONG  biHeight;
							 | 
						||
| 
								 | 
							
										//  	WORD  biPlanes;
							 | 
						||
| 
								 | 
							
										//  	WORD  biBitCount;
							 | 
						||
| 
								 | 
							
										//  	DWORD biCompression;
							 | 
						||
| 
								 | 
							
										//  	DWORD biSizeImage;
							 | 
						||
| 
								 | 
							
										//  	LONG  biXPelsPerMeter;
							 | 
						||
| 
								 | 
							
										//  	LONG  biYPelsPerMeter;
							 | 
						||
| 
								 | 
							
										//  	DWORD biClrUsed;
							 | 
						||
| 
								 | 
							
										//  	DWORD biClrImportant;
							 | 
						||
| 
								 | 
							
										//  } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
							 | 
						||
| 
								 | 
							
										//
							 | 
						||
| 
								 | 
							
										var BITMAPINFOHEADER = [
							 | 
						||
| 
								 | 
							
											// DWORD biSize -- The number of bytes required by the structure
							 | 
						||
| 
								 | 
							
											40, 0, 0, 0,
							 | 
						||
| 
								 | 
							
											// LONG biWidth -- The width of the bitmap, in pixels
							 | 
						||
| 
								 | 
							
											biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
							 | 
						||
| 
								 | 
							
											// LONG biHeight -- The height of the bitmap, in pixels
							 | 
						||
| 
								 | 
							
											biHeight & 0xff, biHeight >> 8  & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
							 | 
						||
| 
								 | 
							
											// WORD biPlanes -- The number of planes for the target device. This value must be set to 1
							 | 
						||
| 
								 | 
							
											1, 0,
							 | 
						||
| 
								 | 
							
											// WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
							 | 
						||
| 
								 | 
							
											// has a maximum of 2^24 colors (16777216, Truecolor)
							 | 
						||
| 
								 | 
							
											24, 0,
							 | 
						||
| 
								 | 
							
											// DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
							 | 
						||
| 
								 | 
							
											0, 0, 0, 0,
							 | 
						||
| 
								 | 
							
											// DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
							 | 
						||
| 
								 | 
							
											biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
							 | 
						||
| 
								 | 
							
											// LONG biXPelsPerMeter, unused
							 | 
						||
| 
								 | 
							
											0,0,0,0,
							 | 
						||
| 
								 | 
							
											// LONG biYPelsPerMeter, unused
							 | 
						||
| 
								 | 
							
											0,0,0,0,
							 | 
						||
| 
								 | 
							
											// DWORD biClrUsed, the number of color indexes of palette, unused
							 | 
						||
| 
								 | 
							
											0,0,0,0,
							 | 
						||
| 
								 | 
							
											// DWORD biClrImportant, unused
							 | 
						||
| 
								 | 
							
											0,0,0,0
							 | 
						||
| 
								 | 
							
										];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var iPadding = (4 - ((biWidth * 3) % 4)) % 4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var aImgData = oData.data;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var strPixelData = '';
							 | 
						||
| 
								 | 
							
										var biWidth4 = biWidth<<2;
							 | 
						||
| 
								 | 
							
										var y = biHeight;
							 | 
						||
| 
								 | 
							
										var fromCharCode = String.fromCharCode;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										do {
							 | 
						||
| 
								 | 
							
											var iOffsetY = biWidth4*(y-1);
							 | 
						||
| 
								 | 
							
											var strPixelRow = '';
							 | 
						||
| 
								 | 
							
											for (var x = 0; x < biWidth; x++) {
							 | 
						||
| 
								 | 
							
												var iOffsetX = x<<2;
							 | 
						||
| 
								 | 
							
												strPixelRow += fromCharCode(aImgData[iOffsetY+iOffsetX+2]) +
							 | 
						||
| 
								 | 
							
															   fromCharCode(aImgData[iOffsetY+iOffsetX+1]) +
							 | 
						||
| 
								 | 
							
															   fromCharCode(aImgData[iOffsetY+iOffsetX]);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for (var c = 0; c < iPadding; c++) {
							 | 
						||
| 
								 | 
							
												strPixelRow += String.fromCharCode(0);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											strPixelData += strPixelRow;
							 | 
						||
| 
								 | 
							
										} while (--y);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										return strEncoded;
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									/**
							 | 
						||
| 
								 | 
							
									 * [saveAsImage]
							 | 
						||
| 
								 | 
							
									 * @param  {[obj]} canvas   [canvasElement]
							 | 
						||
| 
								 | 
							
									 * @param  {[Number]} width    [optional] png width
							 | 
						||
| 
								 | 
							
									 * @param  {[Number]} height   [optional] png height
							 | 
						||
| 
								 | 
							
									 * @param  {[String]} type     [image type]
							 | 
						||
| 
								 | 
							
									 * @param  {[String]} filename [image filename]
							 | 
						||
| 
								 | 
							
									 * @return {[type]}          [description]
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									var saveAsImage = function (canvas, width, height, type,filename) {
							 | 
						||
| 
								 | 
							
										if ($support.canvas && $support.dataURL) {
							 | 
						||
| 
								 | 
							
											if (typeof canvas == "string") { canvas = document.getElementById(canvas); }
							 | 
						||
| 
								 | 
							
											if (type == undefined) { type = 'png'; }
							 | 
						||
| 
								 | 
							
											filename = filename == undefined||filename.length === 0 ?Date.now()+'.'+type: filename+'.'+type
							 | 
						||
| 
								 | 
							
											type = fixType(type);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (/bmp/.test(type)) {
							 | 
						||
| 
								 | 
							
												var data = getImageData(scaleCanvas(canvas, width, height));
							 | 
						||
| 
								 | 
							
												var strData = genBitmapImage(data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												saveFile(makeURI(strData, downloadMimedownloadMime),filename);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												var strData = getDataURL(canvas, type, width, height);
							 | 
						||
| 
								 | 
							
												saveFile(strData.replace(type, downloadMime),filename);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var convertToImage = function (canvas, width, height, type) {
							 | 
						||
| 
								 | 
							
										if ($support.canvas && $support.dataURL) {
							 | 
						||
| 
								 | 
							
											if (typeof canvas == "string") { canvas = document.getElementById(canvas); }
							 | 
						||
| 
								 | 
							
											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, fileName) {
							 | 
						||
| 
								 | 
							
											return saveAsImage(canvas, width, height, 'png',fileName);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										saveAsJPEG: function (canvas, width, height, fileName) {
							 | 
						||
| 
								 | 
							
											return saveAsImage(canvas, width, height, 'jpeg',fileName);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										saveAsGIF: function (canvas, width, height, fileName) {
							 | 
						||
| 
								 | 
							
											return saveAsImage(canvas, width, height, 'gif',fileName);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
										saveAsBMP: function (canvas, width, height, fileName) {
							 | 
						||
| 
								 | 
							
											return saveAsImage(canvas, width, height, 'bmp',fileName);
							 | 
						||
| 
								 | 
							
										},
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										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');
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export default Canvas2Image
							 |