joonsrenderer 1.1-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.
- checksums.yaml +7 -0
- data/.gitignore +53 -0
- data/.mvn/extensions.xml +8 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +6 -0
- data/LICENSE +674 -0
- data/README.md +2 -0
- data/Rakefile +43 -0
- data/docs/.gitignore +6 -0
- data/docs/_config.yml +20 -0
- data/docs/_includes/footer.html +38 -0
- data/docs/_includes/head.html +15 -0
- data/docs/_includes/header.html +27 -0
- data/docs/_includes/icon-github.html +1 -0
- data/docs/_includes/icon-github.svg +1 -0
- data/docs/_includes/icon-twitter.html +1 -0
- data/docs/_includes/icon-twitter.svg +1 -0
- data/docs/_layouts/default.html +20 -0
- data/docs/_layouts/page.html +14 -0
- data/docs/_layouts/post.html +15 -0
- data/docs/_posts/2017-01-08-animated_ray_tracing.md +72 -0
- data/docs/_posts/2017-01-08-welcome.md +78 -0
- data/docs/_sass/_base.scss +206 -0
- data/docs/_sass/_layout.scss +242 -0
- data/docs/_sass/_syntax-highlighting.scss +71 -0
- data/docs/about.md +12 -0
- data/docs/assets/Animation.ogv +0 -0
- data/docs/assets/Animation.png +0 -0
- data/docs/assets/basic.png +0 -0
- data/docs/assets/basic_traced.png +0 -0
- data/docs/css/main.scss +38 -0
- data/docs/favicon.ico +0 -0
- data/docs/feed.xml +30 -0
- data/docs/index.html +38 -0
- data/joonsrenderer.gemspec +23 -0
- data/lib/joonsrenderer.rb +12 -0
- data/lib/joonsrenderer/version.rb +3 -0
- data/pom.rb +75 -0
- data/pom.xml +163 -0
- data/src/main/java/SunflowGUI.java +1354 -0
- data/src/main/java/joons/JRFiller.java +79 -0
- data/src/main/java/joons/JRImagePanel.java +141 -0
- data/src/main/java/joons/JRRecorder.java +183 -0
- data/src/main/java/joons/JRStatics.java +199 -0
- data/src/main/java/joons/JoonsRenderer.java +837 -0
- data/src/main/java/org/sunflow/AsciiFileSunflowAPI.java +98 -0
- data/src/main/java/org/sunflow/Benchmark.java +313 -0
- data/src/main/java/org/sunflow/BinaryFileSunflowAPI.java +228 -0
- data/src/main/java/org/sunflow/FileSunflowAPI.java +354 -0
- data/src/main/java/org/sunflow/PluginRegistry.java +322 -0
- data/src/main/java/org/sunflow/RealtimeBenchmark.java +125 -0
- data/src/main/java/org/sunflow/RenderObjectMap.java +344 -0
- data/src/main/java/org/sunflow/SunflowAPI.java +762 -0
- data/src/main/java/org/sunflow/SunflowAPIInterface.java +277 -0
- data/src/main/java/org/sunflow/core/AccelerationStructure.java +20 -0
- data/src/main/java/org/sunflow/core/AccelerationStructureFactory.java +36 -0
- data/src/main/java/org/sunflow/core/BucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/Camera.java +125 -0
- data/src/main/java/org/sunflow/core/CameraLens.java +29 -0
- data/src/main/java/org/sunflow/core/CausticPhotonMapInterface.java +15 -0
- data/src/main/java/org/sunflow/core/Display.java +78 -0
- data/src/main/java/org/sunflow/core/Filter.java +27 -0
- data/src/main/java/org/sunflow/core/GIEngine.java +42 -0
- data/src/main/java/org/sunflow/core/Geometry.java +157 -0
- data/src/main/java/org/sunflow/core/GlobalPhotonMapInterface.java +21 -0
- data/src/main/java/org/sunflow/core/ImageSampler.java +26 -0
- data/src/main/java/org/sunflow/core/Instance.java +224 -0
- data/src/main/java/org/sunflow/core/InstanceList.java +83 -0
- data/src/main/java/org/sunflow/core/IntersectionState.java +120 -0
- data/src/main/java/org/sunflow/core/LightSample.java +104 -0
- data/src/main/java/org/sunflow/core/LightServer.java +382 -0
- data/src/main/java/org/sunflow/core/LightSource.java +67 -0
- data/src/main/java/org/sunflow/core/Modifier.java +16 -0
- data/src/main/java/org/sunflow/core/Options.java +20 -0
- data/src/main/java/org/sunflow/core/ParameterList.java +758 -0
- data/src/main/java/org/sunflow/core/PhotonStore.java +62 -0
- data/src/main/java/org/sunflow/core/PrimitiveList.java +70 -0
- data/src/main/java/org/sunflow/core/Ray.java +219 -0
- data/src/main/java/org/sunflow/core/RenderObject.java +25 -0
- data/src/main/java/org/sunflow/core/Scene.java +377 -0
- data/src/main/java/org/sunflow/core/SceneParser.java +58 -0
- data/src/main/java/org/sunflow/core/Shader.java +30 -0
- data/src/main/java/org/sunflow/core/ShadingCache.java +84 -0
- data/src/main/java/org/sunflow/core/ShadingState.java +939 -0
- data/src/main/java/org/sunflow/core/Statistics.java +85 -0
- data/src/main/java/org/sunflow/core/Tesselatable.java +36 -0
- data/src/main/java/org/sunflow/core/Texture.java +128 -0
- data/src/main/java/org/sunflow/core/TextureCache.java +48 -0
- data/src/main/java/org/sunflow/core/accel/BoundingIntervalHierarchy.java +652 -0
- data/src/main/java/org/sunflow/core/accel/KDTree.java +833 -0
- data/src/main/java/org/sunflow/core/accel/NullAccelerator.java +30 -0
- data/src/main/java/org/sunflow/core/accel/UniformGrid.java +329 -0
- data/src/main/java/org/sunflow/core/bucket/BucketOrderFactory.java +26 -0
- data/src/main/java/org/sunflow/core/bucket/ColumnBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/DiagonalBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/HilbertBucketOrder.java +65 -0
- data/src/main/java/org/sunflow/core/bucket/InvertedBucketOrder.java +28 -0
- data/src/main/java/org/sunflow/core/bucket/RandomBucketOrder.java +49 -0
- data/src/main/java/org/sunflow/core/bucket/RowBucketOrder.java +21 -0
- data/src/main/java/org/sunflow/core/bucket/SpiralBucketOrder.java +43 -0
- data/src/main/java/org/sunflow/core/camera/FisheyeLens.java +25 -0
- data/src/main/java/org/sunflow/core/camera/PinholeLens.java +43 -0
- data/src/main/java/org/sunflow/core/camera/SphericalLens.java +22 -0
- data/src/main/java/org/sunflow/core/camera/ThinLens.java +107 -0
- data/src/main/java/org/sunflow/core/display/FastDisplay.java +119 -0
- data/src/main/java/org/sunflow/core/display/FileDisplay.java +83 -0
- data/src/main/java/org/sunflow/core/display/FrameDisplay.java +97 -0
- data/src/main/java/org/sunflow/core/display/ImgPipeDisplay.java +109 -0
- data/src/main/java/org/sunflow/core/filter/BlackmanHarrisFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/BoxFilter.java +16 -0
- data/src/main/java/org/sunflow/core/filter/CatmullRomFilter.java +29 -0
- data/src/main/java/org/sunflow/core/filter/CubicBSpline.java +32 -0
- data/src/main/java/org/sunflow/core/filter/GaussianFilter.java +24 -0
- data/src/main/java/org/sunflow/core/filter/LanczosFilter.java +30 -0
- data/src/main/java/org/sunflow/core/filter/MitchellFilter.java +28 -0
- data/src/main/java/org/sunflow/core/filter/SincFilter.java +25 -0
- data/src/main/java/org/sunflow/core/filter/TriangleFilter.java +16 -0
- data/src/main/java/org/sunflow/core/gi/AmbientOcclusionGIEngine.java +57 -0
- data/src/main/java/org/sunflow/core/gi/FakeGIEngine.java +48 -0
- data/src/main/java/org/sunflow/core/gi/InstantGI.java +194 -0
- data/src/main/java/org/sunflow/core/gi/IrradianceCacheGIEngine.java +268 -0
- data/src/main/java/org/sunflow/core/gi/PathTracingGIEngine.java +65 -0
- data/src/main/java/org/sunflow/core/light/DirectionalSpotlight.java +103 -0
- data/src/main/java/org/sunflow/core/light/ImageBasedLight.java +303 -0
- data/src/main/java/org/sunflow/core/light/PointLight.java +72 -0
- data/src/main/java/org/sunflow/core/light/SphereLight.java +166 -0
- data/src/main/java/org/sunflow/core/light/SunSkyLight.java +362 -0
- data/src/main/java/org/sunflow/core/light/TriangleMeshLight.java +296 -0
- data/src/main/java/org/sunflow/core/modifiers/BumpMappingModifier.java +37 -0
- data/src/main/java/org/sunflow/core/modifiers/NormalMapModifier.java +34 -0
- data/src/main/java/org/sunflow/core/modifiers/PerlinModifier.java +80 -0
- data/src/main/java/org/sunflow/core/parser/Keyword.java +39 -0
- data/src/main/java/org/sunflow/core/parser/RA2Parser.java +107 -0
- data/src/main/java/org/sunflow/core/parser/RA3Parser.java +68 -0
- data/src/main/java/org/sunflow/core/parser/SCAbstractParser.java +299 -0
- data/src/main/java/org/sunflow/core/parser/SCAsciiParser.java +251 -0
- data/src/main/java/org/sunflow/core/parser/SCBinaryParser.java +156 -0
- data/src/main/java/org/sunflow/core/parser/SCParser.java +1403 -0
- data/src/main/java/org/sunflow/core/parser/ShaveRibParser.java +174 -0
- data/src/main/java/org/sunflow/core/parser/TriParser.java +79 -0
- data/src/main/java/org/sunflow/core/photonmap/CausticPhotonMap.java +429 -0
- data/src/main/java/org/sunflow/core/photonmap/GlobalPhotonMap.java +530 -0
- data/src/main/java/org/sunflow/core/photonmap/GridPhotonMap.java +308 -0
- data/src/main/java/org/sunflow/core/primitive/Background.java +55 -0
- data/src/main/java/org/sunflow/core/primitive/BanchoffSurface.java +100 -0
- data/src/main/java/org/sunflow/core/primitive/Box.java +210 -0
- data/src/main/java/org/sunflow/core/primitive/CornellBox.java +476 -0
- data/src/main/java/org/sunflow/core/primitive/CubeGrid.java +318 -0
- data/src/main/java/org/sunflow/core/primitive/Cylinder.java +104 -0
- data/src/main/java/org/sunflow/core/primitive/Hair.java +275 -0
- data/src/main/java/org/sunflow/core/primitive/JuliaFractal.java +266 -0
- data/src/main/java/org/sunflow/core/primitive/ParticleSurface.java +114 -0
- data/src/main/java/org/sunflow/core/primitive/Plane.java +163 -0
- data/src/main/java/org/sunflow/core/primitive/QuadMesh.java +413 -0
- data/src/main/java/org/sunflow/core/primitive/Sphere.java +101 -0
- data/src/main/java/org/sunflow/core/primitive/SphereFlake.java +234 -0
- data/src/main/java/org/sunflow/core/primitive/Torus.java +145 -0
- data/src/main/java/org/sunflow/core/primitive/TriangleMesh.java +849 -0
- data/src/main/java/org/sunflow/core/renderer/BucketRenderer.java +491 -0
- data/src/main/java/org/sunflow/core/renderer/MultipassRenderer.java +237 -0
- data/src/main/java/org/sunflow/core/renderer/ProgressiveRenderer.java +171 -0
- data/src/main/java/org/sunflow/core/renderer/SimpleRenderer.java +106 -0
- data/src/main/java/org/sunflow/core/shader/AmbientOcclusionShader.java +53 -0
- data/src/main/java/org/sunflow/core/shader/AnisotropicWardShader.java +216 -0
- data/src/main/java/org/sunflow/core/shader/ConstantShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/DiffuseShader.java +65 -0
- data/src/main/java/org/sunflow/core/shader/GlassShader.java +147 -0
- data/src/main/java/org/sunflow/core/shader/IDShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/MirrorShader.java +68 -0
- data/src/main/java/org/sunflow/core/shader/NormalShader.java +32 -0
- data/src/main/java/org/sunflow/core/shader/PhongShader.java +89 -0
- data/src/main/java/org/sunflow/core/shader/PrimIDShader.java +30 -0
- data/src/main/java/org/sunflow/core/shader/QuickGrayShader.java +63 -0
- data/src/main/java/org/sunflow/core/shader/ShinyDiffuseShader.java +98 -0
- data/src/main/java/org/sunflow/core/shader/SimpleShader.java +24 -0
- data/src/main/java/org/sunflow/core/shader/TexturedAmbientOcclusionShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedPhongShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedShinyDiffuseShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/TexturedWardShader.java +31 -0
- data/src/main/java/org/sunflow/core/shader/UVShader.java +27 -0
- data/src/main/java/org/sunflow/core/shader/UberShader.java +149 -0
- data/src/main/java/org/sunflow/core/shader/ViewCausticsShader.java +33 -0
- data/src/main/java/org/sunflow/core/shader/ViewGlobalPhotonsShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/ViewIrradianceShader.java +25 -0
- data/src/main/java/org/sunflow/core/shader/WireframeShader.java +83 -0
- data/src/main/java/org/sunflow/core/tesselatable/BezierMesh.java +254 -0
- data/src/main/java/org/sunflow/core/tesselatable/FileMesh.java +251 -0
- data/src/main/java/org/sunflow/core/tesselatable/Gumbo.java +1147 -0
- data/src/main/java/org/sunflow/core/tesselatable/Teapot.java +237 -0
- data/src/main/java/org/sunflow/image/Bitmap.java +15 -0
- data/src/main/java/org/sunflow/image/BitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/BitmapWriter.java +79 -0
- data/src/main/java/org/sunflow/image/BlackbodySpectrum.java +16 -0
- data/src/main/java/org/sunflow/image/ChromaticitySpectrum.java +55 -0
- data/src/main/java/org/sunflow/image/Color.java +374 -0
- data/src/main/java/org/sunflow/image/ColorEncoder.java +94 -0
- data/src/main/java/org/sunflow/image/ColorFactory.java +122 -0
- data/src/main/java/org/sunflow/image/ConstantSpectralCurve.java +21 -0
- data/src/main/java/org/sunflow/image/IrregularSpectralCurve.java +57 -0
- data/src/main/java/org/sunflow/image/RGBSpace.java +207 -0
- data/src/main/java/org/sunflow/image/RegularSpectralCurve.java +30 -0
- data/src/main/java/org/sunflow/image/SpectralCurve.java +118 -0
- data/src/main/java/org/sunflow/image/XYZColor.java +50 -0
- data/src/main/java/org/sunflow/image/formats/BitmapBlack.java +27 -0
- data/src/main/java/org/sunflow/image/formats/BitmapG8.java +36 -0
- data/src/main/java/org/sunflow/image/formats/BitmapGA8.java +30 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGB8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBA8.java +40 -0
- data/src/main/java/org/sunflow/image/formats/BitmapRGBE.java +60 -0
- data/src/main/java/org/sunflow/image/formats/BitmapXYZ.java +38 -0
- data/src/main/java/org/sunflow/image/formats/GenericBitmap.java +73 -0
- data/src/main/java/org/sunflow/image/readers/BMPBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/HDRBitmapReader.java +155 -0
- data/src/main/java/org/sunflow/image/readers/IGIBitmapReader.java +104 -0
- data/src/main/java/org/sunflow/image/readers/JPGBitmapReader.java +39 -0
- data/src/main/java/org/sunflow/image/readers/PNGBitmapReader.java +40 -0
- data/src/main/java/org/sunflow/image/readers/TGABitmapReader.java +141 -0
- data/src/main/java/org/sunflow/image/writers/EXRBitmapWriter.java +395 -0
- data/src/main/java/org/sunflow/image/writers/HDRBitmapWriter.java +54 -0
- data/src/main/java/org/sunflow/image/writers/IGIBitmapWriter.java +75 -0
- data/src/main/java/org/sunflow/image/writers/PNGBitmapWriter.java +39 -0
- data/src/main/java/org/sunflow/image/writers/TGABitmapWriter.java +63 -0
- data/src/main/java/org/sunflow/math/BoundingBox.java +340 -0
- data/src/main/java/org/sunflow/math/MathUtils.java +159 -0
- data/src/main/java/org/sunflow/math/Matrix4.java +573 -0
- data/src/main/java/org/sunflow/math/MovingMatrix4.java +119 -0
- data/src/main/java/org/sunflow/math/OrthoNormalBasis.java +110 -0
- data/src/main/java/org/sunflow/math/PerlinScalar.java +331 -0
- data/src/main/java/org/sunflow/math/PerlinVector.java +132 -0
- data/src/main/java/org/sunflow/math/Point2.java +36 -0
- data/src/main/java/org/sunflow/math/Point3.java +133 -0
- data/src/main/java/org/sunflow/math/QMC.java +209 -0
- data/src/main/java/org/sunflow/math/Solvers.java +142 -0
- data/src/main/java/org/sunflow/math/Vector3.java +197 -0
- data/src/main/java/org/sunflow/system/BenchmarkFramework.java +73 -0
- data/src/main/java/org/sunflow/system/BenchmarkTest.java +17 -0
- data/src/main/java/org/sunflow/system/ByteUtil.java +119 -0
- data/src/main/java/org/sunflow/system/FileUtils.java +27 -0
- data/src/main/java/org/sunflow/system/ImagePanel.java +282 -0
- data/src/main/java/org/sunflow/system/Memory.java +18 -0
- data/src/main/java/org/sunflow/system/Parser.java +162 -0
- data/src/main/java/org/sunflow/system/Plugins.java +142 -0
- data/src/main/java/org/sunflow/system/RenderGlobalsPanel.java +209 -0
- data/src/main/java/org/sunflow/system/SearchPath.java +67 -0
- data/src/main/java/org/sunflow/system/Timer.java +53 -0
- data/src/main/java/org/sunflow/system/UI.java +112 -0
- data/src/main/java/org/sunflow/system/UserInterface.java +46 -0
- data/src/main/java/org/sunflow/system/ui/ConsoleInterface.java +48 -0
- data/src/main/java/org/sunflow/system/ui/SilentInterface.java +28 -0
- data/src/main/java/org/sunflow/util/FastHashMap.java +220 -0
- data/src/main/java/org/sunflow/util/FloatArray.java +77 -0
- data/src/main/java/org/sunflow/util/IntArray.java +77 -0
- data/src/test/java/a_maintest.java +129 -0
- 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
|
+
}
|