picrate 2.0.0.pre-java → 2.2.0-java

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -1
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +1 -1
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/CHANGELOG.md +10 -0
  6. data/README.md +11 -9
  7. data/Rakefile +9 -8
  8. data/docs/_config.yml +1 -1
  9. data/docs/_editors/geany.md +1 -0
  10. data/docs/_gems/gems/gems.md +1 -1
  11. data/docs/_methods/alternative_methods.md +2 -1
  12. data/docs/_posts/2018-05-06-getting_started.md +4 -4
  13. data/docs/_posts/2018-05-06-install_jruby.md +5 -11
  14. data/docs/_posts/2018-05-11-arch-linux-arm.md +1 -11
  15. data/docs/_posts/2018-11-18-building-gem.md +4 -2
  16. data/docs/_posts/2018-11-27-getting_started_geany.md +1 -1
  17. data/docs/_posts/2019-11-11-getting_started_buster.md +4 -7
  18. data/docs/_posts/{2018-06-26-auto_install_picrate.md → 2020-03-09-auto_install_picrate.md} +9 -6
  19. data/docs/_posts/2020-05-11-getting_started_manjaro.md +106 -0
  20. data/docs/about.md +1 -1
  21. data/lib/picrate.rb +2 -1
  22. data/lib/picrate/app.rb +1 -0
  23. data/lib/picrate/helper_methods.rb +1 -1
  24. data/lib/picrate/native_folder.rb +6 -7
  25. data/lib/picrate/runner.rb +4 -4
  26. data/lib/picrate/version.rb +1 -1
  27. data/library/jcomplex/jcomplex.rb +1 -0
  28. data/mvnw +2 -2
  29. data/mvnw.cmd +2 -2
  30. data/picrate.gemspec +3 -5
  31. data/pom.rb +18 -15
  32. data/pom.xml +20 -8
  33. data/src/main/java/monkstone/complex/JComplex.java +252 -0
  34. data/src/main/java/processing/awt/PGraphicsJava2D.java +22 -23
  35. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  36. data/src/main/java/processing/awt/ShimAWT.java +545 -0
  37. data/src/main/java/processing/core/PApplet.java +2030 -2556
  38. data/src/main/java/processing/core/PGraphics.java +138 -124
  39. data/src/main/java/processing/core/PImage.java +1517 -1702
  40. data/src/main/java/processing/core/PSurface.java +105 -139
  41. data/src/main/java/processing/core/PSurfaceNone.java +29 -0
  42. data/src/main/java/processing/opengl/PGL.java +649 -3699
  43. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +223 -184
  44. data/src/main/java/processing/opengl/PJOGL.java +374 -1526
  45. data/src/main/java/processing/opengl/PShapeOpenGL.java +5 -6
  46. data/src/main/java/processing/opengl/PSurfaceJOGL.java +220 -86
  47. data/vendors/Rakefile +33 -21
  48. data/vendors/{picrate_sketches.geany → geany.rb} +32 -7
  49. metadata +17 -48
  50. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  51. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  52. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  53. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -1,6 +1,6 @@
1
1
  /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
2
 
3
- /*
3
+ /*
4
4
  Part of the Processing project - http://processing.org
5
5
 
6
6
  Copyright (c) 2004-14 Ben Fry and Casey Reas
@@ -20,36 +20,37 @@
20
20
  Public License along with this library; if not, write to the
21
21
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22
22
  Boston, MA 02111-1307 USA
23
- */
23
+ */
24
+
24
25
  package processing.core;
25
26
 
26
- import java.awt.*;
27
- import java.awt.image.*;
28
- import java.io.*;
29
- import java.util.Iterator;
27
+ import java.io.BufferedOutputStream;
28
+ import java.io.File;
29
+ import java.io.FileOutputStream;
30
+ import java.io.IOException;
31
+ import java.io.InputStream;
32
+ import java.io.OutputStream;
30
33
 
31
- import javax.imageio.*;
32
- import javax.imageio.metadata.*;
33
34
 
34
35
  /**
35
- * ( begin auto-generated from PImage.xml )
36
- *
37
- * Datatype for storing images. Processing can display <b>.gif</b>,
38
- * <b>.jpg</b>, <b>.tga</b>, and <b>.png</b> images. Images may be displayed in
39
- * 2D and 3D space. Before an image is used, it must be loaded with the
40
- * <b>loadImage()</b> function. The <b>PImage</b> class contains fields for the
41
- * <b>width</b> and <b>height</b> of the image, as well as an array called
42
- * <b>pixels[]</b> that contains the values for every pixel in the image. The
43
- * methods described below allow easy access to the image's pixels and alpha
44
- * channel and simplify the process of compositing.
45
- * using the <b>pixels[]</b> array, be sure to use the
46
- * <b>loadPixels()</b> method on the image to make sure that the pixel data is
47
- * properly loaded.
48
- * create a new image, use the <b>createImage()</b> function. Do not use
49
- * the syntax <b>new PImage()</b>.
50
- *
51
- * ( end auto-generated )
52
- *
36
+ * ( begin auto-generated from PImage.xml )
37
+ *
38
+ * Datatype for storing images. Processing can display <b>.gif</b>,
39
+ * <b>.jpg</b>, <b>.tga</b>, and <b>.png</b> images. Images may be
40
+ * displayed in 2D and 3D space. Before an image is used, it must be loaded
41
+ * with the <b>loadImage()</b> function. The <b>PImage</b> class contains
42
+ * fields for the <b>width</b> and <b>height</b> of the image, as well as
43
+ * an array called <b>pixels[]</b> that contains the values for every pixel
44
+ * in the image. The methods described below allow easy access to the
45
+ * image's pixels and alpha channel and simplify the process of compositing.
46
+ * using the <b>pixels[]</b> array, be sure to use the
47
+ * <b>loadPixels()</b> method on the image to make sure that the pixel data
48
+ * is properly loaded.
49
+ * create a new image, use the <b>createImage()</b> function. Do not
50
+ * use the syntax <b>new PImage()</b>.
51
+ *
52
+ * ( end auto-generated )
53
+ *
53
54
  * @webref image
54
55
  * @usage Web &amp; Application
55
56
  * @instanceName pimg any object of type PImage
@@ -59,51 +60,55 @@ import javax.imageio.metadata.*;
59
60
  */
60
61
  public class PImage implements PConstants, Cloneable {
61
62
 
63
+ private static final byte TIFF_HEADER[] = {
64
+ 77, 77, 0, 42, 0, 0, 0, 8, 0, 9, 0, -2, 0, 4, 0, 0, 0, 1, 0, 0,
65
+ 0, 0, 1, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 3, 0, 0, 0, 1,
66
+ 0, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 122, 1, 6, 0, 3, 0,
67
+ 0, 0, 1, 0, 2, 0, 0, 1, 17, 0, 4, 0, 0, 0, 1, 0, 0, 3, 0, 1, 21,
68
+ 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 1, 22, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0,
69
+ 1, 23, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8
70
+ };
71
+
72
+ private static final String TIFF_ERROR = "Error: Processing can only read its own TIFF files.";
73
+
62
74
  /**
63
- * Format for this image, one of RGB, ARGB or ALPHA. note that RGB images
64
- * still require 0xff in the high byte because of how they'll be manipulated
65
- * by other functions
75
+ * Format for this image, one of RGB, ARGB or ALPHA.
76
+ * note that RGB images still require 0xff in the high byte
77
+ * because of how they'll be manipulated by other functions
66
78
  */
67
79
  public int format;
68
80
 
69
81
  /**
70
82
  * ( begin auto-generated from pixels.xml )
71
83
  *
72
- * Array containing the values for all the pixels in the display window. These
73
- * values are of the color datatype. This array is the size of the display
74
- * window. For example, if the image is 100x100 pixels, there will be 10000
75
- * values and if the window is 200x300 pixels, there will be 60000 values. The
76
- * <b>index</b> value defines the position of a value within the array. For
77
- * example, the statement <b>color b = pixels[230]</b> will set the variable
78
- * <b>b</b> to be equal to the value at that location in the array.
79
- *
84
+ * Array containing the values for all the pixels in the display window.
85
+ * These values are of the color datatype. This array is the size of the
86
+ * display window. For example, if the image is 100x100 pixels, there will
87
+ * be 10000 values and if the window is 200x300 pixels, there will be 60000
88
+ * values. The <b>index</b> value defines the position of a value within
89
+ * the array. For example, the statement <b>color b = pixels[230]</b> will
90
+ * set the variable <b>b</b> to be equal to the value at that location in
91
+ * the array.
92
+ *
80
93
  * Before accessing this array, the data must loaded with the
81
- * <b>loadPixels()</b> function. After the array data has been modified, the
82
- * <b>updatePixels()</b> function must be run to update the changes. Without
83
- * <b>loadPixels()</b>, running the code may (or will in future releases)
84
- * result in a NullPointerException.
94
+ * <b>loadPixels()</b> function. After the array data has been modified,
95
+ * the <b>updatePixels()</b> function must be run to update the changes.
96
+ * Without <b>loadPixels()</b>, running the code may (or will in future
97
+ * releases) result in a NullPointerException.
85
98
  *
86
99
  * ( end auto-generated )
87
100
  *
88
101
  * @webref image:pixels
89
102
  * @usage web_application
90
- * @brief Array containing the color of every pixel in the image
103
+ * @brief Array containing the color of every pixel in the image
91
104
  */
92
105
  public int[] pixels;
93
106
 
94
- /**
95
- * 1 for most images, 2 for hi-dpi/retina
96
- */
107
+ /** 1 for most images, 2 for hi-dpi/retina */
97
108
  public int pixelDensity = 1;
98
109
 
99
- /**
100
- * Actual dimensions of pixels array, taking into account the 2x setting.
101
- */
110
+ /** Actual dimensions of pixels array, taking into account the 2x setting. */
102
111
  public int pixelWidth;
103
-
104
- /**
105
- *
106
- */
107
112
  public int pixelHeight;
108
113
 
109
114
  /**
@@ -112,10 +117,9 @@ public class PImage implements PConstants, Cloneable {
112
117
  * The width of the image in units of pixels.
113
118
  *
114
119
  * ( end auto-generated )
115
- *
116
120
  * @webref pimage:field
117
121
  * @usage web_application
118
- * @brief Image width
122
+ * @brief Image width
119
123
  */
120
124
  public int width;
121
125
 
@@ -125,48 +129,32 @@ public class PImage implements PConstants, Cloneable {
125
129
  * The height of the image in units of pixels.
126
130
  *
127
131
  * ( end auto-generated )
128
- *
129
132
  * @webref pimage:field
130
133
  * @usage web_application
131
- * @brief Image height
134
+ * @brief Image height
132
135
  */
133
136
  public int height;
134
137
 
135
138
  /**
136
- * Path to parent object that will be used with save(). This prevents users
137
- * from needing savePath() to use PImage.save().
139
+ * Path to parent object that will be used with save().
140
+ * This prevents users from needing savePath() to use PImage.save().
138
141
  */
139
142
  public PApplet parent;
140
143
 
144
+
141
145
  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
142
- /**
143
- * modified portion of the image
144
- */
145
- protected boolean modified;
146
146
 
147
- /**
148
- *
149
- */
150
- protected int mx1,
151
- /**
152
- *
153
- */
154
- my1,
155
- /**
156
- *
157
- */
158
- mx2,
159
- /**
160
- *
161
- */
162
- my2;
163
147
 
164
- /**
165
- * Loaded pixels flag
166
- */
148
+ /** modified portion of the image */
149
+ protected boolean modified;
150
+ protected int mx1, my1, mx2, my2;
151
+
152
+ /** Loaded pixels flag */
167
153
  public boolean loaded = false;
168
154
 
169
155
  // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
156
+
157
+
170
158
  // private fields
171
159
  private int fracU, ifU, fracV, ifV, u1, u2, v1, v2, sX, sY, iw, iw1, ih1;
172
160
  private int ul, ll, ur, lr, cUL, cLL, cUR, cLR;
@@ -177,9 +165,9 @@ public class PImage implements PConstants, Cloneable {
177
165
  // fixed point precision is limited to 15 bits!!
178
166
  static final int PRECISIONB = 15;
179
167
  static final int PRECISIONF = 1 << PRECISIONB;
180
- static final int PREC_MAXVAL = PRECISIONF - 1;
181
- static final int PREC_ALPHA_SHIFT = 24 - PRECISIONB;
182
- static final int PREC_RED_SHIFT = 16 - PRECISIONB;
168
+ static final int PREC_MAXVAL = PRECISIONF-1;
169
+ static final int PREC_ALPHA_SHIFT = 24-PRECISIONB;
170
+ static final int PREC_RED_SHIFT = 16-PRECISIONB;
183
171
 
184
172
  // internal kernel stuff for the gaussian blur filter
185
173
  private int blurRadius;
@@ -188,46 +176,35 @@ public class PImage implements PConstants, Cloneable {
188
176
  private int[][] blurMult;
189
177
 
190
178
  // colour component bitmasks (moved from PConstants in 2.0b7)
191
- /**
192
- *
193
- */
194
179
  public static final int ALPHA_MASK = 0xff000000;
195
-
196
- /**
197
- *
198
- */
199
- public static final int RED_MASK = 0x00ff0000;
200
-
201
- /**
202
- *
203
- */
180
+ public static final int RED_MASK = 0x00ff0000;
204
181
  public static final int GREEN_MASK = 0x0000ff00;
182
+ public static final int BLUE_MASK = 0x000000ff;
205
183
 
206
- /**
207
- *
208
- */
209
- public static final int BLUE_MASK = 0x000000ff;
210
184
 
211
185
  //////////////////////////////////////////////////////////////
186
+
187
+
212
188
  /**
213
189
  * ( begin auto-generated from PImage.xml )
214
190
  *
215
191
  * Datatype for storing images. Processing can display <b>.gif</b>,
216
- * <b>.jpg</b>, <b>.tga</b>, and <b>.png</b> images. Images may be displayed
217
- * in 2D and 3D space. Before an image is used, it must be loaded with the
218
- * <b>loadImage()</b> function. The <b>PImage</b> object contains fields for
219
- * the <b>width</b> and <b>height</b> of the image, as well as an array called
220
- * <b>pixels[]</b> which contains the values for every pixel in the image. A
221
- * group of methods, described below, allow easy access to the image's pixels
222
- * and alpha channel and simplify the process of compositing.
223
- *
192
+ * <b>.jpg</b>, <b>.tga</b>, and <b>.png</b> images. Images may be
193
+ * displayed in 2D and 3D space. Before an image is used, it must be loaded
194
+ * with the <b>loadImage()</b> function. The <b>PImage</b> object contains
195
+ * fields for the <b>width</b> and <b>height</b> of the image, as well as
196
+ * an array called <b>pixels[]</b> which contains the values for every
197
+ * pixel in the image. A group of methods, described below, allow easy
198
+ * access to the image's pixels and alpha channel and simplify the process
199
+ * of compositing.
200
+ *
224
201
  * Before using the <b>pixels[]</b> array, be sure to use the
225
- * <b>loadPixels()</b> method on the image to make sure that the pixel data is
226
- * properly loaded.
227
- *
228
- * To create a new image, use the <b>createImage()</b> function (do not use
229
- * <b>new PImage()</b>). ( end auto-generated )
202
+ * <b>loadPixels()</b> method on the image to make sure that the pixel data
203
+ * is properly loaded.
230
204
  *
205
+ * To create a new image, use the <b>createImage()</b> function (do not use
206
+ * <b>new PImage()</b>).
207
+ * ( end auto-generated )
231
208
  * @nowebref
232
209
  * @usage web_application
233
210
  * @see PApplet#loadImage(String, String)
@@ -239,8 +216,10 @@ public class PImage implements PConstants, Cloneable {
239
216
  pixelDensity = 1;
240
217
  }
241
218
 
219
+
242
220
  /**
243
- * @nowebref @param width image width
221
+ * @nowebref
222
+ * @param width image width
244
223
  * @param height image height
245
224
  */
246
225
  public PImage(int width, int height) {
@@ -256,9 +235,8 @@ public class PImage implements PConstants, Cloneable {
256
235
  // toxi: agreed and same reasons why i left it out ;)
257
236
  }
258
237
 
238
+
259
239
  /**
260
- * @param width
261
- * @param height
262
240
  * @nowebref
263
241
  * @param format Either RGB, ARGB, ALPHA (grayscale alpha channel)
264
242
  */
@@ -266,39 +244,26 @@ public class PImage implements PConstants, Cloneable {
266
244
  init(width, height, format, 1);
267
245
  }
268
246
 
269
- /**
270
- *
271
- * @param width
272
- * @param height
273
- * @param format
274
- * @param factor
275
- */
247
+
276
248
  public PImage(int width, int height, int format, int factor) {
277
249
  init(width, height, format, factor);
278
250
  }
279
251
 
252
+
280
253
  /**
281
254
  * Do not remove, see notes in the other variant.
282
- *
283
- * @param width
284
- * @param height
285
- * @param format
286
255
  */
287
256
  public void init(int width, int height, int format) { // ignore
288
257
  init(width, height, format, 1);
289
258
  }
290
259
 
260
+
291
261
  /**
292
- * Function to be used by subclasses of PImage to init later than at the
293
- * constructor, or re-init later when things changes. Used by Capture and
294
- * Movie classes (and perhaps others), because the width/height will not be
295
- * known when super() is called. (Leave this public so that other libraries
296
- * can do the same.)
297
- *
298
- * @param width
299
- * @param factor
300
- * @param height
301
- * @param format
262
+ * Function to be used by subclasses of PImage to init later than
263
+ * at the constructor, or re-init later when things changes.
264
+ * Used by Capture and Movie classes (and perhaps others),
265
+ * because the width/height will not be known when super() is called.
266
+ * (Leave this public so that other libraries can do the same.)
302
267
  */
303
268
  public void init(int width, int height, int format, int factor) { // ignore
304
269
  this.width = width;
@@ -311,13 +276,12 @@ public class PImage implements PConstants, Cloneable {
311
276
  this.pixels = new int[pixelWidth * pixelHeight];
312
277
  }
313
278
 
279
+
314
280
  /**
315
281
  * Check the alpha on an image, using a really primitive loop.
316
282
  */
317
- protected void checkAlpha() {
318
- if (pixels == null) {
319
- return;
320
- }
283
+ public void checkAlpha() {
284
+ if (pixels == null) return;
321
285
 
322
286
  for (int i = 0; i < pixels.length; i++) {
323
287
  // since transparency is often at corners, hopefully this
@@ -329,101 +293,60 @@ public class PImage implements PConstants, Cloneable {
329
293
  }
330
294
  }
331
295
 
296
+
332
297
  //////////////////////////////////////////////////////////////
333
- /**
334
- * Construct a new PImage from a java.awt.Image. This constructor assumes that
335
- * you've done the work of making sure a MediaTracker has been used to fully
336
- * download the data and that the img is valid.
337
- *
338
- * @nowebref
339
- * @param img assumes a MediaTracker has been used to fully download the data
340
- * and the img is valid
341
- */
342
- public PImage(Image img) {
343
- format = RGB;
344
- if (img instanceof BufferedImage) {
345
- BufferedImage bi = (BufferedImage) img;
346
- width = bi.getWidth();
347
- height = bi.getHeight();
348
- int type = bi.getType();
349
- if (type == BufferedImage.TYPE_3BYTE_BGR
350
- || type == BufferedImage.TYPE_4BYTE_ABGR) {
351
- pixels = new int[width * height];
352
- bi.getRGB(0, 0, width, height, pixels, 0, width);
353
- if (type == BufferedImage.TYPE_4BYTE_ABGR) {
354
- format = ARGB;
355
- } else {
356
- opaque();
357
- }
358
- } else {
359
- DataBuffer db = bi.getRaster().getDataBuffer();
360
- if (db instanceof DataBufferInt) {
361
- pixels = ((DataBufferInt) db).getData();
362
- if (type == BufferedImage.TYPE_INT_ARGB) {
363
- format = ARGB;
364
- } else if (type == BufferedImage.TYPE_INT_RGB) {
365
- opaque();
366
- }
367
- }
368
- }
298
+
299
+ public PImage(int width, int height, int[] pixels, boolean requiresCheckAlpha, PApplet parent) {
300
+ initFromPixels(
301
+ width,
302
+ height,
303
+ pixels,
304
+ RGB,
305
+ 1
306
+ );
307
+
308
+ this.parent = parent;
309
+
310
+ if (requiresCheckAlpha) {
311
+ checkAlpha();
369
312
  }
370
- // Implements fall-through if not DataBufferInt above, or not a
371
- // known type, or not DataBufferInt for the data itself.
372
- if (pixels == null) { // go the old school Java 1.0 route
373
- width = img.getWidth(null);
374
- height = img.getHeight(null);
375
- pixels = new int[width * height];
376
- PixelGrabber pg
377
- = new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
378
- try {
379
- pg.grabPixels();
380
- } catch (InterruptedException e) {
381
- }
313
+ }
314
+
315
+ public PImage(int width, int height, int[] pixels, boolean requiresCheckAlpha, PApplet parent,
316
+ int format, int factor) {
317
+
318
+ initFromPixels(width, height, pixels, format, factor);
319
+ this.parent = parent;
320
+
321
+ if (requiresCheckAlpha) {
322
+ checkAlpha();
382
323
  }
383
- pixelDensity = 1;
384
- pixelWidth = width;
385
- pixelHeight = height;
386
324
  }
387
325
 
388
- /**
389
- * Use the getNative() method instead, which allows library interfaces to be
390
- * written in a cross-platform fashion for desktop, Android, and others. This
391
- * is still included for PGraphics objects, which may need the image.
392
- *
393
- * @return
394
- */
395
- public Image getImage() { // ignore
396
- return (Image) getNative();
326
+ private void initFromPixels(int width, int height, int[] pixels, int format, int factor) {
327
+ this.width = width;
328
+ this.height = height;
329
+ this.format = format;
330
+ this.pixelDensity = factor;
331
+ this.pixels = pixels;
397
332
  }
398
333
 
399
- /**
400
- * Returns a native BufferedImage from this PImage.
401
- *
402
- * @return
403
- */
334
+
404
335
  public Object getNative() { // ignore
405
- loadPixels();
406
- int type = (format == RGB)
407
- ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
408
- BufferedImage image = new BufferedImage(pixelWidth, pixelHeight, type);
409
- WritableRaster wr = image.getRaster();
410
- wr.setDataElements(0, 0, pixelWidth, pixelHeight, pixels);
411
- return image;
336
+ return null;
412
337
  }
413
338
 
339
+
414
340
  //////////////////////////////////////////////////////////////
341
+
415
342
  // MARKING IMAGE AS MODIFIED / FOR USE w/ GET/SET
416
- /**
417
- *
418
- * @return
419
- */
343
+
344
+
420
345
  public boolean isModified() { // ignore
421
346
  return modified;
422
347
  }
423
348
 
424
- /**
425
- *
426
- */
349
+
427
350
  public void setModified() { // ignore
428
351
  modified = true;
429
352
  mx1 = 0;
@@ -432,86 +355,70 @@ public class PImage implements PConstants, Cloneable {
432
355
  my2 = pixelHeight;
433
356
  }
434
357
 
435
- /**
436
- *
437
- * @param m
438
- */
358
+
439
359
  public void setModified(boolean m) { // ignore
440
360
  modified = m;
441
361
  }
442
362
 
443
- /**
444
- *
445
- * @return
446
- */
363
+
447
364
  public int getModifiedX1() { // ignore
448
365
  return mx1;
449
366
  }
450
367
 
451
- /**
452
- *
453
- * @return
454
- */
368
+
455
369
  public int getModifiedX2() { // ignore
456
370
  return mx2;
457
371
  }
458
372
 
459
- /**
460
- *
461
- * @return
462
- */
373
+
463
374
  public int getModifiedY1() { // ignore
464
375
  return my1;
465
376
  }
466
377
 
467
- /**
468
- *
469
- * @return
470
- */
378
+
471
379
  public int getModifiedY2() { // ignore
472
380
  return my2;
473
381
  }
474
382
 
383
+
475
384
  /**
476
385
  * ( begin auto-generated from PImage_loadPixels.xml )
477
386
  *
478
387
  * Loads the pixel data for the image into its <b>pixels[]</b> array. This
479
- * function must always be called before reading from or writing to
480
- * <b>pixels[]</b>.
388
+ * function must always be called before reading from or writing to <b>pixels[]</b>.
481
389
  * renderers may or may not seem to require <b>loadPixels()</b>
482
390
  * or <b>updatePixels()</b>. However, the rule is that any time you want to
483
391
  * manipulate the <b>pixels[]</b> array, you must first call
484
392
  * <b>loadPixels()</b>, and after changes have been made, call
485
393
  * <b>updatePixels()</b>. Even if the renderer may not seem to use this
486
- * function in the current Processing release, this will always be subject to
487
- * change.
394
+ * function in the current Processing release, this will always be subject
395
+ * to change.
488
396
  *
489
397
  * ( end auto-generated )
490
398
  *
491
399
  * <h3>Advanced</h3>
492
400
  * Call this when you want to mess with the pixels[] array.
493
401
  *
494
- * For subclasses where the pixels[] buffer isn't set by default, this should
495
- * copy all data into the pixels[] array
402
+ * For subclasses where the pixels[] buffer isn't set by default,
403
+ * this should copy all data into the pixels[] array
496
404
  *
497
405
  * @webref pimage:pixels
498
406
  * @brief Loads the pixel data for the image into its pixels[] array
499
407
  * @usage web_application
500
408
  */
501
409
  public void loadPixels() { // ignore
502
- if (pixels == null || pixels.length != pixelWidth * pixelHeight) {
503
- pixels = new int[pixelWidth * pixelHeight];
410
+ if (pixels == null || pixels.length != pixelWidth*pixelHeight) {
411
+ pixels = new int[pixelWidth*pixelHeight];
504
412
  }
505
413
  setLoaded();
506
414
  }
507
415
 
508
- /**
509
- *
510
- */
416
+
511
417
  public void updatePixels() { // ignore
512
418
  updatePixels(0, 0, pixelWidth, pixelHeight);
513
419
  }
514
420
 
421
+
515
422
  /**
516
423
  * ( begin auto-generated from PImage_updatePixels.xml )
517
424
  *
@@ -523,18 +430,18 @@ public class PImage implements PConstants, Cloneable {
523
430
  * manipulate the <b>pixels[]</b> array, you must first call
524
431
  * <b>loadPixels()</b>, and after changes have been made, call
525
432
  * <b>updatePixels()</b>. Even if the renderer may not seem to use this
526
- * function in the current Processing release, this will always be subject to
527
- * change.
528
- *
433
+ * function in the current Processing release, this will always be subject
434
+ * to change.
435
+ *
529
436
  * Currently, none of the renderers use the additional parameters to
530
437
  * <b>updatePixels()</b>, however this may be implemented in the future.
531
438
  *
532
439
  * ( end auto-generated )
533
440
  * <h3>Advanced</h3>
534
- * Mark the pixels in this region as needing an update. This is not currently
535
- * used by any of the renderers, however the api is structured this way in the
536
- * hope of being able to use this to speed things up in the future.
537
- *
441
+ * Mark the pixels in this region as needing an update.
442
+ * This is not currently used by any of the renderers, however the api
443
+ * is structured this way in the hope of being able to use this to
444
+ * speed things up in the future.
538
445
  * @webref pimage:pixels
539
446
  * @brief Updates the image with the data in its pixels[] array
540
447
  * @usage web_application
@@ -555,51 +462,38 @@ public class PImage implements PConstants, Cloneable {
555
462
  modified = true;
556
463
 
557
464
  } else {
558
- if (x < mx1) {
559
- mx1 = PApplet.max(0, x);
560
- }
561
- if (x > mx2) {
562
- mx2 = PApplet.min(pixelWidth, x);
563
- }
564
- if (y < my1) {
565
- my1 = PApplet.max(0, y);
566
- }
567
- if (y > my2) {
568
- my2 = PApplet.min(pixelHeight, y);
569
- }
465
+ if (x < mx1) mx1 = PApplet.max(0, x);
466
+ if (x > mx2) mx2 = PApplet.min(pixelWidth, x);
467
+ if (y < my1) my1 = PApplet.max(0, y);
468
+ if (y > my2) my2 = PApplet.min(pixelHeight, y);
570
469
 
571
- if (x2 < mx1) {
572
- mx1 = PApplet.max(0, x2);
573
- }
574
- if (x2 > mx2) {
575
- mx2 = PApplet.min(pixelWidth, x2);
576
- }
577
- if (y2 < my1) {
578
- my1 = PApplet.max(0, y2);
579
- }
580
- if (y2 > my2) {
581
- my2 = PApplet.min(pixelHeight, y2);
582
- }
470
+ if (x2 < mx1) mx1 = PApplet.max(0, x2);
471
+ if (x2 > mx2) mx2 = PApplet.min(pixelWidth, x2);
472
+ if (y2 < my1) my1 = PApplet.max(0, y2);
473
+ if (y2 > my2) my2 = PApplet.min(pixelHeight, y2);
583
474
  }
584
475
  }
585
476
 
477
+
586
478
  //////////////////////////////////////////////////////////////
479
+
587
480
  // COPYING IMAGE DATA
481
+
482
+
588
483
  /**
589
- * Duplicate an image, returns new PImage object. The pixels[] array for the
590
- * new object will be unique and recopied from the source image. This is
591
- * implemented as an override of Object.clone(). We recommend using get()
592
- * instead, because it prevents you from needing to catch the
484
+ * Duplicate an image, returns new PImage object.
485
+ * The pixels[] array for the new object will be unique
486
+ * and recopied from the source image. This is implemented as an
487
+ * override of Object.clone(). We recommend using get() instead,
488
+ * because it prevents you from needing to catch the
593
489
  * CloneNotSupportedException, and from doing a cast from the result.
594
- *
595
- * @return
596
- * @throws java.lang.CloneNotSupportedException
597
490
  */
598
491
  @Override
599
492
  public Object clone() throws CloneNotSupportedException { // ignore
600
493
  return get();
601
494
  }
602
495
 
496
+
603
497
  /**
604
498
  * ( begin auto-generated from PImage_resize.xml )
605
499
  *
@@ -607,16 +501,15 @@ public class PImage implements PConstants, Cloneable {
607
501
  * proportionally, use 0 as the value for the <b>wide</b> or <b>high</b>
608
502
  * parameter. For instance, to make the width of an image 150 pixels, and
609
503
  * change the height using the same proportion, use resize(150, 0).
610
- *
504
+ *
611
505
  * Even though a PGraphics is technically a PImage, it is not possible to
612
- * rescale the image data found in a PGraphics. (It's simply not possible to
613
- * do this consistently across renderers: technically infeasible with P3D, or
614
- * what would it even do with PDF?) If you want to resize PGraphics content,
615
- * first get a copy of its image data using the <b>get()</b>
506
+ * rescale the image data found in a PGraphics. (It's simply not possible
507
+ * to do this consistently across renderers: technically infeasible with
508
+ * P3D, or what would it even do with PDF?) If you want to resize PGraphics
509
+ * content, first get a copy of its image data using the <b>get()</b>
616
510
  * method, and call <b>resize()</b> on the PImage that is returned.
617
511
  *
618
512
  * ( end auto-generated )
619
- *
620
513
  * @webref pimage:method
621
514
  * @brief Changes the size of an image to a new width and height
622
515
  * @usage web_application
@@ -625,174 +518,77 @@ public class PImage implements PConstants, Cloneable {
625
518
  * @see PImage#get(int, int, int, int)
626
519
  */
627
520
  public void resize(int w, int h) { // ignore
628
- if (w <= 0 && h <= 0) {
629
- throw new IllegalArgumentException("width or height must be > 0 for resize");
630
- }
631
-
632
- if (w == 0) { // Use height to determine relative size
633
- float diff = (float) h / (float) height;
634
- w = (int) (width * diff);
635
- } else if (h == 0) { // Use the width to determine relative size
636
- float diff = (float) w / (float) width;
637
- h = (int) (height * diff);
638
- }
639
-
640
- BufferedImage img
641
- = shrinkImage((BufferedImage) getNative(), w * pixelDensity, h * pixelDensity);
642
-
643
- PImage temp = new PImage(img);
644
- this.pixelWidth = temp.width;
645
- this.pixelHeight = temp.height;
646
-
647
- // Get the resized pixel array
648
- this.pixels = temp.pixels;
649
-
650
- this.width = pixelWidth / pixelDensity;
651
- this.height = pixelHeight / pixelDensity;
652
-
653
- // Mark the pixels array as altered
654
- updatePixels();
521
+ throw new RuntimeException("resize() not implemented for this PImage type");
655
522
  }
656
523
 
657
- // Adapted from getFasterScaledInstance() method from page 111 of
658
- // "Filthy Rich Clients" by Chet Haase and Romain Guy
659
- // Additional modifications and simplifications have been added,
660
- // plus a fix to deal with an infinite loop if images are expanded.
661
- // http://code.google.com/p/processing/issues/detail?id=1463
662
- static private BufferedImage shrinkImage(BufferedImage img,
663
- int targetWidth, int targetHeight) {
664
- int type = (img.getTransparency() == Transparency.OPAQUE)
665
- ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
666
- BufferedImage outgoing = img;
667
- BufferedImage scratchImage = null;
668
- Graphics2D g2 = null;
669
- int prevW = outgoing.getWidth();
670
- int prevH = outgoing.getHeight();
671
- boolean isTranslucent = img.getTransparency() != Transparency.OPAQUE;
672
-
673
- // Use multi-step technique: start with original size, then scale down in
674
- // multiple passes with drawImage() until the target size is reached
675
- int w = img.getWidth();
676
- int h = img.getHeight();
677
-
678
- do {
679
- if (w > targetWidth) {
680
- w /= 2;
681
- // if this is the last step, do the exact size
682
- if (w < targetWidth) {
683
- w = targetWidth;
684
- }
685
- } else if (targetWidth >= w) {
686
- w = targetWidth;
687
- }
688
- if (h > targetHeight) {
689
- h /= 2;
690
- if (h < targetHeight) {
691
- h = targetHeight;
692
- }
693
- } else if (targetHeight >= h) {
694
- h = targetHeight;
695
- }
696
- if (scratchImage == null || isTranslucent) {
697
- // Use a single scratch buffer for all iterations and then copy
698
- // to the final, correctly-sized image before returning
699
- scratchImage = new BufferedImage(w, h, type);
700
- g2 = scratchImage.createGraphics();
701
- }
702
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
703
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
704
- g2.drawImage(outgoing, 0, 0, w, h, 0, 0, prevW, prevH, null);
705
- prevW = w;
706
- prevH = h;
707
- outgoing = scratchImage;
708
- } while (w != targetWidth || h != targetHeight);
709
-
710
- if (g2 != null) {
711
- g2.dispose();
712
- }
713
-
714
- // If we used a scratch buffer that is larger than our target size,
715
- // create an image of the right size and copy the results into it
716
- if (targetWidth != outgoing.getWidth()
717
- || targetHeight != outgoing.getHeight()) {
718
- scratchImage = new BufferedImage(targetWidth, targetHeight, type);
719
- g2 = scratchImage.createGraphics();
720
- g2.drawImage(outgoing, 0, 0, null);
721
- g2.dispose();
722
- outgoing = scratchImage;
723
- }
724
- return outgoing;
725
- }
726
524
 
727
525
  //////////////////////////////////////////////////////////////
526
+
728
527
  // MARKING IMAGE AS LOADED / FOR USE IN RENDERERS
729
- /**
730
- *
731
- * @return
732
- */
528
+
529
+
733
530
  public boolean isLoaded() { // ignore
734
531
  return loaded;
735
532
  }
736
533
 
737
- /**
738
- *
739
- */
534
+
740
535
  public void setLoaded() { // ignore
741
536
  loaded = true;
742
537
  }
743
538
 
744
- /**
745
- *
746
- * @param l
747
- */
539
+
748
540
  public void setLoaded(boolean l) { // ignore
749
541
  loaded = l;
750
542
  }
751
543
 
544
+
752
545
  //////////////////////////////////////////////////////////////
546
+
753
547
  // GET/SET PIXELS
548
+
549
+
754
550
  /**
755
551
  * ( begin auto-generated from PImage_get.xml )
756
552
  *
757
553
  * Reads the color of any pixel or grabs a section of an image. If no
758
554
  * parameters are specified, the entire image is returned. Use the <b>x</b>
759
- * and <b>y</b> parameters to get the value of one pixel. Get a section of the
760
- * display window by specifying an additional <b>width</b> and
555
+ * and <b>y</b> parameters to get the value of one pixel. Get a section of
556
+ * the display window by specifying an additional <b>width</b> and
761
557
  * <b>height</b> parameter. When getting an image, the <b>x</b> and
762
- * <b>y</b> parameters define the coordinates for the upper-left corner of the
763
- * image, regardless of the current <b>imageMode()</b>.
764
- *
765
- * If the pixel requested is outside of the image window, black is returned.
766
- * The numbers returned are scaled according to the current color ranges, but
767
- * only RGB values are returned by this function. For example, even though you
768
- * may have drawn a shape with <b>colorMode(HSB)</b>, the numbers returned
769
- * will be in RGB format.
770
- *
771
- * Getting the color of a single pixel with <b>get(x, y)</b> is easy, but not
772
- * as fast as grabbing the data directly from <b>pixels[]</b>. The equivalent
773
- * statement to <b>get(x, y)</b> using <b>pixels[]</b> is
774
- * <b>pixels[y*width+x]</b>. See the reference for <b>pixels[]</b> for more
775
- * information.
558
+ * <b>y</b> parameters define the coordinates for the upper-left corner of
559
+ * the image, regardless of the current <b>imageMode()</b>.
560
+ *
561
+ * If the pixel requested is outside of the image window, black is
562
+ * returned. The numbers returned are scaled according to the current color
563
+ * ranges, but only RGB values are returned by this function. For example,
564
+ * even though you may have drawn a shape with <b>colorMode(HSB)</b>, the
565
+ * numbers returned will be in RGB format.
566
+ *
567
+ * Getting the color of a single pixel with <b>get(x, y)</b> is easy, but
568
+ * not as fast as grabbing the data directly from <b>pixels[]</b>. The
569
+ * equivalent statement to <b>get(x, y)</b> using <b>pixels[]</b> is
570
+ * <b>pixels[y*width+x]</b>. See the reference for <b>pixels[]</b> for more information.
776
571
  *
777
572
  * ( end auto-generated )
778
573
  *
779
574
  * <h3>Advanced</h3>
780
- * Returns an ARGB "color" type (a packed 32 bit int with the color. If the
781
- * coordinate is outside the image, zero is returned (black, but completely
782
- * transparent).
575
+ * Returns an ARGB "color" type (a packed 32 bit int with the color.
576
+ * If the coordinate is outside the image, zero is returned
577
+ * (black, but completely transparent).
783
578
  * <P>
784
- * If the image is in RGB format (i.e. on a PVideo object), the value will get
785
- * its high bits set, just to avoid cases where they haven't been set already.
579
+ * If the image is in RGB format (i.e. on a PVideo object),
580
+ * the value will get its high bits set, just to avoid cases where
581
+ * they haven't been set already.
786
582
  * <P>
787
- * If the image is in ALPHA format, this returns a white with its alpha value
788
- * set.
583
+ * If the image is in ALPHA format, this returns a white with its
584
+ * alpha value set.
789
585
  * <P>
790
- * This function is included primarily for beginners. It is quite slow because
791
- * it has to check to see if the x, y that was provided is inside the bounds,
792
- * and then has to check to see what image type it is. If you want things to
793
- * be more efficient, access the pixels[] array directly.
586
+ * This function is included primarily for beginners. It is quite
587
+ * slow because it has to check to see if the x, y that was provided
588
+ * is inside the bounds, and then has to check to see what image
589
+ * type it is. If you want things to be more efficient, access the
590
+ * pixels[] array directly.
794
591
  *
795
- * @return
796
592
  * @webref image:pixels
797
593
  * @brief Reads the color of any pixel or grabs a rectangle of pixels
798
594
  * @usage web_application
@@ -803,29 +599,25 @@ public class PImage implements PConstants, Cloneable {
803
599
  * @see PApplet#copy(PImage, int, int, int, int, int, int, int, int)
804
600
  */
805
601
  public int get(int x, int y) {
806
- if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) {
807
- return 0;
808
- }
602
+ if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) return 0;
809
603
 
810
604
  switch (format) {
811
605
  case RGB:
812
- return pixels[y * pixelWidth + x] | 0xff000000;
606
+ return pixels[y*pixelWidth + x] | 0xff000000;
813
607
 
814
608
  case ARGB:
815
- return pixels[y * pixelWidth + x];
609
+ return pixels[y*pixelWidth + x];
816
610
 
817
611
  case ALPHA:
818
- return (pixels[y * pixelWidth + x] << 24) | 0xffffff;
612
+ return (pixels[y*pixelWidth + x] << 24) | 0xffffff;
819
613
  }
820
614
  return 0;
821
615
  }
822
616
 
617
+
823
618
  /**
824
- * @param x
825
- * @param y
826
619
  * @param w width of pixel rectangle to get
827
620
  * @param h height of pixel rectangle to get
828
- * @return
829
621
  */
830
622
  public PImage get(int x, int y, int w, int h) {
831
623
  int targetX = 0;
@@ -869,8 +661,8 @@ public class PImage implements PConstants, Cloneable {
869
661
  }
870
662
 
871
663
  PImage target = new PImage(targetWidth / pixelDensity,
872
- targetHeight / pixelDensity,
873
- targetFormat, pixelDensity);
664
+ targetHeight / pixelDensity,
665
+ targetFormat, pixelDensity);
874
666
  target.parent = parent; // parent may be null so can't use createImage()
875
667
  if (w > 0 && h > 0) {
876
668
  getImpl(x, y, w, h, target, targetX, targetY);
@@ -878,11 +670,10 @@ public class PImage implements PConstants, Cloneable {
878
670
  return target;
879
671
  }
880
672
 
673
+
881
674
  /**
882
675
  * Returns a copy of this PImage. Equivalent to get(0, 0, width, height).
883
676
  * Deprecated, just use copy() instead.
884
- *
885
- * @return
886
677
  */
887
678
  public PImage get() {
888
679
  // Formerly this used clone(), which caused memory problems.
@@ -890,33 +681,23 @@ public class PImage implements PConstants, Cloneable {
890
681
  return get(0, 0, pixelWidth, pixelHeight);
891
682
  }
892
683
 
893
- /**
894
- *
895
- * @return
896
- */
684
+
897
685
  public PImage copy() {
898
686
  return get(0, 0, pixelWidth, pixelHeight);
899
687
  }
900
688
 
689
+
901
690
  /**
902
- * Internal function to actually handle getting a block of pixels that has
903
- * already been properly cropped to a valid region. That is, x/y/w/h are
904
- * guaranteed to be inside the image space, so the implementation can use the
905
- * fastest possible pixel copying method.
906
- *
907
- * @param sourceX
908
- * @param sourceY
909
- * @param sourceWidth
910
- * @param target
911
- * @param sourceHeight
912
- * @param targetX
913
- * @param targetY
691
+ * Internal function to actually handle getting a block of pixels that
692
+ * has already been properly cropped to a valid region. That is, x/y/w/h
693
+ * are guaranteed to be inside the image space, so the implementation can
694
+ * use the fastest possible pixel copying method.
914
695
  */
915
696
  protected void getImpl(int sourceX, int sourceY,
916
- int sourceWidth, int sourceHeight,
917
- PImage target, int targetX, int targetY) {
918
- int sourceIndex = sourceY * pixelWidth + sourceX;
919
- int targetIndex = targetY * target.pixelWidth + targetX;
697
+ int sourceWidth, int sourceHeight,
698
+ PImage target, int targetX, int targetY) {
699
+ int sourceIndex = sourceY*pixelWidth + sourceX;
700
+ int targetIndex = targetY*target.pixelWidth + targetX;
920
701
  for (int row = 0; row < sourceHeight; row++) {
921
702
  System.arraycopy(pixels, sourceIndex, target.pixels, targetIndex, sourceWidth);
922
703
  sourceIndex += pixelWidth;
@@ -924,22 +705,23 @@ public class PImage implements PConstants, Cloneable {
924
705
  }
925
706
  }
926
707
 
708
+
927
709
  /**
928
710
  * ( begin auto-generated from PImage_set.xml )
929
711
  *
930
- * Changes the color of any pixel or writes an image directly into the display
931
- * window.
932
- *
712
+ * Changes the color of any pixel or writes an image directly into the
713
+ * display window.
714
+ *
933
715
  * The <b>x</b> and <b>y</b> parameters specify the pixel to change and the
934
716
  * <b>color</b> parameter specifies the color value. The color parameter is
935
717
  * affected by the current color mode (the default is RGB values from 0 to
936
718
  * 255). When setting an image, the <b>x</b> and <b>y</b> parameters define
937
- * the coordinates for the upper-left corner of the image, regardless of the
938
- * current <b>imageMode()</b>.
939
- *
940
- * Setting the color of a single pixel with <b>set(x, y)</b> is easy, but not
941
- * as fast as putting the data directly into <b>pixels[]</b>. The equivalent
942
- * statement to <b>set(x, y, #000000)</b> using <b>pixels[]</b>
719
+ * the coordinates for the upper-left corner of the image, regardless of
720
+ * the current <b>imageMode()</b>.
721
+ *
722
+ * Setting the color of a single pixel with <b>set(x, y)</b> is easy, but
723
+ * not as fast as putting the data directly into <b>pixels[]</b>. The
724
+ * equivalent statement to <b>set(x, y, #000000)</b> using <b>pixels[]</b>
943
725
  * is <b>pixels[y*width+x] = #000000</b>. See the reference for
944
726
  * <b>pixels[]</b> for more information.
945
727
  *
@@ -956,22 +738,19 @@ public class PImage implements PConstants, Cloneable {
956
738
  * @see PImage#copy(PImage, int, int, int, int, int, int, int, int)
957
739
  */
958
740
  public void set(int x, int y, int c) {
959
- if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) {
960
- return;
961
- }
962
- pixels[y * pixelWidth + x] = c;
741
+ if ((x < 0) || (y < 0) || (x >= pixelWidth) || (y >= pixelHeight)) return;
742
+ pixels[y*pixelWidth + x] = c;
963
743
  updatePixels(x, y, 1, 1); // slow...
964
744
  }
965
745
 
746
+
966
747
  /**
967
748
  * <h3>Advanced</h3>
968
- * Efficient method of drawing an image's pixels directly to this surface. No
969
- * variations are employed, meaning that any scale, tint, or imageMode
749
+ * Efficient method of drawing an image's pixels directly to this surface.
750
+ * No variations are employed, meaning that any scale, tint, or imageMode
970
751
  * settings will be ignored.
971
752
  *
972
- * @param x
973
753
  * @param img image to copy into the original image
974
- * @param y
975
754
  */
976
755
  public void set(int x, int y, PImage img) {
977
756
  int sx = 0;
@@ -997,29 +776,20 @@ public class PImage implements PConstants, Cloneable {
997
776
  }
998
777
 
999
778
  // this could be nonexistent
1000
- if ((sw <= 0) || (sh <= 0)) {
1001
- return;
1002
- }
779
+ if ((sw <= 0) || (sh <= 0)) return;
1003
780
 
1004
781
  setImpl(img, sx, sy, sw, sh, x, y);
1005
782
  }
1006
783
 
784
+
1007
785
  /**
1008
- * Internal function to actually handle setting a block of pixels that has
1009
- * already been properly cropped from the image to a valid region.
1010
- *
1011
- * @param sourceImage
1012
- * @param sourceX
1013
- * @param targetY
1014
- * @param sourceHeight
1015
- * @param sourceY
1016
- * @param sourceWidth
1017
- * @param targetX
786
+ * Internal function to actually handle setting a block of pixels that
787
+ * has already been properly cropped from the image to a valid region.
1018
788
  */
1019
789
  protected void setImpl(PImage sourceImage,
1020
- int sourceX, int sourceY,
1021
- int sourceWidth, int sourceHeight,
1022
- int targetX, int targetY) {
790
+ int sourceX, int sourceY,
791
+ int sourceWidth, int sourceHeight,
792
+ int targetX, int targetY) {
1023
793
  int sourceOffset = sourceY * sourceImage.pixelWidth + sourceX;
1024
794
  int targetOffset = targetY * pixelWidth + targetX;
1025
795
 
@@ -1033,13 +803,18 @@ public class PImage implements PConstants, Cloneable {
1033
803
  updatePixels(targetX, targetY, sourceWidth, sourceHeight);
1034
804
  }
1035
805
 
806
+
807
+
1036
808
  //////////////////////////////////////////////////////////////
809
+
1037
810
  // ALPHA CHANNEL
811
+
812
+
1038
813
  /**
1039
814
  * @param maskArray array of integers used as the alpha channel, needs to be
1040
815
  * the same length as the image's pixel array.
1041
816
  */
1042
- public void mask(int maskArray[]) { // ignore
817
+ public void mask(int[] maskArray) { // ignore
1043
818
  loadPixels();
1044
819
  // don't execute if mask image is different size
1045
820
  if (maskArray.length != pixels.length) {
@@ -1052,32 +827,35 @@ public class PImage implements PConstants, Cloneable {
1052
827
  updatePixels();
1053
828
  }
1054
829
 
830
+
1055
831
  /**
1056
832
  * ( begin auto-generated from PImage_mask.xml )
1057
833
  *
1058
- * Masks part of an image from displaying by loading another image and using
1059
- * it as an alpha channel. This mask image should only contain grayscale data,
1060
- * but only the blue color channel is used. The mask image needs to be the
1061
- * same size as the image to which it is applied.
1062
- *
834
+ * Masks part of an image from displaying by loading another image and
835
+ * using it as an alpha channel. This mask image should only contain
836
+ * grayscale data, but only the blue color channel is used. The mask image
837
+ * needs to be the same size as the image to which it is applied.
838
+ *
1063
839
  * In addition to using a mask image, an integer array containing the alpha
1064
- * channel data can be specified directly. This method is useful for creating
1065
- * dynamically generated alpha masks. This array must be of the same length as
1066
- * the target image's pixels array and should contain only grayscale data of
1067
- * values between 0-255.
840
+ * channel data can be specified directly. This method is useful for
841
+ * creating dynamically generated alpha masks. This array must be of the
842
+ * same length as the target image's pixels array and should contain only
843
+ * grayscale data of values between 0-255.
1068
844
  *
1069
845
  * ( end auto-generated )
1070
846
  *
1071
847
  * <h3>Advanced</h3>
1072
848
  *
1073
- * Set alpha channel for an image. Black colors in the source image will make
1074
- * the destination image completely transparent, and white will make things
1075
- * fully opaque. Gray values will be in-between steps.
849
+ * Set alpha channel for an image. Black colors in the source
850
+ * image will make the destination image completely transparent,
851
+ * and white will make things fully opaque. Gray values will
852
+ * be in-between steps.
1076
853
  * <P>
1077
- * Strictly speaking the "blue" value from the source image is used as the
1078
- * alpha color. For a fully grayscale image, this is correct, but for a color
1079
- * image it's not 100% accurate. For a more accurate conversion, first use
1080
- * filter(GRAY) which will make the image into a "correct" grayscale by
854
+ * Strictly speaking the "blue" value from the source image is
855
+ * used as the alpha color. For a fully grayscale image, this
856
+ * is correct, but for a color image it's not 100% accurate.
857
+ * For a more accurate conversion, first use filter(GRAY)
858
+ * which will make the image into a "correct" grayscale by
1081
859
  * performing a proper luminance-based conversion.
1082
860
  *
1083
861
  * @webref pimage:method
@@ -1090,12 +868,13 @@ public class PImage implements PConstants, Cloneable {
1090
868
  mask(img.pixels);
1091
869
  }
1092
870
 
871
+
872
+
1093
873
  //////////////////////////////////////////////////////////////
874
+
1094
875
  // IMAGE FILTERS
1095
- /**
1096
- *
1097
- * @param kind
1098
- */
876
+
877
+
1099
878
  public void filter(int kind) {
1100
879
  loadPixels();
1101
880
 
@@ -1126,8 +905,8 @@ public class PImage implements PConstants, Cloneable {
1126
905
  // 0.30 * 256 = 77
1127
906
  // 0.59 * 256 = 151
1128
907
  // 0.11 * 256 = 28
1129
- int lum = (77 * (col >> 16 & 0xff) + 151 * (col >> 8 & 0xff) + 28 * (col & 0xff)) >> 8;
1130
- pixels[i] = (col & ALPHA_MASK) | lum << 16 | lum << 8 | lum;
908
+ int lum = (77*(col>>16&0xff) + 151*(col>>8&0xff) + 28*(col&0xff))>>8;
909
+ pixels[i] = (col & ALPHA_MASK) | lum<<16 | lum<<8 | lum;
1131
910
  }
1132
911
  }
1133
912
  break;
@@ -1140,8 +919,8 @@ public class PImage implements PConstants, Cloneable {
1140
919
  break;
1141
920
 
1142
921
  case POSTERIZE:
1143
- throw new RuntimeException("Use filter(POSTERIZE, int levels) "
1144
- + "instead of filter(POSTERIZE)");
922
+ throw new RuntimeException("Use filter(POSTERIZE, int levels) " +
923
+ "instead of filter(POSTERIZE)");
1145
924
 
1146
925
  case OPAQUE:
1147
926
  for (int i = 0; i < pixels.length; i++) {
@@ -1154,7 +933,7 @@ public class PImage implements PConstants, Cloneable {
1154
933
  filter(THRESHOLD, 0.5f);
1155
934
  break;
1156
935
 
1157
- // [toxi 050728] added new filters
936
+ // [toxi 050728] added new filters
1158
937
  case ERODE:
1159
938
  erode(); // former dilate(true);
1160
939
  break;
@@ -1166,33 +945,33 @@ public class PImage implements PConstants, Cloneable {
1166
945
  updatePixels(); // mark as modified
1167
946
  }
1168
947
 
948
+
1169
949
  /**
1170
950
  * ( begin auto-generated from PImage_filter.xml )
1171
951
  *
1172
- * Filters an image as defined by one of the following modes:<br
1173
- * />THRESHOLD - converts the image to black and white pixels depending if
1174
- * they are above or below the threshold defined by the level parameter. The
1175
- * level must be between 0.0 (black) and 1.0(white). If no level is specified,
1176
- * 0.5 is used.
1177
- *
952
+ * Filters an image as defined by one of the following modes:
953
+ * THRESHOLD - converts the image to black and white pixels depending if
954
+ * they are above or below the threshold defined by the level parameter.
955
+ * The level must be between 0.0 (black) and 1.0(white). If no level is
956
+ * specified, 0.5 is used.
957
+ *
1178
958
  * GRAY - converts any colors in the image to grayscale equivalents
1179
- *
959
+ *
1180
960
  * INVERT - sets each pixel to its inverse value
1181
- *
961
+ *
1182
962
  * POSTERIZE - limits each channel of the image to the number of colors
1183
963
  * specified as the level parameter
1184
- *
964
+ *
1185
965
  * BLUR - executes a Guassian blur with the level parameter specifying the
1186
966
  * extent of the blurring. If no level parameter is used, the blur is
1187
967
  * equivalent to Guassian blur of radius 1
1188
- *
968
+ *
1189
969
  * OPAQUE - sets the alpha channel to entirely opaque
1190
- *
970
+ *
1191
971
  * ERODE - reduces the light areas with the amount defined by the level
1192
972
  * parameter
1193
- *
1194
- * DILATE - increases the light areas with the amount defined by the level
1195
- * parameter
973
+ *
974
+ * DILATE - increases the light areas with the amount defined by the level parameter
1196
975
  *
1197
976
  * ( end auto-generated )
1198
977
  *
@@ -1217,8 +996,7 @@ public class PImage implements PConstants, Cloneable {
1217
996
  * @webref image:pixels
1218
997
  * @brief Converts the image to grayscale or black and white
1219
998
  * @usage web_application
1220
- * @param kind Either THRESHOLD, GRAY, OPAQUE, INVERT, POSTERIZE, BLUR, ERODE,
1221
- * or DILATE
999
+ * @param kind Either THRESHOLD, GRAY, OPAQUE, INVERT, POSTERIZE, BLUR, ERODE, or DILATE
1222
1000
  * @param param unique for each, see above
1223
1001
  */
1224
1002
  public void filter(int kind, float param) {
@@ -1226,32 +1004,37 @@ public class PImage implements PConstants, Cloneable {
1226
1004
 
1227
1005
  switch (kind) {
1228
1006
  case BLUR:
1229
- if (format == ALPHA) {
1007
+ switch (format) {
1008
+ case ALPHA:
1230
1009
  blurAlpha(param);
1231
- } else if (format == ARGB) {
1010
+ break;
1011
+ case ARGB:
1232
1012
  blurARGB(param);
1233
- } else {
1013
+ break;
1014
+ default:
1234
1015
  blurRGB(param);
1235
- }
1016
+ break;
1017
+ }
1236
1018
  break;
1237
1019
 
1020
+
1238
1021
  case GRAY:
1239
- throw new RuntimeException("Use filter(GRAY) instead of "
1240
- + "filter(GRAY, param)");
1022
+ throw new RuntimeException("Use filter(GRAY) instead of " +
1023
+ "filter(GRAY, param)");
1241
1024
 
1242
1025
  case INVERT:
1243
- throw new RuntimeException("Use filter(INVERT) instead of "
1244
- + "filter(INVERT, param)");
1026
+ throw new RuntimeException("Use filter(INVERT) instead of " +
1027
+ "filter(INVERT, param)");
1245
1028
 
1246
1029
  case OPAQUE:
1247
- throw new RuntimeException("Use filter(OPAQUE) instead of "
1248
- + "filter(OPAQUE, param)");
1030
+ throw new RuntimeException("Use filter(OPAQUE) instead of " +
1031
+ "filter(OPAQUE, param)");
1249
1032
 
1250
1033
  case POSTERIZE:
1251
- int levels = (int) param;
1034
+ int levels = (int)param;
1252
1035
  if ((levels < 2) || (levels > 255)) {
1253
- throw new RuntimeException("Levels must be between 2 and 255 for "
1254
- + "filter(POSTERIZE, levels)");
1036
+ throw new RuntimeException("Levels must be between 2 and 255 for " +
1037
+ "filter(POSTERIZE, levels)");
1255
1038
  }
1256
1039
  int levels1 = levels - 1;
1257
1040
  for (int i = 0; i < pixels.length; i++) {
@@ -1261,10 +1044,10 @@ public class PImage implements PConstants, Cloneable {
1261
1044
  rlevel = (((rlevel * levels) >> 8) * 255) / levels1;
1262
1045
  glevel = (((glevel * levels) >> 8) * 255) / levels1;
1263
1046
  blevel = (((blevel * levels) >> 8) * 255) / levels1;
1264
- pixels[i] = ((0xff000000 & pixels[i])
1265
- | (rlevel << 16)
1266
- | (glevel << 8)
1267
- | blevel);
1047
+ pixels[i] = ((0xff000000 & pixels[i]) |
1048
+ (rlevel << 16) |
1049
+ (glevel << 8) |
1050
+ blevel);
1268
1051
  }
1269
1052
  break;
1270
1053
 
@@ -1272,76 +1055,71 @@ public class PImage implements PConstants, Cloneable {
1272
1055
  int thresh = (int) (param * 255);
1273
1056
  for (int i = 0; i < pixels.length; i++) {
1274
1057
  int max = Math.max((pixels[i] & RED_MASK) >> 16,
1275
- Math.max((pixels[i] & GREEN_MASK) >> 8,
1276
- (pixels[i] & BLUE_MASK)));
1277
- pixels[i] = (pixels[i] & ALPHA_MASK)
1278
- | ((max < thresh) ? 0x000000 : 0xffffff);
1058
+ Math.max((pixels[i] & GREEN_MASK) >> 8,
1059
+ (pixels[i] & BLUE_MASK)));
1060
+ pixels[i] = (pixels[i] & ALPHA_MASK) |
1061
+ ((max < thresh) ? 0x000000 : 0xffffff);
1279
1062
  }
1280
1063
  break;
1281
1064
 
1282
- // [toxi20050728] added new filters
1283
- case ERODE:
1284
- throw new RuntimeException("Use filter(ERODE) instead of "
1285
- + "filter(ERODE, param)");
1286
- case DILATE:
1287
- throw new RuntimeException("Use filter(DILATE) instead of "
1288
- + "filter(DILATE, param)");
1065
+ // [toxi20050728] added new filters
1066
+ case ERODE:
1067
+ throw new RuntimeException("Use filter(ERODE) instead of " +
1068
+ "filter(ERODE, param)");
1069
+ case DILATE:
1070
+ throw new RuntimeException("Use filter(DILATE) instead of " +
1071
+ "filter(DILATE, param)");
1289
1072
  }
1290
1073
  updatePixels(); // mark as modified
1291
1074
  }
1292
1075
 
1293
- /**
1294
- * Set the high bits of all pixels to opaque.
1295
- */
1076
+
1077
+ /** Set the high bits of all pixels to opaque. */
1296
1078
  protected void opaque() {
1297
1079
  for (int i = 0; i < pixels.length; i++) {
1298
1080
  pixels[i] = 0xFF000000 | pixels[i];
1299
1081
  }
1300
1082
  }
1301
1083
 
1084
+
1302
1085
  /**
1303
- * Optimized code for building the blur kernel. further optimized blur code
1304
- * (approx. 15% for radius=20) bigger speed gains for larger radii (~30%)
1305
- * added support for various image types (ALPHA, RGB, ARGB) [toxi 050728]
1306
- *
1307
- * @param r
1086
+ * Optimized code for building the blur kernel.
1087
+ * further optimized blur code (approx. 15% for radius=20)
1088
+ * bigger speed gains for larger radii (~30%)
1089
+ * added support for various image types (ALPHA, RGB, ARGB)
1090
+ * [toxi 050728]
1308
1091
  */
1309
1092
  protected void buildBlurKernel(float r) {
1310
1093
  int radius = (int) (r * 3.5f);
1311
1094
  radius = (radius < 1) ? 1 : ((radius < 248) ? radius : 248);
1312
1095
  if (blurRadius != radius) {
1313
1096
  blurRadius = radius;
1314
- blurKernelSize = 1 + blurRadius << 1;
1097
+ blurKernelSize = 1 + blurRadius<<1;
1315
1098
  blurKernel = new int[blurKernelSize];
1316
1099
  blurMult = new int[blurKernelSize][256];
1317
1100
 
1318
- int bk, bki;
1319
- int[] bm, bmi;
1101
+ int bk,bki;
1102
+ int[] bm,bmi;
1320
1103
 
1321
1104
  for (int i = 1, radiusi = radius - 1; i < radius; i++) {
1322
- blurKernel[radius + i] = blurKernel[radiusi] = bki = radiusi * radiusi;
1323
- bm = blurMult[radius + i];
1324
- bmi = blurMult[radiusi--];
1325
- for (int j = 0; j < 256; j++) {
1326
- bm[j] = bmi[j] = bki * j;
1327
- }
1105
+ blurKernel[radius+i] = blurKernel[radiusi] = bki = radiusi * radiusi;
1106
+ bm=blurMult[radius+i];
1107
+ bmi=blurMult[radiusi--];
1108
+ for (int j = 0; j < 256; j++)
1109
+ bm[j] = bmi[j] = bki*j;
1328
1110
  }
1329
1111
  bk = blurKernel[radius] = radius * radius;
1330
1112
  bm = blurMult[radius];
1331
- for (int j = 0; j < 256; j++) {
1332
- bm[j] = bk * j;
1333
- }
1113
+ for (int j = 0; j < 256; j++)
1114
+ bm[j] = bk*j;
1334
1115
  }
1335
1116
  }
1336
1117
 
1337
- /**
1338
- *
1339
- * @param r
1340
- */
1118
+
1341
1119
  protected void blurAlpha(float r) {
1342
1120
  int sum, cb;
1343
1121
  int read, ri, ym, ymi, bk0;
1344
- int b2[] = new int[pixels.length];
1122
+ int[] b2 = new int[pixels.length];
1345
1123
  int yi = 0;
1346
1124
 
1347
1125
  buildBlurKernel(r);
@@ -1351,19 +1129,17 @@ public class PImage implements PConstants, Cloneable {
1351
1129
  //cb = cg = cr = sum = 0;
1352
1130
  cb = sum = 0;
1353
1131
  read = x - blurRadius;
1354
- if (read < 0) {
1355
- bk0 = -read;
1356
- read = 0;
1132
+ if (read<0) {
1133
+ bk0=-read;
1134
+ read=0;
1357
1135
  } else {
1358
- if (read >= pixelWidth) {
1136
+ if (read >= pixelWidth)
1359
1137
  break;
1360
- }
1361
- bk0 = 0;
1138
+ bk0=0;
1362
1139
  }
1363
1140
  for (int i = bk0; i < blurKernelSize; i++) {
1364
- if (read >= pixelWidth) {
1141
+ if (read >= pixelWidth)
1365
1142
  break;
1366
- }
1367
1143
  int c = pixels[read + yi];
1368
1144
  int[] bm = blurMult[i];
1369
1145
  cb += bm[c & BLUE_MASK];
@@ -1387,24 +1163,22 @@ public class PImage implements PConstants, Cloneable {
1387
1163
  bk0 = ri = -ym;
1388
1164
  read = x;
1389
1165
  } else {
1390
- if (ym >= pixelHeight) {
1166
+ if (ym >= pixelHeight)
1391
1167
  break;
1392
- }
1393
1168
  bk0 = 0;
1394
1169
  ri = ym;
1395
1170
  read = x + ymi;
1396
1171
  }
1397
1172
  for (int i = bk0; i < blurKernelSize; i++) {
1398
- if (ri >= pixelHeight) {
1173
+ if (ri >= pixelHeight)
1399
1174
  break;
1400
- }
1401
1175
  int[] bm = blurMult[i];
1402
1176
  cb += bm[b2[read]];
1403
1177
  sum += blurKernel[i];
1404
1178
  ri++;
1405
1179
  read += pixelWidth;
1406
1180
  }
1407
- pixels[x + yi] = (cb / sum);
1181
+ pixels[x+yi] = (cb/sum);
1408
1182
  }
1409
1183
  yi += pixelWidth;
1410
1184
  ymi += pixelWidth;
@@ -1412,16 +1186,13 @@ public class PImage implements PConstants, Cloneable {
1412
1186
  }
1413
1187
  }
1414
1188
 
1415
- /**
1416
- *
1417
- * @param r
1418
- */
1189
+
1419
1190
  protected void blurRGB(float r) {
1420
1191
  int sum, cr, cg, cb; //, k;
1421
1192
  int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0;
1422
- int r2[] = new int[pixels.length];
1423
- int g2[] = new int[pixels.length];
1424
- int b2[] = new int[pixels.length];
1193
+ int[] r2 = new int[pixels.length];
1194
+ int[] g2 = new int[pixels.length];
1195
+ int[] b2 = new int[pixels.length];
1425
1196
  int yi = 0;
1426
1197
 
1427
1198
  buildBlurKernel(r);
@@ -1489,7 +1260,7 @@ public class PImage implements PConstants, Cloneable {
1489
1260
  ri++;
1490
1261
  read += pixelWidth;
1491
1262
  }
1492
- pixels[x + yi] = 0xff000000 | (cr / sum) << 16 | (cg / sum) << 8 | (cb / sum);
1263
+ pixels[x+yi] = 0xff000000 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum);
1493
1264
  }
1494
1265
  yi += pixelWidth;
1495
1266
  ymi += pixelWidth;
@@ -1497,18 +1268,15 @@ public class PImage implements PConstants, Cloneable {
1497
1268
  }
1498
1269
  }
1499
1270
 
1500
- /**
1501
- *
1502
- * @param r
1503
- */
1271
+
1504
1272
  protected void blurARGB(float r) {
1505
1273
  int sum, cr, cg, cb, ca;
1506
1274
  int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0;
1507
1275
  int wh = pixels.length;
1508
- int r2[] = new int[wh];
1509
- int g2[] = new int[wh];
1510
- int b2[] = new int[wh];
1511
- int a2[] = new int[wh];
1276
+ int[] r2 = new int[wh];
1277
+ int[] g2 = new int[wh];
1278
+ int[] b2 = new int[wh];
1279
+ int[] a2 = new int[wh];
1512
1280
  int yi = 0;
1513
1281
 
1514
1282
  buildBlurKernel(r);
@@ -1524,14 +1292,14 @@ public class PImage implements PConstants, Cloneable {
1524
1292
  if (read >= pixelWidth) {
1525
1293
  break;
1526
1294
  }
1527
- bk0 = 0;
1295
+ bk0=0;
1528
1296
  }
1529
1297
  for (int i = bk0; i < blurKernelSize; i++) {
1530
1298
  if (read >= pixelWidth) {
1531
1299
  break;
1532
1300
  }
1533
1301
  int c = pixels[read + yi];
1534
- int[] bm = blurMult[i];
1302
+ int[] bm=blurMult[i];
1535
1303
  ca += bm[(c & ALPHA_MASK) >>> 24];
1536
1304
  cr += bm[(c & RED_MASK) >> 16];
1537
1305
  cg += bm[(c & GREEN_MASK) >> 8];
@@ -1570,7 +1338,7 @@ public class PImage implements PConstants, Cloneable {
1570
1338
  if (ri >= pixelHeight) {
1571
1339
  break;
1572
1340
  }
1573
- int[] bm = blurMult[i];
1341
+ int[] bm=blurMult[i];
1574
1342
  ca += bm[a2[read]];
1575
1343
  cr += bm[r2[read]];
1576
1344
  cg += bm[g2[read]];
@@ -1579,7 +1347,7 @@ public class PImage implements PConstants, Cloneable {
1579
1347
  ri++;
1580
1348
  read += pixelWidth;
1581
1349
  }
1582
- pixels[x + yi] = (ca / sum) << 24 | (cr / sum) << 16 | (cg / sum) << 8 | (cb / sum);
1350
+ pixels[x+yi] = (ca/sum)<<24 | (cr/sum)<<16 | (cg/sum)<<8 | (cb/sum);
1583
1351
  }
1584
1352
  yi += pixelWidth;
1585
1353
  ymi += pixelWidth;
@@ -1587,9 +1355,10 @@ public class PImage implements PConstants, Cloneable {
1587
1355
  }
1588
1356
  }
1589
1357
 
1358
+
1590
1359
  /**
1591
- * Generic dilate/erode filter using luminance values as decision factor.
1592
- * [toxi 050728]
1360
+ * Generic dilate/erode filter using luminance values
1361
+ * as decision factor. [toxi 050728]
1593
1362
  */
1594
1363
  protected void dilate() { // formerly dilate(false)
1595
1364
  int index = 0;
@@ -1626,16 +1395,16 @@ public class PImage implements PConstants, Cloneable {
1626
1395
  int colRight = pixels[idxRight];
1627
1396
 
1628
1397
  // compute luminance
1629
- int currLum
1630
- = 77 * (orig >> 16 & 0xff) + 151 * (orig >> 8 & 0xff) + 28 * (orig & 0xff);
1631
- int lumLeft
1632
- = 77 * (colLeft >> 16 & 0xff) + 151 * (colLeft >> 8 & 0xff) + 28 * (colLeft & 0xff);
1633
- int lumRight
1634
- = 77 * (colRight >> 16 & 0xff) + 151 * (colRight >> 8 & 0xff) + 28 * (colRight & 0xff);
1635
- int lumUp
1636
- = 77 * (colUp >> 16 & 0xff) + 151 * (colUp >> 8 & 0xff) + 28 * (colUp & 0xff);
1637
- int lumDown
1638
- = 77 * (colDown >> 16 & 0xff) + 151 * (colDown >> 8 & 0xff) + 28 * (colDown & 0xff);
1398
+ int currLum =
1399
+ 77*(orig>>16&0xff) + 151*(orig>>8&0xff) + 28*(orig&0xff);
1400
+ int lumLeft =
1401
+ 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff);
1402
+ int lumRight =
1403
+ 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff);
1404
+ int lumUp =
1405
+ 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff);
1406
+ int lumDown =
1407
+ 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff);
1639
1408
 
1640
1409
  if (lumLeft > currLum) {
1641
1410
  result = colLeft;
@@ -1659,9 +1428,7 @@ public class PImage implements PConstants, Cloneable {
1659
1428
  System.arraycopy(outgoing, 0, pixels, 0, maxIndex);
1660
1429
  }
1661
1430
 
1662
- /**
1663
- *
1664
- */
1431
+
1665
1432
  protected void erode() { // formerly dilate(true)
1666
1433
  int index = 0;
1667
1434
  int maxIndex = pixels.length;
@@ -1697,16 +1464,16 @@ public class PImage implements PConstants, Cloneable {
1697
1464
  int colRight = pixels[idxRight];
1698
1465
 
1699
1466
  // compute luminance
1700
- int currLum
1701
- = 77 * (orig >> 16 & 0xff) + 151 * (orig >> 8 & 0xff) + 28 * (orig & 0xff);
1702
- int lumLeft
1703
- = 77 * (colLeft >> 16 & 0xff) + 151 * (colLeft >> 8 & 0xff) + 28 * (colLeft & 0xff);
1704
- int lumRight
1705
- = 77 * (colRight >> 16 & 0xff) + 151 * (colRight >> 8 & 0xff) + 28 * (colRight & 0xff);
1706
- int lumUp
1707
- = 77 * (colUp >> 16 & 0xff) + 151 * (colUp >> 8 & 0xff) + 28 * (colUp & 0xff);
1708
- int lumDown
1709
- = 77 * (colDown >> 16 & 0xff) + 151 * (colDown >> 8 & 0xff) + 28 * (colDown & 0xff);
1467
+ int currLum =
1468
+ 77*(orig>>16&0xff) + 151*(orig>>8&0xff) + 28*(orig&0xff);
1469
+ int lumLeft =
1470
+ 77*(colLeft>>16&0xff) + 151*(colLeft>>8&0xff) + 28*(colLeft&0xff);
1471
+ int lumRight =
1472
+ 77*(colRight>>16&0xff) + 151*(colRight>>8&0xff) + 28*(colRight&0xff);
1473
+ int lumUp =
1474
+ 77*(colUp>>16&0xff) + 151*(colUp>>8&0xff) + 28*(colUp&0xff);
1475
+ int lumDown =
1476
+ 77*(colDown>>16&0xff) + 151*(colDown>>8&0xff) + 28*(colDown&0xff);
1710
1477
 
1711
1478
  if (lumLeft < currLum) {
1712
1479
  result = colLeft;
@@ -1730,17 +1497,22 @@ public class PImage implements PConstants, Cloneable {
1730
1497
  System.arraycopy(outgoing, 0, pixels, 0, maxIndex);
1731
1498
  }
1732
1499
 
1500
+
1501
+
1733
1502
  //////////////////////////////////////////////////////////////
1503
+
1734
1504
  // COPY
1505
+
1506
+
1735
1507
  /**
1736
1508
  * ( begin auto-generated from PImage_copy.xml )
1737
1509
  *
1738
1510
  * Copies a region of pixels from one image into another. If the source and
1739
1511
  * destination regions aren't the same size, it will automatically resize
1740
- * source pixels to fit the specified target region. No alpha information is
1741
- * used in the process, however if the source image has an alpha channel set,
1742
- * it will be copied as well.
1743
- *
1512
+ * source pixels to fit the specified target region. No alpha information
1513
+ * is used in the process, however if the source image has an alpha channel
1514
+ * set, it will be copied as well.
1515
+ *
1744
1516
  * As of release 0149, this function ignores <b>imageMode()</b>.
1745
1517
  *
1746
1518
  * ( end auto-generated )
@@ -1760,29 +1532,27 @@ public class PImage implements PConstants, Cloneable {
1760
1532
  * @see PImage#blend(PImage, int, int, int, int, int, int, int, int, int)
1761
1533
  */
1762
1534
  public void copy(int sx, int sy, int sw, int sh,
1763
- int dx, int dy, int dw, int dh) {
1535
+ int dx, int dy, int dw, int dh) {
1764
1536
  blend(this, sx, sy, sw, sh, dx, dy, dw, dh, REPLACE);
1765
1537
  }
1766
1538
 
1767
- /**
1768
- * @param src an image variable referring to the source image.
1769
- * @param sx
1770
- * @param sy
1771
- * @param dh
1772
- * @param sw
1773
- * @param dx
1774
- * @param sh
1775
- * @param dy
1776
- * @param dw
1777
- */
1539
+
1540
+ /**
1541
+ * @param src an image variable referring to the source image.
1542
+ */
1778
1543
  public void copy(PImage src,
1779
- int sx, int sy, int sw, int sh,
1780
- int dx, int dy, int dw, int dh) {
1544
+ int sx, int sy, int sw, int sh,
1545
+ int dx, int dy, int dw, int dh) {
1781
1546
  blend(src, sx, sy, sw, sh, dx, dy, dw, dh, REPLACE);
1782
1547
  }
1783
1548
 
1549
+
1550
+
1784
1551
  //////////////////////////////////////////////////////////////
1552
+
1785
1553
  // BLEND
1554
+
1555
+
1786
1556
  /**
1787
1557
  * ( begin auto-generated from blendColor.xml )
1788
1558
  *
@@ -1794,24 +1564,28 @@ public class PImage implements PConstants, Cloneable {
1794
1564
  * <h3>Advanced</h3>
1795
1565
  * <UL>
1796
1566
  * <LI>REPLACE - destination colour equals colour of source pixel: C = A.
1797
- * Sometimes called "Normal" or "Copy" in other software.
1567
+ * Sometimes called "Normal" or "Copy" in other software.
1798
1568
  *
1799
1569
  * <LI>BLEND - linear interpolation of colours:
1800
- * <TT>C = A*factor + B</TT>
1570
+ * <TT>C = A*factor + B</TT>
1801
1571
  *
1802
1572
  * <LI>ADD - additive blending with white clip:
1803
- * <TT>C = min(A*factor + B, 255)</TT>. Clipped to 0..255, Photoshop calls
1804
- * this "Linear Burn", and Director calls it "Add Pin".
1573
+ * <TT>C = min(A*factor + B, 255)</TT>.
1574
+ * Clipped to 0..255, Photoshop calls this "Linear Burn",
1575
+ * and Director calls it "Add Pin".
1805
1576
  *
1806
1577
  * <LI>SUBTRACT - substractive blend with black clip:
1807
- * <TT>C = max(B - A*factor, 0)</TT>. Clipped to 0..255, Photoshop calls this
1808
- * "Linear Dodge", and Director calls it "Subtract Pin".
1578
+ * <TT>C = max(B - A*factor, 0)</TT>.
1579
+ * Clipped to 0..255, Photoshop calls this "Linear Dodge",
1580
+ * and Director calls it "Subtract Pin".
1809
1581
  *
1810
1582
  * <LI>DARKEST - only the darkest colour succeeds:
1811
- * <TT>C = min(A*factor, B)</TT>. Illustrator calls this "Darken".
1583
+ * <TT>C = min(A*factor, B)</TT>.
1584
+ * Illustrator calls this "Darken".
1812
1585
  *
1813
1586
  * <LI>LIGHTEST - only the lightest colour succeeds:
1814
- * <TT>C = max(A*factor, B)</TT>. Illustrator calls this "Lighten".
1587
+ * <TT>C = max(A*factor, B)</TT>.
1588
+ * Illustrator calls this "Lighten".
1815
1589
  *
1816
1590
  * <LI>DIFFERENCE - subtract colors from underlying image.
1817
1591
  *
@@ -1821,161 +1595,130 @@ public class PImage implements PConstants, Cloneable {
1821
1595
  *
1822
1596
  * <LI>SCREEN - Opposite multiply, uses inverse values of the colors.
1823
1597
  *
1824
- * <LI>OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values, and
1825
- * screens light values.
1598
+ * <LI>OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values,
1599
+ * and screens light values.
1826
1600
  *
1827
1601
  * <LI>HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
1828
1602
  *
1829
- * <LI>SOFT_LIGHT - Mix of DARKEST and LIGHTEST. Works like OVERLAY, but not
1830
- * as harsh.
1603
+ * <LI>SOFT_LIGHT - Mix of DARKEST and LIGHTEST.
1604
+ * Works like OVERLAY, but not as harsh.
1831
1605
  *
1832
1606
  * <LI>DODGE - Lightens light tones and increases contrast, ignores darks.
1833
- * Called "Color Dodge" in Illustrator and Photoshop.
1607
+ * Called "Color Dodge" in Illustrator and Photoshop.
1834
1608
  *
1835
1609
  * <LI>BURN - Darker areas are applied, increasing contrast, ignores lights.
1836
- * Called "Color Burn" in Illustrator and Photoshop.
1610
+ * Called "Color Burn" in Illustrator and Photoshop.
1837
1611
  * </UL>
1838
- * <P>
1839
- * A useful reference for blending modes and their algorithms can be found in
1840
- * the <A HREF="http://www.w3.org/TR/SVG12/rendering.html">SVG</A>
1612
+ * <P>A useful reference for blending modes and their algorithms can be
1613
+ * found in the <A HREF="http://www.w3.org/TR/SVG12/rendering.html">SVG</A>
1841
1614
  * specification.</P>
1842
- * <P>
1843
- * It is important to note that Processing uses "fast" code, not necessarily
1844
- * "correct" code. No biggie, most software does. A nitpicker can find
1845
- * numerous "off by 1 division" problems in the blend code where
1615
+ * <P>It is important to note that Processing uses "fast" code, not
1616
+ * necessarily "correct" code. No biggie, most software does. A nitpicker
1617
+ * can find numerous "off by 1 division" problems in the blend code where
1846
1618
  * <TT>&gt;&gt;8</TT> or <TT>&gt;&gt;7</TT> is used when strictly speaking
1847
- * <TT>/255.0</T> or <TT>/127.0</TT> should have been used.</P>
1848
- * <P>
1849
- * For instance, exclusion (not intended for real-time use) reads
1619
+ * <TT>/255.0</TT> or <TT>/127.0</TT> should have been used.</P>
1620
+ * <P>For instance, exclusion (not intended for real-time use) reads
1850
1621
  * <TT>r1 + r2 - ((2 * r1 * r2) / 255)</TT> because <TT>255 == 1.0</TT>
1851
- * not <TT>256 == 1.0</TT>. In other words, <TT>(255*255)>>8</TT> is not the
1852
- * same as <TT>(255*255)/255</TT>. But for real-time use the shifts are
1853
- * preferrable, and the difference is insignificant for applications built
1854
- * with Processing.</P>
1622
+ * not <TT>256 == 1.0</TT>. In other words, <TT>(255*255)>>8</TT> is not
1623
+ * the same as <TT>(255*255)/255</TT>. But for real-time use the shifts
1624
+ * are preferrable, and the difference is insignificant for applications
1625
+ * built with Processing.</P>
1855
1626
  *
1856
- * @return
1857
1627
  * @webref color:creating_reading
1858
1628
  * @usage web_application
1859
1629
  * @param c1 the first color to blend
1860
1630
  * @param c2 the second color to blend
1861
- * @param mode either BLEND, ADD, SUBTRACT, DARKEST, LIGHTEST, DIFFERENCE,
1862
- * EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, or
1863
- * BURN
1631
+ * @param mode either BLEND, ADD, SUBTRACT, DARKEST, LIGHTEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, or BURN
1864
1632
  * @see PImage#blend(PImage, int, int, int, int, int, int, int, int, int)
1865
1633
  * @see PApplet#color(float, float, float, float)
1866
1634
  */
1867
1635
  static public int blendColor(int c1, int c2, int mode) { // ignore
1868
1636
  switch (mode) {
1869
- case REPLACE:
1870
- return c2;
1871
- case BLEND:
1872
- return blend_blend(c1, c2);
1637
+ case REPLACE: return c2;
1638
+ case BLEND: return blend_blend(c1, c2);
1873
1639
 
1874
- case ADD:
1875
- return blend_add_pin(c1, c2);
1876
- case SUBTRACT:
1877
- return blend_sub_pin(c1, c2);
1640
+ case ADD: return blend_add_pin(c1, c2);
1641
+ case SUBTRACT: return blend_sub_pin(c1, c2);
1878
1642
 
1879
- case LIGHTEST:
1880
- return blend_lightest(c1, c2);
1881
- case DARKEST:
1882
- return blend_darkest(c1, c2);
1643
+ case LIGHTEST: return blend_lightest(c1, c2);
1644
+ case DARKEST: return blend_darkest(c1, c2);
1883
1645
 
1884
- case DIFFERENCE:
1885
- return blend_difference(c1, c2);
1886
- case EXCLUSION:
1887
- return blend_exclusion(c1, c2);
1646
+ case DIFFERENCE: return blend_difference(c1, c2);
1647
+ case EXCLUSION: return blend_exclusion(c1, c2);
1888
1648
 
1889
- case MULTIPLY:
1890
- return blend_multiply(c1, c2);
1891
- case SCREEN:
1892
- return blend_screen(c1, c2);
1649
+ case MULTIPLY: return blend_multiply(c1, c2);
1650
+ case SCREEN: return blend_screen(c1, c2);
1893
1651
 
1894
- case HARD_LIGHT:
1895
- return blend_hard_light(c1, c2);
1896
- case SOFT_LIGHT:
1897
- return blend_soft_light(c1, c2);
1898
- case OVERLAY:
1899
- return blend_overlay(c1, c2);
1652
+ case HARD_LIGHT: return blend_hard_light(c1, c2);
1653
+ case SOFT_LIGHT: return blend_soft_light(c1, c2);
1654
+ case OVERLAY: return blend_overlay(c1, c2);
1900
1655
 
1901
- case DODGE:
1902
- return blend_dodge(c1, c2);
1903
- case BURN:
1904
- return blend_burn(c1, c2);
1656
+ case DODGE: return blend_dodge(c1, c2);
1657
+ case BURN: return blend_burn(c1, c2);
1905
1658
  }
1906
1659
  return 0;
1907
1660
  }
1908
1661
 
1909
- /**
1910
- *
1911
- * @param sx
1912
- * @param sy
1913
- * @param sw
1914
- * @param sh
1915
- * @param dx
1916
- * @param dy
1917
- * @param dw
1918
- * @param dh
1919
- * @param mode
1920
- */
1662
+
1921
1663
  public void blend(int sx, int sy, int sw, int sh,
1922
- int dx, int dy, int dw, int dh, int mode) {
1664
+ int dx, int dy, int dw, int dh, int mode) {
1923
1665
  blend(this, sx, sy, sw, sh, dx, dy, dw, dh, mode);
1924
1666
  }
1925
1667
 
1668
+
1926
1669
  /**
1927
1670
  * ( begin auto-generated from PImage_blend.xml )
1928
1671
  *
1929
1672
  * Blends a region of pixels into the image specified by the <b>img</b>
1930
- * parameter. These copies utilize full alpha channel support and a choice of
1931
- * the following modes to blend the colors of source pixels (A) with the ones
1932
- * of pixels in the destination image (B):
1933
- *
1673
+ * parameter. These copies utilize full alpha channel support and a choice
1674
+ * of the following modes to blend the colors of source pixels (A) with the
1675
+ * ones of pixels in the destination image (B):
1676
+ *
1934
1677
  * BLEND - linear interpolation of colours: C = A*factor + B
1935
- *
1678
+ *
1936
1679
  * ADD - additive blending with white clip: C = min(A*factor + B, 255)
1937
- *
1680
+ *
1938
1681
  * SUBTRACT - subtractive blending with black clip: C = max(B - A*factor,
1939
1682
  * 0)
1940
- *
1683
+ *
1941
1684
  * DARKEST - only the darkest colour succeeds: C = min(A*factor, B)
1942
- *
1685
+ *
1943
1686
  * LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)
1944
- *
1687
+ *
1945
1688
  * DIFFERENCE - subtract colors from underlying image.
1946
- *
1689
+ *
1947
1690
  * EXCLUSION - similar to DIFFERENCE, but less extreme.
1948
- *
1691
+ *
1949
1692
  * MULTIPLY - Multiply the colors, result will always be darker.
1950
- *
1693
+ *
1951
1694
  * SCREEN - Opposite multiply, uses inverse values of the colors.
1952
- *
1953
- * OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values, and screens
1954
- * light values.
1955
- *
1695
+ *
1696
+ * OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values,
1697
+ * and screens light values.
1698
+ *
1956
1699
  * HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
1957
- *
1958
- * SOFT_LIGHT - Mix of DARKEST and LIGHTEST. Works like OVERLAY, but not as
1959
- * harsh.
1960
- *
1961
- * DODGE - Lightens light tones and increases contrast, ignores darks. Called
1962
- * "Color Dodge" in Illustrator and Photoshop.
1963
- *
1700
+ *
1701
+ * SOFT_LIGHT - Mix of DARKEST and LIGHTEST.
1702
+ * Works like OVERLAY, but not as harsh.
1703
+ *
1704
+ * DODGE - Lightens light tones and increases contrast, ignores darks.
1705
+ * Called "Color Dodge" in Illustrator and Photoshop.
1706
+ *
1964
1707
  * BURN - Darker areas are applied, increasing contrast, ignores lights.
1965
1708
  * Called "Color Burn" in Illustrator and Photoshop.
1966
- *
1967
- * All modes use the alpha information (highest byte) of source image pixels
1968
- * as the blending factor. If the source and destination regions are different
1969
- * sizes, the image will be automatically resized to match the destination
1970
- * size. If the <b>srcImg</b> parameter is not used, the display window is
1971
- * used as the source image.
1972
- *
1709
+ *
1710
+ * All modes use the alpha information (highest byte) of source image
1711
+ * pixels as the blending factor. If the source and destination regions are
1712
+ * different sizes, the image will be automatically resized to match the
1713
+ * destination size. If the <b>srcImg</b> parameter is not used, the
1714
+ * display window is used as the source image.
1715
+ *
1973
1716
  * As of release 0149, this function ignores <b>imageMode()</b>.
1974
1717
  *
1975
1718
  * ( end auto-generated )
1976
1719
  *
1977
1720
  * @webref image:pixels
1978
- * @brief Copies a pixel or rectangle of pixels using different blending modes
1721
+ * @brief Copies a pixel or rectangle of pixels using different blending modes
1979
1722
  * @param src an image variable referring to the source image
1980
1723
  * @param sx X coordinate of the source's upper left corner
1981
1724
  * @param sy Y coordinate of the source's upper left corner
@@ -1985,16 +1728,15 @@ public class PImage implements PConstants, Cloneable {
1985
1728
  * @param dy Y coordinate of the destinations's upper left corner
1986
1729
  * @param dw destination image width
1987
1730
  * @param dh destination image height
1988
- * @param mode Either BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, DIFFERENCE,
1989
- * EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN
1731
+ * @param mode Either BLEND, ADD, SUBTRACT, LIGHTEST, DARKEST, DIFFERENCE, EXCLUSION, MULTIPLY, SCREEN, OVERLAY, HARD_LIGHT, SOFT_LIGHT, DODGE, BURN
1990
1732
  *
1991
1733
  * @see PApplet#alpha(int)
1992
1734
  * @see PImage#copy(PImage, int, int, int, int, int, int, int, int)
1993
1735
  * @see PImage#blendColor(int,int,int)
1994
1736
  */
1995
1737
  public void blend(PImage src,
1996
- int sx, int sy, int sw, int sh,
1997
- int dx, int dy, int dw, int dh, int mode) {
1738
+ int sx, int sy, int sw, int sh,
1739
+ int dx, int dy, int dw, int dh, int mode) {
1998
1740
  int sx2 = sx + sw;
1999
1741
  int sy2 = sy + sh;
2000
1742
  int dx2 = dx + dw;
@@ -2004,27 +1746,28 @@ public class PImage implements PConstants, Cloneable {
2004
1746
  if (src == this) {
2005
1747
  if (intersect(sx, sy, sx2, sy2, dx, dy, dx2, dy2)) {
2006
1748
  blit_resize(get(sx, sy, sw, sh),
2007
- 0, 0, sw, sh,
2008
- pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode);
1749
+ 0, 0, sw, sh,
1750
+ pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode);
2009
1751
  } else {
2010
1752
  // same as below, except skip the loadPixels() because it'd be redundant
2011
1753
  blit_resize(src, sx, sy, sx2, sy2,
2012
- pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode);
1754
+ pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode);
2013
1755
  }
2014
1756
  } else {
2015
1757
  src.loadPixels();
2016
1758
  blit_resize(src, sx, sy, sx2, sy2,
2017
- pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode);
1759
+ pixels, pixelWidth, pixelHeight, dx, dy, dx2, dy2, mode);
2018
1760
  //src.updatePixels();
2019
1761
  }
2020
1762
  updatePixels();
2021
1763
  }
2022
1764
 
1765
+
2023
1766
  /**
2024
1767
  * Check to see if two rectangles intersect one another
2025
1768
  */
2026
1769
  private boolean intersect(int sx1, int sy1, int sx2, int sy2,
2027
- int dx1, int dy1, int dx2, int dy2) {
1770
+ int dx1, int dy1, int dx2, int dy2) {
2028
1771
  int sw = sx2 - sx1 + 1;
2029
1772
  int sh = sy2 - sy1 + 1;
2030
1773
  int dw = dx2 - dx1 + 1;
@@ -2055,29 +1798,24 @@ public class PImage implements PConstants, Cloneable {
2055
1798
  return !(dw <= 0 || dh <= 0);
2056
1799
  }
2057
1800
 
1801
+
2058
1802
  //////////////////////////////////////////////////////////////
1803
+
1804
+
2059
1805
  /**
2060
- * Internal blitter/resizer/copier from toxi. Uses bilinear filtering if
2061
- * smooth() has been enabled 'mode' determines the blending mode used in the
2062
- * process.
1806
+ * Internal blitter/resizer/copier from toxi.
1807
+ * Uses bilinear filtering if smooth() has been enabled
1808
+ * 'mode' determines the blending mode used in the process.
2063
1809
  */
2064
1810
  private void blit_resize(PImage img,
2065
- int srcX1, int srcY1, int srcX2, int srcY2,
2066
- int[] destPixels, int screenW, int screenH,
2067
- int destX1, int destY1, int destX2, int destY2,
2068
- int mode) {
2069
- if (srcX1 < 0) {
2070
- srcX1 = 0;
2071
- }
2072
- if (srcY1 < 0) {
2073
- srcY1 = 0;
2074
- }
2075
- if (srcX2 > img.pixelWidth) {
2076
- srcX2 = img.pixelWidth;
2077
- }
2078
- if (srcY2 > img.pixelHeight) {
2079
- srcY2 = img.pixelHeight;
2080
- }
1811
+ int srcX1, int srcY1, int srcX2, int srcY2,
1812
+ int[] destPixels, int screenW, int screenH,
1813
+ int destX1, int destY1, int destX2, int destY2,
1814
+ int mode) {
1815
+ if (srcX1 < 0) srcX1 = 0;
1816
+ if (srcY1 < 0) srcY1 = 0;
1817
+ if (srcX2 > img.pixelWidth) srcX2 = img.pixelWidth;
1818
+ if (srcY2 > img.pixelHeight) srcY2 = img.pixelHeight;
2081
1819
 
2082
1820
  int srcW = srcX2 - srcX1;
2083
1821
  int srcH = srcY2 - srcY1;
@@ -2087,14 +1825,13 @@ public class PImage implements PConstants, Cloneable {
2087
1825
  boolean smooth = true; // may as well go with the smoothing these days
2088
1826
 
2089
1827
  if (!smooth) {
2090
- srcW++;
2091
- srcH++;
1828
+ srcW++; srcH++;
2092
1829
  }
2093
1830
 
2094
- if (destW <= 0 || destH <= 0
2095
- || srcW <= 0 || srcH <= 0
2096
- || destX1 >= screenW || destY1 >= screenH
2097
- || srcX1 >= img.pixelWidth || srcY1 >= img.pixelHeight) {
1831
+ if (destW <= 0 || destH <= 0 ||
1832
+ srcW <= 0 || srcH <= 0 ||
1833
+ destX1 >= screenW || destY1 >= screenH ||
1834
+ srcX1 >= img.pixelWidth || srcY1 >= img.pixelHeight) {
2098
1835
  return;
2099
1836
  }
2100
1837
 
@@ -2127,201 +1864,201 @@ public class PImage implements PConstants, Cloneable {
2127
1864
 
2128
1865
  switch (mode) {
2129
1866
 
2130
- case BLEND:
2131
- for (int y = 0; y < destH; y++) {
2132
- filter_new_scanline();
2133
- for (int x = 0; x < destW; x++) {
2134
- // davbol - renamed old blend_multiply to blend_blend
2135
- destPixels[destOffset + x]
2136
- = blend_blend(destPixels[destOffset + x], filter_bilinear());
2137
- sX += dx;
2138
- }
2139
- destOffset += screenW;
2140
- srcYOffset += dy;
1867
+ case BLEND:
1868
+ for (int y = 0; y < destH; y++) {
1869
+ filter_new_scanline();
1870
+ for (int x = 0; x < destW; x++) {
1871
+ // davbol - renamed old blend_multiply to blend_blend
1872
+ destPixels[destOffset + x] =
1873
+ blend_blend(destPixels[destOffset + x], filter_bilinear());
1874
+ sX += dx;
2141
1875
  }
2142
- break;
1876
+ destOffset += screenW;
1877
+ srcYOffset += dy;
1878
+ }
1879
+ break;
2143
1880
 
2144
- case ADD:
2145
- for (int y = 0; y < destH; y++) {
2146
- filter_new_scanline();
2147
- for (int x = 0; x < destW; x++) {
2148
- destPixels[destOffset + x]
2149
- = blend_add_pin(destPixels[destOffset + x], filter_bilinear());
2150
- sX += dx;
2151
- }
2152
- destOffset += screenW;
2153
- srcYOffset += dy;
1881
+ case ADD:
1882
+ for (int y = 0; y < destH; y++) {
1883
+ filter_new_scanline();
1884
+ for (int x = 0; x < destW; x++) {
1885
+ destPixels[destOffset + x] =
1886
+ blend_add_pin(destPixels[destOffset + x], filter_bilinear());
1887
+ sX += dx;
2154
1888
  }
2155
- break;
1889
+ destOffset += screenW;
1890
+ srcYOffset += dy;
1891
+ }
1892
+ break;
2156
1893
 
2157
- case SUBTRACT:
2158
- for (int y = 0; y < destH; y++) {
2159
- filter_new_scanline();
2160
- for (int x = 0; x < destW; x++) {
2161
- destPixels[destOffset + x]
2162
- = blend_sub_pin(destPixels[destOffset + x], filter_bilinear());
2163
- sX += dx;
2164
- }
2165
- destOffset += screenW;
2166
- srcYOffset += dy;
1894
+ case SUBTRACT:
1895
+ for (int y = 0; y < destH; y++) {
1896
+ filter_new_scanline();
1897
+ for (int x = 0; x < destW; x++) {
1898
+ destPixels[destOffset + x] =
1899
+ blend_sub_pin(destPixels[destOffset + x], filter_bilinear());
1900
+ sX += dx;
2167
1901
  }
2168
- break;
1902
+ destOffset += screenW;
1903
+ srcYOffset += dy;
1904
+ }
1905
+ break;
2169
1906
 
2170
- case LIGHTEST:
2171
- for (int y = 0; y < destH; y++) {
2172
- filter_new_scanline();
2173
- for (int x = 0; x < destW; x++) {
2174
- destPixels[destOffset + x]
2175
- = blend_lightest(destPixels[destOffset + x], filter_bilinear());
2176
- sX += dx;
2177
- }
2178
- destOffset += screenW;
2179
- srcYOffset += dy;
1907
+ case LIGHTEST:
1908
+ for (int y = 0; y < destH; y++) {
1909
+ filter_new_scanline();
1910
+ for (int x = 0; x < destW; x++) {
1911
+ destPixels[destOffset + x] =
1912
+ blend_lightest(destPixels[destOffset + x], filter_bilinear());
1913
+ sX += dx;
2180
1914
  }
2181
- break;
1915
+ destOffset += screenW;
1916
+ srcYOffset += dy;
1917
+ }
1918
+ break;
2182
1919
 
2183
- case DARKEST:
2184
- for (int y = 0; y < destH; y++) {
2185
- filter_new_scanline();
2186
- for (int x = 0; x < destW; x++) {
2187
- destPixels[destOffset + x]
2188
- = blend_darkest(destPixels[destOffset + x], filter_bilinear());
2189
- sX += dx;
2190
- }
2191
- destOffset += screenW;
2192
- srcYOffset += dy;
1920
+ case DARKEST:
1921
+ for (int y = 0; y < destH; y++) {
1922
+ filter_new_scanline();
1923
+ for (int x = 0; x < destW; x++) {
1924
+ destPixels[destOffset + x] =
1925
+ blend_darkest(destPixels[destOffset + x], filter_bilinear());
1926
+ sX += dx;
2193
1927
  }
2194
- break;
1928
+ destOffset += screenW;
1929
+ srcYOffset += dy;
1930
+ }
1931
+ break;
2195
1932
 
2196
- case REPLACE:
2197
- for (int y = 0; y < destH; y++) {
2198
- filter_new_scanline();
2199
- for (int x = 0; x < destW; x++) {
2200
- destPixels[destOffset + x] = filter_bilinear();
2201
- sX += dx;
2202
- }
2203
- destOffset += screenW;
2204
- srcYOffset += dy;
1933
+ case REPLACE:
1934
+ for (int y = 0; y < destH; y++) {
1935
+ filter_new_scanline();
1936
+ for (int x = 0; x < destW; x++) {
1937
+ destPixels[destOffset + x] = filter_bilinear();
1938
+ sX += dx;
2205
1939
  }
2206
- break;
1940
+ destOffset += screenW;
1941
+ srcYOffset += dy;
1942
+ }
1943
+ break;
2207
1944
 
2208
- case DIFFERENCE:
2209
- for (int y = 0; y < destH; y++) {
2210
- filter_new_scanline();
2211
- for (int x = 0; x < destW; x++) {
2212
- destPixels[destOffset + x]
2213
- = blend_difference(destPixels[destOffset + x], filter_bilinear());
2214
- sX += dx;
2215
- }
2216
- destOffset += screenW;
2217
- srcYOffset += dy;
1945
+ case DIFFERENCE:
1946
+ for (int y = 0; y < destH; y++) {
1947
+ filter_new_scanline();
1948
+ for (int x = 0; x < destW; x++) {
1949
+ destPixels[destOffset + x] =
1950
+ blend_difference(destPixels[destOffset + x], filter_bilinear());
1951
+ sX += dx;
2218
1952
  }
2219
- break;
1953
+ destOffset += screenW;
1954
+ srcYOffset += dy;
1955
+ }
1956
+ break;
2220
1957
 
2221
- case EXCLUSION:
2222
- for (int y = 0; y < destH; y++) {
2223
- filter_new_scanline();
2224
- for (int x = 0; x < destW; x++) {
2225
- destPixels[destOffset + x]
2226
- = blend_exclusion(destPixels[destOffset + x], filter_bilinear());
2227
- sX += dx;
2228
- }
2229
- destOffset += screenW;
2230
- srcYOffset += dy;
1958
+ case EXCLUSION:
1959
+ for (int y = 0; y < destH; y++) {
1960
+ filter_new_scanline();
1961
+ for (int x = 0; x < destW; x++) {
1962
+ destPixels[destOffset + x] =
1963
+ blend_exclusion(destPixels[destOffset + x], filter_bilinear());
1964
+ sX += dx;
2231
1965
  }
2232
- break;
1966
+ destOffset += screenW;
1967
+ srcYOffset += dy;
1968
+ }
1969
+ break;
2233
1970
 
2234
- case MULTIPLY:
2235
- for (int y = 0; y < destH; y++) {
2236
- filter_new_scanline();
2237
- for (int x = 0; x < destW; x++) {
2238
- destPixels[destOffset + x]
2239
- = blend_multiply(destPixels[destOffset + x], filter_bilinear());
2240
- sX += dx;
2241
- }
2242
- destOffset += screenW;
2243
- srcYOffset += dy;
1971
+ case MULTIPLY:
1972
+ for (int y = 0; y < destH; y++) {
1973
+ filter_new_scanline();
1974
+ for (int x = 0; x < destW; x++) {
1975
+ destPixels[destOffset + x] =
1976
+ blend_multiply(destPixels[destOffset + x], filter_bilinear());
1977
+ sX += dx;
2244
1978
  }
2245
- break;
1979
+ destOffset += screenW;
1980
+ srcYOffset += dy;
1981
+ }
1982
+ break;
2246
1983
 
2247
- case SCREEN:
2248
- for (int y = 0; y < destH; y++) {
2249
- filter_new_scanline();
2250
- for (int x = 0; x < destW; x++) {
2251
- destPixels[destOffset + x]
2252
- = blend_screen(destPixels[destOffset + x], filter_bilinear());
2253
- sX += dx;
2254
- }
2255
- destOffset += screenW;
2256
- srcYOffset += dy;
1984
+ case SCREEN:
1985
+ for (int y = 0; y < destH; y++) {
1986
+ filter_new_scanline();
1987
+ for (int x = 0; x < destW; x++) {
1988
+ destPixels[destOffset + x] =
1989
+ blend_screen(destPixels[destOffset + x], filter_bilinear());
1990
+ sX += dx;
2257
1991
  }
2258
- break;
1992
+ destOffset += screenW;
1993
+ srcYOffset += dy;
1994
+ }
1995
+ break;
2259
1996
 
2260
- case OVERLAY:
2261
- for (int y = 0; y < destH; y++) {
2262
- filter_new_scanline();
2263
- for (int x = 0; x < destW; x++) {
2264
- destPixels[destOffset + x]
2265
- = blend_overlay(destPixels[destOffset + x], filter_bilinear());
2266
- sX += dx;
2267
- }
2268
- destOffset += screenW;
2269
- srcYOffset += dy;
1997
+ case OVERLAY:
1998
+ for (int y = 0; y < destH; y++) {
1999
+ filter_new_scanline();
2000
+ for (int x = 0; x < destW; x++) {
2001
+ destPixels[destOffset + x] =
2002
+ blend_overlay(destPixels[destOffset + x], filter_bilinear());
2003
+ sX += dx;
2270
2004
  }
2271
- break;
2005
+ destOffset += screenW;
2006
+ srcYOffset += dy;
2007
+ }
2008
+ break;
2272
2009
 
2273
- case HARD_LIGHT:
2274
- for (int y = 0; y < destH; y++) {
2275
- filter_new_scanline();
2276
- for (int x = 0; x < destW; x++) {
2277
- destPixels[destOffset + x]
2278
- = blend_hard_light(destPixels[destOffset + x], filter_bilinear());
2279
- sX += dx;
2280
- }
2281
- destOffset += screenW;
2282
- srcYOffset += dy;
2010
+ case HARD_LIGHT:
2011
+ for (int y = 0; y < destH; y++) {
2012
+ filter_new_scanline();
2013
+ for (int x = 0; x < destW; x++) {
2014
+ destPixels[destOffset + x] =
2015
+ blend_hard_light(destPixels[destOffset + x], filter_bilinear());
2016
+ sX += dx;
2283
2017
  }
2284
- break;
2018
+ destOffset += screenW;
2019
+ srcYOffset += dy;
2020
+ }
2021
+ break;
2285
2022
 
2286
- case SOFT_LIGHT:
2287
- for (int y = 0; y < destH; y++) {
2288
- filter_new_scanline();
2289
- for (int x = 0; x < destW; x++) {
2290
- destPixels[destOffset + x]
2291
- = blend_soft_light(destPixels[destOffset + x], filter_bilinear());
2292
- sX += dx;
2293
- }
2294
- destOffset += screenW;
2295
- srcYOffset += dy;
2023
+ case SOFT_LIGHT:
2024
+ for (int y = 0; y < destH; y++) {
2025
+ filter_new_scanline();
2026
+ for (int x = 0; x < destW; x++) {
2027
+ destPixels[destOffset + x] =
2028
+ blend_soft_light(destPixels[destOffset + x], filter_bilinear());
2029
+ sX += dx;
2296
2030
  }
2297
- break;
2031
+ destOffset += screenW;
2032
+ srcYOffset += dy;
2033
+ }
2034
+ break;
2298
2035
 
2299
- // davbol - proposed 2007-01-09
2300
- case DODGE:
2301
- for (int y = 0; y < destH; y++) {
2302
- filter_new_scanline();
2303
- for (int x = 0; x < destW; x++) {
2304
- destPixels[destOffset + x]
2305
- = blend_dodge(destPixels[destOffset + x], filter_bilinear());
2306
- sX += dx;
2307
- }
2308
- destOffset += screenW;
2309
- srcYOffset += dy;
2036
+ // davbol - proposed 2007-01-09
2037
+ case DODGE:
2038
+ for (int y = 0; y < destH; y++) {
2039
+ filter_new_scanline();
2040
+ for (int x = 0; x < destW; x++) {
2041
+ destPixels[destOffset + x] =
2042
+ blend_dodge(destPixels[destOffset + x], filter_bilinear());
2043
+ sX += dx;
2310
2044
  }
2311
- break;
2045
+ destOffset += screenW;
2046
+ srcYOffset += dy;
2047
+ }
2048
+ break;
2312
2049
 
2313
- case BURN:
2314
- for (int y = 0; y < destH; y++) {
2315
- filter_new_scanline();
2316
- for (int x = 0; x < destW; x++) {
2317
- destPixels[destOffset + x]
2318
- = blend_burn(destPixels[destOffset + x], filter_bilinear());
2319
- sX += dx;
2320
- }
2321
- destOffset += screenW;
2322
- srcYOffset += dy;
2050
+ case BURN:
2051
+ for (int y = 0; y < destH; y++) {
2052
+ filter_new_scanline();
2053
+ for (int x = 0; x < destW; x++) {
2054
+ destPixels[destOffset + x] =
2055
+ blend_burn(destPixels[destOffset + x], filter_bilinear());
2056
+ sX += dx;
2323
2057
  }
2324
- break;
2058
+ destOffset += screenW;
2059
+ srcYOffset += dy;
2060
+ }
2061
+ break;
2325
2062
 
2326
2063
  }
2327
2064
 
@@ -2329,235 +2066,236 @@ public class PImage implements PConstants, Cloneable {
2329
2066
  // nearest neighbour scaling (++fast!)
2330
2067
  switch (mode) {
2331
2068
 
2332
- case BLEND:
2333
- for (int y = 0; y < destH; y++) {
2334
- sX = srcXOffset;
2335
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2336
- for (int x = 0; x < destW; x++) {
2337
- // davbol - renamed old blend_multiply to blend_blend
2338
- destPixels[destOffset + x]
2339
- = blend_blend(destPixels[destOffset + x],
2340
- srcBuffer[sY + (sX >> PRECISIONB)]);
2341
- sX += dx;
2342
- }
2343
- destOffset += screenW;
2344
- srcYOffset += dy;
2069
+ case BLEND:
2070
+ for (int y = 0; y < destH; y++) {
2071
+ sX = srcXOffset;
2072
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2073
+ for (int x = 0; x < destW; x++) {
2074
+ // davbol - renamed old blend_multiply to blend_blend
2075
+ destPixels[destOffset + x] =
2076
+ blend_blend(destPixels[destOffset + x],
2077
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2078
+ sX += dx;
2345
2079
  }
2346
- break;
2080
+ destOffset += screenW;
2081
+ srcYOffset += dy;
2082
+ }
2083
+ break;
2347
2084
 
2348
- case ADD:
2349
- for (int y = 0; y < destH; y++) {
2350
- sX = srcXOffset;
2351
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2352
- for (int x = 0; x < destW; x++) {
2353
- destPixels[destOffset + x]
2354
- = blend_add_pin(destPixels[destOffset + x],
2355
- srcBuffer[sY + (sX >> PRECISIONB)]);
2356
- sX += dx;
2357
- }
2358
- destOffset += screenW;
2359
- srcYOffset += dy;
2085
+ case ADD:
2086
+ for (int y = 0; y < destH; y++) {
2087
+ sX = srcXOffset;
2088
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2089
+ for (int x = 0; x < destW; x++) {
2090
+ destPixels[destOffset + x] =
2091
+ blend_add_pin(destPixels[destOffset + x],
2092
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2093
+ sX += dx;
2360
2094
  }
2361
- break;
2095
+ destOffset += screenW;
2096
+ srcYOffset += dy;
2097
+ }
2098
+ break;
2362
2099
 
2363
- case SUBTRACT:
2364
- for (int y = 0; y < destH; y++) {
2365
- sX = srcXOffset;
2366
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2367
- for (int x = 0; x < destW; x++) {
2368
- destPixels[destOffset + x]
2369
- = blend_sub_pin(destPixels[destOffset + x],
2370
- srcBuffer[sY + (sX >> PRECISIONB)]);
2371
- sX += dx;
2372
- }
2373
- destOffset += screenW;
2374
- srcYOffset += dy;
2100
+ case SUBTRACT:
2101
+ for (int y = 0; y < destH; y++) {
2102
+ sX = srcXOffset;
2103
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2104
+ for (int x = 0; x < destW; x++) {
2105
+ destPixels[destOffset + x] =
2106
+ blend_sub_pin(destPixels[destOffset + x],
2107
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2108
+ sX += dx;
2375
2109
  }
2376
- break;
2110
+ destOffset += screenW;
2111
+ srcYOffset += dy;
2112
+ }
2113
+ break;
2377
2114
 
2378
- case LIGHTEST:
2379
- for (int y = 0; y < destH; y++) {
2380
- sX = srcXOffset;
2381
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2382
- for (int x = 0; x < destW; x++) {
2383
- destPixels[destOffset + x]
2384
- = blend_lightest(destPixels[destOffset + x],
2385
- srcBuffer[sY + (sX >> PRECISIONB)]);
2386
- sX += dx;
2387
- }
2388
- destOffset += screenW;
2389
- srcYOffset += dy;
2115
+ case LIGHTEST:
2116
+ for (int y = 0; y < destH; y++) {
2117
+ sX = srcXOffset;
2118
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2119
+ for (int x = 0; x < destW; x++) {
2120
+ destPixels[destOffset + x] =
2121
+ blend_lightest(destPixels[destOffset + x],
2122
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2123
+ sX += dx;
2390
2124
  }
2391
- break;
2125
+ destOffset += screenW;
2126
+ srcYOffset += dy;
2127
+ }
2128
+ break;
2392
2129
 
2393
- case DARKEST:
2394
- for (int y = 0; y < destH; y++) {
2395
- sX = srcXOffset;
2396
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2397
- for (int x = 0; x < destW; x++) {
2398
- destPixels[destOffset + x]
2399
- = blend_darkest(destPixels[destOffset + x],
2400
- srcBuffer[sY + (sX >> PRECISIONB)]);
2401
- sX += dx;
2402
- }
2403
- destOffset += screenW;
2404
- srcYOffset += dy;
2130
+ case DARKEST:
2131
+ for (int y = 0; y < destH; y++) {
2132
+ sX = srcXOffset;
2133
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2134
+ for (int x = 0; x < destW; x++) {
2135
+ destPixels[destOffset + x] =
2136
+ blend_darkest(destPixels[destOffset + x],
2137
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2138
+ sX += dx;
2405
2139
  }
2406
- break;
2140
+ destOffset += screenW;
2141
+ srcYOffset += dy;
2142
+ }
2143
+ break;
2407
2144
 
2408
- case REPLACE:
2409
- for (int y = 0; y < destH; y++) {
2410
- sX = srcXOffset;
2411
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2412
- for (int x = 0; x < destW; x++) {
2413
- destPixels[destOffset + x] = srcBuffer[sY + (sX >> PRECISIONB)];
2414
- sX += dx;
2415
- }
2416
- destOffset += screenW;
2417
- srcYOffset += dy;
2145
+ case REPLACE:
2146
+ for (int y = 0; y < destH; y++) {
2147
+ sX = srcXOffset;
2148
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2149
+ for (int x = 0; x < destW; x++) {
2150
+ destPixels[destOffset + x] = srcBuffer[sY + (sX >> PRECISIONB)];
2151
+ sX += dx;
2418
2152
  }
2419
- break;
2153
+ destOffset += screenW;
2154
+ srcYOffset += dy;
2155
+ }
2156
+ break;
2420
2157
 
2421
- case DIFFERENCE:
2422
- for (int y = 0; y < destH; y++) {
2423
- sX = srcXOffset;
2424
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2425
- for (int x = 0; x < destW; x++) {
2426
- destPixels[destOffset + x]
2427
- = blend_difference(destPixels[destOffset + x],
2428
- srcBuffer[sY + (sX >> PRECISIONB)]);
2429
- sX += dx;
2430
- }
2431
- destOffset += screenW;
2432
- srcYOffset += dy;
2158
+ case DIFFERENCE:
2159
+ for (int y = 0; y < destH; y++) {
2160
+ sX = srcXOffset;
2161
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2162
+ for (int x = 0; x < destW; x++) {
2163
+ destPixels[destOffset + x] =
2164
+ blend_difference(destPixels[destOffset + x],
2165
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2166
+ sX += dx;
2433
2167
  }
2434
- break;
2168
+ destOffset += screenW;
2169
+ srcYOffset += dy;
2170
+ }
2171
+ break;
2435
2172
 
2436
- case EXCLUSION:
2437
- for (int y = 0; y < destH; y++) {
2438
- sX = srcXOffset;
2439
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2440
- for (int x = 0; x < destW; x++) {
2441
- destPixels[destOffset + x]
2442
- = blend_exclusion(destPixels[destOffset + x],
2443
- srcBuffer[sY + (sX >> PRECISIONB)]);
2444
- sX += dx;
2445
- }
2446
- destOffset += screenW;
2447
- srcYOffset += dy;
2173
+ case EXCLUSION:
2174
+ for (int y = 0; y < destH; y++) {
2175
+ sX = srcXOffset;
2176
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2177
+ for (int x = 0; x < destW; x++) {
2178
+ destPixels[destOffset + x] =
2179
+ blend_exclusion(destPixels[destOffset + x],
2180
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2181
+ sX += dx;
2448
2182
  }
2449
- break;
2183
+ destOffset += screenW;
2184
+ srcYOffset += dy;
2185
+ }
2186
+ break;
2450
2187
 
2451
- case MULTIPLY:
2452
- for (int y = 0; y < destH; y++) {
2453
- sX = srcXOffset;
2454
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2455
- for (int x = 0; x < destW; x++) {
2456
- destPixels[destOffset + x]
2457
- = blend_multiply(destPixels[destOffset + x],
2458
- srcBuffer[sY + (sX >> PRECISIONB)]);
2459
- sX += dx;
2460
- }
2461
- destOffset += screenW;
2462
- srcYOffset += dy;
2188
+ case MULTIPLY:
2189
+ for (int y = 0; y < destH; y++) {
2190
+ sX = srcXOffset;
2191
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2192
+ for (int x = 0; x < destW; x++) {
2193
+ destPixels[destOffset + x] =
2194
+ blend_multiply(destPixels[destOffset + x],
2195
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2196
+ sX += dx;
2463
2197
  }
2464
- break;
2198
+ destOffset += screenW;
2199
+ srcYOffset += dy;
2200
+ }
2201
+ break;
2465
2202
 
2466
- case SCREEN:
2467
- for (int y = 0; y < destH; y++) {
2468
- sX = srcXOffset;
2469
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2470
- for (int x = 0; x < destW; x++) {
2471
- destPixels[destOffset + x]
2472
- = blend_screen(destPixels[destOffset + x],
2473
- srcBuffer[sY + (sX >> PRECISIONB)]);
2474
- sX += dx;
2475
- }
2476
- destOffset += screenW;
2477
- srcYOffset += dy;
2203
+ case SCREEN:
2204
+ for (int y = 0; y < destH; y++) {
2205
+ sX = srcXOffset;
2206
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2207
+ for (int x = 0; x < destW; x++) {
2208
+ destPixels[destOffset + x] =
2209
+ blend_screen(destPixels[destOffset + x],
2210
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2211
+ sX += dx;
2478
2212
  }
2479
- break;
2213
+ destOffset += screenW;
2214
+ srcYOffset += dy;
2215
+ }
2216
+ break;
2480
2217
 
2481
- case OVERLAY:
2482
- for (int y = 0; y < destH; y++) {
2483
- sX = srcXOffset;
2484
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2485
- for (int x = 0; x < destW; x++) {
2486
- destPixels[destOffset + x]
2487
- = blend_overlay(destPixels[destOffset + x],
2488
- srcBuffer[sY + (sX >> PRECISIONB)]);
2489
- sX += dx;
2490
- }
2491
- destOffset += screenW;
2492
- srcYOffset += dy;
2218
+ case OVERLAY:
2219
+ for (int y = 0; y < destH; y++) {
2220
+ sX = srcXOffset;
2221
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2222
+ for (int x = 0; x < destW; x++) {
2223
+ destPixels[destOffset + x] =
2224
+ blend_overlay(destPixels[destOffset + x],
2225
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2226
+ sX += dx;
2493
2227
  }
2494
- break;
2228
+ destOffset += screenW;
2229
+ srcYOffset += dy;
2230
+ }
2231
+ break;
2495
2232
 
2496
- case HARD_LIGHT:
2497
- for (int y = 0; y < destH; y++) {
2498
- sX = srcXOffset;
2499
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2500
- for (int x = 0; x < destW; x++) {
2501
- destPixels[destOffset + x]
2502
- = blend_hard_light(destPixels[destOffset + x],
2503
- srcBuffer[sY + (sX >> PRECISIONB)]);
2504
- sX += dx;
2505
- }
2506
- destOffset += screenW;
2507
- srcYOffset += dy;
2233
+ case HARD_LIGHT:
2234
+ for (int y = 0; y < destH; y++) {
2235
+ sX = srcXOffset;
2236
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2237
+ for (int x = 0; x < destW; x++) {
2238
+ destPixels[destOffset + x] =
2239
+ blend_hard_light(destPixels[destOffset + x],
2240
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2241
+ sX += dx;
2508
2242
  }
2509
- break;
2243
+ destOffset += screenW;
2244
+ srcYOffset += dy;
2245
+ }
2246
+ break;
2510
2247
 
2511
- case SOFT_LIGHT:
2512
- for (int y = 0; y < destH; y++) {
2513
- sX = srcXOffset;
2514
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2515
- for (int x = 0; x < destW; x++) {
2516
- destPixels[destOffset + x]
2517
- = blend_soft_light(destPixels[destOffset + x],
2518
- srcBuffer[sY + (sX >> PRECISIONB)]);
2519
- sX += dx;
2520
- }
2521
- destOffset += screenW;
2522
- srcYOffset += dy;
2248
+ case SOFT_LIGHT:
2249
+ for (int y = 0; y < destH; y++) {
2250
+ sX = srcXOffset;
2251
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2252
+ for (int x = 0; x < destW; x++) {
2253
+ destPixels[destOffset + x] =
2254
+ blend_soft_light(destPixels[destOffset + x],
2255
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2256
+ sX += dx;
2523
2257
  }
2524
- break;
2258
+ destOffset += screenW;
2259
+ srcYOffset += dy;
2260
+ }
2261
+ break;
2525
2262
 
2526
- // davbol - proposed 2007-01-09
2527
- case DODGE:
2528
- for (int y = 0; y < destH; y++) {
2529
- sX = srcXOffset;
2530
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2531
- for (int x = 0; x < destW; x++) {
2532
- destPixels[destOffset + x]
2533
- = blend_dodge(destPixels[destOffset + x],
2534
- srcBuffer[sY + (sX >> PRECISIONB)]);
2535
- sX += dx;
2536
- }
2537
- destOffset += screenW;
2538
- srcYOffset += dy;
2263
+ // davbol - proposed 2007-01-09
2264
+ case DODGE:
2265
+ for (int y = 0; y < destH; y++) {
2266
+ sX = srcXOffset;
2267
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2268
+ for (int x = 0; x < destW; x++) {
2269
+ destPixels[destOffset + x] =
2270
+ blend_dodge(destPixels[destOffset + x],
2271
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2272
+ sX += dx;
2539
2273
  }
2540
- break;
2274
+ destOffset += screenW;
2275
+ srcYOffset += dy;
2276
+ }
2277
+ break;
2541
2278
 
2542
- case BURN:
2543
- for (int y = 0; y < destH; y++) {
2544
- sX = srcXOffset;
2545
- sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2546
- for (int x = 0; x < destW; x++) {
2547
- destPixels[destOffset + x]
2548
- = blend_burn(destPixels[destOffset + x],
2549
- srcBuffer[sY + (sX >> PRECISIONB)]);
2550
- sX += dx;
2551
- }
2552
- destOffset += screenW;
2553
- srcYOffset += dy;
2279
+ case BURN:
2280
+ for (int y = 0; y < destH; y++) {
2281
+ sX = srcXOffset;
2282
+ sY = (srcYOffset >> PRECISIONB) * img.pixelWidth;
2283
+ for (int x = 0; x < destW; x++) {
2284
+ destPixels[destOffset + x] =
2285
+ blend_burn(destPixels[destOffset + x],
2286
+ srcBuffer[sY + (sX >> PRECISIONB)]);
2287
+ sX += dx;
2554
2288
  }
2555
- break;
2289
+ destOffset += screenW;
2290
+ srcYOffset += dy;
2291
+ }
2292
+ break;
2556
2293
 
2557
2294
  }
2558
2295
  }
2559
2296
  }
2560
2297
 
2298
+
2561
2299
  private void filter_new_scanline() {
2562
2300
  sX = srcXOffset;
2563
2301
  fracV = srcYOffset & PREC_MAXVAL;
@@ -2566,6 +2304,7 @@ public class PImage implements PConstants, Cloneable {
2566
2304
  v2 = min((srcYOffset >> PRECISIONB) + 1, ih1) * iw;
2567
2305
  }
2568
2306
 
2307
+
2569
2308
  private int filter_bilinear() {
2570
2309
  fracU = sX & PREC_MAXVAL;
2571
2310
  ifU = PREC_MAXVAL - fracU + 1;
@@ -2582,36 +2321,44 @@ public class PImage implements PConstants, Cloneable {
2582
2321
  cLL = srcBuffer[v2 + u1];
2583
2322
  cLR = srcBuffer[v2 + u2];
2584
2323
 
2585
- r = ((ul * ((cUL & RED_MASK) >> 16) + ll * ((cLL & RED_MASK) >> 16)
2586
- + ur * ((cUR & RED_MASK) >> 16) + lr * ((cLR & RED_MASK) >> 16))
2587
- << PREC_RED_SHIFT) & RED_MASK;
2324
+ r = ((ul*((cUL&RED_MASK)>>16) + ll*((cLL&RED_MASK)>>16) +
2325
+ ur*((cUR&RED_MASK)>>16) + lr*((cLR&RED_MASK)>>16))
2326
+ << PREC_RED_SHIFT) & RED_MASK;
2588
2327
 
2589
- g = ((ul * (cUL & GREEN_MASK) + ll * (cLL & GREEN_MASK)
2590
- + ur * (cUR & GREEN_MASK) + lr * (cLR & GREEN_MASK))
2591
- >>> PRECISIONB) & GREEN_MASK;
2328
+ g = ((ul*(cUL&GREEN_MASK) + ll*(cLL&GREEN_MASK) +
2329
+ ur*(cUR&GREEN_MASK) + lr*(cLR&GREEN_MASK))
2330
+ >>> PRECISIONB) & GREEN_MASK;
2592
2331
 
2593
- b = (ul * (cUL & BLUE_MASK) + ll * (cLL & BLUE_MASK)
2594
- + ur * (cUR & BLUE_MASK) + lr * (cLR & BLUE_MASK))
2595
- >>> PRECISIONB;
2332
+ b = (ul*(cUL&BLUE_MASK) + ll*(cLL&BLUE_MASK) +
2333
+ ur*(cUR&BLUE_MASK) + lr*(cLR&BLUE_MASK))
2334
+ >>> PRECISIONB;
2596
2335
 
2597
- a = ((ul * ((cUL & ALPHA_MASK) >>> 24) + ll * ((cLL & ALPHA_MASK) >>> 24)
2598
- + ur * ((cUR & ALPHA_MASK) >>> 24) + lr * ((cLR & ALPHA_MASK) >>> 24))
2599
- << PREC_ALPHA_SHIFT) & ALPHA_MASK;
2336
+ a = ((ul*((cUL&ALPHA_MASK)>>>24) + ll*((cLL&ALPHA_MASK)>>>24) +
2337
+ ur*((cUR&ALPHA_MASK)>>>24) + lr*((cLR&ALPHA_MASK)>>>24))
2338
+ << PREC_ALPHA_SHIFT) & ALPHA_MASK;
2600
2339
 
2601
2340
  return a | r | g | b;
2602
2341
  }
2603
2342
 
2343
+
2344
+
2604
2345
  //////////////////////////////////////////////////////////////
2346
+
2605
2347
  // internal blending methods
2348
+
2349
+
2606
2350
  private static int min(int a, int b) {
2607
2351
  return (a < b) ? a : b;
2608
2352
  }
2609
2353
 
2354
+
2610
2355
  private static int max(int a, int b) {
2611
2356
  return (a > b) ? a : b;
2612
2357
  }
2613
2358
 
2359
+
2614
2360
  /////////////////////////////////////////////////////////////
2361
+
2615
2362
  // BLEND MODE IMPLEMENTATIONS
2616
2363
 
2617
2364
  /*
@@ -2700,11 +2447,13 @@ int testFunction(int dst, int src) {
2700
2447
  *
2701
2448
  *
2702
2449
  */
2450
+
2703
2451
  private static final int RB_MASK = 0x00FF00FF;
2704
2452
  private static final int GN_MASK = 0x0000FF00;
2705
2453
 
2706
2454
  /**
2707
- * Blend O = S
2455
+ * Blend
2456
+ * O = S
2708
2457
  */
2709
2458
  private static int blend_blend(int dst, int src) {
2710
2459
  int a = src >>> 24;
@@ -2712,13 +2461,15 @@ int testFunction(int dst, int src) {
2712
2461
  int s_a = a + (a >= 0x7F ? 1 : 0);
2713
2462
  int d_a = 0x100 - s_a;
2714
2463
 
2715
- return min((dst >>> 24) + a, 0xFF) << 24
2716
- | ((dst & RB_MASK) * d_a + (src & RB_MASK) * s_a) >>> 8 & RB_MASK
2717
- | ((dst & GN_MASK) * d_a + (src & GN_MASK) * s_a) >>> 8 & GN_MASK;
2464
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2465
+ ((dst & RB_MASK) * d_a + (src & RB_MASK) * s_a) >>> 8 & RB_MASK |
2466
+ ((dst & GN_MASK) * d_a + (src & GN_MASK) * s_a) >>> 8 & GN_MASK;
2718
2467
  }
2719
2468
 
2469
+
2720
2470
  /**
2721
- * Add O = MIN(D + S, 1)
2471
+ * Add
2472
+ * O = MIN(D + S, 1)
2722
2473
  */
2723
2474
  private static int blend_add_pin(int dst, int src) {
2724
2475
  int a = src >>> 24;
@@ -2728,31 +2479,35 @@ int testFunction(int dst, int src) {
2728
2479
  int rb = (dst & RB_MASK) + ((src & RB_MASK) * s_a >>> 8 & RB_MASK);
2729
2480
  int gn = (dst & GN_MASK) + ((src & GN_MASK) * s_a >>> 8);
2730
2481
 
2731
- return min((dst >>> 24) + a, 0xFF) << 24
2732
- | min(rb & 0xFFFF0000, RED_MASK)
2733
- | min(gn & 0x00FFFF00, GREEN_MASK)
2734
- | min(rb & 0x0000FFFF, BLUE_MASK);
2482
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2483
+ min(rb & 0xFFFF0000, RED_MASK) |
2484
+ min(gn & 0x00FFFF00, GREEN_MASK) |
2485
+ min(rb & 0x0000FFFF, BLUE_MASK);
2735
2486
  }
2736
2487
 
2488
+
2737
2489
  /**
2738
- * Subtract O = MAX(0, D - S)
2490
+ * Subtract
2491
+ * O = MAX(0, D - S)
2739
2492
  */
2740
2493
  private static int blend_sub_pin(int dst, int src) {
2741
2494
  int a = src >>> 24;
2742
2495
 
2743
2496
  int s_a = a + (a >= 0x7F ? 1 : 0);
2744
2497
 
2745
- int rb = ((src & RB_MASK) * s_a >>> 8);
2498
+ int rb = ((src & RB_MASK) * s_a >>> 8);
2746
2499
  int gn = ((src & GREEN_MASK) * s_a >>> 8);
2747
2500
 
2748
- return min((dst >>> 24) + a, 0xFF) << 24
2749
- | max((dst & RED_MASK) - (rb & RED_MASK), 0)
2750
- | max((dst & GREEN_MASK) - (gn & GREEN_MASK), 0)
2751
- | max((dst & BLUE_MASK) - (rb & BLUE_MASK), 0);
2501
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2502
+ max((dst & RED_MASK) - (rb & RED_MASK), 0) |
2503
+ max((dst & GREEN_MASK) - (gn & GREEN_MASK), 0) |
2504
+ max((dst & BLUE_MASK) - (rb & BLUE_MASK), 0);
2752
2505
  }
2753
2506
 
2507
+
2754
2508
  /**
2755
- * Lightest O = MAX(D, S)
2509
+ * Lightest
2510
+ * O = MAX(D, S)
2756
2511
  */
2757
2512
  private static int blend_lightest(int dst, int src) {
2758
2513
  int a = src >>> 24;
@@ -2760,17 +2515,19 @@ int testFunction(int dst, int src) {
2760
2515
  int s_a = a + (a >= 0x7F ? 1 : 0);
2761
2516
  int d_a = 0x100 - s_a;
2762
2517
 
2763
- int rb = max(src & RED_MASK, dst & RED_MASK)
2764
- | max(src & BLUE_MASK, dst & BLUE_MASK);
2518
+ int rb = max(src & RED_MASK, dst & RED_MASK) |
2519
+ max(src & BLUE_MASK, dst & BLUE_MASK);
2765
2520
  int gn = max(src & GREEN_MASK, dst & GREEN_MASK);
2766
2521
 
2767
- return min((dst >>> 24) + a, 0xFF) << 24
2768
- | ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK
2769
- | ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2522
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2523
+ ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK |
2524
+ ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2770
2525
  }
2771
2526
 
2527
+
2772
2528
  /**
2773
- * Darkest O = MIN(D, S)
2529
+ * Darkest
2530
+ * O = MIN(D, S)
2774
2531
  */
2775
2532
  private static int blend_darkest(int dst, int src) {
2776
2533
  int a = src >>> 24;
@@ -2778,17 +2535,19 @@ int testFunction(int dst, int src) {
2778
2535
  int s_a = a + (a >= 0x7F ? 1 : 0);
2779
2536
  int d_a = 0x100 - s_a;
2780
2537
 
2781
- int rb = min(src & RED_MASK, dst & RED_MASK)
2782
- | min(src & BLUE_MASK, dst & BLUE_MASK);
2538
+ int rb = min(src & RED_MASK, dst & RED_MASK) |
2539
+ min(src & BLUE_MASK, dst & BLUE_MASK);
2783
2540
  int gn = min(src & GREEN_MASK, dst & GREEN_MASK);
2784
2541
 
2785
- return min((dst >>> 24) + a, 0xFF) << 24
2786
- | ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK
2787
- | ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2542
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2543
+ ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK |
2544
+ ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2788
2545
  }
2789
2546
 
2547
+
2790
2548
  /**
2791
- * Difference O = ABS(D - S)
2549
+ * Difference
2550
+ * O = ABS(D - S)
2792
2551
  */
2793
2552
  private static int blend_difference(int dst, int src) {
2794
2553
  int a = src >>> 24;
@@ -2796,21 +2555,24 @@ int testFunction(int dst, int src) {
2796
2555
  int s_a = a + (a >= 0x7F ? 1 : 0);
2797
2556
  int d_a = 0x100 - s_a;
2798
2557
 
2799
- int r = (dst & RED_MASK) - (src & RED_MASK);
2800
- int b = (dst & BLUE_MASK) - (src & BLUE_MASK);
2558
+ int r = (dst & RED_MASK) - (src & RED_MASK);
2559
+ int b = (dst & BLUE_MASK) - (src & BLUE_MASK);
2801
2560
  int g = (dst & GREEN_MASK) - (src & GREEN_MASK);
2802
2561
 
2803
- int rb = (r < 0 ? -r : r)
2804
- | (b < 0 ? -b : b);
2562
+ int rb = (r < 0 ? -r : r) |
2563
+ (b < 0 ? -b : b);
2805
2564
  int gn = (g < 0 ? -g : g);
2806
2565
 
2807
- return min((dst >>> 24) + a, 0xFF) << 24
2808
- | ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK
2809
- | ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2566
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2567
+ ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK |
2568
+ ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2810
2569
  }
2811
2570
 
2571
+
2812
2572
  /**
2813
- * Exclusion O = (1 - S)D + S(1 - D) O = D + S - 2DS
2573
+ * Exclusion
2574
+ * O = (1 - S)D + S(1 - D)
2575
+ * O = D + S - 2DS
2814
2576
  */
2815
2577
  private static int blend_exclusion(int dst, int src) {
2816
2578
  int a = src >>> 24;
@@ -2826,16 +2588,16 @@ int testFunction(int dst, int src) {
2826
2588
  int f_r = (dst & RED_MASK) >> 16;
2827
2589
  int f_b = (dst & BLUE_MASK);
2828
2590
 
2829
- int rb_sub
2830
- = ((src & RED_MASK) * (f_r + (f_r >= 0x7F ? 1 : 0))
2831
- | (src & BLUE_MASK) * (f_b + (f_b >= 0x7F ? 1 : 0)))
2832
- >>> 7 & 0x01FF01FF;
2591
+ int rb_sub =
2592
+ ((src & RED_MASK) * (f_r + (f_r >= 0x7F ? 1 : 0)) |
2593
+ (src & BLUE_MASK) * (f_b + (f_b >= 0x7F ? 1 : 0)))
2594
+ >>> 7 & 0x01FF01FF;
2833
2595
  int gn_sub = s_gn * (d_gn + (d_gn >= 0x7F00 ? 0x100 : 0))
2834
- >>> 15 & 0x0001FF00;
2596
+ >>> 15 & 0x0001FF00;
2835
2597
 
2836
- return min((dst >>> 24) + a, 0xFF) << 24
2837
- | (d_rb * d_a + (d_rb + (src & RB_MASK) - rb_sub) * s_a) >>> 8 & RB_MASK
2838
- | (d_gn * d_a + (d_gn + s_gn - gn_sub) * s_a) >>> 8 & GN_MASK;
2598
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2599
+ (d_rb * d_a + (d_rb + (src & RB_MASK) - rb_sub) * s_a) >>> 8 & RB_MASK |
2600
+ (d_gn * d_a + (d_gn + s_gn - gn_sub) * s_a) >>> 8 & GN_MASK;
2839
2601
  }
2840
2602
 
2841
2603
 
@@ -2854,21 +2616,24 @@ int testFunction(int dst, int src) {
2854
2616
  int f_r = (dst & RED_MASK) >> 16;
2855
2617
  int f_b = (dst & BLUE_MASK);
2856
2618
 
2857
- int rb
2858
- = ((src & RED_MASK) * (f_r + 1)
2859
- | (src & BLUE_MASK) * (f_b + 1))
2860
- >>> 8 & RB_MASK;
2861
- int gn
2862
- = (src & GREEN_MASK) * (d_gn + 0x100)
2863
- >>> 16 & GN_MASK;
2619
+ int rb =
2620
+ ((src & RED_MASK) * (f_r + 1) |
2621
+ (src & BLUE_MASK) * (f_b + 1))
2622
+ >>> 8 & RB_MASK;
2623
+ int gn =
2624
+ (src & GREEN_MASK) * (d_gn + 0x100)
2625
+ >>> 16 & GN_MASK;
2864
2626
 
2865
- return min((dst >>> 24) + a, 0xFF) << 24
2866
- | ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK
2867
- | (d_gn * d_a + gn * s_a) >>> 8 & GN_MASK;
2627
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2628
+ ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK |
2629
+ (d_gn * d_a + gn * s_a) >>> 8 & GN_MASK;
2868
2630
  }
2869
2631
 
2632
+
2870
2633
  /**
2871
- * Screen O = 1 - (1 - D)(1 - S) O = D + S - DS
2634
+ * Screen
2635
+ * O = 1 - (1 - D)(1 - S)
2636
+ * O = D + S - DS
2872
2637
  */
2873
2638
  private static int blend_screen(int dst, int src) {
2874
2639
  int a = src >>> 24;
@@ -2884,21 +2649,23 @@ int testFunction(int dst, int src) {
2884
2649
  int f_r = (dst & RED_MASK) >> 16;
2885
2650
  int f_b = (dst & BLUE_MASK);
2886
2651
 
2887
- int rb_sub
2888
- = ((src & RED_MASK) * (f_r + 1)
2889
- | (src & BLUE_MASK) * (f_b + 1))
2890
- >>> 8 & RB_MASK;
2652
+ int rb_sub =
2653
+ ((src & RED_MASK) * (f_r + 1) |
2654
+ (src & BLUE_MASK) * (f_b + 1))
2655
+ >>> 8 & RB_MASK;
2891
2656
  int gn_sub = s_gn * (d_gn + 0x100)
2892
- >>> 16 & GN_MASK;
2657
+ >>> 16 & GN_MASK;
2893
2658
 
2894
- return min((dst >>> 24) + a, 0xFF) << 24
2895
- | (d_rb * d_a + (d_rb + (src & RB_MASK) - rb_sub) * s_a) >>> 8 & RB_MASK
2896
- | (d_gn * d_a + (d_gn + s_gn - gn_sub) * s_a) >>> 8 & GN_MASK;
2659
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2660
+ (d_rb * d_a + (d_rb + (src & RB_MASK) - rb_sub) * s_a) >>> 8 & RB_MASK |
2661
+ (d_gn * d_a + (d_gn + s_gn - gn_sub) * s_a) >>> 8 & GN_MASK;
2897
2662
  }
2898
2663
 
2664
+
2899
2665
  /**
2900
- * Overlay O = 2 * MULTIPLY(D, S) = 2DS for D < 0.5 O = 2 * SCREEN(D, S) - 1 =
2901
- * 2(S + D - DS) - 1 otherwise
2666
+ * Overlay
2667
+ * O = 2 * MULTIPLY(D, S) = 2DS for D < 0.5
2668
+ * O = 2 * SCREEN(D, S) - 1 = 2(S + D - DS) - 1 otherwise
2902
2669
  */
2903
2670
  private static int blend_overlay(int dst, int src) {
2904
2671
  int a = src >>> 24;
@@ -2914,26 +2681,28 @@ int testFunction(int dst, int src) {
2914
2681
  int s_g = src & GREEN_MASK;
2915
2682
  int s_b = src & BLUE_MASK;
2916
2683
 
2917
- int r = (d_r < 0x800000)
2918
- ? d_r * ((s_r >>> 16) + 1) >>> 7
2919
- : 0xFF0000 - ((0x100 - (s_r >>> 16)) * (RED_MASK - d_r) >>> 7);
2920
- int g = (d_g < 0x8000)
2921
- ? d_g * (s_g + 0x100) >>> 15
2922
- : (0xFF00 - ((0x10000 - s_g) * (GREEN_MASK - d_g) >>> 15));
2923
- int b = (d_b < 0x80)
2924
- ? d_b * (s_b + 1) >>> 7
2925
- : (0xFF00 - ((0x100 - s_b) * (BLUE_MASK - d_b) << 1)) >>> 8;
2684
+ int r = (d_r < 0x800000) ?
2685
+ d_r * ((s_r >>> 16) + 1) >>> 7 :
2686
+ 0xFF0000 - ((0x100 - (s_r >>> 16)) * (RED_MASK - d_r) >>> 7);
2687
+ int g = (d_g < 0x8000) ?
2688
+ d_g * (s_g + 0x100) >>> 15 :
2689
+ (0xFF00 - ((0x10000 - s_g) * (GREEN_MASK - d_g) >>> 15));
2690
+ int b = (d_b < 0x80) ?
2691
+ d_b * (s_b + 1) >>> 7 :
2692
+ (0xFF00 - ((0x100 - s_b) * (BLUE_MASK - d_b) << 1)) >>> 8;
2926
2693
 
2927
- return min((dst >>> 24) + a, 0xFF) << 24
2928
- | ((dst & RB_MASK) * d_a + ((r | b) & RB_MASK) * s_a) >>> 8 & RB_MASK
2929
- | ((dst & GN_MASK) * d_a + (g & GN_MASK) * s_a) >>> 8 & GN_MASK;
2694
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2695
+ ((dst & RB_MASK) * d_a + ((r | b) & RB_MASK) * s_a) >>> 8 & RB_MASK |
2696
+ ((dst & GN_MASK) * d_a + (g & GN_MASK) * s_a) >>> 8 & GN_MASK;
2930
2697
  }
2931
2698
 
2699
+
2932
2700
  /**
2933
- * Hard Light O = OVERLAY(S, D)
2701
+ * Hard Light
2702
+ * O = OVERLAY(S, D)
2934
2703
  *
2935
- * O = 2 * MULTIPLY(D, S) = 2DS for S < 0.5 O = 2 * SCREEN(D, S) - 1 = 2(S + D
2936
- * - DS) - 1 otherwise
2704
+ * O = 2 * MULTIPLY(D, S) = 2DS for S < 0.5
2705
+ * O = 2 * SCREEN(D, S) - 1 = 2(S + D - DS) - 1 otherwise
2937
2706
  */
2938
2707
  private static int blend_hard_light(int dst, int src) {
2939
2708
  int a = src >>> 24;
@@ -2949,24 +2718,27 @@ int testFunction(int dst, int src) {
2949
2718
  int s_g = src & GREEN_MASK;
2950
2719
  int s_b = src & BLUE_MASK;
2951
2720
 
2952
- int r = (s_r < 0x800000)
2953
- ? s_r * ((d_r >>> 16) + 1) >>> 7
2954
- : 0xFF0000 - ((0x100 - (d_r >>> 16)) * (RED_MASK - s_r) >>> 7);
2955
- int g = (s_g < 0x8000)
2956
- ? s_g * (d_g + 0x100) >>> 15
2957
- : (0xFF00 - ((0x10000 - d_g) * (GREEN_MASK - s_g) >>> 15));
2958
- int b = (s_b < 0x80)
2959
- ? s_b * (d_b + 1) >>> 7
2960
- : (0xFF00 - ((0x100 - d_b) * (BLUE_MASK - s_b) << 1)) >>> 8;
2721
+ int r = (s_r < 0x800000) ?
2722
+ s_r * ((d_r >>> 16) + 1) >>> 7 :
2723
+ 0xFF0000 - ((0x100 - (d_r >>> 16)) * (RED_MASK - s_r) >>> 7);
2724
+ int g = (s_g < 0x8000) ?
2725
+ s_g * (d_g + 0x100) >>> 15 :
2726
+ (0xFF00 - ((0x10000 - d_g) * (GREEN_MASK - s_g) >>> 15));
2727
+ int b = (s_b < 0x80) ?
2728
+ s_b * (d_b + 1) >>> 7 :
2729
+ (0xFF00 - ((0x100 - d_b) * (BLUE_MASK - s_b) << 1)) >>> 8;
2961
2730
 
2962
- return min((dst >>> 24) + a, 0xFF) << 24
2963
- | ((dst & RB_MASK) * d_a + ((r | b) & RB_MASK) * s_a) >>> 8 & RB_MASK
2964
- | ((dst & GN_MASK) * d_a + (g & GN_MASK) * s_a) >>> 8 & GN_MASK;
2731
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2732
+ ((dst & RB_MASK) * d_a + ((r | b) & RB_MASK) * s_a) >>> 8 & RB_MASK |
2733
+ ((dst & GN_MASK) * d_a + (g & GN_MASK) * s_a) >>> 8 & GN_MASK;
2965
2734
  }
2966
2735
 
2736
+
2967
2737
  /**
2968
- * Soft Light (Pegtop) O = (1 - D) * MULTIPLY(D, S) + D * SCREEN(D, S) O = (1
2969
- * - D) * DS + D * (1 - (1 - D)(1 - S)) O = 2DS + DD - 2DDS
2738
+ * Soft Light (Pegtop)
2739
+ * O = (1 - D) * MULTIPLY(D, S) + D * SCREEN(D, S)
2740
+ * O = (1 - D) * DS + D * (1 - (1 - D)(1 - S))
2741
+ * O = 2DS + DD - 2DDS
2970
2742
  */
2971
2743
  private static int blend_soft_light(int dst, int src) {
2972
2744
  int a = src >>> 24;
@@ -2983,23 +2755,25 @@ int testFunction(int dst, int src) {
2983
2755
  int s_b1 = src & BLUE_MASK;
2984
2756
 
2985
2757
  int d_r1 = (d_r >> 16) + (s_r1 < 7F ? 1 : 0);
2986
- int d_g1 = (d_g >> 8) + (s_g1 < 7F ? 1 : 0);
2987
- int d_b1 = d_b + (s_b1 < 7F ? 1 : 0);
2758
+ int d_g1 = (d_g >> 8) + (s_g1 < 7F ? 1 : 0);
2759
+ int d_b1 = d_b + (s_b1 < 7F ? 1 : 0);
2988
2760
 
2989
- int r = (s_r1 * d_r >> 7) + 0xFF * d_r1 * (d_r1 + 1)
2990
- - ((s_r1 * d_r1 * d_r1) << 1) & RED_MASK;
2991
- int g = (s_g1 * d_g << 1) + 0xFF * d_g1 * (d_g1 + 1)
2992
- - ((s_g1 * d_g1 * d_g1) << 1) >>> 8 & GREEN_MASK;
2993
- int b = (s_b1 * d_b << 9) + 0xFF * d_b1 * (d_b1 + 1)
2994
- - ((s_b1 * d_b1 * d_b1) << 1) >>> 16;
2761
+ int r = (s_r1 * d_r >> 7) + 0xFF * d_r1 * (d_r1 + 1) -
2762
+ ((s_r1 * d_r1 * d_r1) << 1) & RED_MASK;
2763
+ int g = (s_g1 * d_g << 1) + 0xFF * d_g1 * (d_g1 + 1) -
2764
+ ((s_g1 * d_g1 * d_g1) << 1) >>> 8 & GREEN_MASK;
2765
+ int b = (s_b1 * d_b << 9) + 0xFF * d_b1 * (d_b1 + 1) -
2766
+ ((s_b1 * d_b1 * d_b1) << 1) >>> 16;
2995
2767
 
2996
- return min((dst >>> 24) + a, 0xFF) << 24
2997
- | ((dst & RB_MASK) * d_a + (r | b) * s_a) >>> 8 & RB_MASK
2998
- | ((dst & GN_MASK) * d_a + g * s_a) >>> 8 & GN_MASK;
2768
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2769
+ ((dst & RB_MASK) * d_a + (r | b) * s_a) >>> 8 & RB_MASK |
2770
+ ((dst & GN_MASK) * d_a + g * s_a) >>> 8 & GN_MASK;
2999
2771
  }
3000
2772
 
2773
+
3001
2774
  /**
3002
- * Dodge O = D / (1 - S)
2775
+ * Dodge
2776
+ * O = D / (1 - S)
3003
2777
  */
3004
2778
  private static int blend_dodge(int dst, int src) {
3005
2779
  int a = src >>> 24;
@@ -3007,23 +2781,25 @@ int testFunction(int dst, int src) {
3007
2781
  int s_a = a + (a >= 0x7F ? 1 : 0);
3008
2782
  int d_a = 0x100 - s_a;
3009
2783
 
3010
- int r = (dst & RED_MASK) / (256 - ((src & RED_MASK) >> 16));
2784
+ int r = (dst & RED_MASK) / (256 - ((src & RED_MASK) >> 16));
3011
2785
  int g = ((dst & GREEN_MASK) << 8) / (256 - ((src & GREEN_MASK) >> 8));
3012
- int b = ((dst & BLUE_MASK) << 8) / (256 - (src & BLUE_MASK));
2786
+ int b = ((dst & BLUE_MASK) << 8) / (256 - (src & BLUE_MASK));
3013
2787
 
3014
- int rb
3015
- = (r > 0xFF00 ? 0xFF0000 : ((r << 8) & RED_MASK))
3016
- | (b > 0x00FF ? 0x0000FF : b);
3017
- int gn
3018
- = (g > 0xFF00 ? 0x00FF00 : (g & GREEN_MASK));
2788
+ int rb =
2789
+ (r > 0xFF00 ? 0xFF0000 : ((r << 8) & RED_MASK)) |
2790
+ (b > 0x00FF ? 0x0000FF : b);
2791
+ int gn =
2792
+ (g > 0xFF00 ? 0x00FF00 : (g & GREEN_MASK));
3019
2793
 
3020
- return min((dst >>> 24) + a, 0xFF) << 24
3021
- | ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK
3022
- | ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2794
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2795
+ ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK |
2796
+ ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
3023
2797
  }
3024
2798
 
2799
+
3025
2800
  /**
3026
- * Burn O = 1 - (1 - A) / B
2801
+ * Burn
2802
+ * O = 1 - (1 - A) / B
3027
2803
  */
3028
2804
  private static int blend_burn(int dst, int src) {
3029
2805
  int a = src >>> 24;
@@ -3031,70 +2807,61 @@ int testFunction(int dst, int src) {
3031
2807
  int s_a = a + (a >= 0x7F ? 1 : 0);
3032
2808
  int d_a = 0x100 - s_a;
3033
2809
 
3034
- int r = ((0xFF0000 - (dst & RED_MASK))) / (1 + (src & RED_MASK >> 16));
2810
+ int r = ((0xFF0000 - (dst & RED_MASK))) / (1 + (src & RED_MASK >> 16));
3035
2811
  int g = ((0x00FF00 - (dst & GREEN_MASK)) << 8) / (1 + (src & GREEN_MASK >> 8));
3036
- int b = ((0x0000FF - (dst & BLUE_MASK)) << 8) / (1 + (src & BLUE_MASK));
2812
+ int b = ((0x0000FF - (dst & BLUE_MASK)) << 8) / (1 + (src & BLUE_MASK));
3037
2813
 
3038
- int rb = RB_MASK
3039
- - (r > 0xFF00 ? 0xFF0000 : ((r << 8) & RED_MASK))
3040
- - (b > 0x00FF ? 0x0000FF : b);
3041
- int gn = GN_MASK
3042
- - (g > 0xFF00 ? 0x00FF00 : (g & GREEN_MASK));
2814
+ int rb = RB_MASK -
2815
+ (r > 0xFF00 ? 0xFF0000 : ((r << 8) & RED_MASK)) -
2816
+ (b > 0x00FF ? 0x0000FF : b);
2817
+ int gn = GN_MASK -
2818
+ (g > 0xFF00 ? 0x00FF00 : (g & GREEN_MASK));
3043
2819
 
3044
- return min((dst >>> 24) + a, 0xFF) << 24
3045
- | ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK
3046
- | ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
2820
+ return min((dst >>> 24) + a, 0xFF) << 24 |
2821
+ ((dst & RB_MASK) * d_a + rb * s_a) >>> 8 & RB_MASK |
2822
+ ((dst & GN_MASK) * d_a + gn * s_a) >>> 8 & GN_MASK;
3047
2823
  }
3048
2824
 
2825
+
3049
2826
  //////////////////////////////////////////////////////////////
2827
+
3050
2828
  // FILE I/O
3051
- static byte TIFF_HEADER[] = {
3052
- 77, 77, 0, 42, 0, 0, 0, 8, 0, 9, 0, -2, 0, 4, 0, 0, 0, 1, 0, 0,
3053
- 0, 0, 1, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 3, 0, 0, 0, 1,
3054
- 0, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 122, 1, 6, 0, 3, 0,
3055
- 0, 0, 1, 0, 2, 0, 0, 1, 17, 0, 4, 0, 0, 0, 1, 0, 0, 3, 0, 1, 21,
3056
- 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 1, 22, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0,
3057
- 1, 23, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8
3058
- };
3059
2829
 
3060
- static final String TIFF_ERROR
3061
- = "Error: Processing can only read its own TIFF files.";
3062
2830
 
3063
- /**
3064
- *
3065
- * @param tiff
3066
- * @return
3067
- */
3068
- static protected PImage loadTIFF(byte tiff[]) {
3069
- if ((tiff[42] != tiff[102])
3070
- || // width/height in both places
3071
- (tiff[43] != tiff[103])) {
2831
+ protected boolean saveImpl(String filename) {
2832
+ return false;
2833
+ }
2834
+
2835
+
2836
+ static public PImage loadTIFF(InputStream input) { // ignore
2837
+ byte tiff[] = PApplet.loadBytes(input);
2838
+
2839
+ if ((tiff[42] != tiff[102]) || // width/height in both places
2840
+ (tiff[43] != tiff[103])) {
3072
2841
  System.err.println(TIFF_ERROR);
3073
2842
  return null;
3074
2843
  }
3075
2844
 
3076
- int width
3077
- = ((tiff[30] & 0xff) << 8) | (tiff[31] & 0xff);
3078
- int height
3079
- = ((tiff[42] & 0xff) << 8) | (tiff[43] & 0xff);
2845
+ int width =
2846
+ ((tiff[30] & 0xff) << 8) | (tiff[31] & 0xff);
2847
+ int height =
2848
+ ((tiff[42] & 0xff) << 8) | (tiff[43] & 0xff);
3080
2849
 
3081
- int count
3082
- = ((tiff[114] & 0xff) << 24)
3083
- | ((tiff[115] & 0xff) << 16)
3084
- | ((tiff[116] & 0xff) << 8)
3085
- | (tiff[117] & 0xff);
2850
+ int count =
2851
+ ((tiff[114] & 0xff) << 24) |
2852
+ ((tiff[115] & 0xff) << 16) |
2853
+ ((tiff[116] & 0xff) << 8) |
2854
+ (tiff[117] & 0xff);
3086
2855
  if (count != width * height * 3) {
3087
- System.err.println(TIFF_ERROR + " (" + width + ", " + height + ")");
2856
+ System.err.println(TIFF_ERROR + " (" + width + ", " + height +")");
3088
2857
  return null;
3089
2858
  }
3090
2859
 
3091
2860
  // check the rest of the header
3092
2861
  for (int i = 0; i < TIFF_HEADER.length; i++) {
3093
- if ((i == 30) || (i == 31) || (i == 42) || (i == 43)
3094
- || (i == 102) || (i == 103)
3095
- || (i == 114) || (i == 115) || (i == 116) || (i == 117)) {
3096
- continue;
3097
- }
2862
+ if ((i == 30) || (i == 31) || (i == 42) || (i == 43) ||
2863
+ (i == 102) || (i == 103) ||
2864
+ (i == 114) || (i == 115) || (i == 116) || (i == 117)) continue;
3098
2865
 
3099
2866
  if (tiff[i] != TIFF_HEADER[i]) {
3100
2867
  System.err.println(TIFF_ERROR + " (" + i + ")");
@@ -3106,20 +2873,15 @@ int testFunction(int dst, int src) {
3106
2873
  int index = 768;
3107
2874
  count /= 3;
3108
2875
  for (int i = 0; i < count; i++) {
3109
- outgoing.pixels[i]
3110
- = 0xFF000000
3111
- | (tiff[index++] & 0xff) << 16
3112
- | (tiff[index++] & 0xff) << 8
3113
- | (tiff[index++] & 0xff);
2876
+ outgoing.pixels[i] =
2877
+ 0xFF000000 |
2878
+ (tiff[index++] & 0xff) << 16 |
2879
+ (tiff[index++] & 0xff) << 8 |
2880
+ (tiff[index++] & 0xff);
3114
2881
  }
3115
2882
  return outgoing;
3116
2883
  }
3117
2884
 
3118
- /**
3119
- *
3120
- * @param output
3121
- * @return
3122
- */
3123
2885
  protected boolean saveTIFF(OutputStream output) {
3124
2886
  // shutting off the warning, people can figure this out themselves
3125
2887
  /*
@@ -3127,9 +2889,9 @@ int testFunction(int dst, int src) {
3127
2889
  System.err.println("Warning: only RGB information is saved with " +
3128
2890
  ".tif files. Use .tga or .png for ARGB images and others.");
3129
2891
  }
3130
- */
2892
+ */
3131
2893
  try {
3132
- byte tiff[] = new byte[768];
2894
+ byte[] tiff = new byte[768];
3133
2895
  System.arraycopy(TIFF_HEADER, 0, tiff, 0, TIFF_HEADER.length);
3134
2896
 
3135
2897
  tiff[30] = (byte) ((pixelWidth >> 8) & 0xff);
@@ -3137,7 +2899,7 @@ int testFunction(int dst, int src) {
3137
2899
  tiff[42] = tiff[102] = (byte) ((pixelHeight >> 8) & 0xff);
3138
2900
  tiff[43] = tiff[103] = (byte) ((pixelHeight) & 0xff);
3139
2901
 
3140
- int count = pixelWidth * pixelHeight * 3;
2902
+ int count = pixelWidth*pixelHeight*3;
3141
2903
  tiff[114] = (byte) ((count >> 24) & 0xff);
3142
2904
  tiff[115] = (byte) ((count >> 16) & 0xff);
3143
2905
  tiff[116] = (byte) ((count >> 8) & 0xff);
@@ -3155,408 +2917,461 @@ int testFunction(int dst, int src) {
3155
2917
  return true;
3156
2918
 
3157
2919
  } catch (IOException e) {
3158
- e.printStackTrace();
3159
2920
  }
3160
2921
  return false;
3161
2922
  }
3162
2923
 
2924
+
3163
2925
  /**
3164
- * Creates a Targa32 formatted byte sequence of specified pixel buffer using
3165
- * RLE compression.
3166
- * </p>
3167
- * Also figured out how to avoid parsing the image upside-down (there's a
3168
- * header flag to set the image origin to top-left)
3169
- * </p>
3170
- * Starting with revision 0092, the format setting is taken into account:
3171
- * <UL>
3172
- * <LI><TT>ALPHA</TT> images written as 8bit grayscale (uses lowest byte)
3173
- * <LI><TT>RGB</TT> &rarr; 24 bits
3174
- * <LI><TT>ARGB</TT> &rarr; 32 bits
3175
- * </UL>
3176
- * All versions are RLE compressed.
3177
- * </p>
3178
- * Contributed by toxi 8-10 May 2005, based on this RLE
3179
- * <A HREF="http://www.wotsit.org/download.asp?f=tga">specification</A>
3180
- *
3181
- * @param output
3182
- * @return
2926
+ * Targa image loader for RLE-compressed TGA files.
2927
+ * <p>
2928
+ * Rewritten for 0115 to read/write RLE-encoded targa images.
2929
+ * For 0125, non-RLE encoded images are now supported, along with
2930
+ * images whose y-order is reversed (which is standard for TGA files).
2931
+ * <p>
2932
+ * A version of this function is in MovieMaker.java. Any fixes here
2933
+ * should be applied over in MovieMaker as well.
2934
+ * <p>
2935
+ * Known issue with RLE encoding and odd behavior in some apps:
2936
+ * https://github.com/processing/processing/issues/2096
2937
+ * Please help!
3183
2938
  */
3184
- protected boolean saveTGA(OutputStream output) {
3185
- byte header[] = new byte[18];
2939
+ static public PImage loadTGA(InputStream input) throws IOException { // ignore
2940
+ byte[] header = new byte[18];
2941
+ int offset = 0;
2942
+ do {
2943
+ int count = input.read(header, offset, header.length - offset);
2944
+ if (count == -1) return null;
2945
+ offset += count;
2946
+ } while (offset < 18);
2947
+
2948
+ /*
2949
+ header[2] image type code
2950
+ 2 (0x02) - Uncompressed, RGB images.
2951
+ 3 (0x03) - Uncompressed, black and white images.
2952
+ 10 (0x0A) - Run-length encoded RGB images.
2953
+ 11 (0x0B) - Compressed, black and white images. (grayscale?)
3186
2954
 
3187
- if (format == ALPHA) { // save ALPHA images as 8bit grayscale
3188
- header[2] = 0x0B;
3189
- header[16] = 0x08;
3190
- header[17] = 0x28;
2955
+ header[16] is the bit depth (8, 24, 32)
3191
2956
 
3192
- } else if (format == RGB) {
3193
- header[2] = 0x0A;
3194
- header[16] = 24;
3195
- header[17] = 0x20;
2957
+ header[17] image descriptor (packed bits)
2958
+ 0x20 is 32 = origin upper-left
2959
+ 0x28 is 32 + 8 = origin upper-left + 32 bits
3196
2960
 
3197
- } else if (format == ARGB) {
3198
- header[2] = 0x0A;
3199
- header[16] = 32;
3200
- header[17] = 0x28;
2961
+ 7 6 5 4 3 2 1 0
2962
+ 128 64 32 16 8 4 2 1
2963
+ */
3201
2964
 
3202
- } else {
3203
- throw new RuntimeException("Image format not recognized inside save()");
2965
+ int format = 0;
2966
+
2967
+ if (((header[2] == 3) || (header[2] == 11)) && // B&W, plus RLE or not
2968
+ (header[16] == 8) && // 8 bits
2969
+ ((header[17] == 0x8) || (header[17] == 0x28))) { // origin, 32 bit
2970
+ format = ALPHA;
2971
+
2972
+ } else if (((header[2] == 2) || (header[2] == 10)) && // RGB, RLE or not
2973
+ (header[16] == 24) && // 24 bits
2974
+ ((header[17] == 0x20) || (header[17] == 0))) { // origin
2975
+ format = RGB;
2976
+
2977
+ } else if (((header[2] == 2) || (header[2] == 10)) &&
2978
+ (header[16] == 32) &&
2979
+ ((header[17] == 0x8) || (header[17] == 0x28))) { // origin, 32
2980
+ format = ARGB;
3204
2981
  }
3205
- // set image dimensions lo-hi byte order
3206
- header[12] = (byte) (pixelWidth & 0xff);
3207
- header[13] = (byte) (pixelWidth >> 8);
3208
- header[14] = (byte) (pixelHeight & 0xff);
3209
- header[15] = (byte) (pixelHeight >> 8);
3210
2982
 
3211
- try {
3212
- output.write(header);
2983
+ if (format == 0) {
2984
+ System.err.println("Unknown .tga file format");
2985
+ return null;
2986
+ }
3213
2987
 
3214
- int maxLen = pixelHeight * pixelWidth;
3215
- int index = 0;
3216
- int col; //, prevCol;
3217
- int[] currChunk = new int[128];
3218
-
3219
- // 8bit image exporter is in separate loop
3220
- // to avoid excessive conditionals...
3221
- if (format == ALPHA) {
3222
- while (index < maxLen) {
3223
- boolean isRLE = false;
3224
- int rle = 1;
3225
- currChunk[0] = col = pixels[index] & 0xff;
3226
- while (index + rle < maxLen) {
3227
- if (col != (pixels[index + rle] & 0xff) || rle == 128) {
3228
- isRLE = (rle > 1);
3229
- break;
2988
+ int w = ((header[13] & 0xff) << 8) + (header[12] & 0xff);
2989
+ int h = ((header[15] & 0xff) << 8) + (header[14] & 0xff);
2990
+ PImage outgoing = new PImage(w, h, format);
2991
+
2992
+ // where "reversed" means upper-left corner (normal for most of
2993
+ // the modernized world, but "reversed" for the tga spec)
2994
+ //boolean reversed = (header[17] & 0x20) != 0;
2995
+ // https://github.com/processing/processing/issues/1682
2996
+ boolean reversed = (header[17] & 0x20) == 0;
2997
+
2998
+ if ((header[2] == 2) || (header[2] == 3)) { // not RLE encoded
2999
+ if (reversed) {
3000
+ int index = (h-1) * w;
3001
+ switch (format) {
3002
+ case ALPHA:
3003
+ for (int y = h-1; y >= 0; y--) {
3004
+ for (int x = 0; x < w; x++) {
3005
+ outgoing.pixels[index + x] = input.read();
3230
3006
  }
3231
- rle++;
3007
+ index -= w;
3232
3008
  }
3233
- if (isRLE) {
3234
- output.write(0x80 | (rle - 1));
3235
- output.write(col);
3236
-
3237
- } else {
3238
- rle = 1;
3239
- while (index + rle < maxLen) {
3240
- int cscan = pixels[index + rle] & 0xff;
3241
- if ((col != cscan && rle < 128) || rle < 3) {
3242
- currChunk[rle] = col = cscan;
3243
- } else {
3244
- if (col == cscan) {
3245
- rle -= 2;
3246
- }
3247
- break;
3248
- }
3249
- rle++;
3250
- }
3251
- output.write(rle - 1);
3252
- for (int i = 0; i < rle; i++) {
3253
- output.write(currChunk[i]);
3254
- }
3255
- }
3256
- index += rle;
3257
- }
3258
- } else { // export 24/32 bit TARGA
3259
- while (index < maxLen) {
3260
- boolean isRLE = false;
3261
- currChunk[0] = col = pixels[index];
3262
- int rle = 1;
3263
- // try to find repeating bytes (min. len = 2 pixels)
3264
- // maximum chunk size is 128 pixels
3265
- while (index + rle < maxLen) {
3266
- if (col != pixels[index + rle] || rle == 128) {
3267
- isRLE = (rle > 1); // set flag for RLE chunk
3268
- break;
3009
+ break;
3010
+ case RGB:
3011
+ for (int y = h-1; y >= 0; y--) {
3012
+ for (int x = 0; x < w; x++) {
3013
+ outgoing.pixels[index + x] =
3014
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3015
+ 0xff000000;
3269
3016
  }
3270
- rle++;
3017
+ index -= w;
3271
3018
  }
3272
- if (isRLE) {
3273
- output.write(128 | (rle - 1));
3274
- output.write(col & 0xff);
3275
- output.write(col >> 8 & 0xff);
3276
- output.write(col >> 16 & 0xff);
3277
- if (format == ARGB) {
3278
- output.write(col >>> 24 & 0xff);
3279
- }
3280
-
3281
- } else { // not RLE
3282
- rle = 1;
3283
- while (index + rle < maxLen) {
3284
- if ((col != pixels[index + rle] && rle < 128) || rle < 3) {
3285
- currChunk[rle] = col = pixels[index + rle];
3286
- } else {
3287
- // check if the exit condition was the start of
3288
- // a repeating colour
3289
- if (col == pixels[index + rle]) {
3290
- rle -= 2;
3291
- }
3292
- break;
3293
- }
3294
- rle++;
3295
- }
3296
- // write uncompressed chunk
3297
- output.write(rle - 1);
3298
- if (format == ARGB) {
3299
- for (int i = 0; i < rle; i++) {
3300
- col = currChunk[i];
3301
- output.write(col & 0xff);
3302
- output.write(col >> 8 & 0xff);
3303
- output.write(col >> 16 & 0xff);
3304
- output.write(col >>> 24 & 0xff);
3305
- }
3306
- } else {
3307
- for (int i = 0; i < rle; i++) {
3308
- col = currChunk[i];
3309
- output.write(col & 0xff);
3310
- output.write(col >> 8 & 0xff);
3311
- output.write(col >> 16 & 0xff);
3312
- }
3019
+ break;
3020
+ case ARGB:
3021
+ for (int y = h-1; y >= 0; y--) {
3022
+ for (int x = 0; x < w; x++) {
3023
+ outgoing.pixels[index + x] =
3024
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3025
+ (input.read() << 24);
3313
3026
  }
3027
+ index -= w;
3314
3028
  }
3315
- index += rle;
3316
3029
  }
3317
- }
3318
- output.flush();
3319
- return true;
3320
-
3321
- } catch (IOException e) {
3322
- e.printStackTrace();
3323
- return false;
3324
- }
3325
- }
3326
-
3327
- /**
3328
- * Use ImageIO functions from Java 1.4 and later to handle image save. Various
3329
- * formats are supported, typically jpeg, png, bmp, and wbmp. To get a list of
3330
- * the supported formats for writing, use: <BR>
3331
- * <TT>println(javax.imageio.ImageIO.getReaderFormatNames())</TT>
3332
- *
3333
- * @param path
3334
- * @return
3335
- * @throws java.io.IOException
3336
- */
3337
- protected boolean saveImageIO(String path) throws IOException {
3338
- try {
3339
- int outputFormat = (format == ARGB)
3340
- ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
3341
-
3342
- String extension
3343
- = path.substring(path.lastIndexOf('.') + 1).toLowerCase();
3344
-
3345
- // JPEG and BMP images that have an alpha channel set get pretty unhappy.
3346
- // BMP just doesn't write, and JPEG writes it as a CMYK image.
3347
- // http://code.google.com/p/processing/issues/detail?id=415
3348
- if (extension.equals("bmp") || extension.equals("jpg") || extension.equals("jpeg")) {
3349
- outputFormat = BufferedImage.TYPE_INT_RGB;
3350
- }
3351
-
3352
- BufferedImage bimage = new BufferedImage(pixelWidth, pixelHeight, outputFormat);
3353
- bimage.setRGB(0, 0, pixelWidth, pixelHeight, pixels, 0, pixelWidth);
3354
-
3355
- File file = new File(path);
3356
-
3357
- ImageWriter writer = null;
3358
- ImageWriteParam param = null;
3359
- IIOMetadata metadata = null;
3360
-
3361
- if (extension.equals("jpg") || extension.equals("jpeg")) {
3362
- if ((writer = imageioWriter("jpeg")) != null) {
3363
- // Set JPEG quality to 90% with baseline optimization. Setting this
3364
- // to 1 was a huge jump (about triple the size), so this seems good.
3365
- // Oddly, a smaller file size than Photoshop at 90%, but I suppose
3366
- // it's a completely different algorithm.
3367
- param = writer.getDefaultWriteParam();
3368
- param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
3369
- param.setCompressionQuality(0.9f);
3030
+ } else { // not reversed
3031
+ int count = w * h;
3032
+ switch (format) {
3033
+ case ALPHA:
3034
+ for (int i = 0; i < count; i++) {
3035
+ outgoing.pixels[i] = input.read();
3036
+ }
3037
+ break;
3038
+ case RGB:
3039
+ for (int i = 0; i < count; i++) {
3040
+ outgoing.pixels[i] =
3041
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3042
+ 0xff000000;
3043
+ }
3044
+ break;
3045
+ case ARGB:
3046
+ for (int i = 0; i < count; i++) {
3047
+ outgoing.pixels[i] =
3048
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3049
+ (input.read() << 24);
3050
+ }
3051
+ break;
3370
3052
  }
3371
3053
  }
3372
3054
 
3373
- if (extension.equals("png")) {
3374
- if ((writer = imageioWriter("png")) != null) {
3375
- param = writer.getDefaultWriteParam();
3376
- if (false) {
3377
- metadata = imageioDPI(writer, param, 100);
3055
+ } else { // header[2] is 10 or 11
3056
+ int index = 0;
3057
+ int[] px = outgoing.pixels;
3058
+
3059
+ while (index < px.length) {
3060
+ int num = input.read();
3061
+ boolean isRLE = (num & 0x80) != 0;
3062
+ if (isRLE) {
3063
+ num -= 127; // (num & 0x7F) + 1
3064
+ int pixel = 0;
3065
+ switch (format) {
3066
+ case ALPHA:
3067
+ pixel = input.read();
3068
+ break;
3069
+ case RGB:
3070
+ pixel = 0xFF000000 |
3071
+ input.read() | (input.read() << 8) | (input.read() << 16);
3072
+ //(is.read() << 16) | (is.read() << 8) | is.read();
3073
+ break;
3074
+ case ARGB:
3075
+ pixel = input.read() |
3076
+ (input.read() << 8) | (input.read() << 16) | (input.read() << 24);
3077
+ break;
3078
+ }
3079
+ for (int i = 0; i < num; i++) {
3080
+ px[index++] = pixel;
3081
+ if (index == px.length) break;
3082
+ }
3083
+ } else { // write up to 127 bytes as uncompressed
3084
+ num += 1;
3085
+ switch (format) {
3086
+ case ALPHA:
3087
+ for (int i = 0; i < num; i++) {
3088
+ px[index++] = input.read();
3089
+ }
3090
+ break;
3091
+ case RGB:
3092
+ for (int i = 0; i < num; i++) {
3093
+ px[index++] = 0xFF000000 |
3094
+ input.read() | (input.read() << 8) | (input.read() << 16);
3095
+ //(is.read() << 16) | (is.read() << 8) | is.read();
3096
+ }
3097
+ break;
3098
+ case ARGB:
3099
+ for (int i = 0; i < num; i++) {
3100
+ px[index++] = input.read() | //(is.read() << 24) |
3101
+ (input.read() << 8) | (input.read() << 16) | (input.read() << 24);
3102
+ //(is.read() << 16) | (is.read() << 8) | is.read();
3103
+ }
3104
+ break;
3378
3105
  }
3379
3106
  }
3380
3107
  }
3381
3108
 
3382
- if (writer != null) {
3383
- BufferedOutputStream output
3384
- = new BufferedOutputStream(PApplet.createOutput(file));
3385
- writer.setOutput(ImageIO.createImageOutputStream(output));
3386
- // writer.write(null, new IIOImage(bimage, null, null), param);
3387
- writer.write(metadata, new IIOImage(bimage, null, metadata), param);
3388
- writer.dispose();
3389
-
3390
- output.flush();
3391
- output.close();
3392
- return true;
3109
+ if (!reversed) {
3110
+ int[] temp = new int[w];
3111
+ for (int y = 0; y < h/2; y++) {
3112
+ int z = (h-1) - y;
3113
+ System.arraycopy(px, y*w, temp, 0, w);
3114
+ System.arraycopy(px, z*w, px, y*w, w);
3115
+ System.arraycopy(temp, 0, px, z*w, w);
3116
+ }
3393
3117
  }
3394
- // If iter.hasNext() somehow fails up top, it falls through to here
3395
- return javax.imageio.ImageIO.write(bimage, extension, file);
3396
-
3397
- } catch (Exception e) {
3398
- e.printStackTrace();
3399
- throw new IOException("image save failed.");
3400
- }
3401
- }
3402
-
3403
- private ImageWriter imageioWriter(String extension) {
3404
- Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName(extension);
3405
- if (iter.hasNext()) {
3406
- return iter.next();
3407
3118
  }
3408
- return null;
3119
+ input.close();
3120
+ return outgoing;
3409
3121
  }
3410
3122
 
3411
- private IIOMetadata imageioDPI(ImageWriter writer, ImageWriteParam param, double dpi) {
3412
- // http://stackoverflow.com/questions/321736/how-to-set-dpi-information-in-an-image
3413
- ImageTypeSpecifier typeSpecifier
3414
- = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
3415
- IIOMetadata metadata
3416
- = writer.getDefaultImageMetadata(typeSpecifier, param);
3417
-
3418
- if (!metadata.isReadOnly() && metadata.isStandardMetadataFormatSupported()) {
3419
- // for PNG, it's dots per millimeter
3420
- double dotsPerMilli = dpi / 25.4;
3421
-
3422
- IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
3423
- horiz.setAttribute("value", Double.toString(dotsPerMilli));
3424
-
3425
- IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
3426
- vert.setAttribute("value", Double.toString(dotsPerMilli));
3427
-
3428
- IIOMetadataNode dim = new IIOMetadataNode("Dimension");
3429
- dim.appendChild(horiz);
3430
- dim.appendChild(vert);
3431
-
3432
- IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
3433
- root.appendChild(dim);
3434
-
3435
- try {
3436
- metadata.mergeTree("javax_imageio_1.0", root);
3437
- return metadata;
3438
-
3439
- } catch (IIOInvalidTreeException e) {
3440
- System.err.println("Could not set the DPI of the output image");
3441
- e.printStackTrace();
3442
- }
3443
- }
3444
- return null;
3445
- }
3446
3123
 
3447
3124
  /**
3125
+ * Creates a Targa32 formatted byte sequence of specified
3126
+ * pixel buffer using RLE compression.
3127
+ * <p>
3128
+ * Also figured out how to avoid parsing the image upside-down
3129
+ * (there's a header flag to set the image origin to top-left)
3130
+ * </p>
3131
+ * Starting with revision 0092, the format setting is taken into account:
3132
+ * <UL>
3133
+ * <LI><TT>ALPHA</TT> images written as 8bit grayscale (uses lowest byte)
3134
+ * <LI><TT>RGB</TT> &rarr; 24 bits
3135
+ * <LI><TT>ARGB</TT> &rarr; 32 bits
3136
+ * </UL>
3137
+ * All versions are RLE compressed.
3448
3138
  *
3139
+ * Contributed by toxi 8-10 May 2005, based on this RLE
3140
+ * <A HREF="http://www.wotsit.org/download.asp?f=tga">specification</A>
3449
3141
  */
3450
- protected String[] saveImageFormats;
3142
+ protected boolean saveTGA(OutputStream output) {
3143
+ byte[] header = new byte[18];
3144
+
3145
+ switch (format) {
3146
+ case ALPHA:
3147
+ // save ALPHA images as 8bit grayscale
3148
+ header[2] = 0x0B;
3149
+ header[16] = 0x08;
3150
+ header[17] = 0x28;
3151
+ break;
3152
+ case RGB:
3153
+ header[2] = 0x0A;
3154
+ header[16] = 24;
3155
+ header[17] = 0x20;
3156
+ break;
3157
+ case ARGB:
3158
+ header[2] = 0x0A;
3159
+ header[16] = 32;
3160
+ header[17] = 0x28;
3161
+ break;
3162
+ default:
3163
+ throw new RuntimeException("Image format not recognized inside save()");
3164
+ }
3165
+ // set image dimensions lo-hi byte order
3166
+ header[12] = (byte) (pixelWidth & 0xff);
3167
+ header[13] = (byte) (pixelWidth >> 8);
3168
+ header[14] = (byte) (pixelHeight & 0xff);
3169
+ header[15] = (byte) (pixelHeight >> 8);
3170
+
3171
+ try {
3172
+ output.write(header);
3173
+
3174
+ int maxLen = pixelHeight * pixelWidth;
3175
+ int index = 0;
3176
+ int col; //, prevCol;
3177
+ int[] currChunk = new int[128];
3178
+
3179
+ // 8bit image exporter is in separate loop
3180
+ // to avoid excessive conditionals...
3181
+ if (format == ALPHA) {
3182
+ while (index < maxLen) {
3183
+ boolean isRLE = false;
3184
+ int rle = 1;
3185
+ currChunk[0] = col = pixels[index] & 0xff;
3186
+ while (index + rle < maxLen) {
3187
+ if (col != (pixels[index + rle]&0xff) || rle == 128) {
3188
+ isRLE = (rle > 1);
3189
+ break;
3190
+ }
3191
+ rle++;
3192
+ }
3193
+ if (isRLE) {
3194
+ output.write(0x80 | (rle - 1));
3195
+ output.write(col);
3196
+
3197
+ } else {
3198
+ rle = 1;
3199
+ while (index + rle < maxLen) {
3200
+ int cscan = pixels[index + rle] & 0xff;
3201
+ if ((col != cscan && rle < 128) || rle < 3) {
3202
+ currChunk[rle] = col = cscan;
3203
+ } else {
3204
+ if (col == cscan) rle -= 2;
3205
+ break;
3206
+ }
3207
+ rle++;
3208
+ }
3209
+ output.write(rle - 1);
3210
+ for (int i = 0; i < rle; i++) output.write(currChunk[i]);
3211
+ }
3212
+ index += rle;
3213
+ }
3214
+ } else { // export 24/32 bit TARGA
3215
+ while (index < maxLen) {
3216
+ boolean isRLE = false;
3217
+ currChunk[0] = col = pixels[index];
3218
+ int rle = 1;
3219
+ // try to find repeating bytes (min. len = 2 pixels)
3220
+ // maximum chunk size is 128 pixels
3221
+ while (index + rle < maxLen) {
3222
+ if (col != pixels[index + rle] || rle == 128) {
3223
+ isRLE = (rle > 1); // set flag for RLE chunk
3224
+ break;
3225
+ }
3226
+ rle++;
3227
+ }
3228
+ if (isRLE) {
3229
+ output.write(128 | (rle - 1));
3230
+ output.write(col & 0xff);
3231
+ output.write(col >> 8 & 0xff);
3232
+ output.write(col >> 16 & 0xff);
3233
+ if (format == ARGB) output.write(col >>> 24 & 0xff);
3234
+
3235
+ } else { // not RLE
3236
+ rle = 1;
3237
+ while (index + rle < maxLen) {
3238
+ if ((col != pixels[index + rle] && rle < 128) || rle < 3) {
3239
+ currChunk[rle] = col = pixels[index + rle];
3240
+ } else {
3241
+ // check if the exit condition was the start of
3242
+ // a repeating colour
3243
+ if (col == pixels[index + rle]) rle -= 2;
3244
+ break;
3245
+ }
3246
+ rle++;
3247
+ }
3248
+ // write uncompressed chunk
3249
+ output.write(rle - 1);
3250
+ if (format == ARGB) {
3251
+ for (int i = 0; i < rle; i++) {
3252
+ col = currChunk[i];
3253
+ output.write(col & 0xff);
3254
+ output.write(col >> 8 & 0xff);
3255
+ output.write(col >> 16 & 0xff);
3256
+ output.write(col >>> 24 & 0xff);
3257
+ }
3258
+ } else {
3259
+ for (int i = 0; i < rle; i++) {
3260
+ col = currChunk[i];
3261
+ output.write(col & 0xff);
3262
+ output.write(col >> 8 & 0xff);
3263
+ output.write(col >> 16 & 0xff);
3264
+ }
3265
+ }
3266
+ }
3267
+ index += rle;
3268
+ }
3269
+ }
3270
+ output.flush();
3271
+ return true;
3272
+
3273
+ } catch (IOException e) {
3274
+ return false;
3275
+ }
3276
+ }
3277
+
3451
3278
 
3452
3279
  /**
3453
3280
  * ( begin auto-generated from PImage_save.xml )
3454
3281
  *
3455
- * Saves the image into a file. Append a file extension to the name of the
3456
- * file, to indicate the file format to be used: either TIFF (.tif), TARGA
3457
- * (.tga), JPEG (.jpg), or PNG (.png). If no extension is included in the
3458
- * filename, the image will save in TIFF format and .tif will be added to the
3459
- * name. These files are saved to the sketch's folder, which may be opened by
3460
- * selecting "Show sketch folder" from the "Sketch" menu.
3461
- * To save an image created within the code, rather than through
3462
- * loading, it's necessary to make the image with the
3463
- * <b>createImage()</b> function so it is aware of the location of the program
3464
- * and can therefore save the file to the right place. See the
3282
+ * Saves the image into a file. Append a file extension to the name of
3283
+ * the file, to indicate the file format to be used: either TIFF (.tif),
3284
+ * TARGA (.tga), JPEG (.jpg), or PNG (.png). If no extension is included
3285
+ * in the filename, the image will save in TIFF format and .tif will be
3286
+ * added to the name. These files are saved to the sketch's folder, which
3287
+ * may be opened by selecting "Show sketch folder" from the "Sketch" menu.
3288
+ * To save an image created within the code, rather
3289
+ * than through loading, it's necessary to make the image with the
3290
+ * <b>createImage()</b> function so it is aware of the location of the
3291
+ * program and can therefore save the file to the right place. See the
3465
3292
  * <b>createImage()</b> reference for more information.
3466
3293
  *
3467
3294
  * ( end auto-generated )
3468
3295
  * <h3>Advanced</h3>
3469
3296
  * Save this image to disk.
3470
3297
  * <p>
3471
- * As of revision 0100, this function requires an absolute path, in order to
3472
- * avoid confusion. To save inside the sketch folder, use the function
3473
- * savePath() from PApplet, or use saveFrame() instead. As of revision 0116,
3474
- * savePath() is not needed if this object has been created (as recommended)
3475
- * via createImage() or createGraphics() or one of its neighbors.
3298
+ * As of revision 0100, this function requires an absolute path,
3299
+ * in order to avoid confusion. To save inside the sketch folder,
3300
+ * use the function savePath() from PApplet, or use saveFrame() instead.
3301
+ * As of revision 0116, savePath() is not needed if this object has been
3302
+ * created (as recommended) via createImage() or createGraphics() or
3303
+ * one of its neighbors.
3476
3304
  * <p>
3477
- * As of revision 0115, when using Java 1.4 and later, you can write to
3478
- * several formats besides tga and tiff. If Java 1.4 is installed and the
3479
- * extension used is supported (usually png, jpg, jpeg, bmp, and tiff), then
3480
- * those methods will be used to write the image. To get a list of the
3481
- * supported formats for writing, use: <BR>
3305
+ * As of revision 0115, when using Java 1.4 and later, you can write
3306
+ * to several formats besides tga and tiff. If Java 1.4 is installed
3307
+ * and the extension used is supported (usually png, jpg, jpeg, bmp,
3308
+ * and tiff), then those methods will be used to write the image.
3309
+ * To get a list of the supported formats for writing, use: <BR>
3482
3310
  * <TT>println(javax.imageio.ImageIO.getReaderFormatNames())</TT>
3483
3311
  * <p>
3484
3312
  * To use the original built-in image writers, use .tga or .tif as the
3485
- * extension, or don't include an extension. When no extension is used, the
3486
- * extension .tif will be added to the file name.
3313
+ * extension, or don't include an extension. When no extension is used,
3314
+ * the extension .tif will be added to the file name.
3487
3315
  * <p>
3488
- * The ImageIO API claims to support wbmp files, however they probably require
3489
- * a black and white image. Basic testing produced a zero-length file with no
3490
- * error.
3316
+ * The ImageIO API claims to support wbmp files, however they probably
3317
+ * require a black and white image. Basic testing produced a zero-length
3318
+ * file with no error.
3491
3319
  *
3492
- * @return
3493
3320
  * @webref pimage:method
3494
3321
  * @brief Saves the image to a TIFF, TARGA, PNG, or JPEG file
3495
3322
  * @usage application
3496
3323
  * @param filename a sequence of letters and numbers
3497
3324
  */
3498
- public boolean save(String filename) { // ignore
3499
- boolean success = false;
3500
-
3501
- if (parent != null) {
3502
- // use savePath(), so that the intermediate directories are created
3503
- filename = parent.savePath(filename);
3504
-
3505
- } else {
3506
- File file = new File(filename);
3507
- if (file.isAbsolute()) {
3508
- // make sure that the intermediate folders have been created
3509
- PApplet.createPath(file);
3510
- } else {
3511
- String msg
3512
- = "PImage.save() requires an absolute path. "
3513
- + "Use createImage(), or pass savePath() to save().";
3514
- PGraphics.showException(msg);
3515
- }
3516
- }
3517
-
3518
- // Make sure the pixel data is ready to go
3519
- loadPixels();
3520
-
3521
- try {
3522
- OutputStream os = null;
3523
-
3524
- if (saveImageFormats == null) {
3525
- saveImageFormats = javax.imageio.ImageIO.getWriterFormatNames();
3526
- }
3527
- if (saveImageFormats != null) {
3528
- for (int i = 0; i < saveImageFormats.length; i++) {
3529
- if (filename.endsWith("." + saveImageFormats[i])) {
3530
- if (!saveImageIO(filename)) {
3531
- System.err.println("Error while saving image.");
3532
- return false;
3533
- }
3534
- return true;
3535
- }
3536
- }
3537
- }
3538
-
3539
- if (filename.toLowerCase().endsWith(".tga")) {
3540
- os = new BufferedOutputStream(new FileOutputStream(filename), 32768);
3541
- success = saveTGA(os); //, pixels, width, height, format);
3542
-
3543
- } else {
3544
- if (!filename.toLowerCase().endsWith(".tif")
3545
- && !filename.toLowerCase().endsWith(".tiff")) {
3546
- // if no .tif extension, add it..
3547
- filename += ".tif";
3548
- }
3549
- os = new BufferedOutputStream(new FileOutputStream(filename), 32768);
3550
- success = saveTIFF(os); //, pixels, width, height);
3551
- }
3552
- os.flush();
3553
- os.close();
3554
-
3555
- } catch (IOException e) {
3556
- System.err.println("Error while saving image.");
3557
- e.printStackTrace();
3558
- success = false;
3559
- }
3560
- return success;
3561
- }
3325
+ public boolean save(String filename) { // ignore
3326
+ boolean success = false;
3327
+
3328
+ if (parent != null) {
3329
+ // use savePath(), so that the intermediate directories are created
3330
+ filename = parent.savePath(filename);
3331
+
3332
+ } else {
3333
+ File file = new File(filename);
3334
+ if (file.isAbsolute()) {
3335
+ // make sure that the intermediate folders have been created
3336
+ PApplet.createPath(file);
3337
+ } else {
3338
+ String msg =
3339
+ "PImage.save() requires an absolute path. " +
3340
+ "Use createImage(), or pass savePath() to save().";
3341
+ PGraphics.showException(msg);
3342
+ }
3343
+ }
3344
+
3345
+ // Make sure the pixel data is ready to go
3346
+ loadPixels();
3347
+
3348
+ try {
3349
+ OutputStream os = null;
3350
+
3351
+ if (saveImpl(filename)) {
3352
+ return true;
3353
+ }
3354
+
3355
+ if (filename.toLowerCase().endsWith(".tga")) {
3356
+ os = new BufferedOutputStream(new FileOutputStream(filename), 32768);
3357
+ success = saveTGA(os); //, pixels, width, height, format);
3358
+
3359
+ } else {
3360
+ if (!filename.toLowerCase().endsWith(".tif") &&
3361
+ !filename.toLowerCase().endsWith(".tiff")) {
3362
+ // if no .tif extension, add it..
3363
+ filename += ".tif";
3364
+ }
3365
+ os = new BufferedOutputStream(new FileOutputStream(filename), 32768);
3366
+ success = saveTIFF(os); //, pixels, width, height);
3367
+ }
3368
+ os.flush();
3369
+ os.close();
3370
+
3371
+ } catch (IOException e) {
3372
+ System.err.println("Error while saving image.");
3373
+ success = false;
3374
+ }
3375
+ return success;
3376
+ }
3562
3377
  }