canvas2image 1.0.0

Allow you save canvas as .png

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/457526/1134364/canvas2image%20100.js

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