propane 3.4.1-java → 3.7.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) 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 +9 -5
  9. data/Rakefile +10 -11
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +4 -2
  12. data/lib/propane/app.rb +2 -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/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 +2 -0
  37. data/pom.rb +37 -36
  38. data/pom.xml +6 -6
  39. data/propane.gemspec +12 -10
  40. data/src/main/java/japplemenubar/JAppleMenuBar.java +3 -3
  41. data/src/main/java/monkstone/ColorUtil.java +1 -3
  42. data/src/main/java/monkstone/MathToolModule.java +10 -9
  43. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  44. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  45. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  46. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  47. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  48. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  49. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  50. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  52. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  53. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  54. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  55. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  56. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  57. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  58. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  59. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  60. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  61. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  62. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  63. data/src/main/java/processing/awt/PSurfaceAWT.java +308 -208
  64. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  65. data/src/main/java/processing/core/PApplet.java +4225 -4855
  66. data/src/main/java/processing/core/PConstants.java +477 -447
  67. data/src/main/java/processing/core/PFont.java +914 -880
  68. data/src/main/java/processing/core/PGraphics.java +150 -134
  69. data/src/main/java/processing/core/PImage.java +275 -372
  70. data/src/main/java/processing/core/PMatrix.java +172 -159
  71. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  72. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  73. data/src/main/java/processing/core/PShape.java +2887 -2651
  74. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  75. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  76. data/src/main/java/processing/core/PStyle.java +40 -37
  77. data/src/main/java/processing/core/PSurface.java +139 -97
  78. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  79. data/src/main/java/processing/core/PVector.java +995 -963
  80. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  81. data/src/main/java/processing/data/DoubleDict.java +756 -710
  82. data/src/main/java/processing/data/DoubleList.java +749 -696
  83. data/src/main/java/processing/data/FloatDict.java +748 -702
  84. data/src/main/java/processing/data/FloatList.java +751 -697
  85. data/src/main/java/processing/data/IntDict.java +720 -673
  86. data/src/main/java/processing/data/IntList.java +699 -633
  87. data/src/main/java/processing/data/JSONArray.java +931 -873
  88. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  89. data/src/main/java/processing/data/JSONTokener.java +351 -341
  90. data/src/main/java/processing/data/LongDict.java +710 -663
  91. data/src/main/java/processing/data/LongList.java +701 -635
  92. data/src/main/java/processing/data/Sort.java +37 -41
  93. data/src/main/java/processing/data/StringDict.java +525 -486
  94. data/src/main/java/processing/data/StringList.java +626 -580
  95. data/src/main/java/processing/data/Table.java +3690 -3510
  96. data/src/main/java/processing/data/TableRow.java +182 -183
  97. data/src/main/java/processing/data/XML.java +957 -883
  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 +20 -20
  105. data/src/main/java/processing/net/Server.java +9 -9
  106. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  107. data/src/main/java/processing/opengl/FrameBuffer.java +389 -377
  108. data/src/main/java/processing/opengl/LinePath.java +132 -89
  109. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  110. data/src/main/java/processing/opengl/PGL.java +660 -567
  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 +369 -461
  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 +35 -40
  131. metadata +42 -22
  132. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  133. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  134. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  135. 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;