diff --git a/.hgtags b/.hgtags
index 61934b7a64..86fa05d977 100755
--- a/.hgtags
+++ b/.hgtags
@@ -520,3 +520,4 @@ d029faf69f20a23007f32420a1ac6a3b89a6d441 3.7.6-release
83959480cb986522d07b151a0c778ab7f920d41b 3.7.7-release
bba9b3722eea08949e4ff69591f736bf0f808434 3.7.8-release
a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
+91dae9494b4d147541c7a01902334ba19a7ec05e 3.7.10-release
diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt
index 36a7d38bb7..8a83ac498f 100755
--- a/indra/integration_tests/llimage_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt
@@ -7,6 +7,7 @@ project (llimage_libtest)
include(00-Common)
include(LLCommon)
include(LLImage)
+include(LLMath)
include(LLImageJ2COJ)
include(LLKDU)
include(LLVFS)
@@ -15,6 +16,7 @@ include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
+ ${LLMATH_INCLUDE_DIRS}
)
include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@@ -64,6 +66,7 @@ endif (DARWIN)
target_link_libraries(llimage_libtest
${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES}
+ ${LLMATH_LIBRARIES}
${LLIMAGE_LIBRARIES}
${LLKDU_LIBRARIES}
${KDU_LIBRARY}
diff --git a/indra/integration_tests/llimage_libtest/filters/1970colorize.xml b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml
new file mode 100644
index 0000000000..0dab2489a0
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/1970colorize.xml
@@ -0,0 +1,41 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.8
+ 1.0
+ 1.0
+ 1.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.5
+ 0.0
+ 0.0
+
+
+ blend
+ 10.0
+ 0.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.1
+ 0.1
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/autocontrast.xml b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml
new file mode 100755
index 0000000000..ec3d7561bd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml
@@ -0,0 +1,11 @@
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/badtrip.xml b/indra/integration_tests/llimage_libtest/filters/badtrip.xml
new file mode 100755
index 0000000000..14ee0baff3
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/badtrip.xml
@@ -0,0 +1,36 @@
+
+
+
+ grayscale
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ posterize
+ 10.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ gradient
+
+
+ colorize
+ 0.0
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+ 0.15
+
+
+ blur
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
new file mode 100644
index 0000000000..2474a1b953
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml
@@ -0,0 +1,25 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ uniform
+ add
+ 0.0
+ 1.0
+
+
+ gamma
+ 0.25
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/blur.xml b/indra/integration_tests/llimage_libtest/filters/blur.xml
new file mode 100644
index 0000000000..addd056855
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/blur.xml
@@ -0,0 +1,7 @@
+
+
+
+ blur
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/brighten.xml b/indra/integration_tests/llimage_libtest/filters/brighten.xml
new file mode 100755
index 0000000000..9b4232229f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/brighten.xml
@@ -0,0 +1,11 @@
+
+
+
+ brighten
+ 0.5
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/colorize.xml b/indra/integration_tests/llimage_libtest/filters/colorize.xml
new file mode 100644
index 0000000000..72e58b0ffe
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/colorize.xml
@@ -0,0 +1,24 @@
+
+
+
+ stencil
+ vignette
+ blend
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 10.0
+
+
+ colorize
+ 1.0
+ 0.0
+ 0.0
+ 0.5
+ 0.5
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/colortransform.xml b/indra/integration_tests/llimage_libtest/filters/colortransform.xml
new file mode 100644
index 0000000000..de4bebcce2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/colortransform.xml
@@ -0,0 +1,16 @@
+
+
+
+ colortransform
+ 0.2125
+ 0.7154
+ 0.0721
+ 0.2125
+ 0.7154
+ 0.0721
+ 0.2125
+ 0.7154
+ 0.0721
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/contrast.xml b/indra/integration_tests/llimage_libtest/filters/contrast.xml
new file mode 100644
index 0000000000..00746b8a9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/contrast.xml
@@ -0,0 +1,11 @@
+
+
+
+ contrast
+ 1.5
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/convolve.xml b/indra/integration_tests/llimage_libtest/filters/convolve.xml
new file mode 100644
index 0000000000..6e65b5f88a
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/convolve.xml
@@ -0,0 +1,18 @@
+
+
+
+ convolve
+ 1.0
+ 0.0
+ 4.0
+ 1.0
+ 4.0
+ 1.0
+ 0.0
+ 1.0
+ 4.0
+ 1.0
+ 4.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/darken.xml b/indra/integration_tests/llimage_libtest/filters/darken.xml
new file mode 100755
index 0000000000..5cec3589b6
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/darken.xml
@@ -0,0 +1,11 @@
+
+
+
+ darken
+ 0.5
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
new file mode 100644
index 0000000000..0e2e0ad68c
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml
@@ -0,0 +1,47 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.4
+ 0.0
+ 0.0
+ 1.0
+ 2.0
+
+
+ contrast
+ 1.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ add
+ -0.8
+ 0.0
+ 0.0
+ 0.0
+ 1.0
+ 2.0
+
+
+ contrast
+ 1.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/edges.xml b/indra/integration_tests/llimage_libtest/filters/edges.xml
new file mode 100644
index 0000000000..a66b81d01e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/edges.xml
@@ -0,0 +1,24 @@
+
+
+
+ gradient
+
+
+ blur
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 2.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/focus.xml b/indra/integration_tests/llimage_libtest/filters/focus.xml
new file mode 100644
index 0000000000..d8525fea62
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/focus.xml
@@ -0,0 +1,39 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ blend
+ 0.0
+ 0.4
+ 0.0
+ 0.0
+ 0.5
+ 2.0
+
+
+ sharpen
+
+
+ stencil
+ vignette
+ blend
+ 1.0
+ 0.0
+ 0.0
+ 0.0
+ 0.5
+ 2.0
+
+
+ blur
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/gamma.xml b/indra/integration_tests/llimage_libtest/filters/gamma.xml
new file mode 100644
index 0000000000..19af09b046
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/gamma.xml
@@ -0,0 +1,11 @@
+
+
+
+ gamma
+ 1.7
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/grayscale.xml b/indra/integration_tests/llimage_libtest/filters/grayscale.xml
new file mode 100644
index 0000000000..984312c4fd
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/grayscale.xml
@@ -0,0 +1,14 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/heatwave.xml b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
new file mode 100644
index 0000000000..a99f41c833
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/heatwave.xml
@@ -0,0 +1,38 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.8
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ fade
+ 0.5
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 4.0
+
+
+ colorize
+ 1.0
+ 0.0
+ 1.0
+ 0.4
+ 0.0
+ 0.2
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
new file mode 100644
index 0000000000..21cab70e54
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml
@@ -0,0 +1,20 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ screen
+ line
+ 0.015
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/julesverne.xml b/indra/integration_tests/llimage_libtest/filters/julesverne.xml
new file mode 100644
index 0000000000..981e221da9
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/julesverne.xml
@@ -0,0 +1,20 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ screen
+ line
+ 0.02
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
new file mode 100644
index 0000000000..0b5af9c82b
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml
@@ -0,0 +1,131 @@
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ gradient
+ add
+ 1.0
+ 0.0
+ -1.0
+ 1.0
+ 1.0
+ -1.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.1
+ 0.1
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 1.0
+ -1.0
+ 1.0
+ 1.5
+ 5.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.6
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 1.0
+ -1.0
+ 1.0
+ 1.0
+ 5.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.6
+ 0.6
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ 0.5
+ -0.5
+ 0.10
+ 20.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.7
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ 0.6
+ -0.6
+ 0.05
+ 20.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.7
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ 0.4
+ -0.4
+ 0.025
+ 20.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.7
+ 0.0
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/lightleak.xml b/indra/integration_tests/llimage_libtest/filters/lightleak.xml
new file mode 100755
index 0000000000..6fe496506e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/lightleak.xml
@@ -0,0 +1,78 @@
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+ brighten
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ gradient
+ add
+ 1.0
+ 0.0
+ -1.0
+ 1.0
+ 1.0
+ -1.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.1
+ 0.1
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 1.0
+ -1.0
+ 1.0
+ 1.5
+ 5.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.8
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 1.0
+ -1.0
+ 1.0
+ 1.0
+ 5.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.8
+ 0.8
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/linearize.xml b/indra/integration_tests/llimage_libtest/filters/linearize.xml
new file mode 100755
index 0000000000..23d0290e07
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/linearize.xml
@@ -0,0 +1,11 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/miniature.xml b/indra/integration_tests/llimage_libtest/filters/miniature.xml
new file mode 100755
index 0000000000..9aa8a87c6f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/miniature.xml
@@ -0,0 +1,118 @@
+
+
+
+ linearize
+ 0.02
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 1.02
+ 1.0
+ 1.0
+ 1.0
+
+
+ saturate
+ 1.2
+
+
+ stencil
+ vignette
+ blend
+ 0.0
+ 0.25
+ 0.0
+ 0.0
+ 0.25
+ 2.0
+
+
+ sharpen
+
+
+ stencil
+ gradient
+ blend
+ 1.0
+ 0.0
+ 0.0
+ -1.0
+ 0.0
+ -0.25
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ stencil
+ gradient
+ blend
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 0.0
+ 0.25
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/newsscreen.xml b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml
new file mode 100755
index 0000000000..50ed27c6db
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/newsscreen.xml
@@ -0,0 +1,20 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ screen
+ 2Dsine
+ 0.015
+ 0.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml
new file mode 100644
index 0000000000..dce5ab3e9e
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml
@@ -0,0 +1,24 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.0
+ 0.3
+ 0.0
+
+
+ saturate
+ 0.35
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
new file mode 100755
index 0000000000..f643419aa0
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml
@@ -0,0 +1,35 @@
+
+
+
+ blur
+
+
+ darken
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.9
+ 1.0
+ 1.0
+ 1.0
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+ posterize
+ 4.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/posterize.xml b/indra/integration_tests/llimage_libtest/filters/posterize.xml
new file mode 100755
index 0000000000..4d03df3c66
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/posterize.xml
@@ -0,0 +1,11 @@
+
+
+
+ posterize
+ 10.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
new file mode 100644
index 0000000000..e25029720f
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml
@@ -0,0 +1,8 @@
+
+
+
+ rotate
+ 180.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/saturate.xml b/indra/integration_tests/llimage_libtest/filters/saturate.xml
new file mode 100644
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/saturate.xml
@@ -0,0 +1,8 @@
+
+
+
+ saturate
+ 3.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/sepia.xml b/indra/integration_tests/llimage_libtest/filters/sepia.xml
new file mode 100644
index 0000000000..0304ead015
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/sepia.xml
@@ -0,0 +1,14 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ sepia
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/sharpen.xml b/indra/integration_tests/llimage_libtest/filters/sharpen.xml
new file mode 100644
index 0000000000..6d3f9ae1a2
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/sharpen.xml
@@ -0,0 +1,7 @@
+
+
+
+ sharpen
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
new file mode 100644
index 0000000000..6cd1a96185
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/slantedscreen.xml
@@ -0,0 +1,20 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ screen
+ line
+ 0.015
+ 45.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/spotlight.xml b/indra/integration_tests/llimage_libtest/filters/spotlight.xml
new file mode 100644
index 0000000000..203130bdee
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/spotlight.xml
@@ -0,0 +1,45 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.8
+ 1.0
+ 1.0
+ 1.0
+
+
+ saturate
+ 1.5
+
+
+ fade
+ 1.0
+ 0.25
+
+
+ saturate
+ 0.8
+
+
+ contrast
+ 1.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ brighten
+ 30
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
new file mode 100644
index 0000000000..d22809a9bf
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilgradient.xml
@@ -0,0 +1,24 @@
+
+
+
+ stencil
+ gradient
+ blend
+ 0.0
+ 1.0
+ 0.0
+ -1.0
+ 0.0
+ 1.0
+
+
+ colorize
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
new file mode 100644
index 0000000000..3ce428503d
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml
@@ -0,0 +1,22 @@
+
+
+
+ stencil
+ scanlines
+ blend
+ 0.0
+ 0.5
+ 0.1
+ 45.0
+
+
+ colorize
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
new file mode 100644
index 0000000000..7d72f0ed93
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stenciluniform.xml
@@ -0,0 +1,20 @@
+
+
+
+ stencil
+ uniform
+ blend
+ 0.0
+ 0.5
+
+
+ colorize
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
new file mode 100644
index 0000000000..d30637fef5
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/stencilvignette.xml
@@ -0,0 +1,24 @@
+
+
+
+ stencil
+ vignette
+ blend
+ 0.0
+ 0.5
+ 0.0
+ 0.0
+ 1.0
+ 10.0
+
+
+ colorize
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/thematrix.xml b/indra/integration_tests/llimage_libtest/filters/thematrix.xml
new file mode 100755
index 0000000000..af9a5eced8
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/thematrix.xml
@@ -0,0 +1,42 @@
+
+
+
+ grayscale
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ posterize
+ 50.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ gradient
+
+
+ screen
+ line
+ 0.025
+ 90.0
+
+
+ colorize
+ 0.0
+ 1.0
+ 0.0
+ 0.1
+ 0.2
+ 0.2
+
+
+ blur
+
+
+
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/toycamera.xml b/indra/integration_tests/llimage_libtest/filters/toycamera.xml
new file mode 100755
index 0000000000..4e76f6b2fb
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/toycamera.xml
@@ -0,0 +1,46 @@
+
+
+
+ stencil
+ vignette
+ fade
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+ 1.2
+ 3.0
+
+
+ linearize
+ 0.05
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ contrast
+ 1.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ blend
+ 1.0
+ 0.0
+ 0.0
+ 0.0
+ 0.5
+ 2.0
+
+
+ blur
+
+
+
\ No newline at end of file
diff --git a/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
new file mode 100644
index 0000000000..0768d1d7e1
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/verticalscreen.xml
@@ -0,0 +1,20 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ screen
+ line
+ 0.015
+ 90.0
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml
new file mode 100755
index 0000000000..fe17f3950a
--- /dev/null
+++ b/indra/integration_tests/llimage_libtest/filters/video.xml
@@ -0,0 +1,44 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ darken
+ 0.15
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ uniform
+ add
+ 0.0
+ 0.5
+
+
+ screen
+ line
+ 0.02
+ 0.0
+
+
+ gamma
+ 0.25
+ 1.0
+ 1.0
+ 1.0
+
+
+ blur
+
+
+ blur
+
+
+
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 034c816742..3d27b4a5b5 100755
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -32,6 +32,7 @@
// Linden library includes
#include "llimage.h"
+#include "llimagefilter.h"
#include "llimagejpeg.h"
#include "llimagepng.h"
#include "llimagebmp.h"
@@ -39,6 +40,8 @@
#include "llimagej2c.h"
#include "lldir.h"
#include "lldiriterator.h"
+#include "v4coloru.h"
+#include "llsdserialize.h"
// system libraries
#include
@@ -83,6 +86,8 @@ static const char USAGE[] = "\n"
" -rev, --reversible\n"
" Set the compression to be lossless (reversible in j2c parlance).\n"
" Only valid for output j2c images.\n"
+" -f, --filter \n"
+" Apply the filter to the input images.\n"
" -log, --logmetrics \n"
" Log performance data for . Results in .slp\n"
" Note: so far, only ImageCompressionTester has been tested.\n"
@@ -99,7 +104,7 @@ static bool sAllDone = false;
// Create an empty formatted image instance of the correct type from the filename
LLPointer create_image(const std::string &filename)
{
- std::string exten = gDirUtilp->getExtension(filename);
+ std::string exten = gDirUtilp->getExtension(filename);
LLPointer image = LLImageFormatted::createFromExtension(exten);
return image;
}
@@ -350,6 +355,7 @@ int main(int argc, char** argv)
int blocks_size = -1;
int levels = 0;
bool reversible = false;
+ std::string filter_name = "";
// Init whatever is necessary
ll_init_apr();
@@ -523,7 +529,26 @@ int main(int argc, char** argv)
break;
}
}
- else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
+ else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f"))
+ {
+ // '--filter' needs to be specified with a named filter argument
+ if ((arg + 1) < argc)
+ {
+ filter_name = argv[arg+1];
+ }
+ if (((arg + 1) >= argc) || (filter_name[0] == '-'))
+ {
+ // We don't have an argument left in the arg list or the next argument is another option
+ std::cout << "No --filter argument given, no filter will be applied" << std::endl;
+ }
+ else
+ {
+ arg += 1; // Skip that arg now we know it's a valid test name
+ if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
+ break;
+ }
+ }
+ else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
{
analyze_performance = true;
}
@@ -553,7 +578,10 @@ int main(int argc, char** argv)
fast_timer_log_thread = new LogThread(LLFastTimer::sLogName);
fast_timer_log_thread->start();
}
-
+
+ // Load the filter once and for all
+ LLImageFilter filter(filter_name);
+
// Perform action on each input file
std::list::iterator in_file = input_filenames.begin();
std::list::iterator out_file = output_filenames.begin();
@@ -568,7 +596,10 @@ int main(int argc, char** argv)
std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;
continue;
}
-
+
+ // Apply the filter
+ filter.executeFilter(raw_image);
+
// Save file
if (out_file != out_end)
{
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index e837b0cac2..293ada7548 100755
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -27,6 +27,7 @@ set(llimage_SOURCE_FILES
llimage.cpp
llimagedimensionsinfo.cpp
llimagedxt.cpp
+ llimagefilter.cpp
llimagej2c.cpp
llimagejpeg.cpp
llimagepng.cpp
@@ -42,6 +43,7 @@ set(llimage_HEADER_FILES
llimagebmp.h
llimagedimensionsinfo.h
llimagedxt.h
+ llimagefilter.h
llimagej2c.h
llimagejpeg.h
llimagepng.h
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 2b5ef60dce..294d4c97a2 100755
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -471,18 +471,8 @@ void LLImageRaw::verticalFlip()
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
{
// Find new sizes
- S32 new_width = MIN_IMAGE_SIZE;
- S32 new_height = MIN_IMAGE_SIZE;
-
- while( (new_width < getWidth()) && (new_width < max_dim) )
- {
- new_width <<= 1;
- }
-
- while( (new_height < getHeight()) && (new_height < max_dim) )
- {
- new_height <<= 1;
- }
+ S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
+ S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim);
scale( new_width, new_height, scale_image );
}
@@ -490,55 +480,61 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
{
// Find new sizes
- S32 new_width = max_dim;
- S32 new_height = max_dim;
-
- while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) )
- {
- new_width >>= 1;
- }
-
- while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) )
- {
- new_height >>= 1;
- }
+ S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
+ S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE);
scale( new_width, new_height, scale_image );
}
-void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
+// static
+S32 LLImageRaw::biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
{
// Strong bias towards rounding down (to save bandwidth)
// No bias would mean THRESHOLD == 1.5f;
- const F32 THRESHOLD = 1.75f;
-
+ const F32 THRESHOLD = 1.75f;
+
// Find new sizes
- S32 larger_w = max_dim; // 2^n >= mWidth
- S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
- while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
+ S32 larger_dim = max_dim; // 2^n >= curr_dim
+ S32 smaller_dim = max_dim; // 2^(n-1) <= curr_dim
+ while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) )
{
- larger_w = smaller_w;
- smaller_w >>= 1;
+ larger_dim = smaller_dim;
+ smaller_dim >>= 1;
}
- S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
+ return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim;
+}
-
- S32 larger_h = max_dim; // 2^m >= mHeight
- S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
- while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
+// static
+S32 LLImageRaw::expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
+{
+ S32 new_dim = MIN_IMAGE_SIZE;
+ while( (new_dim < curr_dim) && (new_dim < max_dim) )
{
- larger_h = smaller_h;
- smaller_h >>= 1;
+ new_dim <<= 1;
}
- S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
+ return new_dim;
+}
+// static
+S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim)
+{
+ S32 new_dim = MAX_IMAGE_SIZE;
+ while( (new_dim > curr_dim) && (new_dim > min_dim) )
+ {
+ new_dim >>= 1;
+ }
+ return new_dim;
+}
+
+void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
+{
+ // Find new sizes
+ S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim);
+ S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim);
scale( new_width, new_height );
}
-
-
-
// Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn!
inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
{
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index ffe4dcd7dc..089cbeb811 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -216,6 +216,9 @@ public:
void verticalFlip();
+ static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
+ static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
+ static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE);
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp
new file mode 100755
index 0000000000..3d0c488768
--- /dev/null
+++ b/indra/llimage/llimagefilter.cpp
@@ -0,0 +1,939 @@
+/**
+ * @file llimagefilter.cpp
+ * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llimagefilter.h"
+
+#include "llmath.h"
+#include "v3color.h"
+#include "v4coloru.h"
+#include "m3math.h"
+#include "v3math.h"
+#include "llsdserialize.h"
+#include "llstring.h"
+
+//---------------------------------------------------------------------------
+// LLImageFilter
+//---------------------------------------------------------------------------
+
+LLImageFilter::LLImageFilter(const std::string& file_path) :
+ mFilterData(LLSD::emptyArray()),
+ mImage(NULL),
+ mHistoRed(NULL),
+ mHistoGreen(NULL),
+ mHistoBlue(NULL),
+ mHistoBrightness(NULL),
+ mStencilBlendMode(STENCIL_BLEND_MODE_BLEND),
+ mStencilShape(STENCIL_SHAPE_UNIFORM),
+ mStencilGamma(1.0),
+ mStencilMin(0.0),
+ mStencilMax(1.0)
+{
+ // Load filter description from file
+ llifstream filter_xml(file_path);
+ if (filter_xml.is_open())
+ {
+ // Load and parse the file
+ LLPointer parser = new LLSDXMLParser();
+ parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED);
+ filter_xml.close();
+ }
+}
+
+LLImageFilter::~LLImageFilter()
+{
+ mImage = NULL;
+ ll_aligned_free_16(mHistoRed);
+ ll_aligned_free_16(mHistoGreen);
+ ll_aligned_free_16(mHistoBlue);
+ ll_aligned_free_16(mHistoBrightness);
+}
+
+/*
+ *TODO
+ * Rename stencil to mask
+ * Improve perf: use LUT for alpha blending in uniform case
+ * Add gradient coloring as a filter
+ */
+
+//============================================================================
+// Apply the filter data to the image passed as parameter
+//============================================================================
+
+void LLImageFilter::executeFilter(LLPointer raw_image)
+{
+ mImage = raw_image;
+
+ //std::cout << "Filter : size = " << mFilterData.size() << std::endl;
+ for (S32 i = 0; i < mFilterData.size(); ++i)
+ {
+ std::string filter_name = mFilterData[i][0].asString();
+ // Dump out the filter values (for debug)
+ //std::cout << "Filter : name = " << mFilterData[i][0].asString() << ", params = ";
+ //for (S32 j = 1; j < mFilterData[i].size(); ++j)
+ //{
+ // std::cout << mFilterData[i][j].asString() << ", ";
+ //}
+ //std::cout << std::endl;
+
+ if (filter_name == "stencil")
+ {
+ // Get the shape of the stencil, that is how the procedural alpha is computed geometrically
+ std::string filter_shape = mFilterData[i][1].asString();
+ EStencilShape shape = STENCIL_SHAPE_UNIFORM;
+ if (filter_shape == "uniform")
+ {
+ shape = STENCIL_SHAPE_UNIFORM;
+ }
+ else if (filter_shape == "gradient")
+ {
+ shape = STENCIL_SHAPE_GRADIENT;
+ }
+ else if (filter_shape == "vignette")
+ {
+ shape = STENCIL_SHAPE_VIGNETTE;
+ }
+ else if (filter_shape == "scanlines")
+ {
+ shape = STENCIL_SHAPE_SCAN_LINES;
+ }
+ // Get the blend mode of the stencil, that is how the effect is blended in the background through the stencil
+ std::string filter_mode = mFilterData[i][2].asString();
+ EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND;
+ if (filter_mode == "blend")
+ {
+ mode = STENCIL_BLEND_MODE_BLEND;
+ }
+ else if (filter_mode == "add")
+ {
+ mode = STENCIL_BLEND_MODE_ADD;
+ }
+ else if (filter_mode == "add_back")
+ {
+ mode = STENCIL_BLEND_MODE_ABACK;
+ }
+ else if (filter_mode == "fade")
+ {
+ mode = STENCIL_BLEND_MODE_FADE;
+ }
+ // Get the float params: mandatory min, max then the optional parameters (4 max)
+ F32 min = (F32)(mFilterData[i][3].asReal());
+ F32 max = (F32)(mFilterData[i][4].asReal());
+ F32 params[4] = {0.0, 0.0, 0.0, 0.0};
+ for (S32 j = 5; (j < mFilterData[i].size()) && (j < 9); j++)
+ {
+ params[j-5] = (F32)(mFilterData[i][j].asReal());
+ }
+ // Set the stencil
+ setStencil(shape,mode,min,max,params);
+ }
+ else if (filter_name == "sepia")
+ {
+ filterSepia();
+ }
+ else if (filter_name == "grayscale")
+ {
+ filterGrayScale();
+ }
+ else if (filter_name == "saturate")
+ {
+ filterSaturate((float)(mFilterData[i][1].asReal()));
+ }
+ else if (filter_name == "rotate")
+ {
+ filterRotate((float)(mFilterData[i][1].asReal()));
+ }
+ else if (filter_name == "gamma")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterGamma((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "colorize")
+ {
+ LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()));
+ LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal()));
+ filterColorize(color,alpha);
+ }
+ else if (filter_name == "contrast")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterContrast((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "brighten")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterBrightness((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "darken")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterBrightness((float)(-mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "linearize")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterLinearize((float)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "posterize")
+ {
+ LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
+ filterEqualize((S32)(mFilterData[i][1].asReal()),color);
+ }
+ else if (filter_name == "screen")
+ {
+ std::string screen_name = mFilterData[i][1].asString();
+ EScreenMode mode = SCREEN_MODE_2DSINE;
+ if (screen_name == "2Dsine")
+ {
+ mode = SCREEN_MODE_2DSINE;
+ }
+ else if (screen_name == "line")
+ {
+ mode = SCREEN_MODE_LINE;
+ }
+ filterScreen(mode,(F32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
+ }
+ else if (filter_name == "blur")
+ {
+ LLMatrix3 kernel;
+ for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[i][j] = 1.0;
+ convolve(kernel,true,false);
+ }
+ else if (filter_name == "sharpen")
+ {
+ LLMatrix3 kernel;
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[k][j] = -1.0;
+ kernel.mMatrix[1][1] = 9.0;
+ convolve(kernel,false,false);
+ }
+ else if (filter_name == "gradient")
+ {
+ LLMatrix3 kernel;
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[k][j] = -1.0;
+ kernel.mMatrix[1][1] = 8.0;
+ convolve(kernel,false,true);
+ }
+ else if (filter_name == "convolve")
+ {
+ LLMatrix3 kernel;
+ S32 index = 1;
+ bool normalize = (mFilterData[i][index++].asReal() > 0.0);
+ bool abs_value = (mFilterData[i][index++].asReal() > 0.0);
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ kernel.mMatrix[k][j] = mFilterData[i][index++].asReal();
+ convolve(kernel,normalize,abs_value);
+ }
+ else if (filter_name == "colortransform")
+ {
+ LLMatrix3 transform;
+ S32 index = 1;
+ for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ transform.mMatrix[k][j] = mFilterData[i][index++].asReal();
+ transform.transpose();
+ colorTransform(transform);
+ }
+ else
+ {
+ llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl;
+ }
+ }
+}
+
+//============================================================================
+// Filter Primitives
+//============================================================================
+
+void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue)
+{
+ F32 inv_alpha = 1.0 - alpha;
+ switch (mStencilBlendMode)
+ {
+ case STENCIL_BLEND_MODE_BLEND:
+ // Classic blend of incoming color with the background image
+ pixel[VRED] = inv_alpha * pixel[VRED] + alpha * red;
+ pixel[VGREEN] = inv_alpha * pixel[VGREEN] + alpha * green;
+ pixel[VBLUE] = inv_alpha * pixel[VBLUE] + alpha * blue;
+ break;
+ case STENCIL_BLEND_MODE_ADD:
+ // Add incoming color to the background image
+ pixel[VRED] = llclampb(pixel[VRED] + alpha * red);
+ pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green);
+ pixel[VBLUE] = llclampb(pixel[VBLUE] + alpha * blue);
+ break;
+ case STENCIL_BLEND_MODE_ABACK:
+ // Add back background image to the incoming color
+ pixel[VRED] = llclampb(inv_alpha * pixel[VRED] + red);
+ pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green);
+ pixel[VBLUE] = llclampb(inv_alpha * pixel[VBLUE] + blue);
+ break;
+ case STENCIL_BLEND_MODE_FADE:
+ // Fade incoming color to black
+ pixel[VRED] = alpha * red;
+ pixel[VGREEN] = alpha * green;
+ pixel[VBLUE] = alpha * blue;
+ break;
+ }
+}
+
+void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ U8* dst_data = mImage->getData();
+ for (S32 j = 0; j < height; j++)
+ {
+ for (S32 i = 0; i < width; i++)
+ {
+ // Blend LUT value
+ blendStencil(getStencilAlpha(i,j), dst_data, lut_red[dst_data[VRED]], lut_green[dst_data[VGREEN]], lut_blue[dst_data[VBLUE]]);
+ dst_data += components;
+ }
+ }
+}
+
+void LLImageFilter::colorTransform(const LLMatrix3 &transform)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ U8* dst_data = mImage->getData();
+ for (S32 j = 0; j < height; j++)
+ {
+ for (S32 i = 0; i < width; i++)
+ {
+ // Compute transform
+ LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
+ LLVector3 dst = src * transform;
+ dst.clamp(0.0f,255.0f);
+
+ // Blend result
+ blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
+ dst_data += components;
+ }
+ }
+}
+
+void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ // Compute normalization factors
+ F32 kernel_min = 0.0;
+ F32 kernel_max = 0.0;
+ for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
+ {
+ for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
+ {
+ if (kernel.mMatrix[i][j] >= 0.0)
+ kernel_max += kernel.mMatrix[i][j];
+ else
+ kernel_min += kernel.mMatrix[i][j];
+ }
+ }
+ if (abs_value)
+ {
+ kernel_max = llabs(kernel_max);
+ kernel_min = llabs(kernel_min);
+ kernel_max = llmax(kernel_max,kernel_min);
+ kernel_min = 0.0;
+ }
+ F32 kernel_range = kernel_max - kernel_min;
+
+ // Allocate temporary buffers and initialize algorithm's data
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ U8* dst_data = mImage->getData();
+
+ S32 buffer_size = width * components;
+ llassert_always(buffer_size > 0);
+ std::vector even_buffer(buffer_size);
+ std::vector odd_buffer(buffer_size);
+
+ U8* south_data = dst_data + buffer_size;
+ U8* east_west_data;
+ U8* north_data;
+
+ // Line 0 : we set the line to 0 (debatable)
+ memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
+ for (S32 i = 0; i < width; i++)
+ {
+ blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
+ dst_data += components;
+ }
+ south_data += buffer_size;
+
+ // All other lines
+ for (S32 j = 1; j < (height-1); j++)
+ {
+ // We need to buffer 2 lines. We flip north and east-west (current) to avoid moving too much memory around
+ if (j % 2)
+ {
+ memcpy( &odd_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
+ east_west_data = &odd_buffer[0];
+ north_data = &even_buffer[0];
+ }
+ else
+ {
+ memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
+ east_west_data = &even_buffer[0];
+ north_data = &odd_buffer[0];
+ }
+ // First pixel : set to 0
+ blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0);
+ dst_data += components;
+ // Set pointers to kernel
+ U8* NW = north_data;
+ U8* N = NW+components;
+ U8* NE = N+components;
+ U8* W = east_west_data;
+ U8* C = W+components;
+ U8* E = C+components;
+ U8* SW = south_data;
+ U8* S = SW+components;
+ U8* SE = S+components;
+ // All other pixels
+ for (S32 i = 1; i < (width-1); i++)
+ {
+ // Compute convolution
+ LLVector3 dst;
+ dst.mV[VRED] = (kernel.mMatrix[0][0]*NW[VRED] + kernel.mMatrix[0][1]*N[VRED] + kernel.mMatrix[0][2]*NE[VRED] +
+ kernel.mMatrix[1][0]*W[VRED] + kernel.mMatrix[1][1]*C[VRED] + kernel.mMatrix[1][2]*E[VRED] +
+ kernel.mMatrix[2][0]*SW[VRED] + kernel.mMatrix[2][1]*S[VRED] + kernel.mMatrix[2][2]*SE[VRED]);
+ dst.mV[VGREEN] = (kernel.mMatrix[0][0]*NW[VGREEN] + kernel.mMatrix[0][1]*N[VGREEN] + kernel.mMatrix[0][2]*NE[VGREEN] +
+ kernel.mMatrix[1][0]*W[VGREEN] + kernel.mMatrix[1][1]*C[VGREEN] + kernel.mMatrix[1][2]*E[VGREEN] +
+ kernel.mMatrix[2][0]*SW[VGREEN] + kernel.mMatrix[2][1]*S[VGREEN] + kernel.mMatrix[2][2]*SE[VGREEN]);
+ dst.mV[VBLUE] = (kernel.mMatrix[0][0]*NW[VBLUE] + kernel.mMatrix[0][1]*N[VBLUE] + kernel.mMatrix[0][2]*NE[VBLUE] +
+ kernel.mMatrix[1][0]*W[VBLUE] + kernel.mMatrix[1][1]*C[VBLUE] + kernel.mMatrix[1][2]*E[VBLUE] +
+ kernel.mMatrix[2][0]*SW[VBLUE] + kernel.mMatrix[2][1]*S[VBLUE] + kernel.mMatrix[2][2]*SE[VBLUE]);
+ if (abs_value)
+ {
+ dst.mV[VRED] = llabs(dst.mV[VRED]);
+ dst.mV[VGREEN] = llabs(dst.mV[VGREEN]);
+ dst.mV[VBLUE] = llabs(dst.mV[VBLUE]);
+ }
+ if (normalize)
+ {
+ dst.mV[VRED] = (dst.mV[VRED] - kernel_min)/kernel_range;
+ dst.mV[VGREEN] = (dst.mV[VGREEN] - kernel_min)/kernel_range;
+ dst.mV[VBLUE] = (dst.mV[VBLUE] - kernel_min)/kernel_range;
+ }
+ dst.clamp(0.0f,255.0f);
+
+ // Blend result
+ blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
+
+ // Next pixel
+ dst_data += components;
+ NW += components;
+ N += components;
+ NE += components;
+ W += components;
+ C += components;
+ E += components;
+ SW += components;
+ S += components;
+ SE += components;
+ }
+ // Last pixel : set to 0
+ blendStencil(getStencilAlpha(width-1,j), dst_data, 0, 0, 0);
+ dst_data += components;
+ south_data += buffer_size;
+ }
+
+ // Last line
+ for (S32 i = 0; i < width; i++)
+ {
+ blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
+ dst_data += components;
+ }
+}
+
+void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle)
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ S32 width = mImage->getWidth();
+ S32 height = mImage->getHeight();
+
+ F32 wave_length_pixels = wave_length * (F32)(height) / 2.0;
+ F32 sin = sinf(angle*DEG_TO_RAD);
+ F32 cos = cosf(angle*DEG_TO_RAD);
+
+ // Precompute the gamma table : gives us the gray level to use when cutting outside the screen (prevents strong aliasing on the screen)
+ U8 gamma[256];
+ for (S32 i = 0; i < 256; i++)
+ {
+ F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/4.0)));
+ gamma[i] = (U8)(255.0 * gamma_i);
+ }
+
+ U8* dst_data = mImage->getData();
+ for (S32 j = 0; j < height; j++)
+ {
+ for (S32 i = 0; i < width; i++)
+ {
+ // Compute screen value
+ F32 value = 0.0;
+ F32 di = 0.0;
+ F32 dj = 0.0;
+ switch (mode)
+ {
+ case SCREEN_MODE_2DSINE:
+ di = cos*i + sin*j;
+ dj = -sin*i + cos*j;
+ value = (sinf(2*F_PI*di/wave_length_pixels)*sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
+ break;
+ case SCREEN_MODE_LINE:
+ dj = sin*i - cos*j;
+ value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
+ break;
+ }
+ U8 dst_value = (dst_data[VRED] >= (U8)(value) ? gamma[dst_data[VRED] - (U8)(value)] : 0);
+
+ // Blend result
+ blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value);
+ dst_data += components;
+ }
+ }
+}
+
+//============================================================================
+// Procedural Stencils
+//============================================================================
+void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params)
+{
+ mStencilShape = shape;
+ mStencilBlendMode = mode;
+ mStencilMin = llmin(llmax(min, -1.0f), 1.0f);
+ mStencilMax = llmin(llmax(max, -1.0f), 1.0f);
+
+ // Each shape will interpret the 4 params differenly.
+ // We compute each systematically, though, clearly, values are meaningless when the shape doesn't correspond to the parameters
+ mStencilCenterX = (S32)(mImage->getWidth() + params[0] * (F32)(mImage->getHeight()))/2;
+ mStencilCenterY = (S32)(mImage->getHeight() + params[1] * (F32)(mImage->getHeight()))/2;
+ mStencilWidth = (S32)(params[2] * (F32)(mImage->getHeight()))/2;
+ mStencilGamma = (params[3] <= 0.0 ? 1.0 : params[3]);
+
+ mStencilWavelength = (params[0] <= 0.0 ? 10.0 : params[0] * (F32)(mImage->getHeight()) / 2.0);
+ mStencilSine = sinf(params[1]*DEG_TO_RAD);
+ mStencilCosine = cosf(params[1]*DEG_TO_RAD);
+
+ mStencilStartX = ((F32)(mImage->getWidth()) + params[0] * (F32)(mImage->getHeight()))/2.0;
+ mStencilStartY = ((F32)(mImage->getHeight()) + params[1] * (F32)(mImage->getHeight()))/2.0;
+ F32 end_x = ((F32)(mImage->getWidth()) + params[2] * (F32)(mImage->getHeight()))/2.0;
+ F32 end_y = ((F32)(mImage->getHeight()) + params[3] * (F32)(mImage->getHeight()))/2.0;
+ mStencilGradX = end_x - mStencilStartX;
+ mStencilGradY = end_y - mStencilStartY;
+ mStencilGradN = mStencilGradX*mStencilGradX + mStencilGradY*mStencilGradY;
+}
+
+F32 LLImageFilter::getStencilAlpha(S32 i, S32 j)
+{
+ F32 alpha = 1.0; // That init actually takes care of the STENCIL_SHAPE_UNIFORM case...
+ if (mStencilShape == STENCIL_SHAPE_VIGNETTE)
+ {
+ // alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
+ // The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
+ F32 d_center_square = (i - mStencilCenterX)*(i - mStencilCenterX) + (j - mStencilCenterY)*(j - mStencilCenterY);
+ alpha = powf(F_E, -(powf((d_center_square/(mStencilWidth*mStencilWidth)),mStencilGamma)/2.0f));
+ }
+ else if (mStencilShape == STENCIL_SHAPE_SCAN_LINES)
+ {
+ // alpha varies according to a squared sine function.
+ F32 d = mStencilSine*i - mStencilCosine*j;
+ alpha = (sinf(2*F_PI*d/mStencilWavelength) > 0.0 ? 1.0 : 0.0);
+ }
+ else if (mStencilShape == STENCIL_SHAPE_GRADIENT)
+ {
+ alpha = (((F32)(i) - mStencilStartX)*mStencilGradX + ((F32)(j) - mStencilStartY)*mStencilGradY) / mStencilGradN;
+ alpha = llclampf(alpha);
+ }
+
+ // We rescale alpha between min and max
+ return (mStencilMin + alpha * (mStencilMax - mStencilMin));
+}
+
+//============================================================================
+// Histograms
+//============================================================================
+
+U32* LLImageFilter::getBrightnessHistogram()
+{
+ if (!mHistoBrightness)
+ {
+ computeHistograms();
+ }
+ return mHistoBrightness;
+}
+
+void LLImageFilter::computeHistograms()
+{
+ const S32 components = mImage->getComponents();
+ llassert( components >= 1 && components <= 4 );
+
+ // Allocate memory for the histograms
+ if (!mHistoRed)
+ {
+ mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+ if (!mHistoGreen)
+ {
+ mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+ if (!mHistoBlue)
+ {
+ mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+ if (!mHistoBrightness)
+ {
+ mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
+ }
+
+ // Initialize them
+ for (S32 i = 0; i < 256; i++)
+ {
+ mHistoRed[i] = 0;
+ mHistoGreen[i] = 0;
+ mHistoBlue[i] = 0;
+ mHistoBrightness[i] = 0;
+ }
+
+ // Compute them
+ S32 pixels = mImage->getWidth() * mImage->getHeight();
+ U8* dst_data = mImage->getData();
+ for (S32 i = 0; i < pixels; i++)
+ {
+ mHistoRed[dst_data[VRED]]++;
+ mHistoGreen[dst_data[VGREEN]]++;
+ mHistoBlue[dst_data[VBLUE]]++;
+ // Note: this is a very simple shorthand for brightness but it's OK for our use
+ S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3;
+ mHistoBrightness[brightness]++;
+ // next pixel...
+ dst_data += components;
+ }
+}
+
+//============================================================================
+// Secondary Filters
+//============================================================================
+
+void LLImageFilter::filterGrayScale()
+{
+ LLMatrix3 gray_scale;
+ LLVector3 luminosity(0.2125, 0.7154, 0.0721);
+ gray_scale.setRows(luminosity, luminosity, luminosity);
+ gray_scale.transpose();
+ colorTransform(gray_scale);
+}
+
+void LLImageFilter::filterSepia()
+{
+ LLMatrix3 sepia;
+ sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368),
+ LLVector3(0.2990, 0.5870, 0.1140),
+ LLVector3(0.2392, 0.4696, 0.0912));
+ sepia.transpose();
+ colorTransform(sepia);
+}
+
+void LLImageFilter::filterSaturate(F32 saturation)
+{
+ // Matrix to Lij
+ LLMatrix3 r_a;
+ LLMatrix3 r_b;
+
+ // 45 degre rotation around z
+ r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3(-OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3( 0.0, 0.0, 1.0));
+ // 54.73 degre rotation around y
+ float oo_sqrt3 = 1.0f / F_SQRT3;
+ float sin_54 = F_SQRT2 * oo_sqrt3;
+ r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+ LLVector3(0.0, 1.0, 0.0),
+ LLVector3(sin_54, 0.0, oo_sqrt3));
+
+ // Coordinate conversion
+ LLMatrix3 Lij = r_b * r_a;
+ LLMatrix3 Lij_inv = Lij;
+ Lij_inv.transpose();
+
+ // Local saturation transform
+ LLMatrix3 s;
+ s.setRows(LLVector3(saturation, 0.0, 0.0),
+ LLVector3(0.0, saturation, 0.0),
+ LLVector3(0.0, 0.0, 1.0));
+
+ // Global saturation transform
+ LLMatrix3 transfo = Lij_inv * s * Lij;
+ colorTransform(transfo);
+}
+
+void LLImageFilter::filterRotate(F32 angle)
+{
+ // Matrix to Lij
+ LLMatrix3 r_a;
+ LLMatrix3 r_b;
+
+ // 45 degre rotation around z
+ r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3(-OO_SQRT2, OO_SQRT2, 0.0),
+ LLVector3( 0.0, 0.0, 1.0));
+ // 54.73 degre rotation around y
+ float oo_sqrt3 = 1.0f / F_SQRT3;
+ float sin_54 = F_SQRT2 * oo_sqrt3;
+ r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
+ LLVector3(0.0, 1.0, 0.0),
+ LLVector3(sin_54, 0.0, oo_sqrt3));
+
+ // Coordinate conversion
+ LLMatrix3 Lij = r_b * r_a;
+ LLMatrix3 Lij_inv = Lij;
+ Lij_inv.transpose();
+
+ // Local color rotation transform
+ LLMatrix3 r;
+ angle *= DEG_TO_RAD;
+ r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0),
+ LLVector3(-sinf(angle), cosf(angle), 0.0),
+ LLVector3( 0.0, 0.0, 1.0));
+
+ // Global color rotation transform
+ LLMatrix3 transfo = Lij_inv * r * Lij;
+ colorTransform(transfo);
+}
+
+void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha)
+{
+ U8 gamma_red_lut[256];
+ U8 gamma_green_lut[256];
+ U8 gamma_blue_lut[256];
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/gamma)));
+ // Blend in with alpha values
+ gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
+ gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
+ gamma_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i);
+ }
+
+ colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
+}
+
+void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha)
+{
+ // Get the histogram
+ U32* histo = getBrightnessHistogram();
+
+ // Compute cumulated histogram
+ U32 cumulated_histo[256];
+ cumulated_histo[0] = histo[0];
+ for (S32 i = 1; i < 256; i++)
+ {
+ cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+ }
+
+ // Compute min and max counts minus tail
+ tail = llclampf(tail);
+ S32 total = cumulated_histo[255];
+ S32 min_c = (S32)((F32)(total) * tail);
+ S32 max_c = (S32)((F32)(total) * (1.0 - tail));
+
+ // Find min and max values
+ S32 min_v = 0;
+ while (cumulated_histo[min_v] < min_c)
+ {
+ min_v++;
+ }
+ S32 max_v = 255;
+ while (cumulated_histo[max_v] > max_c)
+ {
+ max_v--;
+ }
+
+ // Compute linear lookup table
+ U8 linear_red_lut[256];
+ U8 linear_green_lut[256];
+ U8 linear_blue_lut[256];
+ if (max_v == min_v)
+ {
+ // Degenerated binary split case
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (i < min_v ? 0 : 255);
+ // Blend in with alpha values
+ linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+ }
+ else
+ {
+ // Linearize between min and max
+ F32 slope = 255.0 / (F32)(max_v - min_v);
+ F32 translate = -min_v * slope;
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+ // Blend in with alpha values
+ linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+ }
+
+ // Apply lookup table
+ colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut);
+}
+
+void LLImageFilter::filterEqualize(S32 nb_classes, const LLColor3& alpha)
+{
+ // Regularize the parameter: must be between 2 and 255
+ nb_classes = llmax(nb_classes,2);
+ nb_classes = llclampb(nb_classes);
+
+ // Get the histogram
+ U32* histo = getBrightnessHistogram();
+
+ // Compute cumulated histogram
+ U32 cumulated_histo[256];
+ cumulated_histo[0] = histo[0];
+ for (S32 i = 1; i < 256; i++)
+ {
+ cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
+ }
+
+ // Compute deltas
+ S32 total = cumulated_histo[255];
+ S32 delta_count = total / nb_classes;
+ S32 current_count = delta_count;
+ S32 delta_value = 256 / (nb_classes - 1);
+ S32 current_value = 0;
+
+ // Compute equalized lookup table
+ U8 equalize_red_lut[256];
+ U8 equalize_green_lut[256];
+ U8 equalize_blue_lut[256];
+ for (S32 i = 0; i < 256; i++)
+ {
+ // Blend in current_value with alpha values
+ equalize_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value);
+ equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value);
+ equalize_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value);
+ if (cumulated_histo[i] >= current_count)
+ {
+ current_count += delta_count;
+ current_value += delta_value;
+ current_value = llclampb(current_value);
+ }
+ }
+
+ // Apply lookup table
+ colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut);
+}
+
+void LLImageFilter::filterColorize(const LLColor3& color, const LLColor3& alpha)
+{
+ U8 red_lut[256];
+ U8 green_lut[256];
+ U8 blue_lut[256];
+
+ F32 red_composite = 255.0 * alpha.mV[0] * color.mV[0];
+ F32 green_composite = 255.0 * alpha.mV[1] * color.mV[1];
+ F32 blue_composite = 255.0 * alpha.mV[2] * color.mV[2];
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ red_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite)));
+ green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite)));
+ blue_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite)));
+ }
+
+ colorCorrect(red_lut,green_lut,blue_lut);
+}
+
+void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha)
+{
+ U8 contrast_red_lut[256];
+ U8 contrast_green_lut[256];
+ U8 contrast_blue_lut[256];
+
+ F32 translate = 128.0 * (1.0 - slope);
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
+ // Blend in with alpha values
+ contrast_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ contrast_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+
+ colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
+}
+
+void LLImageFilter::filterBrightness(F32 add, const LLColor3& alpha)
+{
+ U8 brightness_red_lut[256];
+ U8 brightness_green_lut[256];
+ U8 brightness_blue_lut[256];
+
+ S32 add_value = (S32)(add * 255.0);
+
+ for (S32 i = 0; i < 256; i++)
+ {
+ U8 value_i = (U8)(llclampb(i + add_value));
+ // Blend in with alpha values
+ brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
+ brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
+ brightness_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
+ }
+
+ colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut);
+}
+
+//============================================================================
diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h
new file mode 100755
index 0000000000..16ec395f76
--- /dev/null
+++ b/indra/llimage/llimagefilter.h
@@ -0,0 +1,137 @@
+/**
+ * @file llimagefilter.h
+ * @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2014, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLIMAGEFILTER_H
+#define LL_LLIMAGEFILTER_H
+
+#include "llsd.h"
+#include "llimage.h"
+
+class LLImageRaw;
+class LLColor4U;
+class LLColor3;
+class LLMatrix3;
+
+typedef enum e_stencil_blend_mode
+{
+ STENCIL_BLEND_MODE_BLEND = 0,
+ STENCIL_BLEND_MODE_ADD = 1,
+ STENCIL_BLEND_MODE_ABACK = 2,
+ STENCIL_BLEND_MODE_FADE = 3
+} EStencilBlendMode;
+
+typedef enum e_stencil_shape
+{
+ STENCIL_SHAPE_UNIFORM = 0,
+ STENCIL_SHAPE_GRADIENT = 1,
+ STENCIL_SHAPE_VIGNETTE = 2,
+ STENCIL_SHAPE_SCAN_LINES = 3
+} EStencilShape;
+
+typedef enum e_screen_mode
+{
+ SCREEN_MODE_2DSINE = 0,
+ SCREEN_MODE_LINE = 1
+} EScreenMode;
+
+//============================================================================
+// LLImageFilter
+//============================================================================
+
+class LLImageFilter
+{
+public:
+ LLImageFilter(const std::string& file_path);
+ ~LLImageFilter();
+
+ void executeFilter(LLPointer raw_image);
+
+private:
+ // Filter Operations : Transforms
+ void filterGrayScale(); // Convert to grayscale
+ void filterSepia(); // Convert to sepia
+ void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates
+ void filterRotate(F32 angle); // Rotates hue according to angle, angle in degrees
+
+ // Filter Operations : Color Corrections
+ // When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
+ // acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply
+ // the effect only to the Red channel. Intermediate values blends the effect with the source color.
+ void filterGamma(F32 gamma, const LLColor3& alpha); // Apply gamma to each channel
+ void filterLinearize(F32 tail, const LLColor3& alpha); // Use histogram to linearize constrast between min and max values minus tail
+ void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
+ void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel
+ void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
+ void filterBrightness(F32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker
+
+ // Filter Primitives
+ void colorTransform(const LLMatrix3 &transform);
+ void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
+ void filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle);
+ void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue);
+ void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value);
+
+ // Procedural Stencils
+ void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params);
+ F32 getStencilAlpha(S32 i, S32 j);
+
+ // Histograms
+ U32* getBrightnessHistogram();
+ void computeHistograms();
+
+ LLSD mFilterData;
+ LLPointer mImage;
+
+ // Histograms (if we ever happen to need them)
+ U32 *mHistoRed;
+ U32 *mHistoGreen;
+ U32 *mHistoBlue;
+ U32 *mHistoBrightness;
+
+ // Current Stencil Settings
+ EStencilBlendMode mStencilBlendMode;
+ EStencilShape mStencilShape;
+ F32 mStencilMin;
+ F32 mStencilMax;
+
+ S32 mStencilCenterX;
+ S32 mStencilCenterY;
+ S32 mStencilWidth;
+ F32 mStencilGamma;
+
+ F32 mStencilWavelength;
+ F32 mStencilSine;
+ F32 mStencilCosine;
+
+ F32 mStencilStartX;
+ F32 mStencilStartY;
+ F32 mStencilGradX;
+ F32 mStencilGradY;
+ F32 mStencilGradN;
+};
+
+
+#endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index d8092e5bc5..7fcd0a9c1b 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -310,6 +310,7 @@ set(viewer_SOURCE_FILES
llfilteredwearablelist.cpp
llfirstuse.cpp
llflexibleobject.cpp
+ llflickrconnect.cpp
llfloaterabout.cpp
llfloaterbvhpreview.cpp
llfloaterauction.cpp
@@ -318,6 +319,7 @@ set(viewer_SOURCE_FILES
llfloateravatarpicker.cpp
llfloateravatartextures.cpp
llfloaterbeacons.cpp
+ llfloaterbigpreview.cpp
llfloaterbuildoptions.cpp
llfloaterbulkpermission.cpp
llfloaterbump.cpp
@@ -339,6 +341,8 @@ set(viewer_SOURCE_FILES
llfloatereditwater.cpp
llfloaterenvironmentsettings.cpp
llfloaterevent.cpp
+ llfloaterfacebook.cpp
+ llfloaterflickr.cpp
llfloaterfonttest.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
@@ -391,7 +395,6 @@ set(viewer_SOURCE_FILES
llfloatersettingsdebug.cpp
llfloatersidepanelcontainer.cpp
llfloatersnapshot.cpp
- llfloatersocial.cpp
llfloatersounddevices.cpp
llfloaterspellchecksettings.cpp
llfloatertelehub.cpp
@@ -403,6 +406,7 @@ set(viewer_SOURCE_FILES
llfloatertos.cpp
llfloatertoybox.cpp
llfloatertranslationsettings.cpp
+ llfloatertwitter.cpp
llfloateruipreview.cpp
llfloaterurlentry.cpp
llfloatervoiceeffect.cpp
@@ -440,6 +444,7 @@ set(viewer_SOURCE_FILES
llhudrender.cpp
llhudtext.cpp
llhudview.cpp
+ llimagefiltersmanager.cpp
llimhandler.cpp
llimview.cpp
llinspect.cpp
@@ -683,6 +688,7 @@ set(viewer_SOURCE_FILES
lltransientdockablefloater.cpp
lltransientfloatermgr.cpp
lltranslate.cpp
+ lltwitterconnect.cpp
lluilistener.cpp
lluploaddialog.cpp
lluploadfloaterobservers.cpp
@@ -1028,6 +1034,7 @@ set(viewer_HEADER_FILES
llfilteredwearablelist.h
llfirstuse.h
llflexibleobject.h
+ llflickrconnect.h
llfloaterabout.h
llfloaterbvhpreview.h
llfloaterauction.h
@@ -1036,6 +1043,7 @@ set(viewer_HEADER_FILES
llfloateravatarpicker.h
llfloateravatartextures.h
llfloaterbeacons.h
+ llfloaterbigpreview.h
llfloaterbuildoptions.h
llfloaterbulkpermission.h
llfloaterbump.h
@@ -1057,6 +1065,8 @@ set(viewer_HEADER_FILES
llfloatereditwater.h
llfloaterenvironmentsettings.h
llfloaterevent.h
+ llfloaterfacebook.h
+ llfloaterflickr.h
llfloaterfonttest.h
llfloatergesture.h
llfloatergodtools.h
@@ -1112,7 +1122,6 @@ set(viewer_HEADER_FILES
llfloatersettingsdebug.h
llfloatersidepanelcontainer.h
llfloatersnapshot.h
- llfloatersocial.h
llfloatersounddevices.h
llfloaterspellchecksettings.h
llfloatertelehub.h
@@ -1124,6 +1133,7 @@ set(viewer_HEADER_FILES
llfloatertos.h
llfloatertoybox.h
llfloatertranslationsettings.h
+ llfloatertwitter.h
llfloateruipreview.h
llfloaterurlentry.h
llfloatervoiceeffect.h
@@ -1160,6 +1170,7 @@ set(viewer_HEADER_FILES
llhudrender.h
llhudtext.h
llhudview.h
+ llimagefiltersmanager.h
llimview.h
llinspect.h
llinspectavatar.h
@@ -1391,6 +1402,7 @@ set(viewer_HEADER_FILES
lltransientdockablefloater.h
lltransientfloatermgr.h
lltranslate.h
+ lltwitterconnect.h
lluiconstants.h
lluilistener.h
lluploaddialog.h
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 3ba6d2ef7b..b111f19479 100755
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -224,15 +224,35 @@
is_running_function="Floater.IsOpen"
is_running_parameters="snapshot"
/>
-
+
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/newview/app_settings/filters/BlackAndWhite.xml b/indra/newview/app_settings/filters/BlackAndWhite.xml
new file mode 100644
index 0000000000..101ed8233a
--- /dev/null
+++ b/indra/newview/app_settings/filters/BlackAndWhite.xml
@@ -0,0 +1,21 @@
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.8
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+
diff --git a/indra/newview/app_settings/filters/Colors1970.xml b/indra/newview/app_settings/filters/Colors1970.xml
new file mode 100644
index 0000000000..730d907fa7
--- /dev/null
+++ b/indra/newview/app_settings/filters/Colors1970.xml
@@ -0,0 +1,47 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.8
+ 1.0
+ 1.0
+ 1.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.3
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ blend
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 10.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.1
+ 0.1
+ 0.0
+
+
+
diff --git a/indra/newview/app_settings/filters/Intense.xml b/indra/newview/app_settings/filters/Intense.xml
new file mode 100644
index 0000000000..b77f07a037
--- /dev/null
+++ b/indra/newview/app_settings/filters/Intense.xml
@@ -0,0 +1,8 @@
+
+
+
+ saturate
+ 3.0
+
+
+
diff --git a/indra/newview/app_settings/filters/LensFlare.xml b/indra/newview/app_settings/filters/LensFlare.xml
new file mode 100644
index 0000000000..e9aef6eea4
--- /dev/null
+++ b/indra/newview/app_settings/filters/LensFlare.xml
@@ -0,0 +1,131 @@
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ gradient
+ add
+ 0.5
+ 0.0
+ -1.0
+ 1.0
+ 1.0
+ -1.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.1
+ 0.1
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ -1.0
+ 1.0
+ 1.5
+ 5.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.6
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ -1.0
+ 1.0
+ 1.0
+ 5.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.6
+ 0.6
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ 0.5
+ -0.5
+ 0.10
+ 20.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.7
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ 0.6
+ -0.6
+ 0.05
+ 20.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.7
+ 0.0
+ 0.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.5
+ 0.4
+ -0.4
+ 0.025
+ 20.0
+
+
+ colorize
+ 1.0
+ 1.0
+ 1.0
+ 0.7
+ 0.0
+ 0.0
+
+
+
diff --git a/indra/newview/app_settings/filters/Miniature.xml b/indra/newview/app_settings/filters/Miniature.xml
new file mode 100755
index 0000000000..9aa8a87c6f
--- /dev/null
+++ b/indra/newview/app_settings/filters/Miniature.xml
@@ -0,0 +1,118 @@
+
+
+
+ linearize
+ 0.02
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 1.02
+ 1.0
+ 1.0
+ 1.0
+
+
+ saturate
+ 1.2
+
+
+ stencil
+ vignette
+ blend
+ 0.0
+ 0.25
+ 0.0
+ 0.0
+ 0.25
+ 2.0
+
+
+ sharpen
+
+
+ stencil
+ gradient
+ blend
+ 1.0
+ 0.0
+ 0.0
+ -1.0
+ 0.0
+ -0.25
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ stencil
+ gradient
+ blend
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 0.0
+ 0.25
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+ blur
+
+
+
\ No newline at end of file
diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml
new file mode 100755
index 0000000000..6cfe319281
--- /dev/null
+++ b/indra/newview/app_settings/filters/Newspaper.xml
@@ -0,0 +1,20 @@
+
+
+
+ linearize
+ 0.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ screen
+ 2Dsine
+ 0.02
+ 0.0
+
+
+
diff --git a/indra/newview/app_settings/filters/Sepia.xml b/indra/newview/app_settings/filters/Sepia.xml
new file mode 100644
index 0000000000..3d577b2998
--- /dev/null
+++ b/indra/newview/app_settings/filters/Sepia.xml
@@ -0,0 +1,32 @@
+
+
+
+ linearize
+ 0.01
+ 1.0
+ 1.0
+ 1.0
+
+
+ contrast
+ 0.8
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ fade
+ 0.5
+ 1.0
+ 0.0
+ 0.0
+ 1.0
+ 4.0
+
+
+ sepia
+
+
+
diff --git a/indra/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml
new file mode 100644
index 0000000000..0e2e0ad68c
--- /dev/null
+++ b/indra/newview/app_settings/filters/Spotlight.xml
@@ -0,0 +1,47 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ add
+ 0.0
+ 0.4
+ 0.0
+ 0.0
+ 1.0
+ 2.0
+
+
+ contrast
+ 1.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ add
+ -0.8
+ 0.0
+ 0.0
+ 0.0
+ 1.0
+ 2.0
+
+
+ contrast
+ 1.0
+ 1.0
+ 1.0
+ 1.0
+
+
+
diff --git a/indra/newview/app_settings/filters/Toycamera.xml b/indra/newview/app_settings/filters/Toycamera.xml
new file mode 100755
index 0000000000..4e76f6b2fb
--- /dev/null
+++ b/indra/newview/app_settings/filters/Toycamera.xml
@@ -0,0 +1,46 @@
+
+
+
+ stencil
+ vignette
+ fade
+ 0.0
+ 1.0
+ 0.0
+ 0.0
+ 1.2
+ 3.0
+
+
+ linearize
+ 0.05
+ 1.0
+ 1.0
+ 1.0
+
+
+ grayscale
+
+
+ contrast
+ 1.1
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ vignette
+ blend
+ 1.0
+ 0.0
+ 0.0
+ 0.0
+ 0.5
+ 2.0
+
+
+ blur
+
+
+
\ No newline at end of file
diff --git a/indra/newview/app_settings/filters/Video.xml b/indra/newview/app_settings/filters/Video.xml
new file mode 100755
index 0000000000..fe17f3950a
--- /dev/null
+++ b/indra/newview/app_settings/filters/Video.xml
@@ -0,0 +1,44 @@
+
+
+
+ linearize
+ 0.0
+ 1.0
+ 1.0
+ 1.0
+
+
+ darken
+ 0.15
+ 1.0
+ 1.0
+ 1.0
+
+
+ stencil
+ uniform
+ add
+ 0.0
+ 0.5
+
+
+ screen
+ line
+ 0.02
+ 0.0
+
+
+ gamma
+ 0.25
+ 1.0
+ 1.0
+ 1.0
+
+
+ blur
+
+
+ blur
+
+
+
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 7756b49a62..d6b395967c 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14313,6 +14313,17 @@ Change of this parameter will affect the layout of buttons in notification toast
Value
0
+ SnapshotFiltersEnabled
+
SnapshotFormat