joonsrenderer 1.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +53 -0
  3. data/.mvn/extensions.xml +8 -0
  4. data/CHANGELOG.md +2 -0
  5. data/Gemfile +6 -0
  6. data/LICENSE +674 -0
  7. data/README.md +2 -0
  8. data/Rakefile +43 -0
  9. data/docs/.gitignore +6 -0
  10. data/docs/_config.yml +20 -0
  11. data/docs/_includes/footer.html +38 -0
  12. data/docs/_includes/head.html +15 -0
  13. data/docs/_includes/header.html +27 -0
  14. data/docs/_includes/icon-github.html +1 -0
  15. data/docs/_includes/icon-github.svg +1 -0
  16. data/docs/_includes/icon-twitter.html +1 -0
  17. data/docs/_includes/icon-twitter.svg +1 -0
  18. data/docs/_layouts/default.html +20 -0
  19. data/docs/_layouts/page.html +14 -0
  20. data/docs/_layouts/post.html +15 -0
  21. data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
  22. data/docs/_posts/2017-01-08-welcome.md +78 -0
  23. data/docs/_sass/_base.scss +206 -0
  24. data/docs/_sass/_layout.scss +242 -0
  25. data/docs/_sass/_syntax-highlighting.scss +71 -0
  26. data/docs/about.md +12 -0
  27. data/docs/assets/Animation.ogv +0 -0
  28. data/docs/assets/Animation.png +0 -0
  29. data/docs/assets/basic.png +0 -0
  30. data/docs/assets/basic_traced.png +0 -0
  31. data/docs/css/main.scss +38 -0
  32. data/docs/favicon.ico +0 -0
  33. data/docs/feed.xml +30 -0
  34. data/docs/index.html +38 -0
  35. data/joonsrenderer.gemspec +23 -0
  36. data/lib/joonsrenderer.rb +12 -0
  37. data/lib/joonsrenderer/version.rb +3 -0
  38. data/pom.rb +75 -0
  39. data/pom.xml +163 -0
  40. data/src/main/java/SunflowGUI.java +1354 -0
  41. data/src/main/java/joons/JRFiller.java +79 -0
  42. data/src/main/java/joons/JRImagePanel.java +141 -0
  43. data/src/main/java/joons/JRRecorder.java +183 -0
  44. data/src/main/java/joons/JRStatics.java +199 -0
  45. data/src/main/java/joons/JoonsRenderer.java +837 -0
  46. data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
  47. data/src/main/java/org/sunflow/Benchmark.java +313 -0
  48. data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
  49. data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
  50. data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
  51. data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
  52. data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
  53. data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
  54. data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
  55. data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
  56. data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
  57. data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
  58. data/src/main/java/org/sunflow/core/Camera.java +125 -0
  59. data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
  60. data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
  61. data/src/main/java/org/sunflow/core/Display.java +78 -0
  62. data/src/main/java/org/sunflow/core/Filter.java +27 -0
  63. data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
  64. data/src/main/java/org/sunflow/core/Geometry.java +157 -0
  65. data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
  66. data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
  67. data/src/main/java/org/sunflow/core/Instance.java +224 -0
  68. data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
  69. data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
  70. data/src/main/java/org/sunflow/core/LightSample.java +104 -0
  71. data/src/main/java/org/sunflow/core/LightServer.java +382 -0
  72. data/src/main/java/org/sunflow/core/LightSource.java +67 -0
  73. data/src/main/java/org/sunflow/core/Modifier.java +16 -0
  74. data/src/main/java/org/sunflow/core/Options.java +20 -0
  75. data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
  76. data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
  77. data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
  78. data/src/main/java/org/sunflow/core/Ray.java +219 -0
  79. data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
  80. data/src/main/java/org/sunflow/core/Scene.java +377 -0
  81. data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
  82. data/src/main/java/org/sunflow/core/Shader.java +30 -0
  83. data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
  84. data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
  85. data/src/main/java/org/sunflow/core/Statistics.java +85 -0
  86. data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
  87. data/src/main/java/org/sunflow/core/Texture.java +128 -0
  88. data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
  89. data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
  90. data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
  91. data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
  92. data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
  93. data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
  94. data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
  95. data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
  96. data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
  97. data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
  98. data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
  99. data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
  100. data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
  101. data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
  102. data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
  103. data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
  104. data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
  105. data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
  106. data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
  107. data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
  108. data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
  109. data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
  110. data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
  111. data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
  112. data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
  113. data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
  114. data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
  115. data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
  116. data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
  117. data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
  118. data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
  119. data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
  120. data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
  121. data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
  122. data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
  123. data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
  124. data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
  125. data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
  126. data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
  127. data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
  128. data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
  129. data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
  130. data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
  131. data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
  132. data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
  133. data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
  134. data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
  135. data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
  136. data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
  137. data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
  138. data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
  139. data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
  140. data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
  141. data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
  142. data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
  143. data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
  144. data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
  145. data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
  146. data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
  147. data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
  148. data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
  149. data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
  150. data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
  151. data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
  152. data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
  153. data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
  154. data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
  155. data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
  156. data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
  157. data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
  158. data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
  159. data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
  160. data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
  161. data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
  162. data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
  163. data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
  164. data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
  165. data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
  166. data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
  167. data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
  168. data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
  169. data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
  170. data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
  171. data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
  172. data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
  173. data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
  174. data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
  175. data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
  176. data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
  177. data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
  178. data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
  179. data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
  180. data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
  181. data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
  182. data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
  183. data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
  184. data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
  185. data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
  186. data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
  187. data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
  188. data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
  189. data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
  190. data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
  191. data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
  192. data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
  193. data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
  194. data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
  195. data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
  196. data/src/main/java/org/sunflow/image/Color.java +374 -0
  197. data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
  198. data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
  199. data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
  200. data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
  201. data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
  202. data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
  203. data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
  204. data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
  205. data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
  206. data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
  207. data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
  208. data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
  209. data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
  210. data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
  211. data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
  212. data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
  213. data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
  214. data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
  215. data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
  216. data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
  217. data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
  218. data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
  219. data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
  220. data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
  221. data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
  222. data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
  223. data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
  224. data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
  225. data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
  226. data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
  227. data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
  228. data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
  229. data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
  230. data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
  231. data/src/main/java/org/sunflow/math/Point2.java +36 -0
  232. data/src/main/java/org/sunflow/math/Point3.java +133 -0
  233. data/src/main/java/org/sunflow/math/QMC.java +209 -0
  234. data/src/main/java/org/sunflow/math/Solvers.java +142 -0
  235. data/src/main/java/org/sunflow/math/Vector3.java +197 -0
  236. data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
  237. data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
  238. data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
  239. data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
  240. data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
  241. data/src/main/java/org/sunflow/system/Memory.java +18 -0
  242. data/src/main/java/org/sunflow/system/Parser.java +162 -0
  243. data/src/main/java/org/sunflow/system/Plugins.java +142 -0
  244. data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
  245. data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
  246. data/src/main/java/org/sunflow/system/Timer.java +53 -0
  247. data/src/main/java/org/sunflow/system/UI.java +112 -0
  248. data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
  249. data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
  250. data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
  251. data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
  252. data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
  253. data/src/main/java/org/sunflow/util/IntArray.java +77 -0
  254. data/src/test/java/a_maintest.java +129 -0
  255. metadata +300 -0
@@ -0,0 +1,94 @@
1
+ package org.sunflow.image;
2
+
3
+ import org.sunflow.math.MathUtils;
4
+
5
+ /**
6
+ * This class contains many static helper methods that may be helpful for
7
+ * encoding colors into files.
8
+ */
9
+ public final class ColorEncoder {
10
+
11
+ /**
12
+ * Undoes the premultiplication of the specified color array. The original
13
+ * colors are not modified.
14
+ *
15
+ * @param color an array of premultiplied colors
16
+ * @param alpha alpha values corresponding to the colors
17
+ * @return an array of unpremultiplied colors
18
+ */
19
+ public static final Color[] unpremult(Color[] color, float[] alpha) {
20
+ Color[] output = new Color[color.length];
21
+ for (int i = 0; i < color.length; i++) {
22
+ output[i] = color[i].copy().mul(1 / alpha[i]);
23
+ }
24
+ return output;
25
+ }
26
+
27
+ /**
28
+ * Moves the colors in the specified array to non-linear space. The original
29
+ * colors are not modified.
30
+ *
31
+ * @param color an array of colors in linear space
32
+ * @return a new array of the same colors in non-linear space
33
+ */
34
+ public static final Color[] unlinearize(Color[] color) {
35
+ Color[] output = new Color[color.length];
36
+ for (int i = 0; i < color.length; i++) {
37
+ output[i] = color[i].copy().toNonLinear();
38
+ }
39
+ return output;
40
+ }
41
+
42
+ /**
43
+ * Quantize the specified colors to 8-bit RGB format. The returned array
44
+ * contains 3 bytes for each color in the original array.
45
+ *
46
+ * @param color array of colors to quantize
47
+ * @return array of quantized RGB values
48
+ */
49
+ public static final byte[] quantizeRGB8(Color[] color) {
50
+ byte[] output = new byte[color.length * 3];
51
+ for (int i = 0, index = 0; i < color.length; i++, index += 3) {
52
+ float[] rgb = color[i].getRGB();
53
+ output[index + 0] = (byte) MathUtils.clamp((int) (rgb[0] * 255 + 0.5f), 0, 255);
54
+ output[index + 1] = (byte) MathUtils.clamp((int) (rgb[1] * 255 + 0.5f), 0, 255);
55
+ output[index + 2] = (byte) MathUtils.clamp((int) (rgb[2] * 255 + 0.5f), 0, 255);
56
+ }
57
+ return output;
58
+ }
59
+
60
+ /**
61
+ * Quantize the specified colors to 8-bit RGBA format. The returned array
62
+ * contains 4 bytes for each color in the original array.
63
+ *
64
+ * @param color array of colors to quantize
65
+ * @param alpha array of alpha values (same length as color)
66
+ * @return array of quantized RGBA values
67
+ */
68
+ public static final byte[] quantizeRGBA8(Color[] color, float[] alpha) {
69
+ byte[] output = new byte[color.length * 4];
70
+ for (int i = 0, index = 0; i < color.length; i++, index += 4) {
71
+ float[] rgb = color[i].getRGB();
72
+ output[index + 0] = (byte) MathUtils.clamp((int) (rgb[0] * 255 + 0.5f), 0, 255);
73
+ output[index + 1] = (byte) MathUtils.clamp((int) (rgb[1] * 255 + 0.5f), 0, 255);
74
+ output[index + 2] = (byte) MathUtils.clamp((int) (rgb[2] * 255 + 0.5f), 0, 255);
75
+ output[index + 3] = (byte) MathUtils.clamp((int) (alpha[i] * 255 + 0.5f), 0, 255);
76
+ }
77
+ return output;
78
+ }
79
+
80
+ /**
81
+ * Encode the specified colors using Ward's RGBE technique. The returned
82
+ * array contains one int for each color in the original array.
83
+ *
84
+ * @param color array of colors to encode
85
+ * @return array of encoded colors
86
+ */
87
+ public static final int[] encodeRGBE(Color[] color) {
88
+ int[] output = new int[color.length];
89
+ for (int i = 0; i < color.length; i++) {
90
+ output[i] = color[i].toRGBE();
91
+ }
92
+ return output;
93
+ }
94
+ }
@@ -0,0 +1,122 @@
1
+ package org.sunflow.image;
2
+
3
+ public final class ColorFactory {
4
+
5
+ /**
6
+ * Return the name of the internal color space. This string can be used
7
+ * interchangeably with
8
+ * <code>null</code> in the following methods.
9
+ *
10
+ * @return internal colorspace name
11
+ */
12
+ public static String getInternalColorspace() {
13
+ return "sRGB linear";
14
+ }
15
+
16
+ /**
17
+ * Checks to see how many values are required to specify a color using the
18
+ * given colorspace. This number can be variable for spectrum colors, in
19
+ * which case the returned value is -1. If the colorspace name is invalid,
20
+ * this method returns -2. No exception is thrown. This method is intended
21
+ * for parsers that want to know how many floating values to retrieve from a
22
+ * file.
23
+ *
24
+ * @param colorspace
25
+ * @return number of floating point numbers expected, -1 for any, -2 on
26
+ * error
27
+ */
28
+ public static int getRequiredDataValues(String colorspace) {
29
+ if (colorspace == null) {
30
+ return 3;
31
+ }
32
+ if (colorspace.equals("sRGB nonlinear")) {
33
+ return 3;
34
+ } else if (colorspace.equals("sRGB linear")) {
35
+ return 3;
36
+ } else if (colorspace.equals("XYZ")) {
37
+ return 3;
38
+ } else if (colorspace.equals("blackbody")) {
39
+ return 1;
40
+ } else if (colorspace.startsWith("spectrum")) {
41
+ return -1;
42
+ } else {
43
+ return -2;
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Creates a color value in the renderer's internal color space from a
49
+ * string (representing the color space name) and an array of floating point
50
+ * values. If the colorspace string is null, we assume the data was supplied
51
+ * in internal space. This method does much error checking and may throw a
52
+ * {@link RuntimeException} if its parameters are not consistent. Here are
53
+ * the currently supported color spaces:
54
+ * <ul>
55
+ * <li><code>"sRGB nonlinear"</code> - requires 3 values</li>
56
+ * <li><code>"sRGB linear"</code> - requires 3 values</li>
57
+ * <li><code>"XYZ"</code> - requires 3 values</li>
58
+ * <li><code>blackbody</code> - requires 1 value (temperature in
59
+ * Kelvins)</li>
60
+ * <li><code>spectrum [min] [max]</code> - any number of values (must be
61
+ * >0), [start] and [stop] is the range over which the spectrum is defined
62
+ * in nanometers.</li>
63
+ * </ul>
64
+ *
65
+ * @param colorspace color space name
66
+ * @param data data describing this color
67
+ * @return a valid color in the renderer's color space
68
+ * @throws ColorSpecificationException
69
+ */
70
+ public static Color createColor(String colorspace, float... data) throws ColorSpecificationException {
71
+ int required = getRequiredDataValues(colorspace);
72
+ if (required == -2) {
73
+ throw new ColorSpecificationException("unknown colorspace %s");
74
+ }
75
+ if (required != -1 && required != data.length) {
76
+ throw new ColorSpecificationException(required, data.length);
77
+ }
78
+ if (colorspace == null) {
79
+ return new Color(data[0], data[1], data[2]);
80
+ } else if (colorspace.equals("sRGB nonlinear")) {
81
+ return new Color(data[0], data[1], data[2]).toLinear();
82
+ } else if (colorspace.equals("sRGB linear")) {
83
+ return new Color(data[0], data[1], data[2]);
84
+ } else if (colorspace.equals("XYZ")) {
85
+ return RGBSpace.SRGB.convertXYZtoRGB(new XYZColor(data[0], data[1], data[2]));
86
+ } else if (colorspace.equals("blackbody")) {
87
+ return RGBSpace.SRGB.convertXYZtoRGB(new BlackbodySpectrum(data[0]).toXYZ());
88
+ } else if (colorspace.startsWith("spectrum")) {
89
+ String[] tokens = colorspace.split("\\s+");
90
+ if (tokens.length != 3) {
91
+ throw new ColorSpecificationException("invalid spectrum specification");
92
+ }
93
+ if (data.length == 0) {
94
+ throw new ColorSpecificationException("missing spectrum data");
95
+ }
96
+ try {
97
+ float lambdaMin = Float.parseFloat(tokens[1]);
98
+ float lambdaMax = Float.parseFloat(tokens[2]);
99
+ return RGBSpace.SRGB.convertXYZtoRGB(new RegularSpectralCurve(data, lambdaMin, lambdaMax).toXYZ());
100
+ } catch (NumberFormatException e) {
101
+ throw new ColorSpecificationException("unable to parse spectrum wavelength range");
102
+ }
103
+ }
104
+ throw new ColorSpecificationException(String.format("Inconsistent code! Please report this error. (Input %s - %d)", colorspace, data.length));
105
+ }
106
+
107
+ @SuppressWarnings("serial")
108
+ public static final class ColorSpecificationException extends Exception {
109
+
110
+ private ColorSpecificationException() {
111
+ super("Invalid color specification");
112
+ }
113
+
114
+ private ColorSpecificationException(String message) {
115
+ super(String.format("Invalid color specification: %s", message));
116
+ }
117
+
118
+ private ColorSpecificationException(int expected, int found) {
119
+ this(String.format("invalid data length, expecting %d values, found %d", expected, found));
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,21 @@
1
+ package org.sunflow.image;
2
+
3
+ /**
4
+ * Very simple class equivalent to a constant spectral curve. Note that this is
5
+ * most likely physically impossible for amplitudes > 0, however this class can
6
+ * be handy since in practice spectral curves end up being integrated against
7
+ * the finite width color matching functions.
8
+ */
9
+ public class ConstantSpectralCurve extends SpectralCurve {
10
+
11
+ private final float amp;
12
+
13
+ public ConstantSpectralCurve(float amp) {
14
+ this.amp = amp;
15
+ }
16
+
17
+ @Override
18
+ public float sample(float lambda) {
19
+ return amp;
20
+ }
21
+ }
@@ -0,0 +1,57 @@
1
+ package org.sunflow.image;
2
+
3
+ /**
4
+ * This class allows spectral curves to be defined from irregularly sampled
5
+ * data. Note that the wavelength array is assumed to be sorted low to high. Any
6
+ * values beyond the defined range will simply be extended to infinity from the
7
+ * end points. Points inside the valid range will be linearly interpolated
8
+ * between the two nearest samples. No explicit error checking is performed, but
9
+ * this class will run into {@link ArrayIndexOutOfBoundsException}s if the array
10
+ * lengths don't match.
11
+ */
12
+ public class IrregularSpectralCurve extends SpectralCurve {
13
+
14
+ private final float[] wavelengths;
15
+ private final float[] amplitudes;
16
+
17
+ /**
18
+ * Define an irregular spectral curve from the provided (sorted) wavelengths
19
+ * and amplitude data. The wavelength array is assumed to contain values in
20
+ * nanometers. Array lengths must match.
21
+ *
22
+ * @param wavelengths sampled wavelengths in nm
23
+ * @param amplitudes amplitude of the curve at the sampled points
24
+ */
25
+ public IrregularSpectralCurve(float[] wavelengths, float[] amplitudes) {
26
+ this.wavelengths = wavelengths;
27
+ this.amplitudes = amplitudes;
28
+ if (wavelengths.length != amplitudes.length) {
29
+ throw new RuntimeException(String.format("Error creating irregular spectral curve: %d wavelengths and %d amplitudes", wavelengths.length, amplitudes.length));
30
+ }
31
+ for (int i = 1; i < wavelengths.length; i++) {
32
+ if (wavelengths[i - 1] >= wavelengths[i]) {
33
+ throw new RuntimeException(String.format("Error creating irregular spectral curve: values are not sorted - error at index %d", i));
34
+ }
35
+ }
36
+ }
37
+
38
+ @Override
39
+ public float sample(float lambda) {
40
+ if (wavelengths.length == 0) {
41
+ return 0; // no data
42
+ }
43
+ if (wavelengths.length == 1 || lambda <= wavelengths[0]) {
44
+ return amplitudes[0];
45
+ }
46
+ if (lambda >= wavelengths[wavelengths.length - 1]) {
47
+ return amplitudes[wavelengths.length - 1];
48
+ }
49
+ for (int i = 1; i < wavelengths.length; i++) {
50
+ if (lambda < wavelengths[i]) {
51
+ float dx = (lambda - wavelengths[i - 1]) / (wavelengths[i] - wavelengths[i - 1]);
52
+ return (1 - dx) * amplitudes[i - 1] + dx * amplitudes[i];
53
+ }
54
+ }
55
+ return amplitudes[wavelengths.length - 1];
56
+ }
57
+ }
@@ -0,0 +1,207 @@
1
+ package org.sunflow.image;
2
+
3
+ import org.sunflow.math.MathUtils;
4
+
5
+ public final class RGBSpace {
6
+
7
+ public static final RGBSpace ADOBE = new RGBSpace(0.6400f, 0.3300f, 0.2100f, 0.7100f, 0.1500f, 0.0600f, 0.31271f, 0.32902f, 2.2f, 0);
8
+ public static final RGBSpace APPLE = new RGBSpace(0.6250f, 0.3400f, 0.2800f, 0.5950f, 0.1550f, 0.0700f, 0.31271f, 0.32902f, 1.8f, 0);
9
+ public static final RGBSpace NTSC = new RGBSpace(0.6700f, 0.3300f, 0.2100f, 0.7100f, 0.1400f, 0.0800f, 0.31010f, 0.31620f, 20.0f / 9.0f, 0.018f);
10
+ public static final RGBSpace HDTV = new RGBSpace(0.6400f, 0.3300f, 0.3000f, 0.6000f, 0.1500f, 0.0600f, 0.31271f, 0.32902f, 20.0f / 9.0f, 0.018f);
11
+ public static final RGBSpace SRGB = new RGBSpace(0.6400f, 0.3300f, 0.3000f, 0.6000f, 0.1500f, 0.0600f, 0.31271f, 0.32902f, 2.4f, 0.00304f);
12
+ public static final RGBSpace CIE = new RGBSpace(0.7350f, 0.2650f, 0.2740f, 0.7170f, 0.1670f, 0.0090f, 1 / 3.0f, 1 / 3.0f, 2.2f, 0);
13
+ public static final RGBSpace EBU = new RGBSpace(0.6400f, 0.3300f, 0.2900f, 0.6000f, 0.1500f, 0.0600f, 0.31271f, 0.32902f, 20.0f / 9.0f, 0.018f);
14
+ public static final RGBSpace SMPTE_C = new RGBSpace(0.6300f, 0.3400f, 0.3100f, 0.5950f, 0.1550f, 0.0700f, 0.31271f, 0.32902f, 20.0f / 9.0f, 0.018f);
15
+ public static final RGBSpace SMPTE_240M = new RGBSpace(0.6300f, 0.3400f, 0.3100f, 0.5950f, 0.1550f, 0.0700f, 0.31271f, 0.32902f, 20.0f / 9.0f, 0.018f);
16
+ public static final RGBSpace WIDE_GAMUT = new RGBSpace(0.7347f, 0.2653f, 0.1152f, 0.8264f, 0.1566f, 0.0177f, 0.3457f, 0.3585f, 2.2f, 0);
17
+ private final float gamma, breakPoint;
18
+ private final float slope, slopeMatch, segmentOffset;
19
+ private final float xr, yr, zr, xg, yg, zg, xb, yb, zb;
20
+ private final float xw, yw, zw;
21
+ private final float rx, ry, rz, gx, gy, gz, bx, by, bz;
22
+ private final float rw, gw, bw;
23
+ private final int[] GAMMA_CURVE;
24
+ private final int[] INV_GAMMA_CURVE;
25
+
26
+ public RGBSpace(float xRed, float yRed, float xGreen, float yGreen, float xBlue, float yBlue, float xWhite, float yWhite, float gamma, float breakPoint) {
27
+ this.gamma = gamma;
28
+ this.breakPoint = breakPoint;
29
+
30
+ if (breakPoint > 0) {
31
+ slope = 1 / (gamma / (float) Math.pow(breakPoint, 1 / gamma - 1) - gamma * breakPoint + breakPoint);
32
+ slopeMatch = gamma * slope / (float) Math.pow(breakPoint, 1 / gamma - 1);
33
+ segmentOffset = slopeMatch * (float) Math.pow(breakPoint, 1 / gamma) - slope * breakPoint;
34
+ } else {
35
+ slope = 1;
36
+ slopeMatch = 1;
37
+ segmentOffset = 0;
38
+ }
39
+
40
+ // prepare gamma curves
41
+ GAMMA_CURVE = new int[256];
42
+ INV_GAMMA_CURVE = new int[256];
43
+ for (int i = 0; i < 256; i++) {
44
+ float c = i / 255.0f;
45
+ GAMMA_CURVE[i] = MathUtils.clamp((int) (gammaCorrect(c) * 255 + 0.5f), 0, 255);
46
+ INV_GAMMA_CURVE[i] = MathUtils.clamp((int) (ungammaCorrect(c) * 255 + 0.5f), 0, 255);
47
+ }
48
+
49
+ float xr = xRed;
50
+ float yr = yRed;
51
+ float zr = 1 - (xr + yr);
52
+ float xg = xGreen;
53
+ float yg = yGreen;
54
+ float zg = 1 - (xg + yg);
55
+ float xb = xBlue;
56
+ float yb = yBlue;
57
+ float zb = 1 - (xb + yb);
58
+
59
+ xw = xWhite;
60
+ yw = yWhite;
61
+ zw = 1 - (xw + yw);
62
+
63
+ // xyz -> rgb matrix, before scaling to white.
64
+ float rx = (yg * zb) - (yb * zg);
65
+ float ry = (xb * zg) - (xg * zb);
66
+ float rz = (xg * yb) - (xb * yg);
67
+ float gx = (yb * zr) - (yr * zb);
68
+ float gy = (xr * zb) - (xb * zr);
69
+ float gz = (xb * yr) - (xr * yb);
70
+ float bx = (yr * zg) - (yg * zr);
71
+ float by = (xg * zr) - (xr * zg);
72
+ float bz = (xr * yg) - (xg * yr);
73
+ // White scaling factors
74
+ // Dividing by yw scales the white luminance to unity, as conventional
75
+ rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw;
76
+ gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw;
77
+ bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw;
78
+
79
+ // xyz -> rgb matrix, correctly scaled to white
80
+ this.rx = rx / rw;
81
+ this.ry = ry / rw;
82
+ this.rz = rz / rw;
83
+ this.gx = gx / gw;
84
+ this.gy = gy / gw;
85
+ this.gz = gz / gw;
86
+ this.bx = bx / bw;
87
+ this.by = by / bw;
88
+ this.bz = bz / bw;
89
+
90
+ // invert matrix again to get proper rgb -> xyz matrix
91
+ float s = 1 / (this.rx * (this.gy * this.bz - this.by * this.gz) - this.ry * (this.gx * this.bz - this.bx * this.gz) + this.rz * (this.gx * this.by - this.bx * this.gy));
92
+ this.xr = s * (this.gy * this.bz - this.gz * this.by);
93
+ this.xg = s * (this.rz * this.by - this.ry * this.bz);
94
+ this.xb = s * (this.ry * this.gz - this.rz * this.gy);
95
+
96
+ this.yr = s * (this.gz * this.bx - this.gx * this.bz);
97
+ this.yg = s * (this.rx * this.bz - this.rz * this.bx);
98
+ this.yb = s * (this.rz * this.gx - this.rx * this.gz);
99
+
100
+ this.zr = s * (this.gx * this.by - this.gy * this.bx);
101
+ this.zg = s * (this.ry * this.bx - this.rx * this.by);
102
+ this.zb = s * (this.rx * this.gy - this.ry * this.gx);
103
+ }
104
+
105
+ public final Color convertXYZtoRGB(XYZColor c) {
106
+ return convertXYZtoRGB(c.getX(), c.getY(), c.getZ());
107
+ }
108
+
109
+ public final Color convertXYZtoRGB(float X, float Y, float Z) {
110
+ float r = (rx * X) + (ry * Y) + (rz * Z);
111
+ float g = (gx * X) + (gy * Y) + (gz * Z);
112
+ float b = (bx * X) + (by * Y) + (bz * Z);
113
+ return new Color(r, g, b);
114
+ }
115
+
116
+ public final XYZColor convertRGBtoXYZ(Color c) {
117
+ float[] rgb = c.getRGB();
118
+ float X = (xr * rgb[0]) + (xg * rgb[1]) + (xb * rgb[2]);
119
+ float Y = (yr * rgb[0]) + (yg * rgb[1]) + (yb * rgb[2]);
120
+ float Z = (zr * rgb[0]) + (zg * rgb[1]) + (zb * rgb[2]);
121
+ return new XYZColor(X, Y, Z);
122
+ }
123
+
124
+ public final boolean insideGamut(float r, float g, float b) {
125
+ return r >= 0 && g >= 0 && b >= 0;
126
+ }
127
+
128
+ public final float gammaCorrect(float v) {
129
+ float gammac = 0;
130
+ if (v >= 0) {
131
+ if (v >= 1) {
132
+ gammac = 1f;
133
+ } else if (v <= breakPoint) {
134
+ gammac = slope * v;
135
+ } else {
136
+ gammac = slopeMatch * (float) Math.pow(v, 1 / gamma) - segmentOffset;
137
+ }
138
+ }
139
+ return gammac;
140
+ }
141
+
142
+ public final float ungammaCorrect(float vp) {
143
+ float gammac = 0;
144
+ if (vp > 0) {
145
+ if (vp >= 1) {
146
+ gammac = 1f;
147
+ } else if (vp <= breakPoint * slope) {
148
+ gammac = vp / slope;
149
+ } else {
150
+ gammac = (float) Math.pow((vp + segmentOffset) / slopeMatch, gamma);
151
+ }
152
+ }
153
+ return gammac;
154
+ }
155
+
156
+ public final int rgbToNonLinear(int rgb) {
157
+ // gamma correct 24bit rgb value via tables
158
+ int rp = GAMMA_CURVE[(rgb >> 16) & 0xFF];
159
+ int gp = GAMMA_CURVE[(rgb >> 8) & 0xFF];
160
+ int bp = GAMMA_CURVE[rgb & 0xFF];
161
+ return (rp << 16) | (gp << 8) | bp;
162
+ }
163
+
164
+ public final int rgbToLinear(int rgb) {
165
+ // convert a packed RGB triplet to a linearized
166
+ // one by applying the proper LUT
167
+ int rp = INV_GAMMA_CURVE[(rgb >> 16) & 0xFF];
168
+ int gp = INV_GAMMA_CURVE[(rgb >> 8) & 0xFF];
169
+ int bp = INV_GAMMA_CURVE[rgb & 0xFF];
170
+ return (rp << 16) | (gp << 8) | bp;
171
+ }
172
+
173
+ public final byte rgbToNonLinear(byte r) {
174
+ return (byte) GAMMA_CURVE[r & 0xFF];
175
+ }
176
+
177
+ public final byte rgbToLinear(byte r) {
178
+ return (byte) INV_GAMMA_CURVE[r & 0xFF];
179
+ }
180
+
181
+ @Override
182
+ public final String toString() {
183
+ String MATRIX_FORMAT = "| %7.4f %7.4f %7.4f|\n";
184
+ StringBuilder info = new StringBuilder(200);
185
+ info.append("Gamma function parameters:\n");
186
+ info.append(String.format(" * Gamma: %7.4f\n", gamma));
187
+ info.append(String.format(" * Breakpoint: %7.4f\n", breakPoint));
188
+ info.append(String.format(" * Slope: %7.4f\n", slope));
189
+ info.append(String.format(" * Slope Match: %7.4f\n", slopeMatch));
190
+ info.append(String.format(" * Segment Offset: %7.4f\n", segmentOffset));
191
+ info.append("XYZ -> RGB Matrix:\n");
192
+ info.append(String.format(MATRIX_FORMAT, rx, ry, rz));
193
+ info.append(String.format(MATRIX_FORMAT, gx, gy, gz));
194
+ info.append(String.format(MATRIX_FORMAT, bx, by, bz));
195
+ info.append("RGB -> XYZ Matrix:\n");
196
+ info.append(String.format(MATRIX_FORMAT, xr, xg, xb));
197
+ info.append(String.format(MATRIX_FORMAT, yr, yg, yb));
198
+ info.append(String.format(MATRIX_FORMAT, zr, zg, zb));
199
+ return info.toString();
200
+ }
201
+
202
+ public static void main(String[] args) {
203
+ System.out.println(SRGB.toString());
204
+ System.out.println(HDTV.toString());
205
+ System.out.println(WIDE_GAMUT.toString());
206
+ }
207
+ }