propane 3.4.2-java → 3.5.0-java

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