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