picrate 2.0.1-java → 2.1.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  }