| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 | /* * Canvas2Image v0.1 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk * MIT License [http://www.opensource.org/licenses/mit-license.php] */var Canvas2Image = (function() {	// check if we have canvas support	var bHasCanvas = false;	var oCanvas = document.createElement("canvas");	if (oCanvas.getContext("2d")) {		bHasCanvas = true;	}	// no canvas, bail out.	if (!bHasCanvas) {		return {			saveAsBMP : function(){},			saveAsPNG : function(){},			saveAsJPEG : function(){}		}	}	var bHasImageData = !!(oCanvas.getContext("2d").getImageData);	var bHasDataURL = !!(oCanvas.toDataURL);	var bHasBase64 = !!(window.btoa);	var strDownloadMime = "image/octet-stream";	// ok, we're good	var readCanvasData = function(oCanvas) {		var iWidth = parseInt(oCanvas.width);		var iHeight = parseInt(oCanvas.height);		return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);	}	// base64 encodes either a string or an array of charcodes	var encodeData = function(data) {		var strData = "";		if (typeof data == "string") {			strData = data;		} else {			var aData = data;			for (var i=0;i<aData.length;i++) {				strData += String.fromCharCode(aData[i]);			}		}		return btoa(strData);	}	// creates a base64 encoded string containing BMP data	// takes an imagedata object as argument	var createBMP = function(oData) {		var aHeader = [];			var iWidth = oData.width;		var iHeight = oData.height;		aHeader.push(0x42); // magic 1		aHeader.push(0x4D); 			var iFileSize = iWidth*iHeight*3 + 54; // total header size = 54 bytes		aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);		aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);		aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);		aHeader.push(iFileSize % 256);		aHeader.push(0); // reserved		aHeader.push(0);		aHeader.push(0); // reserved		aHeader.push(0);		aHeader.push(54); // dataoffset		aHeader.push(0);		aHeader.push(0);		aHeader.push(0);		var aInfoHeader = [];		aInfoHeader.push(40); // info header size		aInfoHeader.push(0);		aInfoHeader.push(0);		aInfoHeader.push(0);		var iImageWidth = iWidth;		aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);		aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);		aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);		aInfoHeader.push(iImageWidth % 256);			var iImageHeight = iHeight;		aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);		aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);		aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);		aInfoHeader.push(iImageHeight % 256);			aInfoHeader.push(1); // num of planes		aInfoHeader.push(0);			aInfoHeader.push(24); // num of bits per pixel		aInfoHeader.push(0);			aInfoHeader.push(0); // compression = none		aInfoHeader.push(0);		aInfoHeader.push(0);		aInfoHeader.push(0);			var iDataSize = iWidth*iHeight*3; 		aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);		aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);		aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);		aInfoHeader.push(iDataSize % 256); 			for (var i=0;i<16;i++) {			aInfoHeader.push(0);	// these bytes not used		}			var iPadding = (4 - ((iWidth * 3) % 4)) % 4;		var aImgData = oData.data;		var strPixelData = "";		var y = iHeight;		do {			var iOffsetY = iWidth*(y-1)*4;			var strPixelRow = "";			for (var x=0;x<iWidth;x++) {				var iOffsetX = 4*x;				strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+2]);				strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX+1]);				strPixelRow += String.fromCharCode(aImgData[iOffsetY+iOffsetX]);			}			for (var c=0;c<iPadding;c++) {				strPixelRow += String.fromCharCode(0);			}			strPixelData += strPixelRow;		} while (--y);		var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);		return strEncoded;	}	// sends the generated file to the client	var saveFile = function(strData) {		document.location.href = strData;	}	var makeDataURI = function(strData, strMime) {		return "data:" + strMime + ";base64," + strData;	}	// generates a <img> object containing the imagedata	var makeImageObject = function(strSource) {		var oImgElement = document.createElement("img");		oImgElement.src = strSource;		return oImgElement;	}	var scaleCanvas = function(oCanvas, iWidth, iHeight) {		if (iWidth && iHeight) {			var oSaveCanvas = document.createElement("canvas");			oSaveCanvas.width = iWidth;			oSaveCanvas.height = iHeight;			oSaveCanvas.style.width = iWidth+"px";			oSaveCanvas.style.height = iHeight+"px";			var oSaveCtx = oSaveCanvas.getContext("2d");			oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);			return oSaveCanvas;		}		return oCanvas;	}	return {		saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {			if (!bHasDataURL) {				return false;			}			var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);			var strData = oScaledCanvas.toDataURL("image/png");			if (bReturnImg) {				return makeImageObject(strData);			} else {				saveFile(strData.replace("image/png", strDownloadMime));			}			return true;		},		saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {			if (!bHasDataURL) {				return false;			}			var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);			var strMime = "image/jpeg";			var strData = oScaledCanvas.toDataURL(strMime);				// check if browser actually supports jpeg by looking for the mime type in the data uri.			// if not, return false			if (strData.indexOf(strMime) != 5) {				return false;			}			if (bReturnImg) {				return makeImageObject(strData);			} else {				saveFile(strData.replace(strMime, strDownloadMime));			}			return true;		},		saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {			if (!(bHasImageData && bHasBase64)) {				return false;			}			var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);			var oData = readCanvasData(oScaledCanvas);			var strImgData = createBMP(oData);			if (bReturnImg) {				return makeImageObject(makeDataURI(strImgData, "image/bmp"));			} else {				saveFile(makeDataURI(strImgData, strDownloadMime));			}			return true;		}	};})();
 |