propane 3.4.2-java → 3.8.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -1
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +2 -2
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG.md +9 -1
  7. data/Gemfile +2 -0
  8. data/README.md +7 -10
  9. data/Rakefile +10 -11
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +4 -2
  12. data/lib/propane/app.rb +5 -1
  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 +22 -23
  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 +20 -14
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +2 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +2 -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 +2 -0
  33. data/library/slider/slider.rb +23 -22
  34. data/library/vector_utils/vector_utils.rb +4 -0
  35. data/library/video_event/video_event.rb +2 -0
  36. data/pom.rb +37 -36
  37. data/pom.xml +7 -7
  38. data/propane.gemspec +13 -9
  39. data/src/main/java/japplemenubar/JAppleMenuBar.java +3 -3
  40. data/src/main/java/monkstone/ColorUtil.java +1 -3
  41. data/src/main/java/monkstone/MathToolModule.java +1 -1
  42. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  43. data/src/main/java/monkstone/fastmath/DegLutTables.java +111 -0
  44. data/src/main/java/monkstone/fastmath/Deglut.java +6 -56
  45. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  46. data/src/main/java/monkstone/noise/Noise.java +116 -0
  47. data/src/main/java/monkstone/noise/NoiseGenerator.java +63 -0
  48. data/src/main/java/monkstone/noise/NoiseMode.java +15 -0
  49. data/src/main/java/monkstone/noise/SimplexNoise.java +137 -103
  50. data/src/main/java/monkstone/noise/ValueNoise.java +170 -0
  51. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  52. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  53. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  54. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  55. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  56. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  57. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  58. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  59. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  60. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  61. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  62. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  63. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  64. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  65. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  66. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  67. data/src/main/java/processing/awt/PSurfaceAWT.java +308 -208
  68. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  69. data/src/main/java/processing/core/PApplet.java +13142 -13883
  70. data/src/main/java/processing/core/PConstants.java +477 -447
  71. data/src/main/java/processing/core/PFont.java +914 -880
  72. data/src/main/java/processing/core/PGraphics.java +152 -136
  73. data/src/main/java/processing/core/PImage.java +275 -372
  74. data/src/main/java/processing/core/PMatrix.java +172 -159
  75. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  76. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  77. data/src/main/java/processing/core/PShape.java +2887 -2651
  78. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  79. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  80. data/src/main/java/processing/core/PStyle.java +40 -37
  81. data/src/main/java/processing/core/PSurface.java +139 -97
  82. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  83. data/src/main/java/processing/core/PVector.java +995 -963
  84. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  85. data/src/main/java/processing/data/DoubleDict.java +756 -710
  86. data/src/main/java/processing/data/DoubleList.java +749 -696
  87. data/src/main/java/processing/data/FloatDict.java +748 -702
  88. data/src/main/java/processing/data/FloatList.java +751 -697
  89. data/src/main/java/processing/data/IntDict.java +720 -673
  90. data/src/main/java/processing/data/IntList.java +699 -633
  91. data/src/main/java/processing/data/JSONArray.java +931 -873
  92. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  93. data/src/main/java/processing/data/JSONTokener.java +351 -341
  94. data/src/main/java/processing/data/LongDict.java +710 -663
  95. data/src/main/java/processing/data/LongList.java +701 -635
  96. data/src/main/java/processing/data/Sort.java +37 -41
  97. data/src/main/java/processing/data/StringDict.java +525 -486
  98. data/src/main/java/processing/data/StringList.java +626 -580
  99. data/src/main/java/processing/data/Table.java +3690 -3510
  100. data/src/main/java/processing/data/TableRow.java +182 -183
  101. data/src/main/java/processing/data/XML.java +957 -883
  102. data/src/main/java/processing/event/Event.java +87 -67
  103. data/src/main/java/processing/event/KeyEvent.java +48 -41
  104. data/src/main/java/processing/event/MouseEvent.java +88 -113
  105. data/src/main/java/processing/event/TouchEvent.java +10 -6
  106. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  107. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  108. data/src/main/java/processing/net/Client.java +20 -20
  109. data/src/main/java/processing/net/Server.java +9 -9
  110. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  111. data/src/main/java/processing/opengl/FrameBuffer.java +389 -377
  112. data/src/main/java/processing/opengl/LinePath.java +132 -89
  113. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  114. data/src/main/java/processing/opengl/PGL.java +660 -567
  115. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  116. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  117. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  118. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  119. data/src/main/java/processing/opengl/PShader.java +369 -461
  120. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  121. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  122. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  123. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  124. data/test/create_test.rb +21 -20
  125. data/test/deglut_spec_test.rb +4 -2
  126. data/test/helper_methods_test.rb +49 -20
  127. data/test/math_tool_test.rb +39 -32
  128. data/test/native_folder.rb +47 -0
  129. data/test/respond_to_test.rb +3 -2
  130. data/test/sketches/key_event.rb +2 -2
  131. data/test/sketches/library/my_library/my_library.rb +3 -0
  132. data/test/test_helper.rb +2 -0
  133. data/test/vecmath_spec_test.rb +35 -22
  134. data/vendors/Rakefile +35 -40
  135. metadata +47 -23
  136. data/library/simplex_noise/simplex_noise.rb +0 -3
  137. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  138. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  139. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  140. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -24,13 +24,12 @@
24
24
 
25
25
  package processing.core;
26
26
 
27
- import java.awt.*;
28
- import java.awt.image.*;
29
- import java.io.*;
30
- import java.util.Iterator;
31
-
32
- import javax.imageio.*;
33
- import javax.imageio.metadata.*;
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;
34
33
 
35
34
 
36
35
  /**
@@ -43,11 +42,11 @@ import javax.imageio.metadata.*;
43
42
  * fields for the <b>width</b> and <b>height</b> of the image, as well as
44
43
  * an array called <b>pixels[]</b> that contains the values for every pixel
45
44
  * in the image. The methods described below allow easy access to the
46
- * image's pixels and alpha channel and simplify the process of compositing.<br/>
47
- * <br/> using the <b>pixels[]</b> array, be sure to use the
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
48
47
  * <b>loadPixels()</b> method on the image to make sure that the pixel data
49
- * is properly loaded.<br/>
50
- * <br/> create a new image, use the <b>createImage()</b> function. Do not
48
+ * is properly loaded.
49
+ * create a new image, use the <b>createImage()</b> function. Do not
51
50
  * use the syntax <b>new PImage()</b>.
52
51
  *
53
52
  * ( end auto-generated )
@@ -198,11 +197,11 @@ public class PImage implements PConstants, Cloneable {
198
197
  * pixel in the image. A group of methods, described below, allow easy
199
198
  * access to the image's pixels and alpha channel and simplify the process
200
199
  * of compositing.
201
- *
200
+ *
202
201
  * Before using the <b>pixels[]</b> array, be sure to use the
203
202
  * <b>loadPixels()</b> method on the image to make sure that the pixel data
204
203
  * is properly loaded.
205
- *
204
+ *
206
205
  * To create a new image, use the <b>createImage()</b> function (do not use
207
206
  * <b>new PImage()</b>).
208
207
  * ( end auto-generated )
@@ -281,7 +280,7 @@ public class PImage implements PConstants, Cloneable {
281
280
  /**
282
281
  * Check the alpha on an image, using a really primitive loop.
283
282
  */
284
- protected void checkAlpha() {
283
+ public void checkAlpha() {
285
284
  if (pixels == null) return;
286
285
 
287
286
  for (int i = 0; i < pixels.length; i++) {
@@ -332,82 +331,9 @@ public class PImage implements PConstants, Cloneable {
332
331
  this.pixels = pixels;
333
332
  }
334
333
 
335
- /**
336
- * Construct a new PImage from a java.awt.Image. This constructor assumes
337
- * that you've done the work of making sure a MediaTracker has been used
338
- * to fully download the data and that the img is valid.
339
- *
340
- * @nowebref
341
- * @param img assumes a MediaTracker has been used to fully download
342
- * the data and the img is valid
343
- */
344
- public PImage(Image img) {
345
- format = RGB;
346
- if (img instanceof BufferedImage) {
347
- BufferedImage bi = (BufferedImage) img;
348
- width = bi.getWidth();
349
- height = bi.getHeight();
350
- int type = bi.getType();
351
- if (type == BufferedImage.TYPE_3BYTE_BGR ||
352
- type == BufferedImage.TYPE_4BYTE_ABGR) {
353
- pixels = new int[width * height];
354
- bi.getRGB(0, 0, width, height, pixels, 0, width);
355
- if (type == BufferedImage.TYPE_4BYTE_ABGR) {
356
- format = ARGB;
357
- } else {
358
- opaque();
359
- }
360
- } else {
361
- DataBuffer db = bi.getRaster().getDataBuffer();
362
- if (db instanceof DataBufferInt) {
363
- pixels = ((DataBufferInt) db).getData();
364
- if (type == BufferedImage.TYPE_INT_ARGB) {
365
- format = ARGB;
366
- } else if (type == BufferedImage.TYPE_INT_RGB) {
367
- opaque();
368
- }
369
- }
370
- }
371
- }
372
- // Implements fall-through if not DataBufferInt above, or not a
373
- // known type, or not DataBufferInt for the data itself.
374
- if (pixels == null) { // go the old school Java 1.0 route
375
- width = img.getWidth(null);
376
- height = img.getHeight(null);
377
- pixels = new int[width * height];
378
- PixelGrabber pg =
379
- new PixelGrabber(img, 0, 0, width, height, pixels, 0, width);
380
- try {
381
- pg.grabPixels();
382
- } catch (InterruptedException e) { }
383
- }
384
- pixelDensity = 1;
385
- pixelWidth = width;
386
- pixelHeight = height;
387
- }
388
-
389
334
 
390
- /**
391
- * Use the getNative() method instead, which allows library interfaces to be
392
- * written in a cross-platform fashion for desktop, Android, and others.
393
- * This is still included for PGraphics objects, which may need the image.
394
- */
395
- public Image getImage() { // ignore
396
- return (Image) getNative();
397
- }
398
-
399
-
400
- /**
401
- * Returns a native BufferedImage from this PImage.
402
- */
403
335
  public Object getNative() { // ignore
404
- loadPixels();
405
- int type = (format == RGB) ?
406
- BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
407
- BufferedImage image = new BufferedImage(pixelWidth, pixelHeight, type);
408
- WritableRaster wr = image.getRaster();
409
- wr.setDataElements(0, 0, pixelWidth, pixelHeight, pixels);
410
- return image;
336
+ return null;
411
337
  }
412
338
 
413
339
 
@@ -506,7 +432,7 @@ public class PImage implements PConstants, Cloneable {
506
432
  * <b>updatePixels()</b>. Even if the renderer may not seem to use this
507
433
  * function in the current Processing release, this will always be subject
508
434
  * to change.
509
- *
435
+ *
510
436
  * Currently, none of the renderers use the additional parameters to
511
437
  * <b>updatePixels()</b>, however this may be implemented in the future.
512
438
  *
@@ -592,104 +518,7 @@ public class PImage implements PConstants, Cloneable {
592
518
  * @see PImage#get(int, int, int, int)
593
519
  */
594
520
  public void resize(int w, int h) { // ignore
595
- if (w <= 0 && h <= 0) {
596
- throw new IllegalArgumentException("width or height must be > 0 for resize");
597
- }
598
-
599
- if (w == 0) { // Use height to determine relative size
600
- float diff = (float) h / (float) height;
601
- w = (int) (width * diff);
602
- } else if (h == 0) { // Use the width to determine relative size
603
- float diff = (float) w / (float) width;
604
- h = (int) (height * diff);
605
- }
606
-
607
- BufferedImage img =
608
- shrinkImage((BufferedImage) getNative(), w*pixelDensity, h*pixelDensity);
609
-
610
- PImage temp = new PImage(img);
611
- this.pixelWidth = temp.width;
612
- this.pixelHeight = temp.height;
613
-
614
- // Get the resized pixel array
615
- this.pixels = temp.pixels;
616
-
617
- this.width = pixelWidth / pixelDensity;
618
- this.height = pixelHeight / pixelDensity;
619
-
620
- // Mark the pixels array as altered
621
- updatePixels();
622
- }
623
-
624
-
625
- // Adapted from getFasterScaledInstance() method from page 111 of
626
- // "Filthy Rich Clients" by Chet Haase and Romain Guy
627
- // Additional modifications and simplifications have been added,
628
- // plus a fix to deal with an infinite loop if images are expanded.
629
- // http://code.google.com/p/processing/issues/detail?id=1463
630
- static private BufferedImage shrinkImage(BufferedImage img,
631
- int targetWidth, int targetHeight) {
632
- int type = (img.getTransparency() == Transparency.OPAQUE) ?
633
- BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
634
- BufferedImage outgoing = img;
635
- BufferedImage scratchImage = null;
636
- Graphics2D g2 = null;
637
- int prevW = outgoing.getWidth();
638
- int prevH = outgoing.getHeight();
639
- boolean isTranslucent = img.getTransparency() != Transparency.OPAQUE;
640
-
641
- // Use multi-step technique: start with original size, then scale down in
642
- // multiple passes with drawImage() until the target size is reached
643
- int w = img.getWidth();
644
- int h = img.getHeight();
645
-
646
- do {
647
- if (w > targetWidth) {
648
- w /= 2;
649
- // if this is the last step, do the exact size
650
- if (w < targetWidth) {
651
- w = targetWidth;
652
- }
653
- } else if (targetWidth >= w) {
654
- w = targetWidth;
655
- }
656
- if (h > targetHeight) {
657
- h /= 2;
658
- if (h < targetHeight) {
659
- h = targetHeight;
660
- }
661
- } else if (targetHeight >= h) {
662
- h = targetHeight;
663
- }
664
- if (scratchImage == null || isTranslucent) {
665
- // Use a single scratch buffer for all iterations and then copy
666
- // to the final, correctly-sized image before returning
667
- scratchImage = new BufferedImage(w, h, type);
668
- g2 = scratchImage.createGraphics();
669
- }
670
- g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
671
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
672
- g2.drawImage(outgoing, 0, 0, w, h, 0, 0, prevW, prevH, null);
673
- prevW = w;
674
- prevH = h;
675
- outgoing = scratchImage;
676
- } while (w != targetWidth || h != targetHeight);
677
-
678
- if (g2 != null) {
679
- g2.dispose();
680
- }
681
-
682
- // If we used a scratch buffer that is larger than our target size,
683
- // create an image of the right size and copy the results into it
684
- if (targetWidth != outgoing.getWidth() ||
685
- targetHeight != outgoing.getHeight()) {
686
- scratchImage = new BufferedImage(targetWidth, targetHeight, type);
687
- g2 = scratchImage.createGraphics();
688
- g2.drawImage(outgoing, 0, 0, null);
689
- g2.dispose();
690
- outgoing = scratchImage;
691
- }
692
- return outgoing;
521
+ throw new RuntimeException("resize() not implemented for this PImage type");
693
522
  }
694
523
 
695
524
 
@@ -889,7 +718,7 @@ public class PImage implements PConstants, Cloneable {
889
718
  * 255). When setting an image, the <b>x</b> and <b>y</b> parameters define
890
719
  * the coordinates for the upper-left corner of the image, regardless of
891
720
  * the current <b>imageMode()</b>.
892
-
721
+ *
893
722
  * Setting the color of a single pixel with <b>set(x, y)</b> is easy, but
894
723
  * not as fast as putting the data directly into <b>pixels[]</b>. The
895
724
  * equivalent statement to <b>set(x, y, #000000)</b> using <b>pixels[]</b>
@@ -985,7 +814,7 @@ public class PImage implements PConstants, Cloneable {
985
814
  * @param maskArray array of integers used as the alpha channel, needs to be
986
815
  * the same length as the image's pixel array.
987
816
  */
988
- public void mask(int maskArray[]) { // ignore
817
+ public void mask(int[] maskArray) { // ignore
989
818
  loadPixels();
990
819
  // don't execute if mask image is different size
991
820
  if (maskArray.length != pixels.length) {
@@ -1120,8 +949,8 @@ public class PImage implements PConstants, Cloneable {
1120
949
  /**
1121
950
  * ( begin auto-generated from PImage_filter.xml )
1122
951
  *
1123
- * Filters an image as defined by one of the following modes:<br
1124
- * />THRESHOLD - converts the image to black and white pixels depending if
952
+ * Filters an image as defined by one of the following modes:
953
+ * THRESHOLD - converts the image to black and white pixels depending if
1125
954
  * they are above or below the threshold defined by the level parameter.
1126
955
  * The level must be between 0.0 (black) and 1.0(white). If no level is
1127
956
  * specified, 0.5 is used.
@@ -1175,14 +1004,20 @@ public class PImage implements PConstants, Cloneable {
1175
1004
 
1176
1005
  switch (kind) {
1177
1006
  case BLUR:
1178
- if (format == ALPHA)
1007
+ switch (format) {
1008
+ case ALPHA:
1179
1009
  blurAlpha(param);
1180
- else if (format == ARGB)
1010
+ break;
1011
+ case ARGB:
1181
1012
  blurARGB(param);
1182
- else
1013
+ break;
1014
+ default:
1183
1015
  blurRGB(param);
1016
+ break;
1017
+ }
1184
1018
  break;
1185
1019
 
1020
+
1186
1021
  case GRAY:
1187
1022
  throw new RuntimeException("Use filter(GRAY) instead of " +
1188
1023
  "filter(GRAY, param)");
@@ -1284,7 +1119,7 @@ public class PImage implements PConstants, Cloneable {
1284
1119
  protected void blurAlpha(float r) {
1285
1120
  int sum, cb;
1286
1121
  int read, ri, ym, ymi, bk0;
1287
- int b2[] = new int[pixels.length];
1122
+ int[] b2 = new int[pixels.length];
1288
1123
  int yi = 0;
1289
1124
 
1290
1125
  buildBlurKernel(r);
@@ -1355,9 +1190,9 @@ public class PImage implements PConstants, Cloneable {
1355
1190
  protected void blurRGB(float r) {
1356
1191
  int sum, cr, cg, cb; //, k;
1357
1192
  int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0;
1358
- int r2[] = new int[pixels.length];
1359
- int g2[] = new int[pixels.length];
1360
- int b2[] = new int[pixels.length];
1193
+ int[] r2 = new int[pixels.length];
1194
+ int[] g2 = new int[pixels.length];
1195
+ int[] b2 = new int[pixels.length];
1361
1196
  int yi = 0;
1362
1197
 
1363
1198
  buildBlurKernel(r);
@@ -1438,10 +1273,10 @@ public class PImage implements PConstants, Cloneable {
1438
1273
  int sum, cr, cg, cb, ca;
1439
1274
  int /*pixel,*/ read, ri, /*roff,*/ ym, ymi, /*riw,*/ bk0;
1440
1275
  int wh = pixels.length;
1441
- int r2[] = new int[wh];
1442
- int g2[] = new int[wh];
1443
- int b2[] = new int[wh];
1444
- int a2[] = new int[wh];
1276
+ int[] r2 = new int[wh];
1277
+ int[] g2 = new int[wh];
1278
+ int[] b2 = new int[wh];
1279
+ int[] a2 = new int[wh];
1445
1280
  int yi = 0;
1446
1281
 
1447
1282
  buildBlurKernel(r);
@@ -1677,7 +1512,7 @@ public class PImage implements PConstants, Cloneable {
1677
1512
  * source pixels to fit the specified target region. No alpha information
1678
1513
  * is used in the process, however if the source image has an alpha channel
1679
1514
  * set, it will be copied as well.
1680
-
1515
+ *
1681
1516
  * As of release 0149, this function ignores <b>imageMode()</b>.
1682
1517
  *
1683
1518
  * ( end auto-generated )
@@ -1781,7 +1616,7 @@ public class PImage implements PConstants, Cloneable {
1781
1616
  * necessarily "correct" code. No biggie, most software does. A nitpicker
1782
1617
  * can find numerous "off by 1 division" problems in the blend code where
1783
1618
  * <TT>&gt;&gt;8</TT> or <TT>&gt;&gt;7</TT> is used when strictly speaking
1784
- * <TT>/255.0</T> or <TT>/127.0</TT> should have been used.</P>
1619
+ * <TT>/255.0</TT> or <TT>/127.0</TT> should have been used.</P>
1785
1620
  * <P>For instance, exclusion (not intended for real-time use) reads
1786
1621
  * <TT>r1 + r2 - ((2 * r1 * r2) / 255)</TT> because <TT>255 == 1.0</TT>
1787
1622
  * not <TT>256 == 1.0</TT>. In other words, <TT>(255*255)>>8</TT> is not
@@ -2992,7 +2827,15 @@ int testFunction(int dst, int src) {
2992
2827
 
2993
2828
  // FILE I/O
2994
2829
 
2995
- static protected PImage loadTIFF(byte tiff[]) {
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
+
2996
2839
  if ((tiff[42] != tiff[102]) || // width/height in both places
2997
2840
  (tiff[43] != tiff[103])) {
2998
2841
  System.err.println(TIFF_ERROR);
@@ -3048,14 +2891,8 @@ int testFunction(int dst, int src) {
3048
2891
  }
3049
2892
  */
3050
2893
  try {
3051
- byte tiff[] = new byte[768];
3052
- System.arraycopy(
3053
- TIFF_HEADER,
3054
- 0,
3055
- tiff,
3056
- 0,
3057
- TIFF_HEADER.length
3058
- );
2894
+ byte[] tiff = new byte[768];
2895
+ System.arraycopy(TIFF_HEADER, 0, tiff, 0, TIFF_HEADER.length);
3059
2896
 
3060
2897
  tiff[30] = (byte) ((pixelWidth >> 8) & 0xff);
3061
2898
  tiff[31] = (byte) ((pixelWidth) & 0xff);
@@ -3080,16 +2917,214 @@ int testFunction(int dst, int src) {
3080
2917
  return true;
3081
2918
 
3082
2919
  } catch (IOException e) {
3083
- e.printStackTrace();
3084
2920
  }
3085
2921
  return false;
3086
2922
  }
3087
2923
 
3088
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
+
3089
3124
  /**
3090
3125
  * Creates a Targa32 formatted byte sequence of specified
3091
3126
  * pixel buffer using RLE compression.
3092
- * </p>
3127
+ * <p>
3093
3128
  * Also figured out how to avoid parsing the image upside-down
3094
3129
  * (there's a header flag to set the image origin to top-left)
3095
3130
  * </p>
@@ -3100,31 +3135,33 @@ int testFunction(int dst, int src) {
3100
3135
  * <LI><TT>ARGB</TT> &rarr; 32 bits
3101
3136
  * </UL>
3102
3137
  * All versions are RLE compressed.
3103
- * </p>
3138
+ *
3104
3139
  * Contributed by toxi 8-10 May 2005, based on this RLE
3105
3140
  * <A HREF="http://www.wotsit.org/download.asp?f=tga">specification</A>
3106
3141
  */
3107
3142
  protected boolean saveTGA(OutputStream output) {
3108
- byte header[] = new byte[18];
3109
-
3110
- if (format == ALPHA) { // save ALPHA images as 8bit grayscale
3111
- header[2] = 0x0B;
3112
- header[16] = 0x08;
3113
- header[17] = 0x28;
3143
+ byte[] header = new byte[18];
3114
3144
 
3115
- } else if (format == RGB) {
3116
- header[2] = 0x0A;
3117
- header[16] = 24;
3118
- header[17] = 0x20;
3119
-
3120
- } else if (format == ARGB) {
3121
- header[2] = 0x0A;
3122
- header[16] = 32;
3123
- header[17] = 0x28;
3124
-
3125
- } else {
3126
- throw new RuntimeException("Image format not recognized inside save()");
3127
- }
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
+ }
3128
3165
  // set image dimensions lo-hi byte order
3129
3166
  header[12] = (byte) (pixelWidth & 0xff);
3130
3167
  header[13] = (byte) (pixelWidth >> 8);
@@ -3234,133 +3271,11 @@ int testFunction(int dst, int src) {
3234
3271
  return true;
3235
3272
 
3236
3273
  } catch (IOException e) {
3237
- e.printStackTrace();
3238
3274
  return false;
3239
3275
  }
3240
3276
  }
3241
3277
 
3242
3278
 
3243
- /**
3244
- * Use ImageIO functions from Java 1.4 and later to handle image save.
3245
- * Various formats are supported, typically jpeg, png, bmp, and wbmp.
3246
- * To get a list of the supported formats for writing, use: <BR>
3247
- * <TT>println(javax.imageio.ImageIO.getReaderFormatNames())</TT>
3248
- */
3249
- protected boolean saveImageIO(String path) throws IOException {
3250
- try {
3251
- int outputFormat = (format == ARGB) ?
3252
- BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB;
3253
-
3254
- String extension =
3255
- path.substring(path.lastIndexOf('.') + 1).toLowerCase();
3256
-
3257
- // JPEG and BMP images that have an alpha channel set get pretty unhappy.
3258
- // BMP just doesn't write, and JPEG writes it as a CMYK image.
3259
- // http://code.google.com/p/processing/issues/detail?id=415
3260
- if (extension.equals("bmp") || extension.equals("jpg") || extension.equals("jpeg")) {
3261
- outputFormat = BufferedImage.TYPE_INT_RGB;
3262
- }
3263
-
3264
- BufferedImage bimage = new BufferedImage(pixelWidth, pixelHeight, outputFormat);
3265
- bimage.setRGB(0, 0, pixelWidth, pixelHeight, pixels, 0, pixelWidth);
3266
-
3267
- File file = new File(path);
3268
-
3269
- ImageWriter writer = null;
3270
- ImageWriteParam param = null;
3271
- IIOMetadata metadata = null;
3272
-
3273
- if (extension.equals("jpg") || extension.equals("jpeg")) {
3274
- if ((writer = imageioWriter("jpeg")) != null) {
3275
- // Set JPEG quality to 90% with baseline optimization. Setting this
3276
- // to 1 was a huge jump (about triple the size), so this seems good.
3277
- // Oddly, a smaller file size than Photoshop at 90%, but I suppose
3278
- // it's a completely different algorithm.
3279
- param = writer.getDefaultWriteParam();
3280
- param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
3281
- param.setCompressionQuality(0.9f);
3282
- }
3283
- }
3284
-
3285
- if (extension.equals("png")) {
3286
- if ((writer = imageioWriter("png")) != null) {
3287
- param = writer.getDefaultWriteParam();
3288
- if (false) {
3289
- metadata = imageioDPI(writer, param, 100);
3290
- }
3291
- }
3292
- }
3293
-
3294
- if (writer != null) {
3295
- BufferedOutputStream output =
3296
- new BufferedOutputStream(PApplet.createOutput(file));
3297
- writer.setOutput(ImageIO.createImageOutputStream(output));
3298
- // writer.write(null, new IIOImage(bimage, null, null), param);
3299
- writer.write(metadata, new IIOImage(bimage, null, metadata), param);
3300
- writer.dispose();
3301
-
3302
- output.flush();
3303
- output.close();
3304
- return true;
3305
- }
3306
- // If iter.hasNext() somehow fails up top, it falls through to here
3307
- return javax.imageio.ImageIO.write(bimage, extension, file);
3308
-
3309
- } catch (Exception e) {
3310
- e.printStackTrace();
3311
- throw new IOException("image save failed.");
3312
- }
3313
- }
3314
-
3315
-
3316
- private ImageWriter imageioWriter(String extension) {
3317
- Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName(extension);
3318
- if (iter.hasNext()) {
3319
- return iter.next();
3320
- }
3321
- return null;
3322
- }
3323
-
3324
-
3325
- private IIOMetadata imageioDPI(ImageWriter writer, ImageWriteParam param, double dpi) {
3326
- // http://stackoverflow.com/questions/321736/how-to-set-dpi-information-in-an-image
3327
- ImageTypeSpecifier typeSpecifier =
3328
- ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
3329
- IIOMetadata metadata =
3330
- writer.getDefaultImageMetadata(typeSpecifier, param);
3331
-
3332
- if (!metadata.isReadOnly() && metadata.isStandardMetadataFormatSupported()) {
3333
- // for PNG, it's dots per millimeter
3334
- double dotsPerMilli = dpi / 25.4;
3335
-
3336
- IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
3337
- horiz.setAttribute("value", Double.toString(dotsPerMilli));
3338
-
3339
- IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
3340
- vert.setAttribute("value", Double.toString(dotsPerMilli));
3341
-
3342
- IIOMetadataNode dim = new IIOMetadataNode("Dimension");
3343
- dim.appendChild(horiz);
3344
- dim.appendChild(vert);
3345
-
3346
- IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
3347
- root.appendChild(dim);
3348
-
3349
- try {
3350
- metadata.mergeTree("javax_imageio_1.0", root);
3351
- return metadata;
3352
-
3353
- } catch (IIOInvalidTreeException e) {
3354
- System.err.println("Could not set the DPI of the output image");
3355
- e.printStackTrace();
3356
- }
3357
- }
3358
- return null;
3359
- }
3360
-
3361
-
3362
- protected String[] saveImageFormats;
3363
-
3364
3279
  /**
3365
3280
  * ( begin auto-generated from PImage_save.xml )
3366
3281
  *
@@ -3370,7 +3285,7 @@ int testFunction(int dst, int src) {
3370
3285
  * in the filename, the image will save in TIFF format and .tif will be
3371
3286
  * added to the name. These files are saved to the sketch's folder, which
3372
3287
  * may be opened by selecting "Show sketch folder" from the "Sketch" menu.
3373
- To save an image created within the code, rather
3288
+ * To save an image created within the code, rather
3374
3289
  * than through loading, it's necessary to make the image with the
3375
3290
  * <b>createImage()</b> function so it is aware of the location of the
3376
3291
  * program and can therefore save the file to the right place. See the
@@ -3433,19 +3348,8 @@ int testFunction(int dst, int src) {
3433
3348
  try {
3434
3349
  OutputStream os = null;
3435
3350
 
3436
- if (saveImageFormats == null) {
3437
- saveImageFormats = javax.imageio.ImageIO.getWriterFormatNames();
3438
- }
3439
- if (saveImageFormats != null) {
3440
- for (int i = 0; i < saveImageFormats.length; i++) {
3441
- if (filename.endsWith("." + saveImageFormats[i])) {
3442
- if (!saveImageIO(filename)) {
3443
- System.err.println("Error while saving image.");
3444
- return false;
3445
- }
3446
- return true;
3447
- }
3448
- }
3351
+ if (saveImpl(filename)) {
3352
+ return true;
3449
3353
  }
3450
3354
 
3451
3355
  if (filename.toLowerCase().endsWith(".tga")) {
@@ -3466,7 +3370,6 @@ int testFunction(int dst, int src) {
3466
3370
 
3467
3371
  } catch (IOException e) {
3468
3372
  System.err.println("Error while saving image.");
3469
- e.printStackTrace();
3470
3373
  success = false;
3471
3374
  }
3472
3375
  return success;