html5 boiler plate
[scannr.git] / js / flotr2 / lib / canvas2image.js
blob:a/js/flotr2/lib/canvas2image.js -> blob:b/js/flotr2/lib/canvas2image.js
--- a/js/flotr2/lib/canvas2image.js
+++ b/js/flotr2/lib/canvas2image.js
@@ -1,1 +1,198 @@
+/*
+ * 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"),
+      sc = String.fromCharCode,
+      strDownloadMime = "image/octet-stream",
+      bReplaceDownloadMime = false;
+  
+  // no canvas, bail out.
+  if (!oCanvas.getContext) {
+    return {
+      saveAsBMP : function(){},
+      saveAsPNG : function(){},
+      saveAsJPEG : function(){}
+    }
+  }
+
+  var bHasImageData = !!(oCanvas.getContext("2d").getImageData),
+      bHasDataURL = !!(oCanvas.toDataURL),
+      bHasBase64 = !!(window.btoa);
+
+  // ok, we're good
+  var readCanvasData = function(oCanvas) {
+    var iWidth = parseInt(oCanvas.width),
+        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 i, aData, strData = "";
+    
+    if (typeof data == "string") {
+      strData = data;
+    } else {
+      aData = data;
+      for (i = 0; i < aData.length; i++) {
+        strData += sc(aData[i]);
+      }
+    }
+    return btoa(strData);
+  }
+
+  // creates a base64 encoded string containing BMP data takes an imagedata object as argument
+  var createBMP = function(oData) {
+    var strHeader = '',
+        iWidth = oData.width,
+        iHeight = oData.height;
+
+    strHeader += 'BM';
+  
+    var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes
+    strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+    strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+    strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
+    strHeader += sc(iFileSize % 256);
+
+    strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
+    strHeader += sc(40, 0, 0, 0); // info header size
+
+    var iImageWidth = iWidth;
+    strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+    strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+    strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
+    strHeader += sc(iImageWidth % 256);
+  
+    var iImageHeight = iHeight;
+    strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+    strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+    strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
+    strHeader += sc(iImageHeight % 256);
+  
+    strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
+    strHeader += sc(0, 0, 0, 0); // compression = none
+  
+    var iDataSize = iWidth*iHeight*4; 
+    strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+    strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+    strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
+    strHeader += sc(iDataSize % 256); 
+  
+    strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
+  
+    var aImgData = oData.data,
+        strPixelData = "",
+        c, x, y = iHeight,
+        iOffsetX, iOffsetY, strPixelRow;
+    
+    do {
+      iOffsetY = iWidth*(y-1)*4;
+      strPixelRow = "";
+      for (x = 0; x < iWidth; x++) {
+        iOffsetX = 4*x;
+        strPixelRow += sc(
+          aImgData[iOffsetY + iOffsetX + 2], // B
+          aImgData[iOffsetY + iOffsetX + 1], // G
+          aImgData[iOffsetY + iOffsetX],     // R
+          aImgData[iOffsetY + iOffsetX + 3]  // A
+        );
+      }
+      strPixelData += strPixelRow;
+    } while (--y);
+
+    return encodeData(strHeader + 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),
+          strMime = "image/png",
+          strData = oScaledCanvas.toDataURL(strMime);
+        
+      if (bReturnImg) {
+        return makeImageObject(strData);
+      } else {
+        saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
+      }
+      return true;
+    },
+
+    saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
+      if (!bHasDataURL) return false;
+
+      var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
+          strMime = "image/jpeg",
+          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(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
+      }
+      return true;
+    },
+
+    saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
+      if (!(bHasDataURL && bHasImageData && bHasBase64)) return false;
+
+      var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
+          strMime = "image/bmp",
+          oData = readCanvasData(oScaledCanvas),
+          strImgData = createBMP(oData);
+        
+      if (bReturnImg) {
+        return makeImageObject(makeDataURI(strImgData, strMime));
+      } else {
+        saveFile(makeDataURI(strImgData, strMime));
+      }
+      return true;
+    }
+  };
+})();