propane 3.4.0-java → 3.7.0.pre-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -2
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +2 -2
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/.travis.yml +2 -2
  6. data/CHANGELOG.md +12 -0
  7. data/Gemfile +2 -0
  8. data/README.md +17 -8
  9. data/Rakefile +10 -11
  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 +10 -9
  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/pom.rb +37 -36
  38. data/pom.xml +7 -7
  39. data/propane.gemspec +16 -12
  40. data/src/main/java/monkstone/ColorUtil.java +13 -1
  41. data/src/main/java/monkstone/MathToolModule.java +253 -203
  42. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  43. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  44. data/src/main/java/monkstone/filechooser/Chooser.java +2 -1
  45. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  46. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  47. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  48. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  49. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  50. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  51. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  52. data/src/main/java/monkstone/slider/WheelHandler.java +7 -6
  53. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  54. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  55. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +3 -3
  56. data/src/main/java/monkstone/videoevent/CaptureEvent.java +27 -0
  57. data/src/main/java/monkstone/videoevent/{VideoInterface.java → MovieEvent.java} +11 -27
  58. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  59. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  60. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  61. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  62. data/src/main/java/processing/awt/PSurfaceAWT.java +309 -209
  63. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  64. data/src/main/java/processing/core/PApplet.java +4510 -4503
  65. data/src/main/java/processing/core/PConstants.java +477 -447
  66. data/src/main/java/processing/core/PFont.java +914 -880
  67. data/src/main/java/processing/core/PGraphics.java +193 -177
  68. data/src/main/java/processing/core/PImage.java +611 -309
  69. data/src/main/java/processing/core/PMatrix.java +172 -159
  70. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  71. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  72. data/src/main/java/processing/core/PShape.java +2888 -2652
  73. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  74. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  75. data/src/main/java/processing/core/PStyle.java +40 -37
  76. data/src/main/java/processing/core/PSurface.java +139 -97
  77. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  78. data/src/main/java/processing/core/PVector.java +997 -965
  79. data/src/main/java/processing/core/ThinkDifferent.java +15 -13
  80. data/src/main/java/processing/data/DoubleDict.java +756 -710
  81. data/src/main/java/processing/data/DoubleList.java +749 -696
  82. data/src/main/java/processing/data/FloatDict.java +748 -702
  83. data/src/main/java/processing/data/FloatList.java +751 -697
  84. data/src/main/java/processing/data/IntDict.java +720 -673
  85. data/src/main/java/processing/data/IntList.java +699 -633
  86. data/src/main/java/processing/data/JSONArray.java +931 -873
  87. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  88. data/src/main/java/processing/data/JSONTokener.java +351 -341
  89. data/src/main/java/processing/data/LongDict.java +710 -663
  90. data/src/main/java/processing/data/LongList.java +701 -635
  91. data/src/main/java/processing/data/Sort.java +37 -41
  92. data/src/main/java/processing/data/StringDict.java +525 -486
  93. data/src/main/java/processing/data/StringList.java +626 -580
  94. data/src/main/java/processing/data/Table.java +3690 -3510
  95. data/src/main/java/processing/data/TableRow.java +182 -183
  96. data/src/main/java/processing/data/XML.java +957 -883
  97. data/src/main/java/processing/dxf/RawDXF.java +404 -0
  98. data/src/main/java/processing/event/Event.java +87 -67
  99. data/src/main/java/processing/event/KeyEvent.java +48 -41
  100. data/src/main/java/processing/event/MouseEvent.java +88 -113
  101. data/src/main/java/processing/event/TouchEvent.java +10 -6
  102. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  103. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  104. data/src/main/java/processing/net/Client.java +744 -0
  105. data/src/main/java/processing/net/Server.java +388 -0
  106. data/src/main/java/processing/opengl/FontTexture.java +289 -270
  107. data/src/main/java/processing/opengl/FrameBuffer.java +386 -364
  108. data/src/main/java/processing/opengl/LinePath.java +547 -500
  109. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  110. data/src/main/java/processing/opengl/PGL.java +3047 -2914
  111. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  112. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  113. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  114. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  115. data/src/main/java/processing/opengl/PShader.java +1266 -1257
  116. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  117. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  118. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  119. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  120. data/test/create_test.rb +21 -20
  121. data/test/deglut_spec_test.rb +4 -2
  122. data/test/helper_methods_test.rb +49 -20
  123. data/test/math_tool_test.rb +39 -32
  124. data/test/native_folder.rb +47 -0
  125. data/test/respond_to_test.rb +3 -2
  126. data/test/sketches/key_event.rb +2 -2
  127. data/test/sketches/library/my_library/my_library.rb +3 -0
  128. data/test/test_helper.rb +2 -0
  129. data/test/vecmath_spec_test.rb +35 -22
  130. data/vendors/Rakefile +33 -62
  131. metadata +56 -48
  132. data/src/main/java/processing/core/util/image/ImageLoadFacade.java +0 -161
  133. data/src/main/java/processing/core/util/image/ImageSaveFacade.java +0 -169
  134. data/src/main/java/processing/core/util/image/constants/TifConstants.java +0 -45
  135. data/src/main/java/processing/core/util/image/load/AwtImageLoadStrategy.java +0 -80
  136. data/src/main/java/processing/core/util/image/load/Base64StringImageLoadStrategy.java +0 -73
  137. data/src/main/java/processing/core/util/image/load/FallbackImageLoadStrategy.java +0 -70
  138. data/src/main/java/processing/core/util/image/load/ImageIoImageLoadStrategy.java +0 -132
  139. data/src/main/java/processing/core/util/image/load/ImageLoadStrategy.java +0 -48
  140. data/src/main/java/processing/core/util/image/load/ImageLoadUtil.java +0 -45
  141. data/src/main/java/processing/core/util/image/load/TgaImageLoadStrategy.java +0 -255
  142. data/src/main/java/processing/core/util/image/load/TiffImageLoadStrategy.java +0 -98
  143. data/src/main/java/processing/core/util/image/save/ImageSaveStrategy.java +0 -49
  144. data/src/main/java/processing/core/util/image/save/ImageSaveUtil.java +0 -48
  145. data/src/main/java/processing/core/util/image/save/ImageWriterImageSaveStrategy.java +0 -179
  146. data/src/main/java/processing/core/util/image/save/SaveImageException.java +0 -41
  147. data/src/main/java/processing/core/util/image/save/TgaImageSaveStrategy.java +0 -198
  148. data/src/main/java/processing/core/util/image/save/TiffImageSaveStrategy.java +0 -91
  149. data/src/main/java/processing/core/util/image/save/TiffNakedFilenameImageSaveStrategy.java +0 -57
  150. data/src/main/java/processing/core/util/io/InputFactory.java +0 -285
  151. data/src/main/java/processing/core/util/io/PathUtil.java +0 -109
  152. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  153. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  154. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  155. 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
  /**
@@ -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.
@@ -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
 
@@ -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
  *
@@ -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
  }