Source: extract/webgl/WebGLExtract.js

extract/webgl/WebGLExtract.js

  1. import * as core from '../../core';
  2. //引入小程序补丁
  3. import { Image } from '@ali/pixi-miniprogram-adapter';
  4. const TEMP_RECT = new core.Rectangle();
  5. const BYTES_PER_PIXEL = 4;
  6. /**
  7. * The extract manager provides functionality to export content from the renderers.
  8. *
  9. * An instance of this class is automatically created by default, and can be found at renderer.plugins.extract
  10. *
  11. * @class
  12. * @memberof PIXI.extract
  13. */
  14. export default class WebGLExtract
  15. {
  16. /**
  17. * @param {PIXI.WebGLRenderer} renderer - A reference to the current renderer
  18. */
  19. constructor(renderer)
  20. {
  21. this.renderer = renderer;
  22. /**
  23. * Collection of methods for extracting data (image, pixels, etc.) from a display object or render texture
  24. *
  25. * @member {PIXI.extract.WebGLExtract} extract
  26. * @memberof PIXI.WebGLRenderer#
  27. * @see PIXI.extract.WebGLExtract
  28. */
  29. renderer.extract = this;
  30. }
  31. /**
  32. * Will return a HTML Image of the target
  33. *
  34. * @param {PIXI.DisplayObject|PIXI.RenderTexture} target - A displayObject or renderTexture
  35. * to convert. If left empty will use use the main renderer
  36. * @return {HTMLImageElement} HTML Image of the target
  37. */
  38. image(target)
  39. {
  40. const image = new Image();
  41. image.src = this.base64(target);
  42. return image;
  43. }
  44. /**
  45. * Will return a a base64 encoded string of this target. It works by calling
  46. * `WebGLExtract.getCanvas` and then running toDataURL on that.
  47. *
  48. * @param {PIXI.DisplayObject|PIXI.RenderTexture} target - A displayObject or renderTexture
  49. * to convert. If left empty will use use the main renderer
  50. * @return {string} A base64 encoded string of the texture.
  51. */
  52. base64(target)
  53. {
  54. return this.canvas(target).toDataURL();
  55. }
  56. /**
  57. * Creates a Canvas element, renders this target to it and then returns it.
  58. *
  59. * @param {PIXI.DisplayObject|PIXI.RenderTexture} target - A displayObject or renderTexture
  60. * to convert. If left empty will use use the main renderer
  61. * @param {number} scale - scale size
  62. * @return {HTMLCanvasElement} A Canvas element with the texture rendered on.
  63. */
  64. canvas(target, scale = 1)
  65. {
  66. const renderer = this.renderer;
  67. let textureBuffer;
  68. let resolution;
  69. let frame;
  70. let flipY = false;
  71. let renderTexture;
  72. let generated = false;
  73. if (target)
  74. {
  75. if (target instanceof core.RenderTexture)
  76. {
  77. renderTexture = target;
  78. }
  79. else
  80. {
  81. renderTexture = this.renderer.generateTexture(target);
  82. generated = true;
  83. }
  84. }
  85. if (renderTexture)
  86. {
  87. textureBuffer = renderTexture.baseTexture._glRenderTargets[this.renderer.CONTEXT_UID];
  88. resolution = textureBuffer.resolution;
  89. frame = renderTexture.frame;
  90. flipY = false;
  91. }
  92. else
  93. {
  94. textureBuffer = this.renderer.rootRenderTarget;
  95. resolution = textureBuffer.resolution;
  96. flipY = true;
  97. frame = TEMP_RECT;
  98. frame.width = textureBuffer.size.width;
  99. frame.height = textureBuffer.size.height;
  100. }
  101. const width = Math.floor((frame.width * scale * resolution) + 1e-4);
  102. const height = Math.floor((frame.height * scale * resolution) + 1e-4);
  103. const canvasBuffer = new core.CanvasRenderTarget(width, height, 1);
  104. if (textureBuffer)
  105. {
  106. // bind the buffer
  107. renderer.bindRenderTarget(textureBuffer);
  108. // set up an array of pixels
  109. const webglPixels = new Uint8Array(BYTES_PER_PIXEL * width * height);
  110. // read pixels to the array
  111. const gl = renderer.gl;
  112. gl.readPixels(
  113. frame.x * scale * resolution,
  114. frame.y * scale * resolution,
  115. width,
  116. height,
  117. gl.RGBA,
  118. gl.UNSIGNED_BYTE,
  119. webglPixels
  120. );
  121. // add the pixels to the canvas
  122. const canvasData = canvasBuffer.context.getImageData(0, 0, width, height);
  123. canvasData.data.set(webglPixels);
  124. canvasBuffer.context.putImageData(canvasData, 0, 0);
  125. // pulling pixels
  126. if (flipY)
  127. {
  128. canvasBuffer.context.scale(1, -1);
  129. canvasBuffer.context.drawImage(canvasBuffer.canvas, 0, -height);
  130. }
  131. }
  132. if (generated)
  133. {
  134. renderTexture.destroy(true);
  135. }
  136. // send the canvas back..
  137. return canvasBuffer.canvas;
  138. }
  139. /**
  140. * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA
  141. * order, with integer values between 0 and 255 (included).
  142. *
  143. * @param {PIXI.DisplayObject|PIXI.RenderTexture} target - A displayObject or renderTexture
  144. * to convert. If left empty will use use the main renderer
  145. * @return {Uint8ClampedArray} One-dimensional array containing the pixel data of the entire texture
  146. */
  147. pixels(target)
  148. {
  149. const renderer = this.renderer;
  150. let textureBuffer;
  151. let resolution;
  152. let frame;
  153. let renderTexture;
  154. let generated = false;
  155. if (target)
  156. {
  157. if (target instanceof core.RenderTexture)
  158. {
  159. renderTexture = target;
  160. }
  161. else
  162. {
  163. renderTexture = this.renderer.generateTexture(target);
  164. generated = true;
  165. }
  166. }
  167. if (renderTexture)
  168. {
  169. textureBuffer = renderTexture.baseTexture._glRenderTargets[this.renderer.CONTEXT_UID];
  170. resolution = textureBuffer.resolution;
  171. frame = renderTexture.frame;
  172. }
  173. else
  174. {
  175. textureBuffer = this.renderer.rootRenderTarget;
  176. resolution = textureBuffer.resolution;
  177. frame = TEMP_RECT;
  178. frame.width = textureBuffer.size.width;
  179. frame.height = textureBuffer.size.height;
  180. }
  181. const width = frame.width * resolution;
  182. const height = frame.height * resolution;
  183. const webglPixels = new Uint8Array(BYTES_PER_PIXEL * width * height);
  184. if (textureBuffer)
  185. {
  186. // bind the buffer
  187. renderer.bindRenderTarget(textureBuffer);
  188. // read pixels to the array
  189. const gl = renderer.gl;
  190. gl.readPixels(
  191. frame.x * resolution,
  192. frame.y * resolution,
  193. width,
  194. height,
  195. gl.RGBA,
  196. gl.UNSIGNED_BYTE,
  197. webglPixels
  198. );
  199. }
  200. if (generated)
  201. {
  202. renderTexture.destroy(true);
  203. }
  204. return webglPixels;
  205. }
  206. /**
  207. * Destroys the extract
  208. *
  209. */
  210. destroy()
  211. {
  212. this.renderer.extract = null;
  213. this.renderer = null;
  214. }
  215. }
  216. core.WebGLRenderer.registerPlugin('extract', WebGLExtract);