canvas2Image.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. /*
  2. * Canvas2Image v0.1
  3. * Copyright (c) 2008 Jacob Seidelin, cupboy@gmail.com
  4. * MIT License [http://www.opensource.org/licenses/mit-license.php]
  5. */
  6. var Canvas2Image = (function() {
  7. // check if we have canvas support
  8. var oCanvas = document.createElement("canvas"),
  9. sc = String.fromCharCode,
  10. strDownloadMime = "image/octet-stream",
  11. bReplaceDownloadMime = false;
  12. // no canvas, bail out.
  13. if (!oCanvas.getContext) {
  14. return {
  15. saveAsBMP : function(){},
  16. saveAsPNG : function(){},
  17. saveAsJPEG : function(){}
  18. }
  19. }
  20. var bHasImageData = !!(oCanvas.getContext("2d").getImageData),
  21. bHasDataURL = !!(oCanvas.toDataURL),
  22. bHasBase64 = !!(window.btoa);
  23. // ok, we're good
  24. var readCanvasData = function(oCanvas) {
  25. var iWidth = parseInt(oCanvas.width),
  26. iHeight = parseInt(oCanvas.height);
  27. return oCanvas.getContext("2d").getImageData(0,0,iWidth,iHeight);
  28. }
  29. // base64 encodes either a string or an array of charcodes
  30. var encodeData = function(data) {
  31. var i, aData, strData = "";
  32. if (typeof data == "string") {
  33. strData = data;
  34. } else {
  35. aData = data;
  36. for (i = 0; i < aData.length; i++) {
  37. strData += sc(aData[i]);
  38. }
  39. }
  40. return btoa(strData);
  41. }
  42. // creates a base64 encoded string containing BMP data takes an imagedata object as argument
  43. var createBMP = function(oData) {
  44. var strHeader = '',
  45. iWidth = oData.width,
  46. iHeight = oData.height;
  47. strHeader += 'BM';
  48. var iFileSize = iWidth*iHeight*4 + 54; // total header size = 54 bytes
  49. strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
  50. strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
  51. strHeader += sc(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
  52. strHeader += sc(iFileSize % 256);
  53. strHeader += sc(0, 0, 0, 0, 54, 0, 0, 0); // data offset
  54. strHeader += sc(40, 0, 0, 0); // info header size
  55. var iImageWidth = iWidth;
  56. strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
  57. strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
  58. strHeader += sc(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
  59. strHeader += sc(iImageWidth % 256);
  60. var iImageHeight = iHeight;
  61. strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
  62. strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
  63. strHeader += sc(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
  64. strHeader += sc(iImageHeight % 256);
  65. strHeader += sc(1, 0, 32, 0); // num of planes & num of bits per pixel
  66. strHeader += sc(0, 0, 0, 0); // compression = none
  67. var iDataSize = iWidth*iHeight*4;
  68. strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
  69. strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
  70. strHeader += sc(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
  71. strHeader += sc(iDataSize % 256);
  72. strHeader += sc(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // these bytes are not used
  73. var aImgData = oData.data,
  74. strPixelData = "",
  75. c, x, y = iHeight,
  76. iOffsetX, iOffsetY, strPixelRow;
  77. do {
  78. iOffsetY = iWidth*(y-1)*4;
  79. strPixelRow = "";
  80. for (x = 0; x < iWidth; x++) {
  81. iOffsetX = 4*x;
  82. strPixelRow += sc(
  83. aImgData[iOffsetY + iOffsetX + 2], // B
  84. aImgData[iOffsetY + iOffsetX + 1], // G
  85. aImgData[iOffsetY + iOffsetX], // R
  86. aImgData[iOffsetY + iOffsetX + 3] // A
  87. );
  88. }
  89. strPixelData += strPixelRow;
  90. } while (--y);
  91. return encodeData(strHeader + strPixelData);
  92. }
  93. // sends the generated file to the client
  94. var saveFile = function(strData) {
  95. if (!window.open(strData)) {
  96. document.location.href = strData;
  97. }
  98. }
  99. var makeDataURI = function(strData, strMime) {
  100. return "data:" + strMime + ";base64," + strData;
  101. }
  102. // generates a <img> object containing the imagedata
  103. var makeImageObject = function(strSource) {
  104. var oImgElement = document.createElement("img");
  105. oImgElement.src = strSource;
  106. return oImgElement;
  107. }
  108. var scaleCanvas = function(oCanvas, iWidth, iHeight) {
  109. if (iWidth && iHeight) {
  110. var oSaveCanvas = document.createElement("canvas");
  111. oSaveCanvas.width = iWidth;
  112. oSaveCanvas.height = iHeight;
  113. oSaveCanvas.style.width = iWidth+"px";
  114. oSaveCanvas.style.height = iHeight+"px";
  115. var oSaveCtx = oSaveCanvas.getContext("2d");
  116. oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iWidth);
  117. return oSaveCanvas;
  118. }
  119. return oCanvas;
  120. }
  121. return {
  122. saveAsPNG : function(oCanvas, bReturnImg, iWidth, iHeight) {
  123. if (!bHasDataURL) return false;
  124. var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
  125. strMime = "image/png",
  126. strData = oScaledCanvas.toDataURL(strMime);
  127. if (bReturnImg) {
  128. return makeImageObject(strData);
  129. } else {
  130. saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
  131. }
  132. return true;
  133. },
  134. saveAsJPEG : function(oCanvas, bReturnImg, iWidth, iHeight) {
  135. if (!bHasDaaURL) return false;
  136. var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
  137. strMime = "image/jpeg",
  138. strData = oScaledCanvas.toDataURL(strMime);
  139. // check if browser actually supports jpeg by looking for the mime type in the data uri. if not, return false
  140. if (strData.indexOf(strMime) != 5) return false;
  141. if (bReturnImg) {
  142. return makeImageObject(strData);
  143. } else {
  144. saveFile(bReplaceDownloadMime ? strData.replace(strMime, strDownloadMime) : strData);
  145. }
  146. return true;
  147. },
  148. saveAsBMP : function(oCanvas, bReturnImg, iWidth, iHeight) {
  149. if (!(bHasDataURL && bHasImageData && bHasBase64)) return false;
  150. var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight),
  151. strMime = "image/bmp",
  152. oData = readCanvasData(oScaledCanvas),
  153. strImgData = createBMP(oData);
  154. if (bReturnImg) {
  155. return makeImageObject(makeDataURI(strImgData, strMime));
  156. } else {
  157. saveFile(makeDataURI(strImgData, strMime));
  158. }
  159. return true;
  160. }
  161. };
  162. })();