Experiment about making graphs of route trips
[busui.git] / js / flotr / lib / canvas2image.js
blob:a/js/flotr/lib/canvas2image.js -> blob:b/js/flotr/lib/canvas2image.js
--- a/js/flotr/lib/canvas2image.js
+++ b/js/flotr/lib/canvas2image.js
@@ -1,1 +1,230 @@
-
+/*

+ * Canvas2Image v0.1

+ * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com

+ * MIT License [http://www.opensource.org/licenses/mit-license.php]

+ */

+

+var Canvas2Image = (function() {

+	// check if we have canvas support

+	var oCanvas = document.createElement("canvas");

+  

+	// no canvas, bail out.

+	if (!oCanvas.getContext) {

+		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); // data offset

+		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);

+

+		return encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);

+	}

+

+	// sends the generated file to the client

+	var saveFile = function(strData) {

+    if (!window.open(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, iWidth);

+			

+			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;

+		}

+	};

+

+})();