propane 3.4.2-java → 3.5.0-java

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