extract.mjs 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*!
  2. * @pixi/extract - v6.5.10
  3. * Compiled Thu, 06 Jul 2023 15:25:11 UTC
  4. *
  5. * @pixi/extract is licensed under the MIT License.
  6. * http://www.opensource.org/licenses/mit-license
  7. */
  8. import { MSAA_QUALITY } from '@pixi/constants';
  9. import { CanvasRenderTarget } from '@pixi/utils';
  10. import { Rectangle } from '@pixi/math';
  11. import { ExtensionType, RenderTexture } from '@pixi/core';
  12. var TEMP_RECT = new Rectangle();
  13. var BYTES_PER_PIXEL = 4;
  14. /**
  15. * This class provides renderer-specific plugins for exporting content from a renderer.
  16. * For instance, these plugins can be used for saving an Image, Canvas element or for exporting the raw image data (pixels).
  17. *
  18. * Do not instantiate these plugins directly. It is available from the `renderer.plugins` property.
  19. * See {@link PIXI.CanvasRenderer#plugins} or {@link PIXI.Renderer#plugins}.
  20. * @example
  21. * // Create a new app (will auto-add extract plugin to renderer)
  22. * const app = new PIXI.Application();
  23. *
  24. * // Draw a red circle
  25. * const graphics = new PIXI.Graphics()
  26. * .beginFill(0xFF0000)
  27. * .drawCircle(0, 0, 50);
  28. *
  29. * // Render the graphics as an HTMLImageElement
  30. * const image = app.renderer.plugins.extract.image(graphics);
  31. * document.body.appendChild(image);
  32. * @memberof PIXI
  33. */
  34. var Extract = /** @class */ (function () {
  35. /**
  36. * @param renderer - A reference to the current renderer
  37. */
  38. function Extract(renderer) {
  39. this.renderer = renderer;
  40. }
  41. /**
  42. * Will return a HTML Image of the target
  43. * @param target - A displayObject or renderTexture
  44. * to convert. If left empty will use the main renderer
  45. * @param format - Image format, e.g. "image/jpeg" or "image/webp".
  46. * @param quality - JPEG or Webp compression from 0 to 1. Default is 0.92.
  47. * @returns - HTML Image of the target
  48. */
  49. Extract.prototype.image = function (target, format, quality) {
  50. var image = new Image();
  51. image.src = this.base64(target, format, quality);
  52. return image;
  53. };
  54. /**
  55. * Will return a base64 encoded string of this target. It works by calling
  56. * `Extract.getCanvas` and then running toDataURL on that.
  57. * @param target - A displayObject or renderTexture
  58. * to convert. If left empty will use the main renderer
  59. * @param format - Image format, e.g. "image/jpeg" or "image/webp".
  60. * @param quality - JPEG or Webp compression from 0 to 1. Default is 0.92.
  61. * @returns - A base64 encoded string of the texture.
  62. */
  63. Extract.prototype.base64 = function (target, format, quality) {
  64. return this.canvas(target).toDataURL(format, quality);
  65. };
  66. /**
  67. * Creates a Canvas element, renders this target to it and then returns it.
  68. * @param target - A displayObject or renderTexture
  69. * to convert. If left empty will use the main renderer
  70. * @param frame - The frame the extraction is restricted to.
  71. * @returns - A Canvas element with the texture rendered on.
  72. */
  73. Extract.prototype.canvas = function (target, frame) {
  74. var _a = this._rawPixels(target, frame), pixels = _a.pixels, width = _a.width, height = _a.height, flipY = _a.flipY;
  75. var canvasBuffer = new CanvasRenderTarget(width, height, 1);
  76. // Add the pixels to the canvas
  77. var canvasData = canvasBuffer.context.getImageData(0, 0, width, height);
  78. Extract.arrayPostDivide(pixels, canvasData.data);
  79. canvasBuffer.context.putImageData(canvasData, 0, 0);
  80. // Flipping pixels
  81. if (flipY) {
  82. var target_1 = new CanvasRenderTarget(canvasBuffer.width, canvasBuffer.height, 1);
  83. target_1.context.scale(1, -1);
  84. // We can't render to itself because we should be empty before render.
  85. target_1.context.drawImage(canvasBuffer.canvas, 0, -height);
  86. canvasBuffer.destroy();
  87. canvasBuffer = target_1;
  88. }
  89. // Send the canvas back
  90. return canvasBuffer.canvas;
  91. };
  92. /**
  93. * Will return a one-dimensional array containing the pixel data of the entire texture in RGBA
  94. * order, with integer values between 0 and 255 (included).
  95. * @param target - A displayObject or renderTexture
  96. * to convert. If left empty will use the main renderer
  97. * @param frame - The frame the extraction is restricted to.
  98. * @returns - One-dimensional array containing the pixel data of the entire texture
  99. */
  100. Extract.prototype.pixels = function (target, frame) {
  101. var pixels = this._rawPixels(target, frame).pixels;
  102. Extract.arrayPostDivide(pixels, pixels);
  103. return pixels;
  104. };
  105. Extract.prototype._rawPixels = function (target, frame) {
  106. var renderer = this.renderer;
  107. var resolution;
  108. var flipY = false;
  109. var renderTexture;
  110. var generated = false;
  111. if (target) {
  112. if (target instanceof RenderTexture) {
  113. renderTexture = target;
  114. }
  115. else {
  116. var multisample = renderer.context.webGLVersion >= 2 ? renderer.multisample : MSAA_QUALITY.NONE;
  117. renderTexture = this.renderer.generateTexture(target, { multisample: multisample });
  118. if (multisample !== MSAA_QUALITY.NONE) {
  119. // Resolve the multisampled texture to a non-multisampled texture
  120. var resolvedTexture = RenderTexture.create({
  121. width: renderTexture.width,
  122. height: renderTexture.height,
  123. });
  124. renderer.framebuffer.bind(renderTexture.framebuffer);
  125. renderer.framebuffer.blit(resolvedTexture.framebuffer);
  126. renderer.framebuffer.bind(null);
  127. renderTexture.destroy(true);
  128. renderTexture = resolvedTexture;
  129. }
  130. generated = true;
  131. }
  132. }
  133. if (renderTexture) {
  134. resolution = renderTexture.baseTexture.resolution;
  135. frame = frame !== null && frame !== void 0 ? frame : renderTexture.frame;
  136. flipY = false;
  137. renderer.renderTexture.bind(renderTexture);
  138. }
  139. else {
  140. resolution = renderer.resolution;
  141. if (!frame) {
  142. frame = TEMP_RECT;
  143. frame.width = renderer.width;
  144. frame.height = renderer.height;
  145. }
  146. flipY = true;
  147. renderer.renderTexture.bind(null);
  148. }
  149. var width = Math.round(frame.width * resolution);
  150. var height = Math.round(frame.height * resolution);
  151. var pixels = new Uint8Array(BYTES_PER_PIXEL * width * height);
  152. // Read pixels to the array
  153. var gl = renderer.gl;
  154. gl.readPixels(Math.round(frame.x * resolution), Math.round(frame.y * resolution), width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
  155. if (generated) {
  156. renderTexture.destroy(true);
  157. }
  158. return { pixels: pixels, width: width, height: height, flipY: flipY };
  159. };
  160. /** Destroys the extract. */
  161. Extract.prototype.destroy = function () {
  162. this.renderer = null;
  163. };
  164. /**
  165. * Takes premultiplied pixel data and produces regular pixel data
  166. * @private
  167. * @param pixels - array of pixel data
  168. * @param out - output array
  169. */
  170. Extract.arrayPostDivide = function (pixels, out) {
  171. for (var i = 0; i < pixels.length; i += 4) {
  172. var alpha = out[i + 3] = pixels[i + 3];
  173. if (alpha !== 0) {
  174. out[i] = Math.round(Math.min(pixels[i] * 255.0 / alpha, 255.0));
  175. out[i + 1] = Math.round(Math.min(pixels[i + 1] * 255.0 / alpha, 255.0));
  176. out[i + 2] = Math.round(Math.min(pixels[i + 2] * 255.0 / alpha, 255.0));
  177. }
  178. else {
  179. out[i] = pixels[i];
  180. out[i + 1] = pixels[i + 1];
  181. out[i + 2] = pixels[i + 2];
  182. }
  183. }
  184. };
  185. /** @ignore */
  186. Extract.extension = {
  187. name: 'extract',
  188. type: ExtensionType.RendererPlugin,
  189. };
  190. return Extract;
  191. }());
  192. export { Extract };
  193. //# sourceMappingURL=extract.mjs.map