propane 3.3.1-java → 3.6.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -2
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +117 -0
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -3
  5. data/.travis.yml +9 -0
  6. data/CHANGELOG.md +17 -5
  7. data/Gemfile +2 -0
  8. data/README.md +17 -8
  9. data/Rakefile +16 -30
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +6 -4
  12. data/lib/propane/app.rb +20 -10
  13. data/lib/propane/creators/sketch_class.rb +7 -1
  14. data/lib/propane/creators/sketch_factory.rb +4 -2
  15. data/lib/propane/creators/sketch_writer.rb +1 -0
  16. data/lib/propane/helper_methods.rb +23 -24
  17. data/lib/propane/helpers/numeric.rb +2 -0
  18. data/lib/propane/helpers/version_error.rb +1 -0
  19. data/lib/propane/library.rb +5 -1
  20. data/lib/propane/library_loader.rb +2 -0
  21. data/lib/propane/native_folder.rb +21 -15
  22. data/lib/propane/native_loader.rb +3 -0
  23. data/lib/propane/runner.rb +14 -6
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +28 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +6 -0
  29. data/library/file_chooser/chooser.rb +10 -9
  30. data/library/file_chooser/file_chooser.rb +10 -9
  31. data/library/library_proxy/library_proxy.rb +2 -0
  32. data/library/net/net.rb +7 -0
  33. data/library/simplex_noise/simplex_noise.rb +2 -0
  34. data/library/slider/slider.rb +23 -22
  35. data/library/vector_utils/vector_utils.rb +4 -0
  36. data/library/video_event/video_event.rb +4 -1
  37. data/mvnw +127 -51
  38. data/mvnw.cmd +182 -145
  39. data/pom.rb +53 -50
  40. data/pom.xml +17 -8
  41. data/propane.gemspec +13 -11
  42. data/src/main/java/monkstone/ColorUtil.java +13 -1
  43. data/src/main/java/monkstone/MathToolModule.java +253 -203
  44. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  45. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  46. data/src/main/java/monkstone/filechooser/Chooser.java +2 -1
  47. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  48. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  49. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  50. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  53. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  54. data/src/main/java/monkstone/slider/WheelHandler.java +7 -6
  55. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  56. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
  57. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
  58. data/src/main/java/monkstone/videoevent/CaptureEvent.java +27 -0
  59. data/src/main/java/monkstone/videoevent/{VideoInterface.java → MovieEvent.java} +11 -27
  60. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  61. data/src/main/java/processing/awt/PGraphicsJava2D.java +2164 -1661
  62. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  63. data/src/main/java/processing/awt/PShapeJava2D.java +280 -268
  64. data/src/main/java/processing/awt/PSurfaceAWT.java +942 -829
  65. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  66. data/src/main/java/processing/core/PApplet.java +831 -824
  67. data/src/main/java/processing/core/PConstants.java +477 -447
  68. data/src/main/java/processing/core/PFont.java +914 -880
  69. data/src/main/java/processing/core/PGraphics.java +229 -213
  70. data/src/main/java/processing/core/PImage.java +620 -318
  71. data/src/main/java/processing/core/PMatrix.java +172 -159
  72. data/src/main/java/processing/core/PMatrix2D.java +478 -409
  73. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  74. data/src/main/java/processing/core/PShape.java +2888 -2652
  75. data/src/main/java/processing/core/PShapeOBJ.java +436 -415
  76. data/src/main/java/processing/core/PShapeSVG.java +1702 -1479
  77. data/src/main/java/processing/core/PStyle.java +40 -37
  78. data/src/main/java/processing/core/PSurface.java +139 -97
  79. data/src/main/java/processing/core/PSurfaceNone.java +296 -208
  80. data/src/main/java/processing/core/PVector.java +997 -965
  81. data/src/main/java/processing/core/ThinkDifferent.java +12 -17
  82. data/src/main/java/processing/data/DoubleDict.java +756 -710
  83. data/src/main/java/processing/data/DoubleList.java +749 -696
  84. data/src/main/java/processing/data/FloatDict.java +748 -702
  85. data/src/main/java/processing/data/FloatList.java +751 -697
  86. data/src/main/java/processing/data/IntDict.java +720 -673
  87. data/src/main/java/processing/data/IntList.java +699 -633
  88. data/src/main/java/processing/data/JSONArray.java +931 -873
  89. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  90. data/src/main/java/processing/data/JSONTokener.java +351 -341
  91. data/src/main/java/processing/data/LongDict.java +710 -663
  92. data/src/main/java/processing/data/LongList.java +701 -635
  93. data/src/main/java/processing/data/Sort.java +37 -41
  94. data/src/main/java/processing/data/StringDict.java +525 -486
  95. data/src/main/java/processing/data/StringList.java +626 -580
  96. data/src/main/java/processing/data/Table.java +3690 -3510
  97. data/src/main/java/processing/data/TableRow.java +182 -183
  98. data/src/main/java/processing/data/XML.java +957 -883
  99. data/src/main/java/processing/dxf/RawDXF.java +404 -0
  100. data/src/main/java/processing/event/Event.java +87 -66
  101. data/src/main/java/processing/event/KeyEvent.java +48 -41
  102. data/src/main/java/processing/event/MouseEvent.java +88 -113
  103. data/src/main/java/processing/event/TouchEvent.java +10 -6
  104. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  105. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  106. data/src/main/java/processing/net/Client.java +744 -0
  107. data/src/main/java/processing/net/Server.java +388 -0
  108. data/src/main/java/processing/opengl/FontTexture.java +289 -270
  109. data/src/main/java/processing/opengl/FrameBuffer.java +386 -364
  110. data/src/main/java/processing/opengl/LinePath.java +547 -500
  111. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  112. data/src/main/java/processing/opengl/PGL.java +3047 -2914
  113. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  114. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  115. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  116. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  117. data/src/main/java/processing/opengl/PShader.java +1266 -1257
  118. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  119. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  120. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  121. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  122. data/test/create_test.rb +21 -20
  123. data/test/deglut_spec_test.rb +4 -2
  124. data/test/helper_methods_test.rb +49 -20
  125. data/test/math_tool_test.rb +39 -32
  126. data/test/native_folder.rb +47 -0
  127. data/test/respond_to_test.rb +3 -2
  128. data/test/sketches/key_event.rb +2 -2
  129. data/test/sketches/library/my_library/my_library.rb +3 -0
  130. data/test/test_helper.rb +2 -0
  131. data/test/vecmath_spec_test.rb +35 -22
  132. data/vendors/Rakefile +33 -62
  133. metadata +54 -45
  134. data/src/main/java/processing/core/util/image/ImageLoadFacade.java +0 -161
  135. data/src/main/java/processing/core/util/image/ImageSaveFacade.java +0 -169
  136. data/src/main/java/processing/core/util/image/constants/TifConstants.java +0 -45
  137. data/src/main/java/processing/core/util/image/load/AwtImageLoadStrategy.java +0 -80
  138. data/src/main/java/processing/core/util/image/load/Base64StringImageLoadStrategy.java +0 -73
  139. data/src/main/java/processing/core/util/image/load/FallbackImageLoadStrategy.java +0 -70
  140. data/src/main/java/processing/core/util/image/load/ImageIoImageLoadStrategy.java +0 -132
  141. data/src/main/java/processing/core/util/image/load/ImageLoadStrategy.java +0 -48
  142. data/src/main/java/processing/core/util/image/load/ImageLoadUtil.java +0 -45
  143. data/src/main/java/processing/core/util/image/load/TgaImageLoadStrategy.java +0 -255
  144. data/src/main/java/processing/core/util/image/load/TiffImageLoadStrategy.java +0 -98
  145. data/src/main/java/processing/core/util/image/save/ImageSaveStrategy.java +0 -49
  146. data/src/main/java/processing/core/util/image/save/ImageSaveUtil.java +0 -48
  147. data/src/main/java/processing/core/util/image/save/ImageWriterImageSaveStrategy.java +0 -179
  148. data/src/main/java/processing/core/util/image/save/SaveImageException.java +0 -41
  149. data/src/main/java/processing/core/util/image/save/TgaImageSaveStrategy.java +0 -198
  150. data/src/main/java/processing/core/util/image/save/TiffImageSaveStrategy.java +0 -91
  151. data/src/main/java/processing/core/util/image/save/TiffNakedFilenameImageSaveStrategy.java +0 -57
  152. data/src/main/java/processing/core/util/io/InputFactory.java +0 -285
  153. data/src/main/java/processing/core/util/io/PathUtil.java +0 -109
  154. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  155. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  156. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  157. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -24,10 +24,12 @@
24
24
 
25
25
  package processing.core;
26
26
 
27
- import processing.core.util.image.ImageSaveFacade;
28
-
29
- import java.awt.*;
30
- import java.awt.image.*;
27
+ import java.io.BufferedOutputStream;
28
+ import java.io.File;
29
+ import java.io.FileOutputStream;
30
+ import java.io.IOException;
31
+ import java.io.InputStream;
32
+ import java.io.OutputStream;
31
33
 
32
34
 
33
35
  /**
@@ -40,11 +42,11 @@ import java.awt.image.*;
40
42
  * fields for the <b>width</b> and <b>height</b> of the image, as well as
41
43
  * an array called <b>pixels[]</b> that contains the values for every pixel
42
44
  * in the image. The methods described below allow easy access to the
43
- * image's pixels and alpha channel and simplify the process of compositing.<br/>
44
- * <br/> using the <b>pixels[]</b> array, be sure to use the
45
+ * image's pixels and alpha channel and simplify the process of compositing.
46
+ * using the <b>pixels[]</b> array, be sure to use the
45
47
  * <b>loadPixels()</b> method on the image to make sure that the pixel data
46
- * is properly loaded.<br/>
47
- * <br/> create a new image, use the <b>createImage()</b> function. Do not
48
+ * is properly loaded.
49
+ * create a new image, use the <b>createImage()</b> function. Do not
48
50
  * use the syntax <b>new PImage()</b>.
49
51
  *
50
52
  * ( end auto-generated )
@@ -58,6 +60,17 @@ import java.awt.image.*;
58
60
  */
59
61
  public class PImage implements PConstants, Cloneable {
60
62
 
63
+ private static final byte TIFF_HEADER[] = {
64
+ 77, 77, 0, 42, 0, 0, 0, 8, 0, 9, 0, -2, 0, 4, 0, 0, 0, 1, 0, 0,
65
+ 0, 0, 1, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 3, 0, 0, 0, 1,
66
+ 0, 0, 0, 0, 1, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 122, 1, 6, 0, 3, 0,
67
+ 0, 0, 1, 0, 2, 0, 0, 1, 17, 0, 4, 0, 0, 0, 1, 0, 0, 3, 0, 1, 21,
68
+ 0, 3, 0, 0, 0, 1, 0, 3, 0, 0, 1, 22, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0,
69
+ 1, 23, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 8, 0, 8
70
+ };
71
+
72
+ private static final String TIFF_ERROR = "Error: Processing can only read its own TIFF files.";
73
+
61
74
  /**
62
75
  * Format for this image, one of RGB, ARGB or ALPHA.
63
76
  * note that RGB images still require 0xff in the high byte
@@ -75,8 +88,8 @@ public class PImage implements PConstants, Cloneable {
75
88
  * values. The <b>index</b> value defines the position of a value within
76
89
  * the array. For example, the statement <b>color b = pixels[230]</b> will
77
90
  * set the variable <b>b</b> to be equal to the value at that location in
78
- * the array.<br />
79
- * <br />
91
+ * the array.
92
+ *
80
93
  * Before accessing this array, the data must loaded with the
81
94
  * <b>loadPixels()</b> function. After the array data has been modified,
82
95
  * the <b>updatePixels()</b> function must be run to update the changes.
@@ -184,11 +197,11 @@ public class PImage implements PConstants, Cloneable {
184
197
  * pixel in the image. A group of methods, described below, allow easy
185
198
  * access to the image's pixels and alpha channel and simplify the process
186
199
  * of compositing.
187
- * <br/> <br/>
200
+ *
188
201
  * Before using the <b>pixels[]</b> array, be sure to use the
189
202
  * <b>loadPixels()</b> method on the image to make sure that the pixel data
190
203
  * is properly loaded.
191
- * <br/> <br/>
204
+ *
192
205
  * To create a new image, use the <b>createImage()</b> function (do not use
193
206
  * <b>new PImage()</b>).
194
207
  * ( end auto-generated )
@@ -236,6 +249,7 @@ public class PImage implements PConstants, Cloneable {
236
249
  init(width, height, format, factor);
237
250
  }
238
251
 
252
+
239
253
  /**
240
254
  * Do not remove, see notes in the other variant.
241
255
  */
@@ -266,7 +280,7 @@ public class PImage implements PConstants, Cloneable {
266
280
  /**
267
281
  * Check the alpha on an image, using a really primitive loop.
268
282
  */
269
- private void checkAlpha() {
283
+ public void checkAlpha() {
270
284
  if (pixels == null) return;
271
285
 
272
286
  for (int i = 0; i < pixels.length; i++) {
@@ -315,117 +329,11 @@ public class PImage implements PConstants, Cloneable {
315
329
  this.format = format;
316
330
  this.pixelDensity = factor;
317
331
  this.pixels = pixels;
318
- this.pixelWidth = width * pixelDensity;
319
- this.pixelHeight = height * pixelDensity;
320
- }
321
-
322
- /**
323
- * Construct a new PImage from a java.awt.Image. This constructor assumes
324
- * that you've done the work of making sure a MediaTracker has been used
325
- * to fully download the data and that the img is valid.
326
- *
327
- * @nowebref
328
- * @param img assumes a MediaTracker has been used to fully download
329
- * the data and the img is valid
330
- */
331
- public PImage(Image img) {
332
- initFromImage(img);
333
- }
334
-
335
- /**
336
- * @nowebref
337
- *
338
- * @param requiresCheckAlpha
339
- */
340
- public PImage(Image img, boolean requiresCheckAlpha) {
341
- initFromImage(img);
342
-
343
- if (requiresCheckAlpha) {
344
- checkAlpha();
345
- }
346
- }
347
-
348
- /**
349
- * @nowebref
350
- *
351
- * @param requiresCheckAlpha
352
- */
353
- public PImage(Image img, boolean requiresCheckAlpha, PApplet parent) {
354
- initFromImage(img);
355
-
356
- this.parent = parent;
357
-
358
- if (requiresCheckAlpha) {
359
- checkAlpha();
360
- }
361
- }
362
-
363
- private void initFromImage(Image img) {
364
- format = RGB;
365
- if (img instanceof BufferedImage) {
366
- BufferedImage bi = (BufferedImage) img;
367
- width = bi.getWidth();
368
- height = bi.getHeight();
369
- int type = bi.getType();
370
- if (type == BufferedImage.TYPE_3BYTE_BGR ||
371
- type == BufferedImage.TYPE_4BYTE_ABGR) {
372
- pixels = new int[width * height];
373
- bi.getRGB(0, 0, width, height, pixels, 0, width);
374
- if (type == BufferedImage.TYPE_4BYTE_ABGR) {
375
- format = ARGB;
376
- } else {
377
- opaque();
378
- }
379
- } else {
380
- DataBuffer db = bi.getRaster().getDataBuffer();
381
- if (db instanceof DataBufferInt) {
382
- pixels = ((DataBufferInt) db).getData();
383
- if (type == BufferedImage.TYPE_INT_ARGB) {
384
- format = ARGB;
385
- } else if (type == BufferedImage.TYPE_INT_RGB) {
386
- opaque();
387
- }
388
- }
389
- }
390
- }
391
- // Implements fall-through if not DataBufferInt above, or not a
392
- // known type, or not DataBufferInt for the data itself.
393
- if (pixels == null) { // go the old school Java 1.0 route
394
- width = img.getWidth(null);
395
- height = img.getHeight(null);
396
- pixels = new int[width * height];
397
- PixelGrabber pg =
398
- new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
399
- try {
400
- pg.grabPixels();
401
- } catch (InterruptedException e) { }
402
- }
403
- pixelDensity = 1;
404
- pixelWidth = width;
405
- pixelHeight = height;
406
- }
407
-
408
- /**
409
- * Use the getNative() method instead, which allows library interfaces to be
410
- * written in a cross-platform fashion for desktop, Android, and others.
411
- * This is still included for PGraphics objects, which may need the image.
412
- */
413
- public Image getImage() { // ignore
414
- return (Image) getNative();
415
332
  }
416
333
 
417
334
 
418
- /**
419
- * Returns a native BufferedImage from this PImage.
420
- */
421
335
  public Object getNative() { // ignore
422
- loadPixels();
423
- int type = (format == RGB) ?
424
- BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
425
- BufferedImage image = new BufferedImage(pixelWidth, pixelHeight, type);
426
- WritableRaster wr = image.getRaster();
427
- wr.setDataElements(0, 0, pixelWidth, pixelHeight, pixels);
428
- return image;
336
+ return null;
429
337
  }
430
338
 
431
339
 
@@ -478,7 +386,7 @@ public class PImage implements PConstants, Cloneable {
478
386
  *
479
387
  * Loads the pixel data for the image into its <b>pixels[]</b> array. This
480
388
  * function must always be called before reading from or writing to <b>pixels[]</b>.
481
- * <br/><br/> renderers may or may not seem to require <b>loadPixels()</b>
389
+ * renderers may or may not seem to require <b>loadPixels()</b>
482
390
  * or <b>updatePixels()</b>. However, the rule is that any time you want to
483
391
  * manipulate the <b>pixels[]</b> array, you must first call
484
392
  * <b>loadPixels()</b>, and after changes have been made, call
@@ -490,7 +398,7 @@ public class PImage implements PConstants, Cloneable {
490
398
  *
491
399
  * <h3>Advanced</h3>
492
400
  * Call this when you want to mess with the pixels[] array.
493
- * <p/>
401
+ *
494
402
  * For subclasses where the pixels[] buffer isn't set by default,
495
403
  * this should copy all data into the pixels[] array
496
404
  *
@@ -517,14 +425,14 @@ public class PImage implements PConstants, Cloneable {
517
425
  * Updates the image with the data in its <b>pixels[]</b> array. Use in
518
426
  * conjunction with <b>loadPixels()</b>. If you're only reading pixels from
519
427
  * the array, there's no need to call <b>updatePixels()</b>.
520
- * <br/><br/> renderers may or may not seem to require <b>loadPixels()</b>
428
+ * renderers may or may not seem to require <b>loadPixels()</b>
521
429
  * or <b>updatePixels()</b>. However, the rule is that any time you want to
522
430
  * manipulate the <b>pixels[]</b> array, you must first call
523
431
  * <b>loadPixels()</b>, and after changes have been made, call
524
432
  * <b>updatePixels()</b>. Even if the renderer may not seem to use this
525
433
  * function in the current Processing release, this will always be subject
526
434
  * to change.
527
- * <br/> <br/>
435
+ *
528
436
  * Currently, none of the renderers use the additional parameters to
529
437
  * <b>updatePixels()</b>, however this may be implemented in the future.
530
438
  *
@@ -592,8 +500,8 @@ public class PImage implements PConstants, Cloneable {
592
500
  * Resize the image to a new width and height. To make the image scale
593
501
  * proportionally, use 0 as the value for the <b>wide</b> or <b>high</b>
594
502
  * parameter. For instance, to make the width of an image 150 pixels, and
595
- * change the height using the same proportion, use resize(150, 0).<br />
596
- * <br />
503
+ * change the height using the same proportion, use resize(150, 0).
504
+ *
597
505
  * Even though a PGraphics is technically a PImage, it is not possible to
598
506
  * rescale the image data found in a PGraphics. (It's simply not possible
599
507
  * to do this consistently across renderers: technically infeasible with
@@ -610,104 +518,7 @@ public class PImage implements PConstants, Cloneable {
610
518
  * @see PImage#get(int, int, int, int)
611
519
  */
612
520
  public void resize(int w, int h) { // ignore
613
- if (w <= 0 && h <= 0) {
614
- throw new IllegalArgumentException("width or height must be > 0 for resize");
615
- }
616
-
617
- if (w == 0) { // Use height to determine relative size
618
- float diff = (float) h / (float) height;
619
- w = (int) (width * diff);
620
- } else if (h == 0) { // Use the width to determine relative size
621
- float diff = (float) w / (float) width;
622
- h = (int) (height * diff);
623
- }
624
-
625
- BufferedImage img =
626
- shrinkImage((BufferedImage) getNative(), w*pixelDensity, h*pixelDensity);
627
-
628
- PImage temp = new PImage(img);
629
- this.pixelWidth = temp.width;
630
- this.pixelHeight = temp.height;
631
-
632
- // Get the resized pixel array
633
- this.pixels = temp.pixels;
634
-
635
- this.width = pixelWidth / pixelDensity;
636
- this.height = pixelHeight / pixelDensity;
637
-
638
- // Mark the pixels array as altered
639
- updatePixels();
640
- }
641
-
642
-
643
- // Adapted from getFasterScaledInstance() method from page 111 of
644
- // "Filthy Rich Clients" by Chet Haase and Romain Guy
645
- // Additional modifications and simplifications have been added,
646
- // plus a fix to deal with an infinite loop if images are expanded.
647
- // http://code.google.com/p/processing/issues/detail?id=1463
648
- static private BufferedImage shrinkImage(BufferedImage img,
649
- int targetWidth, int targetHeight) {
650
- int type = (img.getTransparency() == Transparency.OPAQUE) ?
651
- BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
652
- BufferedImage outgoing = img;
653
- BufferedImage scratchImage = null;
654
- Graphics2D g2 = null;
655
- int prevW = outgoing.getWidth();
656
- int prevH = outgoing.getHeight();
657
- boolean isTranslucent = img.getTransparency() != Transparency.OPAQUE;
658
-
659
- // Use multi-step technique: start with original size, then scale down in
660
- // multiple passes with drawImage() until the target size is reached
661
- int w = img.getWidth();
662
- int h = img.getHeight();
663
-
664
- do {
665
- if (w > targetWidth) {
666
- w /= 2;
667
- // if this is the last step, do the exact size
668
- if (w < targetWidth) {
669
- w = targetWidth;
670
- }
671
- } else if (targetWidth >= w) {
672
- w = targetWidth;
673
- }
674
- if (h > targetHeight) {
675
- h /= 2;
676
- if (h < targetHeight) {
677
- h = targetHeight;
678
- }
679
- } else if (targetHeight >= h) {
680
- h = targetHeight;
681
- }
682
- if (scratchImage == null || isTranslucent) {
683
- // Use a single scratch buffer for all iterations and then copy
684
- // to the final, correctly-sized image before returning
685
- scratchImage = new BufferedImage(w, h, type);
686
- g2 = scratchImage.createGraphics();
687
- }
688
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
689
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
690
- g2.drawImage(outgoing, 0, 0, w, h, 0, 0, prevW, prevH, null);
691
- prevW = w;
692
- prevH = h;
693
- outgoing = scratchImage;
694
- } while (w != targetWidth || h != targetHeight);
695
-
696
- if (g2 != null) {
697
- g2.dispose();
698
- }
699
-
700
- // If we used a scratch buffer that is larger than our target size,
701
- // create an image of the right size and copy the results into it
702
- if (targetWidth != outgoing.getWidth() ||
703
- targetHeight != outgoing.getHeight()) {
704
- scratchImage = new BufferedImage(targetWidth, targetHeight, type);
705
- g2 = scratchImage.createGraphics();
706
- g2.drawImage(outgoing, 0, 0, null);
707
- g2.dispose();
708
- outgoing = scratchImage;
709
- }
710
- return outgoing;
521
+ throw new RuntimeException("resize() not implemented for this PImage type");
711
522
  }
712
523
 
713
524
 
@@ -745,14 +556,14 @@ public class PImage implements PConstants, Cloneable {
745
556
  * the display window by specifying an additional <b>width</b> and
746
557
  * <b>height</b> parameter. When getting an image, the <b>x</b> and
747
558
  * <b>y</b> parameters define the coordinates for the upper-left corner of
748
- * the image, regardless of the current <b>imageMode()</b>.<br />
749
- * <br />
559
+ * the image, regardless of the current <b>imageMode()</b>.
560
+ *
750
561
  * If the pixel requested is outside of the image window, black is
751
562
  * returned. The numbers returned are scaled according to the current color
752
563
  * ranges, but only RGB values are returned by this function. For example,
753
564
  * even though you may have drawn a shape with <b>colorMode(HSB)</b>, the
754
- * numbers returned will be in RGB format.<br />
755
- * <br />
565
+ * numbers returned will be in RGB format.
566
+ *
756
567
  * Getting the color of a single pixel with <b>get(x, y)</b> is easy, but
757
568
  * not as fast as grabbing the data directly from <b>pixels[]</b>. The
758
569
  * equivalent statement to <b>get(x, y)</b> using <b>pixels[]</b> is
@@ -899,15 +710,15 @@ public class PImage implements PConstants, Cloneable {
899
710
  * ( begin auto-generated from PImage_set.xml )
900
711
  *
901
712
  * Changes the color of any pixel or writes an image directly into the
902
- * display window.<br />
903
- * <br />
713
+ * display window.
714
+ *
904
715
  * The <b>x</b> and <b>y</b> parameters specify the pixel to change and the
905
716
  * <b>color</b> parameter specifies the color value. The color parameter is
906
717
  * affected by the current color mode (the default is RGB values from 0 to
907
718
  * 255). When setting an image, the <b>x</b> and <b>y</b> parameters define
908
719
  * the coordinates for the upper-left corner of the image, regardless of
909
720
  * the current <b>imageMode()</b>.
910
- * <br /><br />
721
+ *
911
722
  * Setting the color of a single pixel with <b>set(x, y)</b> is easy, but
912
723
  * not as fast as putting the data directly into <b>pixels[]</b>. The
913
724
  * equivalent statement to <b>set(x, y, #000000)</b> using <b>pixels[]</b>
@@ -1003,7 +814,7 @@ public class PImage implements PConstants, Cloneable {
1003
814
  * @param maskArray array of integers used as the alpha channel, needs to be
1004
815
  * the same length as the image's pixel array.
1005
816
  */
1006
- public void mask(int maskArray[]) { // ignore
817
+ public void mask(int[] maskArray) { // ignore
1007
818
  loadPixels();
1008
819
  // don't execute if mask image is different size
1009
820
  if (maskArray.length != pixels.length) {
@@ -1023,8 +834,8 @@ public class PImage implements PConstants, Cloneable {
1023
834
  * Masks part of an image from displaying by loading another image and
1024
835
  * using it as an alpha channel. This mask image should only contain
1025
836
  * grayscale data, but only the blue color channel is used. The mask image
1026
- * needs to be the same size as the image to which it is applied.<br />
1027
- * <br />
837
+ * needs to be the same size as the image to which it is applied.
838
+ *
1028
839
  * In addition to using a mask image, an integer array containing the alpha
1029
840
  * channel data can be specified directly. This method is useful for
1030
841
  * creating dynamically generated alpha masks. This array must be of the
@@ -1138,28 +949,28 @@ public class PImage implements PConstants, Cloneable {
1138
949
  /**
1139
950
  * ( begin auto-generated from PImage_filter.xml )
1140
951
  *
1141
- * Filters an image as defined by one of the following modes:<br /><br
1142
- * />THRESHOLD - converts the image to black and white pixels depending if
952
+ * Filters an image as defined by one of the following modes:
953
+ * THRESHOLD - converts the image to black and white pixels depending if
1143
954
  * they are above or below the threshold defined by the level parameter.
1144
955
  * The level must be between 0.0 (black) and 1.0(white). If no level is
1145
- * specified, 0.5 is used.<br />
1146
- * <br />
1147
- * GRAY - converts any colors in the image to grayscale equivalents<br />
1148
- * <br />
1149
- * INVERT - sets each pixel to its inverse value<br />
1150
- * <br />
956
+ * specified, 0.5 is used.
957
+ *
958
+ * GRAY - converts any colors in the image to grayscale equivalents
959
+ *
960
+ * INVERT - sets each pixel to its inverse value
961
+ *
1151
962
  * POSTERIZE - limits each channel of the image to the number of colors
1152
- * specified as the level parameter<br />
1153
- * <br />
963
+ * specified as the level parameter
964
+ *
1154
965
  * BLUR - executes a Guassian blur with the level parameter specifying the
1155
966
  * extent of the blurring. If no level parameter is used, the blur is
1156
- * equivalent to Guassian blur of radius 1<br />
1157
- * <br />
1158
- * OPAQUE - sets the alpha channel to entirely opaque<br />
1159
- * <br />
967
+ * equivalent to Guassian blur of radius 1
968
+ *
969
+ * OPAQUE - sets the alpha channel to entirely opaque
970
+ *
1160
971
  * ERODE - reduces the light areas with the amount defined by the level
1161
- * parameter<br />
1162
- * <br />
972
+ * parameter
973
+ *
1163
974
  * DILATE - increases the light areas with the amount defined by the level parameter
1164
975
  *
1165
976
  * ( end auto-generated )
@@ -1178,7 +989,7 @@ public class PImage implements PConstants, Cloneable {
1178
989
  * </UL>
1179
990
  * Luminance conversion code contributed by
1180
991
  * <A HREF="http://www.toxi.co.uk">toxi</A>
1181
- * <P/>
992
+ *
1182
993
  * Gaussian blur code contributed by
1183
994
  * <A HREF="http://incubator.quasimondo.com">Mario Klingemann</A>
1184
995
  *
@@ -1193,14 +1004,20 @@ public class PImage implements PConstants, Cloneable {
1193
1004
 
1194
1005
  switch (kind) {
1195
1006
  case BLUR:
1196
- if (format == ALPHA)
1007
+ switch (format) {
1008
+ case ALPHA:
1197
1009
  blurAlpha(param);
1198
- else if (format == ARGB)
1010
+ break;
1011
+ case ARGB:
1199
1012
  blurARGB(param);
1200
- else
1013
+ break;
1014
+ default:
1201
1015
  blurRGB(param);
1016
+ break;
1017
+ }
1202
1018
  break;
1203
1019
 
1020
+
1204
1021
  case GRAY:
1205
1022
  throw new RuntimeException("Use filter(GRAY) instead of " +
1206
1023
  "filter(GRAY, param)");
@@ -1302,7 +1119,7 @@ public class PImage implements PConstants, Cloneable {
1302
1119
  protected void blurAlpha(float r) {
1303
1120
  int sum, cb;
1304
1121
  int read, ri, ym, ymi, bk0;
1305
- int b2[] = new int[pixels.length];
1122
+ int[] b2 = new int[pixels.length];
1306
1123
  int yi = 0;
1307
1124
 
1308
1125
  buildBlurKernel(r);
@@ -1373,9 +1190,9 @@ public class PImage implements PConstants, Cloneable {
1373
1190
  protected void blurRGB(float r) {
1374
1191
  int sum, cr, cg, cb; //, k;
1375
1192
  int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0;
1376
- int r2[] = new int[pixels.length];
1377
- int g2[] = new int[pixels.length];
1378
- int b2[] = new int[pixels.length];
1193
+ int[] r2 = new int[pixels.length];
1194
+ int[] g2 = new int[pixels.length];
1195
+ int[] b2 = new int[pixels.length];
1379
1196
  int yi = 0;
1380
1197
 
1381
1198
  buildBlurKernel(r);
@@ -1456,10 +1273,10 @@ public class PImage implements PConstants, Cloneable {
1456
1273
  int sum, cr, cg, cb, ca;
1457
1274
  int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0;
1458
1275
  int wh = pixels.length;
1459
- int r2[] = new int[wh];
1460
- int g2[] = new int[wh];
1461
- int b2[] = new int[wh];
1462
- int a2[] = new int[wh];
1276
+ int[] r2 = new int[wh];
1277
+ int[] g2 = new int[wh];
1278
+ int[] b2 = new int[wh];
1279
+ int[] a2 = new int[wh];
1463
1280
  int yi = 0;
1464
1281
 
1465
1282
  buildBlurKernel(r);
@@ -1695,7 +1512,7 @@ public class PImage implements PConstants, Cloneable {
1695
1512
  * source pixels to fit the specified target region. No alpha information
1696
1513
  * is used in the process, however if the source image has an alpha channel
1697
1514
  * set, it will be copied as well.
1698
- * <br /><br />
1515
+ *
1699
1516
  * As of release 0149, this function ignores <b>imageMode()</b>.
1700
1517
  *
1701
1518
  * ( end auto-generated )
@@ -1799,7 +1616,7 @@ public class PImage implements PConstants, Cloneable {
1799
1616
  * necessarily "correct" code. No biggie, most software does. A nitpicker
1800
1617
  * can find numerous "off by 1 division" problems in the blend code where
1801
1618
  * <TT>&gt;&gt;8</TT> or <TT>&gt;&gt;7</TT> is used when strictly speaking
1802
- * <TT>/255.0</T> or <TT>/127.0</TT> should have been used.</P>
1619
+ * <TT>/255.0</TT> or <TT>/127.0</TT> should have been used.</P>
1803
1620
  * <P>For instance, exclusion (not intended for real-time use) reads
1804
1621
  * <TT>r1 + r2 - ((2 * r1 * r2) / 255)</TT> because <TT>255 == 1.0</TT>
1805
1622
  * not <TT>256 == 1.0</TT>. In other words, <TT>(255*255)>>8</TT> is not
@@ -1855,47 +1672,47 @@ public class PImage implements PConstants, Cloneable {
1855
1672
  * Blends a region of pixels into the image specified by the <b>img</b>
1856
1673
  * parameter. These copies utilize full alpha channel support and a choice
1857
1674
  * of the following modes to blend the colors of source pixels (A) with the
1858
- * ones of pixels in the destination image (B):<br />
1859
- * <br />
1860
- * BLEND - linear interpolation of colours: C = A*factor + B<br />
1861
- * <br />
1862
- * ADD - additive blending with white clip: C = min(A*factor + B, 255)<br />
1863
- * <br />
1675
+ * ones of pixels in the destination image (B):
1676
+ *
1677
+ * BLEND - linear interpolation of colours: C = A*factor + B
1678
+ *
1679
+ * ADD - additive blending with white clip: C = min(A*factor + B, 255)
1680
+ *
1864
1681
  * SUBTRACT - subtractive blending with black clip: C = max(B - A*factor,
1865
- * 0)<br />
1866
- * <br />
1867
- * DARKEST - only the darkest colour succeeds: C = min(A*factor, B)<br />
1868
- * <br />
1869
- * LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)<br />
1870
- * <br />
1871
- * DIFFERENCE - subtract colors from underlying image.<br />
1872
- * <br />
1873
- * EXCLUSION - similar to DIFFERENCE, but less extreme.<br />
1874
- * <br />
1875
- * MULTIPLY - Multiply the colors, result will always be darker.<br />
1876
- * <br />
1877
- * SCREEN - Opposite multiply, uses inverse values of the colors.<br />
1878
- * <br />
1682
+ * 0)
1683
+ *
1684
+ * DARKEST - only the darkest colour succeeds: C = min(A*factor, B)
1685
+ *
1686
+ * LIGHTEST - only the lightest colour succeeds: C = max(A*factor, B)
1687
+ *
1688
+ * DIFFERENCE - subtract colors from underlying image.
1689
+ *
1690
+ * EXCLUSION - similar to DIFFERENCE, but less extreme.
1691
+ *
1692
+ * MULTIPLY - Multiply the colors, result will always be darker.
1693
+ *
1694
+ * SCREEN - Opposite multiply, uses inverse values of the colors.
1695
+ *
1879
1696
  * OVERLAY - A mix of MULTIPLY and SCREEN. Multiplies dark values,
1880
- * and screens light values.<br />
1881
- * <br />
1882
- * HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.<br />
1883
- * <br />
1697
+ * and screens light values.
1698
+ *
1699
+ * HARD_LIGHT - SCREEN when greater than 50% gray, MULTIPLY when lower.
1700
+ *
1884
1701
  * SOFT_LIGHT - Mix of DARKEST and LIGHTEST.
1885
- * Works like OVERLAY, but not as harsh.<br />
1886
- * <br />
1702
+ * Works like OVERLAY, but not as harsh.
1703
+ *
1887
1704
  * DODGE - Lightens light tones and increases contrast, ignores darks.
1888
- * Called "Color Dodge" in Illustrator and Photoshop.<br />
1889
- * <br />
1705
+ * Called "Color Dodge" in Illustrator and Photoshop.
1706
+ *
1890
1707
  * BURN - Darker areas are applied, increasing contrast, ignores lights.
1891
- * Called "Color Burn" in Illustrator and Photoshop.<br />
1892
- * <br />
1708
+ * Called "Color Burn" in Illustrator and Photoshop.
1709
+ *
1893
1710
  * All modes use the alpha information (highest byte) of source image
1894
1711
  * pixels as the blending factor. If the source and destination regions are
1895
1712
  * different sizes, the image will be automatically resized to match the
1896
1713
  * destination size. If the <b>srcImg</b> parameter is not used, the
1897
- * display window is used as the source image.<br />
1898
- * <br />
1714
+ * display window is used as the source image.
1715
+ *
1899
1716
  * As of release 0149, this function ignores <b>imageMode()</b>.
1900
1717
  *
1901
1718
  * ( end auto-generated )
@@ -3010,18 +2827,465 @@ int testFunction(int dst, int src) {
3010
2827
 
3011
2828
  // FILE I/O
3012
2829
 
3013
- protected String[] saveImageFormats;
2830
+
2831
+ protected boolean saveImpl(String filename) {
2832
+ return false;
2833
+ }
2834
+
2835
+
2836
+ static public PImage loadTIFF(InputStream input) { // ignore
2837
+ byte tiff[] = PApplet.loadBytes(input);
2838
+
2839
+ if ((tiff[42] != tiff[102]) || // width/height in both places
2840
+ (tiff[43] != tiff[103])) {
2841
+ System.err.println(TIFF_ERROR);
2842
+ return null;
2843
+ }
2844
+
2845
+ int width =
2846
+ ((tiff[30] & 0xff) << 8) | (tiff[31] & 0xff);
2847
+ int height =
2848
+ ((tiff[42] & 0xff) << 8) | (tiff[43] & 0xff);
2849
+
2850
+ int count =
2851
+ ((tiff[114] & 0xff) << 24) |
2852
+ ((tiff[115] & 0xff) << 16) |
2853
+ ((tiff[116] & 0xff) << 8) |
2854
+ (tiff[117] & 0xff);
2855
+ if (count != width * height * 3) {
2856
+ System.err.println(TIFF_ERROR + " (" + width + ", " + height +")");
2857
+ return null;
2858
+ }
2859
+
2860
+ // check the rest of the header
2861
+ for (int i = 0; i < TIFF_HEADER.length; i++) {
2862
+ if ((i == 30) || (i == 31) || (i == 42) || (i == 43) ||
2863
+ (i == 102) || (i == 103) ||
2864
+ (i == 114) || (i == 115) || (i == 116) || (i == 117)) continue;
2865
+
2866
+ if (tiff[i] != TIFF_HEADER[i]) {
2867
+ System.err.println(TIFF_ERROR + " (" + i + ")");
2868
+ return null;
2869
+ }
2870
+ }
2871
+
2872
+ PImage outgoing = new PImage(width, height, RGB);
2873
+ int index = 768;
2874
+ count /= 3;
2875
+ for (int i = 0; i < count; i++) {
2876
+ outgoing.pixels[i] =
2877
+ 0xFF000000 |
2878
+ (tiff[index++] & 0xff) << 16 |
2879
+ (tiff[index++] & 0xff) << 8 |
2880
+ (tiff[index++] & 0xff);
2881
+ }
2882
+ return outgoing;
2883
+ }
2884
+
2885
+ protected boolean saveTIFF(OutputStream output) {
2886
+ // shutting off the warning, people can figure this out themselves
2887
+ /*
2888
+ if (format != RGB) {
2889
+ System.err.println("Warning: only RGB information is saved with " +
2890
+ ".tif files. Use .tga or .png for ARGB images and others.");
2891
+ }
2892
+ */
2893
+ try {
2894
+ byte[] tiff = new byte[768];
2895
+ System.arraycopy(TIFF_HEADER, 0, tiff, 0, TIFF_HEADER.length);
2896
+
2897
+ tiff[30] = (byte) ((pixelWidth >> 8) & 0xff);
2898
+ tiff[31] = (byte) ((pixelWidth) & 0xff);
2899
+ tiff[42] = tiff[102] = (byte) ((pixelHeight >> 8) & 0xff);
2900
+ tiff[43] = tiff[103] = (byte) ((pixelHeight) & 0xff);
2901
+
2902
+ int count = pixelWidth*pixelHeight*3;
2903
+ tiff[114] = (byte) ((count >> 24) & 0xff);
2904
+ tiff[115] = (byte) ((count >> 16) & 0xff);
2905
+ tiff[116] = (byte) ((count >> 8) & 0xff);
2906
+ tiff[117] = (byte) ((count) & 0xff);
2907
+
2908
+ // spew the header to the disk
2909
+ output.write(tiff);
2910
+
2911
+ for (int i = 0; i < pixels.length; i++) {
2912
+ output.write((pixels[i] >> 16) & 0xff);
2913
+ output.write((pixels[i] >> 8) & 0xff);
2914
+ output.write(pixels[i] & 0xff);
2915
+ }
2916
+ output.flush();
2917
+ return true;
2918
+
2919
+ } catch (IOException e) {
2920
+ }
2921
+ return false;
2922
+ }
2923
+
2924
+
2925
+ /**
2926
+ * Targa image loader for RLE-compressed TGA files.
2927
+ * <p>
2928
+ * Rewritten for 0115 to read/write RLE-encoded targa images.
2929
+ * For 0125, non-RLE encoded images are now supported, along with
2930
+ * images whose y-order is reversed (which is standard for TGA files).
2931
+ * <p>
2932
+ * A version of this function is in MovieMaker.java. Any fixes here
2933
+ * should be applied over in MovieMaker as well.
2934
+ * <p>
2935
+ * Known issue with RLE encoding and odd behavior in some apps:
2936
+ * https://github.com/processing/processing/issues/2096
2937
+ * Please help!
2938
+ */
2939
+ static public PImage loadTGA(InputStream input) throws IOException { // ignore
2940
+ byte[] header = new byte[18];
2941
+ int offset = 0;
2942
+ do {
2943
+ int count = input.read(header, offset, header.length - offset);
2944
+ if (count == -1) return null;
2945
+ offset += count;
2946
+ } while (offset < 18);
2947
+
2948
+ /*
2949
+ header[2] image type code
2950
+ 2 (0x02) - Uncompressed, RGB images.
2951
+ 3 (0x03) - Uncompressed, black and white images.
2952
+ 10 (0x0A) - Run-length encoded RGB images.
2953
+ 11 (0x0B) - Compressed, black and white images. (grayscale?)
2954
+
2955
+ header[16] is the bit depth (8, 24, 32)
2956
+
2957
+ header[17] image descriptor (packed bits)
2958
+ 0x20 is 32 = origin upper-left
2959
+ 0x28 is 32 + 8 = origin upper-left + 32 bits
2960
+
2961
+ 7 6 5 4 3 2 1 0
2962
+ 128 64 32 16 8 4 2 1
2963
+ */
2964
+
2965
+ int format = 0;
2966
+
2967
+ if (((header[2] == 3) || (header[2] == 11)) && // B&W, plus RLE or not
2968
+ (header[16] == 8) && // 8 bits
2969
+ ((header[17] == 0x8) || (header[17] == 0x28))) { // origin, 32 bit
2970
+ format = ALPHA;
2971
+
2972
+ } else if (((header[2] == 2) || (header[2] == 10)) && // RGB, RLE or not
2973
+ (header[16] == 24) && // 24 bits
2974
+ ((header[17] == 0x20) || (header[17] == 0))) { // origin
2975
+ format = RGB;
2976
+
2977
+ } else if (((header[2] == 2) || (header[2] == 10)) &&
2978
+ (header[16] == 32) &&
2979
+ ((header[17] == 0x8) || (header[17] == 0x28))) { // origin, 32
2980
+ format = ARGB;
2981
+ }
2982
+
2983
+ if (format == 0) {
2984
+ System.err.println("Unknown .tga file format");
2985
+ return null;
2986
+ }
2987
+
2988
+ int w = ((header[13] & 0xff) << 8) + (header[12] & 0xff);
2989
+ int h = ((header[15] & 0xff) << 8) + (header[14] & 0xff);
2990
+ PImage outgoing = new PImage(w, h, format);
2991
+
2992
+ // where "reversed" means upper-left corner (normal for most of
2993
+ // the modernized world, but "reversed" for the tga spec)
2994
+ //boolean reversed = (header[17] & 0x20) != 0;
2995
+ // https://github.com/processing/processing/issues/1682
2996
+ boolean reversed = (header[17] & 0x20) == 0;
2997
+
2998
+ if ((header[2] == 2) || (header[2] == 3)) { // not RLE encoded
2999
+ if (reversed) {
3000
+ int index = (h-1) * w;
3001
+ switch (format) {
3002
+ case ALPHA:
3003
+ for (int y = h-1; y >= 0; y--) {
3004
+ for (int x = 0; x < w; x++) {
3005
+ outgoing.pixels[index + x] = input.read();
3006
+ }
3007
+ index -= w;
3008
+ }
3009
+ break;
3010
+ case RGB:
3011
+ for (int y = h-1; y >= 0; y--) {
3012
+ for (int x = 0; x < w; x++) {
3013
+ outgoing.pixels[index + x] =
3014
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3015
+ 0xff000000;
3016
+ }
3017
+ index -= w;
3018
+ }
3019
+ break;
3020
+ case ARGB:
3021
+ for (int y = h-1; y >= 0; y--) {
3022
+ for (int x = 0; x < w; x++) {
3023
+ outgoing.pixels[index + x] =
3024
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3025
+ (input.read() << 24);
3026
+ }
3027
+ index -= w;
3028
+ }
3029
+ }
3030
+ } else { // not reversed
3031
+ int count = w * h;
3032
+ switch (format) {
3033
+ case ALPHA:
3034
+ for (int i = 0; i < count; i++) {
3035
+ outgoing.pixels[i] = input.read();
3036
+ }
3037
+ break;
3038
+ case RGB:
3039
+ for (int i = 0; i < count; i++) {
3040
+ outgoing.pixels[i] =
3041
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3042
+ 0xff000000;
3043
+ }
3044
+ break;
3045
+ case ARGB:
3046
+ for (int i = 0; i < count; i++) {
3047
+ outgoing.pixels[i] =
3048
+ input.read() | (input.read() << 8) | (input.read() << 16) |
3049
+ (input.read() << 24);
3050
+ }
3051
+ break;
3052
+ }
3053
+ }
3054
+
3055
+ } else { // header[2] is 10 or 11
3056
+ int index = 0;
3057
+ int[] px = outgoing.pixels;
3058
+
3059
+ while (index < px.length) {
3060
+ int num = input.read();
3061
+ boolean isRLE = (num & 0x80) != 0;
3062
+ if (isRLE) {
3063
+ num -= 127; // (num & 0x7F) + 1
3064
+ int pixel = 0;
3065
+ switch (format) {
3066
+ case ALPHA:
3067
+ pixel = input.read();
3068
+ break;
3069
+ case RGB:
3070
+ pixel = 0xFF000000 |
3071
+ input.read() | (input.read() << 8) | (input.read() << 16);
3072
+ //(is.read() << 16) | (is.read() << 8) | is.read();
3073
+ break;
3074
+ case ARGB:
3075
+ pixel = input.read() |
3076
+ (input.read() << 8) | (input.read() << 16) | (input.read() << 24);
3077
+ break;
3078
+ }
3079
+ for (int i = 0; i < num; i++) {
3080
+ px[index++] = pixel;
3081
+ if (index == px.length) break;
3082
+ }
3083
+ } else { // write up to 127 bytes as uncompressed
3084
+ num += 1;
3085
+ switch (format) {
3086
+ case ALPHA:
3087
+ for (int i = 0; i < num; i++) {
3088
+ px[index++] = input.read();
3089
+ }
3090
+ break;
3091
+ case RGB:
3092
+ for (int i = 0; i < num; i++) {
3093
+ px[index++] = 0xFF000000 |
3094
+ input.read() | (input.read() << 8) | (input.read() << 16);
3095
+ //(is.read() << 16) | (is.read() << 8) | is.read();
3096
+ }
3097
+ break;
3098
+ case ARGB:
3099
+ for (int i = 0; i < num; i++) {
3100
+ px[index++] = input.read() | //(is.read() << 24) |
3101
+ (input.read() << 8) | (input.read() << 16) | (input.read() << 24);
3102
+ //(is.read() << 16) | (is.read() << 8) | is.read();
3103
+ }
3104
+ break;
3105
+ }
3106
+ }
3107
+ }
3108
+
3109
+ if (!reversed) {
3110
+ int[] temp = new int[w];
3111
+ for (int y = 0; y < h/2; y++) {
3112
+ int z = (h-1) - y;
3113
+ System.arraycopy(px, y*w, temp, 0, w);
3114
+ System.arraycopy(px, z*w, px, y*w, w);
3115
+ System.arraycopy(temp, 0, px, z*w, w);
3116
+ }
3117
+ }
3118
+ }
3119
+ input.close();
3120
+ return outgoing;
3121
+ }
3122
+
3123
+
3124
+ /**
3125
+ * Creates a Targa32 formatted byte sequence of specified
3126
+ * pixel buffer using RLE compression.
3127
+ * <p>
3128
+ * Also figured out how to avoid parsing the image upside-down
3129
+ * (there's a header flag to set the image origin to top-left)
3130
+ * </p>
3131
+ * Starting with revision 0092, the format setting is taken into account:
3132
+ * <UL>
3133
+ * <LI><TT>ALPHA</TT> images written as 8bit grayscale (uses lowest byte)
3134
+ * <LI><TT>RGB</TT> &rarr; 24 bits
3135
+ * <LI><TT>ARGB</TT> &rarr; 32 bits
3136
+ * </UL>
3137
+ * All versions are RLE compressed.
3138
+ *
3139
+ * Contributed by toxi 8-10 May 2005, based on this RLE
3140
+ * <A HREF="http://www.wotsit.org/download.asp?f=tga">specification</A>
3141
+ */
3142
+ protected boolean saveTGA(OutputStream output) {
3143
+ byte[] header = new byte[18];
3144
+
3145
+ switch (format) {
3146
+ case ALPHA:
3147
+ // save ALPHA images as 8bit grayscale
3148
+ header[2] = 0x0B;
3149
+ header[16] = 0x08;
3150
+ header[17] = 0x28;
3151
+ break;
3152
+ case RGB:
3153
+ header[2] = 0x0A;
3154
+ header[16] = 24;
3155
+ header[17] = 0x20;
3156
+ break;
3157
+ case ARGB:
3158
+ header[2] = 0x0A;
3159
+ header[16] = 32;
3160
+ header[17] = 0x28;
3161
+ break;
3162
+ default:
3163
+ throw new RuntimeException("Image format not recognized inside save()");
3164
+ }
3165
+ // set image dimensions lo-hi byte order
3166
+ header[12] = (byte) (pixelWidth & 0xff);
3167
+ header[13] = (byte) (pixelWidth >> 8);
3168
+ header[14] = (byte) (pixelHeight & 0xff);
3169
+ header[15] = (byte) (pixelHeight >> 8);
3170
+
3171
+ try {
3172
+ output.write(header);
3173
+
3174
+ int maxLen = pixelHeight * pixelWidth;
3175
+ int index = 0;
3176
+ int col; //, prevCol;
3177
+ int[] currChunk = new int[128];
3178
+
3179
+ // 8bit image exporter is in separate loop
3180
+ // to avoid excessive conditionals...
3181
+ if (format == ALPHA) {
3182
+ while (index < maxLen) {
3183
+ boolean isRLE = false;
3184
+ int rle = 1;
3185
+ currChunk[0] = col = pixels[index] & 0xff;
3186
+ while (index + rle < maxLen) {
3187
+ if (col != (pixels[index + rle]&0xff) || rle == 128) {
3188
+ isRLE = (rle > 1);
3189
+ break;
3190
+ }
3191
+ rle++;
3192
+ }
3193
+ if (isRLE) {
3194
+ output.write(0x80 | (rle - 1));
3195
+ output.write(col);
3196
+
3197
+ } else {
3198
+ rle = 1;
3199
+ while (index + rle < maxLen) {
3200
+ int cscan = pixels[index + rle] & 0xff;
3201
+ if ((col != cscan && rle < 128) || rle < 3) {
3202
+ currChunk[rle] = col = cscan;
3203
+ } else {
3204
+ if (col == cscan) rle -= 2;
3205
+ break;
3206
+ }
3207
+ rle++;
3208
+ }
3209
+ output.write(rle - 1);
3210
+ for (int i = 0; i < rle; i++) output.write(currChunk[i]);
3211
+ }
3212
+ index += rle;
3213
+ }
3214
+ } else { // export 24/32 bit TARGA
3215
+ while (index < maxLen) {
3216
+ boolean isRLE = false;
3217
+ currChunk[0] = col = pixels[index];
3218
+ int rle = 1;
3219
+ // try to find repeating bytes (min. len = 2 pixels)
3220
+ // maximum chunk size is 128 pixels
3221
+ while (index + rle < maxLen) {
3222
+ if (col != pixels[index + rle] || rle == 128) {
3223
+ isRLE = (rle > 1); // set flag for RLE chunk
3224
+ break;
3225
+ }
3226
+ rle++;
3227
+ }
3228
+ if (isRLE) {
3229
+ output.write(128 | (rle - 1));
3230
+ output.write(col & 0xff);
3231
+ output.write(col >> 8 & 0xff);
3232
+ output.write(col >> 16 & 0xff);
3233
+ if (format == ARGB) output.write(col >>> 24 & 0xff);
3234
+
3235
+ } else { // not RLE
3236
+ rle = 1;
3237
+ while (index + rle < maxLen) {
3238
+ if ((col != pixels[index + rle] && rle < 128) || rle < 3) {
3239
+ currChunk[rle] = col = pixels[index + rle];
3240
+ } else {
3241
+ // check if the exit condition was the start of
3242
+ // a repeating colour
3243
+ if (col == pixels[index + rle]) rle -= 2;
3244
+ break;
3245
+ }
3246
+ rle++;
3247
+ }
3248
+ // write uncompressed chunk
3249
+ output.write(rle - 1);
3250
+ if (format == ARGB) {
3251
+ for (int i = 0; i < rle; i++) {
3252
+ col = currChunk[i];
3253
+ output.write(col & 0xff);
3254
+ output.write(col >> 8 & 0xff);
3255
+ output.write(col >> 16 & 0xff);
3256
+ output.write(col >>> 24 & 0xff);
3257
+ }
3258
+ } else {
3259
+ for (int i = 0; i < rle; i++) {
3260
+ col = currChunk[i];
3261
+ output.write(col & 0xff);
3262
+ output.write(col >> 8 & 0xff);
3263
+ output.write(col >> 16 & 0xff);
3264
+ }
3265
+ }
3266
+ }
3267
+ index += rle;
3268
+ }
3269
+ }
3270
+ output.flush();
3271
+ return true;
3272
+
3273
+ } catch (IOException e) {
3274
+ return false;
3275
+ }
3276
+ }
3277
+
3014
3278
 
3015
3279
  /**
3016
3280
  * ( begin auto-generated from PImage_save.xml )
3017
3281
  *
3018
- * Saves the image into a file.Append a file extension to the name of
3019
- the file, to indicate the file format to be used: either TIFF (.tif),
3020
- TARGA (.tga), JPEG (.jpg), or PNG (.png). If no extension is included
3021
- in the filename, the image will save in TIFF format and .tif will be
3022
- added to the name. These files are saved to the sketch's folder, which
3023
- may be opened by selecting "Show sketch folder" from the "Sketch" menu.
3024
- <br /><br />To save an image created within the code, rather
3282
+ * Saves the image into a file. Append a file extension to the name of
3283
+ * the file, to indicate the file format to be used: either TIFF (.tif),
3284
+ * TARGA (.tga), JPEG (.jpg), or PNG (.png). If no extension is included
3285
+ * in the filename, the image will save in TIFF format and .tif will be
3286
+ * added to the name. These files are saved to the sketch's folder, which
3287
+ * may be opened by selecting "Show sketch folder" from the "Sketch" menu.
3288
+ * To save an image created within the code, rather
3025
3289
  * than through loading, it's necessary to make the image with the
3026
3290
  * <b>createImage()</b> function so it is aware of the location of the
3027
3291
  * program and can therefore save the file to the right place. See the
@@ -3053,23 +3317,61 @@ int testFunction(int dst, int src) {
3053
3317
  * require a black and white image. Basic testing produced a zero-length
3054
3318
  * file with no error.
3055
3319
  *
3056
- * @return
3057
3320
  * @webref pimage:method
3058
3321
  * @brief Saves the image to a TIFF, TARGA, PNG, or JPEG file
3059
3322
  * @usage application
3060
3323
  * @param filename a sequence of letters and numbers
3061
3324
  */
3062
- public boolean save(String filename) { // ignore
3063
- // Make sure the pixel data is ready to go
3064
- loadPixels();
3065
-
3066
- return ImageSaveFacade.get().save(
3067
- pixels,
3068
- pixelWidth,
3069
- pixelHeight,
3070
- format,
3071
- filename,
3072
- parent
3073
- );
3074
- }
3325
+ public boolean save(String filename) { // ignore
3326
+ boolean success = false;
3327
+
3328
+ if (parent != null) {
3329
+ // use savePath(), so that the intermediate directories are created
3330
+ filename = parent.savePath(filename);
3331
+
3332
+ } else {
3333
+ File file = new File(filename);
3334
+ if (file.isAbsolute()) {
3335
+ // make sure that the intermediate folders have been created
3336
+ PApplet.createPath(file);
3337
+ } else {
3338
+ String msg =
3339
+ "PImage.save() requires an absolute path. " +
3340
+ "Use createImage(), or pass savePath() to save().";
3341
+ PGraphics.showException(msg);
3342
+ }
3343
+ }
3344
+
3345
+ // Make sure the pixel data is ready to go
3346
+ loadPixels();
3347
+
3348
+ try {
3349
+ OutputStream os = null;
3350
+
3351
+ if (saveImpl(filename)) {
3352
+ return true;
3353
+ }
3354
+
3355
+ if (filename.toLowerCase().endsWith(".tga")) {
3356
+ os = new BufferedOutputStream(new FileOutputStream(filename), 32768);
3357
+ success = saveTGA(os); //, pixels, width, height, format);
3358
+
3359
+ } else {
3360
+ if (!filename.toLowerCase().endsWith(".tif") &&
3361
+ !filename.toLowerCase().endsWith(".tiff")) {
3362
+ // if no .tif extension, add it..
3363
+ filename += ".tif";
3364
+ }
3365
+ os = new BufferedOutputStream(new FileOutputStream(filename), 32768);
3366
+ success = saveTIFF(os); //, pixels, width, height);
3367
+ }
3368
+ os.flush();
3369
+ os.close();
3370
+
3371
+ } catch (IOException e) {
3372
+ System.err.println("Error while saving image.");
3373
+ success = false;
3374
+ }
3375
+ return success;
3376
+ }
3075
3377
  }