canvas2image.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /**
  2. * covert canvas to image
  3. * and save the image file
  4. */
  5. var Canvas2Image = function () {
  6. // check if support sth.
  7. var $support = function () {
  8. var canvas = document.createElement('canvas'),
  9. ctx = canvas.getContext('2d');
  10. return {
  11. canvas: !!ctx,
  12. imageData: !!ctx.getImageData,
  13. dataURL: !!canvas.toDataURL,
  14. btoa: !!window.btoa
  15. };
  16. }();
  17. var downloadMime = 'image/octet-stream';
  18. function scaleCanvas (canvas, width, height) {
  19. var w = canvas.width,
  20. h = canvas.height;
  21. if (width == undefined) {
  22. width = w;
  23. }
  24. if (height == undefined) {
  25. height = h;
  26. }
  27. var retCanvas = document.createElement('canvas');
  28. var retCtx = retCanvas.getContext('2d');
  29. retCanvas.width = width;
  30. retCanvas.height = height;
  31. retCtx.drawImage(canvas, 0, 0, w, h, 0, 0, width, height);
  32. return retCanvas;
  33. }
  34. function getDataURL (canvas, type, width, height) {
  35. canvas = scaleCanvas(canvas, width, height);
  36. return canvas.toDataURL(type);
  37. }
  38. function saveFile (strData,filename) {
  39. var save_link = document.createElement('a');
  40. save_link.href = strData;
  41. save_link.download = filename;
  42. var event = new MouseEvent('click',{"bubbles":false, "cancelable":false});
  43. save_link.dispatchEvent(event);
  44. }
  45. function genImage(strData) {
  46. var img = document.createElement('img');
  47. img.src = strData;
  48. return img;
  49. }
  50. function fixType (type) {
  51. type = type.toLowerCase().replace(/jpg/i, 'jpeg');
  52. var r = type.match(/png|jpeg|bmp|gif/)[0];
  53. return 'image/' + r;
  54. }
  55. function encodeData (data) {
  56. if (!window.btoa) { throw 'btoa undefined' }
  57. var str = '';
  58. if (typeof data == 'string') {
  59. str = data;
  60. } else {
  61. for (var i = 0; i < data.length; i ++) {
  62. str += String.fromCharCode(data[i]);
  63. }
  64. }
  65. return btoa(str);
  66. }
  67. function getImageData (canvas) {
  68. var w = canvas.width,
  69. h = canvas.height;
  70. return canvas.getContext('2d').getImageData(0, 0, w, h);
  71. }
  72. function makeURI (strData, type) {
  73. return 'data:' + type + ';base64,' + strData;
  74. }
  75. /**
  76. * create bitmap image
  77. * 鎸夌収瑙勫垯鐢熸垚鍥剧墖鍝嶅簲澶村拰鍝嶅簲浣�
  78. */
  79. var genBitmapImage = function (oData) {
  80. //
  81. // BITMAPFILEHEADER: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183374(v=vs.85).aspx
  82. // BITMAPINFOHEADER: http://msdn.microsoft.com/en-us/library/dd183376.aspx
  83. //
  84. var biWidth = oData.width;
  85. var biHeight = oData.height;
  86. var biSizeImage = biWidth * biHeight * 3;
  87. var bfSize = biSizeImage + 54; // total header size = 54 bytes
  88. //
  89. // typedef struct tagBITMAPFILEHEADER {
  90. // WORD bfType;
  91. // DWORD bfSize;
  92. // WORD bfReserved1;
  93. // WORD bfReserved2;
  94. // DWORD bfOffBits;
  95. // } BITMAPFILEHEADER;
  96. //
  97. var BITMAPFILEHEADER = [
  98. // WORD bfType -- The file type signature; must be "BM"
  99. 0x42, 0x4D,
  100. // DWORD bfSize -- The size, in bytes, of the bitmap file
  101. bfSize & 0xff, bfSize >> 8 & 0xff, bfSize >> 16 & 0xff, bfSize >> 24 & 0xff,
  102. // WORD bfReserved1 -- Reserved; must be zero
  103. 0, 0,
  104. // WORD bfReserved2 -- Reserved; must be zero
  105. 0, 0,
  106. // DWORD bfOffBits -- The offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to the bitmap bits.
  107. 54, 0, 0, 0
  108. ];
  109. //
  110. // typedef struct tagBITMAPINFOHEADER {
  111. // DWORD biSize;
  112. // LONG biWidth;
  113. // LONG biHeight;
  114. // WORD biPlanes;
  115. // WORD biBitCount;
  116. // DWORD biCompression;
  117. // DWORD biSizeImage;
  118. // LONG biXPelsPerMeter;
  119. // LONG biYPelsPerMeter;
  120. // DWORD biClrUsed;
  121. // DWORD biClrImportant;
  122. // } BITMAPINFOHEADER, *PBITMAPINFOHEADER;
  123. //
  124. var BITMAPINFOHEADER = [
  125. // DWORD biSize -- The number of bytes required by the structure
  126. 40, 0, 0, 0,
  127. // LONG biWidth -- The width of the bitmap, in pixels
  128. biWidth & 0xff, biWidth >> 8 & 0xff, biWidth >> 16 & 0xff, biWidth >> 24 & 0xff,
  129. // LONG biHeight -- The height of the bitmap, in pixels
  130. biHeight & 0xff, biHeight >> 8 & 0xff, biHeight >> 16 & 0xff, biHeight >> 24 & 0xff,
  131. // WORD biPlanes -- The number of planes for the target device. This value must be set to 1
  132. 1, 0,
  133. // WORD biBitCount -- The number of bits-per-pixel, 24 bits-per-pixel -- the bitmap
  134. // has a maximum of 2^24 colors (16777216, Truecolor)
  135. 24, 0,
  136. // DWORD biCompression -- The type of compression, BI_RGB (code 0) -- uncompressed
  137. 0, 0, 0, 0,
  138. // DWORD biSizeImage -- The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps
  139. biSizeImage & 0xff, biSizeImage >> 8 & 0xff, biSizeImage >> 16 & 0xff, biSizeImage >> 24 & 0xff,
  140. // LONG biXPelsPerMeter, unused
  141. 0,0,0,0,
  142. // LONG biYPelsPerMeter, unused
  143. 0,0,0,0,
  144. // DWORD biClrUsed, the number of color indexes of palette, unused
  145. 0,0,0,0,
  146. // DWORD biClrImportant, unused
  147. 0,0,0,0
  148. ];
  149. var iPadding = (4 - ((biWidth * 3) % 4)) % 4;
  150. var aImgData = oData.data;
  151. var strPixelData = '';
  152. var biWidth4 = biWidth<<2;
  153. var y = biHeight;
  154. var fromCharCode = String.fromCharCode;
  155. do {
  156. var iOffsetY = biWidth4*(y-1);
  157. var strPixelRow = '';
  158. for (var x = 0; x < biWidth; x++) {
  159. var iOffsetX = x<<2;
  160. strPixelRow += fromCharCode(aImgData[iOffsetY+iOffsetX+2]) +
  161. fromCharCode(aImgData[iOffsetY+iOffsetX+1]) +
  162. fromCharCode(aImgData[iOffsetY+iOffsetX]);
  163. }
  164. for (var c = 0; c < iPadding; c++) {
  165. strPixelRow += String.fromCharCode(0);
  166. }
  167. strPixelData += strPixelRow;
  168. } while (--y);
  169. var strEncoded = encodeData(BITMAPFILEHEADER.concat(BITMAPINFOHEADER)) + encodeData(strPixelData);
  170. return strEncoded;
  171. };
  172. /**
  173. * [saveAsImage]
  174. * @param {[obj]} canvas [canvasElement]
  175. * @param {[Number]} width [optional] png width
  176. * @param {[Number]} height [optional] png height
  177. * @param {[String]} type [image type]
  178. * @param {[String]} filename [image filename]
  179. * @return {[type]} [description]
  180. */
  181. var saveAsImage = function (canvas, width, height, type,filename) {
  182. if ($support.canvas && $support.dataURL) {
  183. if (typeof canvas == "string") { canvas = document.getElementById(canvas); }
  184. if (type == undefined) { type = 'png'; }
  185. filename = filename == undefined||filename.length === 0 ?Date.now()+'.'+type: filename+'.'+type
  186. type = fixType(type);
  187. if (/bmp/.test(type)) {
  188. var data = getImageData(scaleCanvas(canvas, width, height));
  189. var strData = genBitmapImage(data);
  190. saveFile(makeURI(strData, downloadMimedownloadMime),filename);
  191. } else {
  192. var strData = getDataURL(canvas, type, width, height);
  193. saveFile(strData.replace(type, downloadMime),filename);
  194. }
  195. }
  196. };
  197. var convertToImage = function (canvas, width, height, type) {
  198. if ($support.canvas && $support.dataURL) {
  199. if (typeof canvas == "string") { canvas = document.getElementById(canvas); }
  200. if (type == undefined) { type = 'png'; }
  201. type = fixType(type);
  202. if (/bmp/.test(type)) {
  203. var data = getImageData(scaleCanvas(canvas, width, height));
  204. var strData = genBitmapImage(data);
  205. return genImage(makeURI(strData, 'image/bmp'));
  206. } else {
  207. var strData = getDataURL(canvas, type, width, height);
  208. return genImage(strData);
  209. }
  210. }
  211. };
  212. return {
  213. saveAsImage: saveAsImage,
  214. saveAsPNG: function (canvas, width, height, fileName) {
  215. return saveAsImage(canvas, width, height, 'png',fileName);
  216. },
  217. saveAsJPEG: function (canvas, width, height, fileName) {
  218. return saveAsImage(canvas, width, height, 'jpeg',fileName);
  219. },
  220. saveAsGIF: function (canvas, width, height, fileName) {
  221. return saveAsImage(canvas, width, height, 'gif',fileName);
  222. },
  223. saveAsBMP: function (canvas, width, height, fileName) {
  224. return saveAsImage(canvas, width, height, 'bmp',fileName);
  225. },
  226. convertToImage: convertToImage,
  227. convertToPNG: function (canvas, width, height) {
  228. return convertToImage(canvas, width, height, 'png');
  229. },
  230. convertToJPEG: function (canvas, width, height) {
  231. return convertToImage(canvas, width, height, 'jpeg');
  232. },
  233. convertToGIF: function (canvas, width, height) {
  234. return convertToImage(canvas, width, height, 'gif');
  235. },
  236. convertToBMP: function (canvas, width, height) {
  237. return convertToImage(canvas, width, height, 'bmp');
  238. }
  239. };
  240. }();