p5 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/{src → dist}/accessibility/color_namer.js +48 -3
  2. package/{src → dist}/accessibility/describe.js +2 -2
  3. package/{src → dist}/accessibility/gridOutput.js +2 -2
  4. package/dist/accessibility/index.js +60 -0
  5. package/{src → dist}/accessibility/outputs.js +2 -2
  6. package/{src → dist}/accessibility/textOutput.js +2 -2
  7. package/dist/app.js +120 -0
  8. package/{src → dist}/color/color_conversion.js +48 -10
  9. package/{src → dist}/color/color_spaces/hsb.js +3 -1
  10. package/dist/color/creating_reading.js +3 -0
  11. package/dist/color/index.js +13 -0
  12. package/dist/color/p5.Color.culori.js +1 -0
  13. package/dist/color/p5.Color.js +3 -0
  14. package/{src → dist}/color/setting.js +9 -6
  15. package/{src/core/constants.js → dist/constants-C-g_eAdC.js} +266 -130
  16. package/{src → dist}/core/States.js +3 -1
  17. package/dist/core/constants.js +1 -0
  18. package/{src → dist}/core/environment.js +7 -6
  19. package/{src → dist}/core/friendly_errors/browser_errors.js +1 -1
  20. package/{src → dist}/core/friendly_errors/fes_core.js +14 -44
  21. package/{src → dist}/core/friendly_errors/file_errors.js +6 -3
  22. package/dist/core/friendly_errors/index.js +23 -0
  23. package/dist/core/friendly_errors/param_validator.js +5455 -0
  24. package/{src → dist}/core/friendly_errors/sketch_reader.js +50 -4
  25. package/{src → dist}/core/friendly_errors/sketch_verifier.js +6 -6
  26. package/{src → dist}/core/friendly_errors/stacktrace.js +3 -5
  27. package/{src → dist}/core/friendly_errors/validate_params.js +50 -41
  28. package/{src → dist}/core/helpers.js +9 -6
  29. package/dist/core/init.js +105 -0
  30. package/dist/core/internationalization.js +302 -0
  31. package/dist/core/legacy.js +73 -0
  32. package/dist/core/main.js +44 -0
  33. package/dist/core/noop.js +3 -0
  34. package/dist/core/p5.Graphics.js +40 -0
  35. package/dist/core/p5.Renderer.js +11 -0
  36. package/dist/core/p5.Renderer2D.js +44 -0
  37. package/dist/core/reference.js +1 -0
  38. package/dist/core/rendering.js +40 -0
  39. package/{src → dist}/core/structure.js +3 -3
  40. package/{src → dist}/core/transform.js +2 -2
  41. package/{src/color/creating_reading.js → dist/creating_reading-D4AAKRbx.js} +841 -13
  42. package/{src → dist}/data/index.js +3 -1
  43. package/{src → dist}/data/local_storage.js +2 -8
  44. package/{src → dist}/dom/dom.js +11 -5
  45. package/dist/dom/index.js +18 -0
  46. package/{src → dist}/dom/p5.Element.js +14 -12
  47. package/{src → dist}/dom/p5.File.js +4 -4
  48. package/{src → dist}/dom/p5.MediaElement.js +10 -4
  49. package/{src → dist}/events/acceleration.js +2 -2
  50. package/{src → dist}/events/index.js +3 -1
  51. package/{src → dist}/events/keyboard.js +14 -11
  52. package/{src → dist}/events/pointer.js +16 -17
  53. package/dist/image/const.js +9 -0
  54. package/{src → dist}/image/filterRenderer2D.js +57 -37
  55. package/{src → dist}/image/filters.js +1 -3
  56. package/dist/image/image.js +40 -0
  57. package/dist/image/index.js +51 -0
  58. package/dist/image/loading_displaying.js +40 -0
  59. package/dist/image/p5.Image.js +11 -0
  60. package/{src → dist}/image/pixels.js +4 -3
  61. package/{src → dist}/io/csv.js +72 -70
  62. package/dist/io/files.js +40 -0
  63. package/dist/io/index.js +51 -0
  64. package/{src → dist}/io/p5.Table.js +6 -6
  65. package/{src → dist}/io/p5.TableRow.js +3 -4
  66. package/{src → dist}/io/p5.XML.js +2 -5
  67. package/{src → dist}/io/utilities.js +1 -1
  68. package/{src/core/p5.Renderer2D.js → dist/main-s72KWcUy.js} +735 -57
  69. package/{src → dist}/math/Matrices/Matrix.js +10 -8
  70. package/{src → dist}/math/Matrices/MatrixInterface.js +5 -3
  71. package/{src → dist}/math/Matrices/MatrixNumjs.js +12 -26
  72. package/{src → dist}/math/calculation.js +2 -2
  73. package/{src → dist}/math/index.js +6 -3
  74. package/{src → dist}/math/math.js +2 -2
  75. package/{src → dist}/math/noise.js +2 -2
  76. package/{src → dist}/math/p5.Matrix.js +7 -4
  77. package/{src → dist}/math/p5.Vector.js +6 -6
  78. package/{src → dist}/math/random.js +2 -2
  79. package/{src → dist}/math/trigonometry.js +16 -15
  80. package/{src/image/p5.Image.js → dist/p5.Renderer-CwAYZOC2.js} +390 -19
  81. package/dist/rendering--aAe5aq3.js +24925 -0
  82. package/{src → dist}/shape/2d_primitives.js +18 -17
  83. package/{src → dist}/shape/attributes.js +18 -17
  84. package/{src → dist}/shape/curves.js +2 -2
  85. package/{src → dist}/shape/custom_shapes.js +44 -64
  86. package/{src → dist}/shape/index.js +10 -2
  87. package/{src → dist}/shape/vertex.js +2 -3
  88. package/dist/type/index.js +25 -0
  89. package/{src → dist}/type/lib/Typr.js +76 -94
  90. package/{src → dist}/type/p5.Font.js +37 -61
  91. package/{src → dist}/type/textCore.js +34 -57
  92. package/{src → dist}/type/unicodeRanges.js +3 -1
  93. package/{src → dist}/utilities/conversion.js +2 -2
  94. package/{src → dist}/utilities/index.js +3 -1
  95. package/{src → dist}/utilities/time_date.js +6 -7
  96. package/{src → dist}/utilities/utility_functions.js +2 -2
  97. package/dist/webgl/3d_primitives.js +40 -0
  98. package/{src → dist}/webgl/GeometryBufferCache.js +3 -1
  99. package/{src → dist}/webgl/GeometryBuilder.js +12 -8
  100. package/{src → dist}/webgl/ShaderGenerator.js +79 -82
  101. package/{src → dist}/webgl/ShapeBuilder.js +26 -23
  102. package/dist/webgl/index.js +76 -0
  103. package/{src → dist}/webgl/interaction.js +7 -6
  104. package/dist/webgl/light.js +40 -0
  105. package/{src → dist}/webgl/loading.js +45 -12
  106. package/dist/webgl/material.js +40 -0
  107. package/dist/webgl/p5.Camera.js +40 -0
  108. package/{src → dist}/webgl/p5.DataArray.js +3 -5
  109. package/dist/webgl/p5.Framebuffer.js +40 -0
  110. package/{src → dist}/webgl/p5.Geometry.js +12 -15
  111. package/{src → dist}/webgl/p5.Quat.js +5 -4
  112. package/{src → dist}/webgl/p5.RenderBuffer.js +2 -3
  113. package/dist/webgl/p5.RendererGL.js +40 -0
  114. package/dist/webgl/p5.Shader.js +40 -0
  115. package/dist/webgl/p5.Texture.js +40 -0
  116. package/{src → dist}/webgl/text.js +51 -9
  117. package/lib/p5.esm.js +102 -48
  118. package/lib/p5.js +102 -48
  119. package/lib/p5.min.js +1 -1
  120. package/package.json +17 -16
  121. package/translations/dev.js +6 -6
  122. package/translations/index.js +1 -1
  123. package/src/README.md +0 -27
  124. package/src/accessibility/index.js +0 -13
  125. package/src/app.js +0 -61
  126. package/src/color/index.js +0 -9
  127. package/src/color/p5.Color.culori.js +0 -66
  128. package/src/color/p5.Color.js +0 -851
  129. package/src/core/README.md +0 -91
  130. package/src/core/friendly_errors/index.js +0 -13
  131. package/src/core/friendly_errors/param_validator.js +0 -561
  132. package/src/core/init.js +0 -58
  133. package/src/core/internationalization.js +0 -195
  134. package/src/core/legacy.js +0 -29
  135. package/src/core/main.js +0 -689
  136. package/src/core/noop.js +0 -1
  137. package/src/core/p5.Graphics.js +0 -696
  138. package/src/core/p5.Renderer.js +0 -408
  139. package/src/core/reference.js +0 -2060
  140. package/src/core/rendering.js +0 -697
  141. package/src/dom/index.js +0 -11
  142. package/src/image/const.js +0 -6
  143. package/src/image/image.js +0 -731
  144. package/src/image/index.js +0 -15
  145. package/src/image/loading_displaying.js +0 -1431
  146. package/src/io/files.js +0 -2210
  147. package/src/io/index.js +0 -11
  148. package/src/math/README.md +0 -40
  149. package/src/type/index.js +0 -9
  150. package/src/webgl/3d_primitives.js +0 -2741
  151. package/src/webgl/index.js +0 -37
  152. package/src/webgl/light.js +0 -1851
  153. package/src/webgl/material.js +0 -3854
  154. package/src/webgl/p5.Camera.js +0 -4010
  155. package/src/webgl/p5.Framebuffer.js +0 -1865
  156. package/src/webgl/p5.RendererGL.js +0 -2867
  157. package/src/webgl/p5.Shader.js +0 -1505
  158. package/src/webgl/p5.Texture.js +0 -541
  159. package/src/webgl/shaders/basic.frag +0 -6
  160. package/src/webgl/shaders/filters/base.frag +0 -22
  161. package/src/webgl/shaders/filters/base.vert +0 -19
  162. package/src/webgl/shaders/filters/blur.frag +0 -60
  163. package/src/webgl/shaders/filters/default.vert +0 -18
  164. package/src/webgl/shaders/filters/dilate.frag +0 -39
  165. package/src/webgl/shaders/filters/erode.frag +0 -39
  166. package/src/webgl/shaders/filters/gray.frag +0 -16
  167. package/src/webgl/shaders/filters/invert.frag +0 -15
  168. package/src/webgl/shaders/filters/opaque.frag +0 -12
  169. package/src/webgl/shaders/filters/posterize.frag +0 -29
  170. package/src/webgl/shaders/filters/threshold.frag +0 -23
  171. package/src/webgl/shaders/font.frag +0 -216
  172. package/src/webgl/shaders/font.vert +0 -44
  173. package/src/webgl/shaders/imageLight.vert +0 -33
  174. package/src/webgl/shaders/imageLightDiffused.frag +0 -82
  175. package/src/webgl/shaders/imageLightSpecular.frag +0 -134
  176. package/src/webgl/shaders/light.vert +0 -37
  177. package/src/webgl/shaders/light_texture.frag +0 -26
  178. package/src/webgl/shaders/lighting.glsl +0 -227
  179. package/src/webgl/shaders/line.frag +0 -74
  180. package/src/webgl/shaders/line.vert +0 -294
  181. package/src/webgl/shaders/normal.frag +0 -6
  182. package/src/webgl/shaders/normal.vert +0 -72
  183. package/src/webgl/shaders/phong.frag +0 -84
  184. package/src/webgl/shaders/phong.vert +0 -87
  185. package/src/webgl/shaders/point.frag +0 -29
  186. package/src/webgl/shaders/point.vert +0 -19
  187. package/src/webgl/shaders/sphereMapping.frag +0 -26
  188. package/src/webgl/shaders/webgl2Compatibility.glsl +0 -34
@@ -1,731 +0,0 @@
1
- /**
2
- * @module Image
3
- * @submodule Image
4
- * @for p5
5
- * @requires core
6
- */
7
-
8
- /**
9
- * This module defines the p5 methods for the <a href="#/p5.Image">p5.Image</a> class
10
- * for drawing images to the main display canvas.
11
- */
12
- import * as omggif from 'omggif';
13
- import { Element } from '../dom/p5.Element';
14
- import { Framebuffer } from '../webgl/p5.Framebuffer';
15
-
16
- function image(p5, fn){
17
- /**
18
- * Creates a new <a href="#/p5.Image">p5.Image</a> object.
19
- *
20
- * `createImage()` uses the `width` and `height` parameters to set the new
21
- * <a href="#/p5.Image">p5.Image</a> object's dimensions in pixels. The new
22
- * <a href="#/p5.Image">p5.Image</a> can be modified by updating its
23
- * <a href="#/p5.Image/pixels">pixels</a> array or by calling its
24
- * <a href="#/p5.Image/get">get()</a> and
25
- * <a href="#/p5.Image/set">set()</a> methods. The
26
- * <a href="#/p5.Image/loadPixels">loadPixels()</a> method must be called
27
- * before reading or modifying pixel values. The
28
- * <a href="#/p5.Image/updatePixels">updatePixels()</a> method must be called
29
- * for updates to take effect.
30
- *
31
- * Note: The new <a href="#/p5.Image">p5.Image</a> object is transparent by
32
- * default.
33
- *
34
- * @method createImage
35
- * @param {Integer} width width in pixels.
36
- * @param {Integer} height height in pixels.
37
- * @return {p5.Image} new <a href="#/p5.Image">p5.Image</a> object.
38
- *
39
- * @example
40
- * <div>
41
- * <code>
42
- * function setup() {
43
- * createCanvas(100, 100);
44
- *
45
- * background(200);
46
- *
47
- * // Create a p5.Image object.
48
- * let img = createImage(66, 66);
49
- *
50
- * // Load the image's pixels into memory.
51
- * img.loadPixels();
52
- *
53
- * // Set all the image's pixels to black.
54
- * for (let x = 0; x < img.width; x += 1) {
55
- * for (let y = 0; y < img.height; y += 1) {
56
- * img.set(x, y, 0);
57
- * }
58
- * }
59
- *
60
- * // Update the image's pixel values.
61
- * img.updatePixels();
62
- *
63
- * // Draw the image.
64
- * image(img, 17, 17);
65
- *
66
- * describe('A black square drawn in the middle of a gray square.');
67
- * }
68
- * </code>
69
- * </div>
70
- *
71
- * <div>
72
- * <code>
73
- * function setup() {
74
- * createCanvas(100, 100);
75
- *
76
- * background(200);
77
- *
78
- * // Create a p5.Image object.
79
- * let img = createImage(66, 66);
80
- *
81
- * // Load the image's pixels into memory.
82
- * img.loadPixels();
83
- *
84
- * // Create a color gradient.
85
- * for (let x = 0; x < img.width; x += 1) {
86
- * for (let y = 0; y < img.height; y += 1) {
87
- * // Calculate the transparency.
88
- * let a = map(x, 0, img.width, 0, 255);
89
- *
90
- * // Create a p5.Color object.
91
- * let c = color(0, a);
92
- *
93
- * // Set the pixel's color.
94
- * img.set(x, y, c);
95
- * }
96
- * }
97
- *
98
- * // Update the image's pixels.
99
- * img.updatePixels();
100
- *
101
- * // Display the image.
102
- * image(img, 17, 17);
103
- *
104
- * describe('A square with a horizontal color gradient that transitions from gray to black.');
105
- * }
106
- * </code>
107
- * </div>
108
- *
109
- * <div>
110
- * <code>
111
- * function setup() {
112
- * createCanvas(100, 100);
113
- *
114
- * background(200);
115
- *
116
- * // Create a p5.Image object.
117
- * let img = createImage(66, 66);
118
- *
119
- * // Load the pixels into memory.
120
- * img.loadPixels();
121
- * // Get the current pixel density.
122
- * let d = pixelDensity();
123
- *
124
- * // Calculate the pixel that is halfway through the image's pixel array.
125
- * let halfImage = 4 * (d * img.width) * (d * img.height / 2);
126
- *
127
- * // Set half of the image's pixels to black.
128
- * for (let i = 0; i < halfImage; i += 4) {
129
- * // Red.
130
- * img.pixels[i] = 0;
131
- * // Green.
132
- * img.pixels[i + 1] = 0;
133
- * // Blue.
134
- * img.pixels[i + 2] = 0;
135
- * // Alpha.
136
- * img.pixels[i + 3] = 255;
137
- * }
138
- *
139
- * // Update the image's pixels.
140
- * img.updatePixels();
141
- *
142
- * // Display the image.
143
- * image(img, 17, 17);
144
- *
145
- * describe('A black square drawn in the middle of a gray square.');
146
- * }
147
- * </code>
148
- * </div>
149
- */
150
- fn.createImage = function(width, height) {
151
- // p5._validateParameters('createImage', arguments);
152
- return new p5.Image(width, height);
153
- };
154
-
155
- /**
156
- * Saves the current canvas as an image.
157
- *
158
- * By default, `saveCanvas()` saves the canvas as a PNG image called
159
- * `untitled.png`.
160
- *
161
- * The first parameter, `filename`, is optional. It's a string that sets the
162
- * file's name. If a file extension is included, as in
163
- * `saveCanvas('drawing.png')`, then the image will be saved using that
164
- * format.
165
- *
166
- * The second parameter, `extension`, is also optional. It sets the files format.
167
- * Either `'png'`, `'webp'`, or `'jpg'` can be used. For example, `saveCanvas('drawing', 'jpg')`
168
- * saves the canvas to a file called `drawing.jpg`.
169
- *
170
- * Note: The browser will either save the file immediately or prompt the user
171
- * with a dialogue window.
172
- *
173
- * @method saveCanvas
174
- * @param {p5.Framebuffer|p5.Element|HTMLCanvasElement} selectedCanvas reference to a
175
- * specific HTML5 canvas element.
176
- * @param {String} [filename] file name. Defaults to 'untitled'.
177
- * @param {String} [extension] file extension, either 'png', 'webp', or 'jpg'. Defaults to 'png'.
178
- *
179
- * @example
180
- * <div class='norender'>
181
- * <code>
182
- * function setup() {
183
- * createCanvas(100, 100);
184
- * background(255);
185
- *
186
- * // Save the canvas to 'untitled.png'.
187
- * saveCanvas();
188
- *
189
- * describe('A white square.');
190
- * }
191
- * </code>
192
- * </div>
193
- *
194
- * <div class='norender'>
195
- * <code>
196
- * function setup() {
197
- * createCanvas(100, 100);
198
- *
199
- * background(255);
200
- *
201
- * // Save the canvas to 'myCanvas.jpg'.
202
- * saveCanvas('myCanvas.jpg');
203
- *
204
- * describe('A white square.');
205
- * }
206
- * </code>
207
- * </div>
208
- *
209
- * <div class='norender'>
210
- * <code>
211
- * function setup() {
212
- * createCanvas(100, 100);
213
- *
214
- * background(255);
215
- *
216
- * // Save the canvas to 'myCanvas.jpg'.
217
- * saveCanvas('myCanvas', 'jpg');
218
- *
219
- * describe('A white square.');
220
- * }
221
- * </code>
222
- * </div>
223
- *
224
- * <div class='norender'>
225
- * <code>
226
- * function setup() {
227
- * let cnv = createCanvas(100, 100);
228
- *
229
- * background(255);
230
- *
231
- * // Save the canvas to 'untitled.png'.
232
- * saveCanvas(cnv);
233
- *
234
- * describe('A white square.');
235
- * }
236
- * </code>
237
- * </div>
238
- *
239
- * <div class='norender'>
240
- * <code>
241
- * function setup() {
242
- * let cnv = createCanvas(100, 100);
243
- *
244
- * background(255);
245
- *
246
- * // Save the canvas to 'myCanvas.jpg'.
247
- * saveCanvas(cnv, 'myCanvas.jpg');
248
- *
249
- * describe('A white square.');
250
- * }
251
- * </code>
252
- * </div>
253
- *
254
- * <div class='norender'>
255
- * <code>
256
- * function setup() {
257
- * let cnv = createCanvas(100, 100);
258
- *
259
- * background(255);
260
- *
261
- * // Save the canvas to 'myCanvas.jpg'.
262
- * saveCanvas(cnv, 'myCanvas', 'jpg');
263
- *
264
- * describe('A white square.');
265
- * }
266
- * </code>
267
- * </div>
268
- */
269
- /**
270
- * @method saveCanvas
271
- * @param {String} [filename]
272
- * @param {String} [extension]
273
- */
274
- fn.saveCanvas = function(...args) {
275
- // copy arguments to array
276
- let htmlCanvas, filename, extension, temporaryGraphics;
277
-
278
- if (args[0] instanceof HTMLCanvasElement) {
279
- htmlCanvas = args[0];
280
- args.shift();
281
- } else if (args[0] instanceof Element) {
282
- htmlCanvas = args[0].elt;
283
- args.shift();
284
- } else if (args[0] instanceof Framebuffer) {
285
- const framebuffer = args[0];
286
- temporaryGraphics = this.createGraphics(framebuffer.width,
287
- framebuffer.height);
288
- temporaryGraphics.pixelDensity(framebuffer.pixelDensity());
289
- framebuffer.loadPixels();
290
- temporaryGraphics.loadPixels();
291
- temporaryGraphics.pixels.set(framebuffer.pixels);
292
- temporaryGraphics.updatePixels();
293
-
294
- htmlCanvas = temporaryGraphics._renderer.canvas;
295
- args.shift();
296
- } else {
297
- htmlCanvas = this._curElement && this._curElement.elt;
298
- }
299
-
300
- if (args.length >= 1) {
301
- filename = args[0];
302
- }
303
- if (args.length >= 2) {
304
- extension = args[1];
305
- }
306
-
307
- extension =
308
- extension ||
309
- fn._checkFileExtension(filename, extension)[1] ||
310
- 'png';
311
-
312
- let mimeType;
313
- switch (extension) {
314
- default:
315
- //case 'png':
316
- mimeType = 'image/png';
317
- break;
318
- case 'webp':
319
- mimeType = 'image/webp';
320
- break;
321
- case 'jpeg':
322
- case 'jpg':
323
- mimeType = 'image/jpeg';
324
- break;
325
- }
326
-
327
- htmlCanvas.toBlob(blob => {
328
- fn.downloadFile(blob, filename, extension);
329
- if(temporaryGraphics) temporaryGraphics.remove();
330
- }, mimeType);
331
- };
332
-
333
- // this is the old saveGif, left here for compatibility purposes
334
- // the only place I found it being used was on image/p5.Image.js, on the
335
- // save function. that has been changed to use this function.
336
- fn.encodeAndDownloadGif = function(pImg, filename) {
337
- const props = pImg.gifProperties;
338
-
339
- //convert loopLimit back into Netscape Block formatting
340
- let loopLimit = props.loopLimit;
341
- if (loopLimit === 1) {
342
- loopLimit = null;
343
- } else if (loopLimit === null) {
344
- loopLimit = 0;
345
- }
346
- const buffer = new Uint8Array(pImg.width * pImg.height * props.numFrames);
347
-
348
- const allFramesPixelColors = [];
349
-
350
- // Used to determine the occurrence of unique palettes and the frames
351
- // which use them
352
- const paletteFreqsAndFrames = {};
353
-
354
- // Pass 1:
355
- //loop over frames and get the frequency of each palette
356
- for (let i = 0; i < props.numFrames; i++) {
357
- const paletteSet = new Set();
358
- const data = props.frames[i].image.data;
359
- const dataLength = data.length;
360
- // The color for each pixel in this frame ( for easier lookup later )
361
- const pixelColors = new Uint32Array(pImg.width * pImg.height);
362
- for (let j = 0, k = 0; j < dataLength; j += 4, k++) {
363
- const r = data[j + 0];
364
- const g = data[j + 1];
365
- const b = data[j + 2];
366
- const color = (r << 16) | (g << 8) | (b << 0);
367
- paletteSet.add(color);
368
-
369
- // What color does this pixel have in this frame ?
370
- pixelColors[k] = color;
371
- }
372
-
373
- // A way to put use the entire palette as an object key
374
- const paletteStr = [...paletteSet].sort().toString();
375
- if (paletteFreqsAndFrames[paletteStr] === undefined) {
376
- paletteFreqsAndFrames[paletteStr] = { freq: 1, frames: [i] };
377
- } else {
378
- paletteFreqsAndFrames[paletteStr].freq += 1;
379
- paletteFreqsAndFrames[paletteStr].frames.push(i);
380
- }
381
-
382
- allFramesPixelColors.push(pixelColors);
383
- }
384
-
385
- let framesUsingGlobalPalette = [];
386
-
387
- // Now to build the global palette
388
- // Sort all the unique palettes in descending order of their occurrence
389
- const palettesSortedByFreq = Object.keys(paletteFreqsAndFrames).sort(function(
390
- a,
391
- b
392
- ) {
393
- return paletteFreqsAndFrames[b].freq - paletteFreqsAndFrames[a].freq;
394
- });
395
-
396
- // The initial global palette is the one with the most occurrence
397
- const globalPalette = palettesSortedByFreq[0]
398
- .split(',')
399
- .map(a => parseInt(a));
400
-
401
- framesUsingGlobalPalette = framesUsingGlobalPalette.concat(
402
- paletteFreqsAndFrames[globalPalette].frames
403
- );
404
-
405
- const globalPaletteSet = new Set(globalPalette);
406
-
407
- // Build a more complete global palette
408
- // Iterate over the remaining palettes in the order of
409
- // their occurrence and see if the colors in this palette which are
410
- // not in the global palette can be added there, while keeping the length
411
- // of the global palette <= 256
412
- for (let i = 1; i < palettesSortedByFreq.length; i++) {
413
- const palette = palettesSortedByFreq[i].split(',').map(a => parseInt(a));
414
-
415
- const difference = palette.filter(x => !globalPaletteSet.has(x));
416
- if (globalPalette.length + difference.length <= 256) {
417
- for (let j = 0; j < difference.length; j++) {
418
- globalPalette.push(difference[j]);
419
- globalPaletteSet.add(difference[j]);
420
- }
421
-
422
- // All frames using this palette now use the global palette
423
- framesUsingGlobalPalette = framesUsingGlobalPalette.concat(
424
- paletteFreqsAndFrames[palettesSortedByFreq[i]].frames
425
- );
426
- }
427
- }
428
-
429
- framesUsingGlobalPalette = new Set(framesUsingGlobalPalette);
430
-
431
- // Build a lookup table of the index of each color in the global palette
432
- // Maps a color to its index
433
- const globalIndicesLookup = {};
434
- for (let i = 0; i < globalPalette.length; i++) {
435
- if (!globalIndicesLookup[globalPalette[i]]) {
436
- globalIndicesLookup[globalPalette[i]] = i;
437
- }
438
- }
439
-
440
- // force palette to be power of 2
441
- let powof2 = 1;
442
- while (powof2 < globalPalette.length) {
443
- powof2 <<= 1;
444
- }
445
- globalPalette.length = powof2;
446
-
447
- // global opts
448
- const opts = {
449
- loop: loopLimit,
450
- palette: new Uint32Array(globalPalette)
451
- };
452
- const gifWriter = new omggif.GifWriter(buffer, pImg.width, pImg.height, opts);
453
- let previousFrame = {};
454
-
455
- // Pass 2
456
- // Determine if the frame needs a local palette
457
- // Also apply transparency optimization. This function will often blow up
458
- // the size of a GIF if not for transparency. If a pixel in one frame has
459
- // the same color in the previous frame, that pixel can be marked as
460
- // transparent. We decide one particular color as transparent and make all
461
- // transparent pixels take this color. This helps in later in compression.
462
- for (let i = 0; i < props.numFrames; i++) {
463
- const localPaletteRequired = !framesUsingGlobalPalette.has(i);
464
- const palette = localPaletteRequired ? [] : globalPalette;
465
- const pixelPaletteIndex = new Uint8Array(pImg.width * pImg.height);
466
-
467
- // Lookup table mapping color to its indices
468
- const colorIndicesLookup = {};
469
-
470
- // All the colors that cannot be marked transparent in this frame
471
- const cannotBeTransparent = new Set();
472
-
473
- allFramesPixelColors[i].forEach((color, k) => {
474
- if (localPaletteRequired) {
475
- if (colorIndicesLookup[color] === undefined) {
476
- colorIndicesLookup[color] = palette.length;
477
- palette.push(color);
478
- }
479
- pixelPaletteIndex[k] = colorIndicesLookup[color];
480
- } else {
481
- pixelPaletteIndex[k] = globalIndicesLookup[color];
482
- }
483
-
484
- if (i > 0) {
485
- // If even one pixel of this color has changed in this frame
486
- // from the previous frame, we cannot mark it as transparent
487
- if (allFramesPixelColors[i - 1][k] !== color) {
488
- cannotBeTransparent.add(color);
489
- }
490
- }
491
- });
492
-
493
- const frameOpts = {};
494
-
495
- // Transparency optimization
496
- const canBeTransparent = palette.filter(a => !cannotBeTransparent.has(a));
497
- if (canBeTransparent.length > 0) {
498
- // Select a color to mark as transparent
499
- const transparent = canBeTransparent[0];
500
- const transparentIndex = localPaletteRequired
501
- ? colorIndicesLookup[transparent]
502
- : globalIndicesLookup[transparent];
503
- if (i > 0) {
504
- for (let k = 0; k < allFramesPixelColors[i].length; k++) {
505
- // If this pixel in this frame has the same color in previous frame
506
- if (allFramesPixelColors[i - 1][k] === allFramesPixelColors[i][k]) {
507
- pixelPaletteIndex[k] = transparentIndex;
508
- }
509
- }
510
- frameOpts.transparent = transparentIndex;
511
- // If this frame has any transparency, do not dispose the previous frame
512
- previousFrame.frameOpts.disposal = 1;
513
- }
514
- }
515
- frameOpts.delay = props.frames[i].delay / 10; // Move timing back into GIF formatting
516
- if (localPaletteRequired) {
517
- // force palette to be power of 2
518
- let powof2 = 1;
519
- while (powof2 < palette.length) {
520
- powof2 <<= 1;
521
- }
522
- palette.length = powof2;
523
- frameOpts.palette = new Uint32Array(palette);
524
- }
525
- if (i > 0) {
526
- // add the frame that came before the current one
527
- gifWriter.addFrame(
528
- 0,
529
- 0,
530
- pImg.width,
531
- pImg.height,
532
- previousFrame.pixelPaletteIndex,
533
- previousFrame.frameOpts
534
- );
535
- }
536
- // previous frame object should now have details of this frame
537
- previousFrame = {
538
- pixelPaletteIndex,
539
- frameOpts
540
- };
541
- }
542
-
543
- previousFrame.frameOpts.disposal = 1;
544
- // add the last frame
545
- gifWriter.addFrame(
546
- 0,
547
- 0,
548
- pImg.width,
549
- pImg.height,
550
- previousFrame.pixelPaletteIndex,
551
- previousFrame.frameOpts
552
- );
553
-
554
- const extension = 'gif';
555
- const blob = new Blob([buffer.slice(0, gifWriter.end())], {
556
- type: 'image/gif'
557
- });
558
- fn.downloadFile(blob, filename, extension);
559
- };
560
-
561
- /**
562
- * Captures a sequence of frames from the canvas that can be saved as images.
563
- *
564
- * `saveFrames()` creates an array of frame objects. Each frame is stored as
565
- * an object with its file type, file name, and image data as a string. For
566
- * example, the first saved frame might have the following properties:
567
- *
568
- * `{ ext: 'png', filenmame: 'frame0', imageData: 'data:image/octet-stream;base64, abc123' }`.
569
- *
570
- * The first parameter, `filename`, sets the prefix for the file names. For
571
- * example, setting the prefix to `'frame'` would generate the image files
572
- * `frame0.png`, `frame1.png`, and so on.
573
- *
574
- * The second parameter, `extension`, sets the file type to either `'png'` or
575
- * `'jpg'`.
576
- *
577
- * The third parameter, `duration`, sets the duration to record in seconds.
578
- * The maximum duration is 15 seconds.
579
- *
580
- * The fourth parameter, `framerate`, sets the number of frames to record per
581
- * second. The maximum frame rate value is 22. Limits are placed on `duration`
582
- * and `framerate` to avoid using too much memory. Recording large canvases
583
- * can easily crash sketches or even web browsers.
584
- *
585
- * The fifth parameter, `callback`, is optional. If a function is passed,
586
- * image files won't be saved by default. The callback function can be used
587
- * to process an array containing the data for each captured frame. The array
588
- * of image data contains a sequence of objects with three properties for each
589
- * frame: `imageData`, `filename`, and `extension`.
590
- *
591
- * Note: Frames are downloaded as individual image files by default.
592
- *
593
- * @method saveFrames
594
- * @param {String} filename prefix of file name.
595
- * @param {String} extension file extension, either 'jpg' or 'png'.
596
- * @param {Number} duration duration in seconds to record. This parameter will be constrained to be less or equal to 15.
597
- * @param {Number} framerate number of frames to save per second. This parameter will be constrained to be less or equal to 22.
598
- * @param {function(Array)} [callback] callback function that will be executed
599
- to handle the image data. This function
600
- should accept an array as argument. The
601
- array will contain the specified number of
602
- frames of objects. Each object has three
603
- properties: `imageData`, `filename`, and `extension`.
604
- * @example
605
- * <div>
606
- * <code>
607
- * function setup() {
608
- * createCanvas(100, 100);
609
- *
610
- * describe('A square repeatedly changes color from blue to pink.');
611
- * }
612
- *
613
- * function draw() {
614
- * let r = frameCount % 255;
615
- * let g = 50;
616
- * let b = 100;
617
- * background(r, g, b);
618
- * }
619
- *
620
- * // Save the frames when the user presses the 's' key.
621
- * function keyPressed() {
622
- * if (key === 's') {
623
- * saveFrames('frame', 'png', 1, 5);
624
- * }
625
- * }
626
- * </code>
627
- * </div>
628
- *
629
- * <div>
630
- * <code>
631
- * function setup() {
632
- * createCanvas(100, 100);
633
- *
634
- * describe('A square repeatedly changes color from blue to pink.');
635
- * }
636
- *
637
- * function draw() {
638
- * let r = frameCount % 255;
639
- * let g = 50;
640
- * let b = 100;
641
- * background(r, g, b);
642
- * }
643
- *
644
- * // Print 5 frames when the user presses the mouse.
645
- * function mousePressed() {
646
- * saveFrames('frame', 'png', 1, 5, printFrames);
647
- * }
648
- *
649
- * // Prints an array of objects containing raw image data, filenames, and extensions.
650
- * function printFrames(frames) {
651
- * for (let frame of frames) {
652
- * print(frame);
653
- * }
654
- * }
655
- * </code>
656
- * </div>
657
- */
658
- fn.saveFrames = function(fName, ext, _duration, _fps, callback) {
659
- // p5._validateParameters('saveFrames', arguments);
660
- let duration = _duration || 3;
661
- duration = Math.max(Math.min(duration, 15), 0);
662
- duration = duration * 1000;
663
- let fps = _fps || 15;
664
- fps = Math.max(Math.min(fps, 22), 0);
665
- let count = 0;
666
-
667
- const makeFrame = fn._makeFrame;
668
- const cnv = this._curElement.elt;
669
- let frames = [];
670
- const frameFactory = setInterval(() => {
671
- frames.push(makeFrame(fName + count, ext, cnv));
672
- count++;
673
- }, 1000 / fps);
674
-
675
- setTimeout(() => {
676
- clearInterval(frameFactory);
677
- if (callback) {
678
- callback(frames);
679
- } else {
680
- for (const f of frames) {
681
- fn.downloadFile(f.imageData, f.filename, f.ext);
682
- }
683
- }
684
- frames = []; // clear frames
685
- }, duration + 0.01);
686
- };
687
-
688
- fn._makeFrame = function(filename, extension, _cnv) {
689
- let cnv;
690
- if (this) {
691
- cnv = this._curElement.elt;
692
- } else {
693
- cnv = _cnv;
694
- }
695
- let mimeType;
696
- if (!extension) {
697
- extension = 'png';
698
- mimeType = 'image/png';
699
- } else {
700
- switch (extension.toLowerCase()) {
701
- case 'png':
702
- mimeType = 'image/png';
703
- break;
704
- case 'jpeg':
705
- mimeType = 'image/jpeg';
706
- break;
707
- case 'jpg':
708
- mimeType = 'image/jpeg';
709
- break;
710
- default:
711
- mimeType = 'image/png';
712
- break;
713
- }
714
- }
715
- const downloadMime = 'image/octet-stream';
716
- let imageData = cnv.toDataURL(mimeType);
717
- imageData = imageData.replace(mimeType, downloadMime);
718
-
719
- const thisFrame = {};
720
- thisFrame.imageData = imageData;
721
- thisFrame.filename = filename;
722
- thisFrame.ext = extension;
723
- return thisFrame;
724
- };
725
- }
726
-
727
- export default image;
728
-
729
- if(typeof p5 !== 'undefined'){
730
- image(p5, p5.prototype);
731
- }