From 54ad7de61b5be2014c2e061a4964b7d6620a5dd4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 13 Jan 2014 17:01:44 -0800 Subject: ACME-1244 : Introduced llimage/llimagefilter, refactored the filter execution code, simplified llimage_libtest filter testing --- indra/llimage/llimagefilter.cpp | 269 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100755 indra/llimage/llimagefilter.cpp (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp new file mode 100755 index 0000000000..e2d281e48d --- /dev/null +++ b/indra/llimage/llimagefilter.cpp @@ -0,0 +1,269 @@ +/** + * @file llimagefilter.cpp + * @brief Simple Image Filtering. + * + * $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" + +//--------------------------------------------------------------------------- +// LLImageFilter +//--------------------------------------------------------------------------- + +LLImageFilter::LLImageFilter() : + mFilterData(LLSD::emptyArray()) +{ +} + +LLImageFilter::~LLImageFilter() +{ +} + +/* + " -f, --filter []\n" + " Apply the filter to the input images using the optional value. Admissible names:\n" + " - 'grayscale' converts to grayscale (no param).\n" + " - 'sepia' converts to sepia (no param).\n" + " - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" + " - 'rotate' rotates the color hue according to (in degree, positive value only).\n" + " - 'gamma' applies gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" + " - 'colorize' applies a red tint to the image using as an alpha (transparency between 0.0 and 1.0) value.\n" + " - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" + " - 'brighten' adds light to the image ( between 0 and 255).\n" + " - 'darken' substracts light to the image ( between 0 and 255).\n" + " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" + " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" + " - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n" + " - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n" + " - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" + " - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" + " - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" + " -v, --vignette [ ]\n" + " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" + " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" + " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" + + // Set the vignette if any + if (vignette_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); + } + else if (vignette_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); + } + + // Apply filter if any + if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } + else if (filter_name == "saturate") + { + raw_image->filterSaturate((float)(filter_param)); + } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(filter_param)); + } + else if (filter_name == "gamma") + { + raw_image->filterGamma((float)(filter_param),LLColor3::white); + } + else if (filter_name == "colorize") + { + // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter + LLColor3 color(1.0,0.0,0.0); + LLColor3 alpha((F32)(filter_param),0.0,0.0); + raw_image->filterColorize(color,alpha); + } + else if (filter_name == "contrast") + { + raw_image->filterContrast((float)(filter_param),LLColor3::white); + } + else if (filter_name == "brighten") + { + raw_image->filterBrightness((S32)(filter_param),LLColor3::white); + } + else if (filter_name == "darken") + { + raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); + } + else if (filter_name == "linearize") + { + raw_image->filterLinearize((float)(filter_param),LLColor3::white); + } + else if (filter_name == "posterize") + { + raw_image->filterEqualize((S32)(filter_param),LLColor3::white); + } + else if (filter_name == "newsscreen") + { + raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0); + } + else if (filter_name == "horizontalscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0); + } + else if (filter_name == "verticalscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0); + } + else if (filter_name == "slantedscreen") + { + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); + } + + */ + +// Load filter from file +void LLImageFilter::loadFromFile(const std::string& file_path) +{ + //std::cout << "Loading filter settings from : " << file_path << std::endl; + 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(); + } + else + { + // File couldn't be open, reset the filter data + mFilterData = LLSD(); + } +} + +// Apply the filter data to the image passed as parameter +void LLImageFilter::executeFilter(LLPointer 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; + + // Execute the filter described on this line + if (filter_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + } + else if (filter_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + } + else if (filter_name == "lines") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + } + else if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } + else if (filter_name == "saturate") + { + raw_image->filterSaturate((float)(mFilterData[i][1].asReal())); + } + else if (filter_name == "rotate") + { + raw_image->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())); + raw_image->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())); + raw_image->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())); + raw_image->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())); + raw_image->filterBrightness((S32)(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())); + raw_image->filterBrightness((S32)(-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())); + raw_image->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())); + raw_image->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; + } + raw_image->filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); + } + } +} + + +//============================================================================ -- cgit v1.3 From 7cc64a09a3ca9211354427206f04d157c9ac30a2 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 14 Jan 2014 21:01:51 -0800 Subject: ACME-1236 : Refactor filters and vignette into llimagefilter, add example filters to llimage_libtest --- .../llimage_libtest/1970colorize.xml | 41 ++ .../integration_tests/llimage_libtest/brighten.xml | 11 + .../integration_tests/llimage_libtest/colorize.xml | 20 + .../integration_tests/llimage_libtest/contrast.xml | 18 + indra/integration_tests/llimage_libtest/darken.xml | 11 + indra/integration_tests/llimage_libtest/gamma.xml | 18 + .../llimage_libtest/grayscale.xml | 14 + .../llimage_libtest/horizontalscreen.xml | 25 + .../llimage_libtest/linearize.xml | 11 + .../llimage_libtest/newsscreen.xml | 25 + .../llimage_libtest/posterize.xml | 18 + .../llimage_libtest/rotatecolors180.xml | 8 + .../integration_tests/llimage_libtest/saturate.xml | 8 + indra/integration_tests/llimage_libtest/sepia.xml | 14 + .../llimage_libtest/slantedscreen.xml | 25 + .../llimage_libtest/spotlight.xml | 45 ++ .../llimage_libtest/verticalscreen.xml | 25 + indra/integration_tests/llimage_libtest/video.xml | 23 + indra/llimage/llimage.cpp | 527 +---------------- indra/llimage/llimage.h | 61 -- indra/llimage/llimagefilter.cpp | 641 ++++++++++++++++++--- indra/llimage/llimagefilter.h | 50 +- 22 files changed, 956 insertions(+), 683 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/1970colorize.xml create mode 100755 indra/integration_tests/llimage_libtest/brighten.xml create mode 100644 indra/integration_tests/llimage_libtest/colorize.xml create mode 100644 indra/integration_tests/llimage_libtest/contrast.xml create mode 100755 indra/integration_tests/llimage_libtest/darken.xml create mode 100644 indra/integration_tests/llimage_libtest/gamma.xml create mode 100644 indra/integration_tests/llimage_libtest/grayscale.xml create mode 100644 indra/integration_tests/llimage_libtest/horizontalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/linearize.xml create mode 100755 indra/integration_tests/llimage_libtest/newsscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/posterize.xml create mode 100644 indra/integration_tests/llimage_libtest/rotatecolors180.xml create mode 100644 indra/integration_tests/llimage_libtest/saturate.xml create mode 100644 indra/integration_tests/llimage_libtest/sepia.xml create mode 100644 indra/integration_tests/llimage_libtest/slantedscreen.xml create mode 100644 indra/integration_tests/llimage_libtest/spotlight.xml create mode 100644 indra/integration_tests/llimage_libtest/verticalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/video.xml (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/integration_tests/llimage_libtest/1970colorize.xml b/indra/integration_tests/llimage_libtest/1970colorize.xml new file mode 100644 index 0000000000..0dab2489a0 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/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/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml new file mode 100755 index 0000000000..d17b96d2d7 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/brighten.xml @@ -0,0 +1,11 @@ + + + + brighten + 50.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml new file mode 100644 index 0000000000..18c6cd3425 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/colorize.xml @@ -0,0 +1,20 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.2 + 0.0 + 0.2 + + + diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml new file mode 100644 index 0000000000..8dcdd1a9a9 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/contrast.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + contrast + 1.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml new file mode 100755 index 0000000000..8d110452e9 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/darken.xml @@ -0,0 +1,11 @@ + + + + darken + 50.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml new file mode 100644 index 0000000000..7505a03027 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/gamma.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + gamma + 1.5 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/grayscale.xml b/indra/integration_tests/llimage_libtest/grayscale.xml new file mode 100644 index 0000000000..984312c4fd --- /dev/null +++ b/indra/integration_tests/llimage_libtest/grayscale.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + grayscale + + + diff --git a/indra/integration_tests/llimage_libtest/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/horizontalscreen.xml new file mode 100644 index 0000000000..ddff4d1977 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/horizontalscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/linearize.xml b/indra/integration_tests/llimage_libtest/linearize.xml new file mode 100755 index 0000000000..23d0290e07 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/linearize.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/newsscreen.xml b/indra/integration_tests/llimage_libtest/newsscreen.xml new file mode 100755 index 0000000000..8247c34500 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/newsscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + 2Dsine + 5.0 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/posterize.xml b/indra/integration_tests/llimage_libtest/posterize.xml new file mode 100755 index 0000000000..f026278f9e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/posterize.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + posterize + 10.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/rotatecolors180.xml new file mode 100644 index 0000000000..e25029720f --- /dev/null +++ b/indra/integration_tests/llimage_libtest/rotatecolors180.xml @@ -0,0 +1,8 @@ + + + + rotate + 180.0 + + + diff --git a/indra/integration_tests/llimage_libtest/saturate.xml b/indra/integration_tests/llimage_libtest/saturate.xml new file mode 100644 index 0000000000..b77f07a037 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/saturate.xml @@ -0,0 +1,8 @@ + + + + saturate + 3.0 + + + diff --git a/indra/integration_tests/llimage_libtest/sepia.xml b/indra/integration_tests/llimage_libtest/sepia.xml new file mode 100644 index 0000000000..0304ead015 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/sepia.xml @@ -0,0 +1,14 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + sepia + + + diff --git a/indra/integration_tests/llimage_libtest/slantedscreen.xml b/indra/integration_tests/llimage_libtest/slantedscreen.xml new file mode 100644 index 0000000000..63ad01d51d --- /dev/null +++ b/indra/integration_tests/llimage_libtest/slantedscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 45.0 + + + diff --git a/indra/integration_tests/llimage_libtest/spotlight.xml b/indra/integration_tests/llimage_libtest/spotlight.xml new file mode 100644 index 0000000000..203130bdee --- /dev/null +++ b/indra/integration_tests/llimage_libtest/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/verticalscreen.xml b/indra/integration_tests/llimage_libtest/verticalscreen.xml new file mode 100644 index 0000000000..71e48df656 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/verticalscreen.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + grayscale + + + blend + 0.0 + 0.0 + + + screen + line + 5.0 + 90.0 + + + diff --git a/indra/integration_tests/llimage_libtest/video.xml b/indra/integration_tests/llimage_libtest/video.xml new file mode 100755 index 0000000000..8b10687ef5 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/video.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + lines + 10.0 + 0.0 + + + brighten + 100.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 3105fe3746..7981ca7364 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -98,14 +98,7 @@ LLImageBase::LLImageBase() mHeight(0), mComponents(0), mBadBufferAllocation(false), - mAllowOverSize(false), - mHistoRed(NULL), - mHistoGreen(NULL), - mHistoBlue(NULL), - mHistoBrightness(NULL), - mVignetteMode(VIGNETTE_MODE_NONE), - mVignetteGamma(1.0), - mVignetteMin(0.0) + mAllowOverSize(false) { } @@ -113,10 +106,6 @@ LLImageBase::LLImageBase() LLImageBase::~LLImageBase() { deleteData(); // virtual - ll_aligned_free_16(mHistoRed); - ll_aligned_free_16(mHistoGreen); - ll_aligned_free_16(mHistoBlue); - ll_aligned_free_16(mHistoBrightness); } //static @@ -947,520 +936,6 @@ BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) return TRUE ; } -// Filter Operations -void LLImageRaw::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 LLImageRaw::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 LLImageRaw::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 LLImageRaw::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 LLImageRaw::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,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 LLImageRaw::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 LLImageRaw::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 LLImageRaw::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 LLImageRaw::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 LLImageRaw::filterBrightness(S32 add, const LLColor3& alpha) -{ - U8 brightness_red_lut[256]; - U8 brightness_green_lut[256]; - U8 brightness_blue_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - U8 value_i = (U8)(llclampb((S32)((S32)(i) + add))); - // 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); -} - -// Filter Primitives -void LLImageRaw::colorTransform(const LLMatrix3 &transform) -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - S32 width = getWidth(); - S32 height = getHeight(); - - U8* dst_data = getData(); - for (S32 j = 0; j < height; j++) - { - for (S32 i = 0; i < width; i++) - { - LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); - LLVector3 dst = src * transform; - dst.clamp(0.0f,255.0f); - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst.mV[VRED]; - dst_data[VGREEN] = dst.mV[VGREEN]; - dst_data[VBLUE] = dst.mV[VBLUE]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; - dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst.mV[VRED]; - dst_data[VGREEN] = alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = alpha * dst.mV[VBLUE]; - } - } - dst_data += components; - } - } -} - -void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue) -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - S32 width = getWidth(); - S32 height = getHeight(); - - U8* dst_data = getData(); - for (S32 j = 0; j < height; j++) - { - for (S32 i = 0; i < width; i++) - { - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = lut_red[dst_data[VRED]]; - dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = alpha * lut_blue[dst_data[VBLUE]]; - } - } - dst_data += components; - } - } -} - -void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) -{ - const S32 components = getComponents(); - llassert( components >= 1 && components <= 4 ); - - S32 width = getWidth(); - S32 height = getHeight(); - - F32 sin = sinf(angle*DEG_TO_RAD); - F32 cos = cosf(angle*DEG_TO_RAD); - - U8* dst_data = getData(); - for (S32 j = 0; j < height; j++) - { - for (S32 i = 0; i < width; i++) - { - F32 value = 0.0; - F32 d = 0.0; - switch (mode) - { - case SCREEN_MODE_2DSINE: - value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; - break; - case SCREEN_MODE_LINE: - d = sin*i - cos*j; - value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; - break; - } - U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); - - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst_value; - dst_data[VGREEN] = dst_value; - dst_data[VBLUE] = dst_value; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst_value; - dst_data[VGREEN] = alpha * dst_value; - dst_data[VBLUE] = alpha * dst_value; - } - } - dst_data += components; - } - } -} - -void LLImageRaw::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) -{ - mVignetteMode = mode; - mVignetteType = type; - mVignetteGamma = gamma; - mVignetteMin = llclampf(min); - // We always center the vignette on the image and fits it in the image smallest dimension - mVignetteCenterX = getWidth()/2; - mVignetteCenterY = getHeight()/2; - mVignetteWidth = llmin(getWidth()/2,getHeight()/2); -} - -F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) -{ - F32 alpha = 1.0; - if (mVignetteType == VIGNETTE_TYPE_CENTER) - { - // 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 - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); - alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); - } - else if (mVignetteType == VIGNETTE_TYPE_LINES) - { - // alpha varies according to a squared sine function vertically. - // gamma is interpreted as the wavelength (in pixels) of the sine in that case. - alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); - } - // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. - return (mVignetteMin + alpha * (1.0 - mVignetteMin)); -} - -U32* LLImageRaw::getBrightnessHistogram() -{ - if (!mHistoBrightness) - { - computeHistograms(); - } - return mHistoBrightness; -} - -void LLImageRaw::computeHistograms() -{ - const S32 components = 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 = getWidth() * getHeight(); - U8* dst_data = 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; - } -} - void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step ) { const S32 components = getComponents(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index a600f2e4a6..4b1da233e1 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -88,25 +88,6 @@ typedef enum e_image_codec IMG_CODEC_EOF = 8 } EImageCodec; -typedef enum e_vignette_mode -{ - VIGNETTE_MODE_NONE = 0, - VIGNETTE_MODE_BLEND = 1, - VIGNETTE_MODE_FADE = 2 -} EVignetteMode; - -typedef enum e_vignette_type -{ - VIGNETTE_TYPE_CENTER = 0, - VIGNETTE_TYPE_LINES = 1 -} EVignetteType; - -typedef enum e_screen_mode -{ - SCREEN_MODE_2DSINE = 0, - SCREEN_MODE_LINE = 1 -} EScreenMode; - //============================================================================ // library initialization class @@ -171,21 +152,6 @@ protected: // special accessor to allow direct setting of mData and mDataSize by LLImageFormatted void setDataAndSize(U8 *data, S32 size); - // Histograms (if we ever happen to need them) - U32 *mHistoRed; - U32 *mHistoGreen; - U32 *mHistoBlue; - U32 *mHistoBrightness; - - // Vignette filtering - EVignetteMode mVignetteMode; - EVignetteType mVignetteType; - S32 mVignetteCenterX; - S32 mVignetteCenterY; - S32 mVignetteWidth; - F32 mVignetteGamma; - F32 mVignetteMin; - public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -291,30 +257,6 @@ public: // Src and dst are same size. Src has 4 components. Dst has 3 components. void compositeUnscaled4onto3( LLImageRaw* src ); - - // 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(S32 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 S32 wave_length, const F32 angle); - void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); - U32* getBrightnessHistogram(); protected: // Create an image from a local file (generally used in tools) @@ -327,9 +269,6 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; - void computeHistograms(); - F32 getVignetteAlpha(S32 i, S32 j); - public: static S32 sGlobalRawMemory; static S32 sRawImageCount; diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index e2d281e48d..ed97d9ae17 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -40,16 +40,28 @@ //--------------------------------------------------------------------------- LLImageFilter::LLImageFilter() : - mFilterData(LLSD::emptyArray()) + mFilterData(LLSD::emptyArray()), + mImage(NULL), + mHistoRed(NULL), + mHistoGreen(NULL), + mHistoBlue(NULL), + mHistoBrightness(NULL), + mVignetteMode(VIGNETTE_MODE_NONE), + mVignetteGamma(1.0), + mVignetteMin(0.0) { } LLImageFilter::~LLImageFilter() { + mImage = NULL; + ll_aligned_free_16(mHistoRed); + ll_aligned_free_16(mHistoGreen); + ll_aligned_free_16(mHistoBlue); + ll_aligned_free_16(mHistoBrightness); } /* - " -f, --filter []\n" " Apply the filter to the input images using the optional value. Admissible names:\n" " - 'grayscale' converts to grayscale (no param).\n" " - 'sepia' converts to sepia (no param).\n" @@ -67,86 +79,10 @@ LLImageFilter::~LLImageFilter() " - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" " - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" " - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" - " -v, --vignette [ ]\n" + " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" - - // Set the vignette if any - if (vignette_name == "blend") - { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); - } - else if (vignette_name == "fade") - { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); - } - - // Apply filter if any - if (filter_name == "sepia") - { - raw_image->filterSepia(); - } - else if (filter_name == "grayscale") - { - raw_image->filterGrayScale(); - } - else if (filter_name == "saturate") - { - raw_image->filterSaturate((float)(filter_param)); - } - else if (filter_name == "rotate") - { - raw_image->filterRotate((float)(filter_param)); - } - else if (filter_name == "gamma") - { - raw_image->filterGamma((float)(filter_param),LLColor3::white); - } - else if (filter_name == "colorize") - { - // For testing, we just colorize in the red channel, modulate by the alpha passed as a parameter - LLColor3 color(1.0,0.0,0.0); - LLColor3 alpha((F32)(filter_param),0.0,0.0); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "contrast") - { - raw_image->filterContrast((float)(filter_param),LLColor3::white); - } - else if (filter_name == "brighten") - { - raw_image->filterBrightness((S32)(filter_param),LLColor3::white); - } - else if (filter_name == "darken") - { - raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); - } - else if (filter_name == "linearize") - { - raw_image->filterLinearize((float)(filter_param),LLColor3::white); - } - else if (filter_name == "posterize") - { - raw_image->filterEqualize((S32)(filter_param),LLColor3::white); - } - else if (filter_name == "newsscreen") - { - raw_image->filterScreen(SCREEN_MODE_2DSINE,(S32)(filter_param),0.0); - } - else if (filter_name == "horizontalscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),0.0); - } - else if (filter_name == "verticalscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),90.0); - } - else if (filter_name == "slantedscreen") - { - raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); - } - */ // Load filter from file @@ -171,6 +107,8 @@ void LLImageFilter::loadFromFile(const std::string& file_path) // 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) { @@ -186,67 +124,67 @@ void LLImageFilter::executeFilter(LLPointer raw_image) // Execute the filter described on this line if (filter_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); } else if (filter_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); } else if (filter_name == "lines") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); } else if (filter_name == "sepia") { - raw_image->filterSepia(); + filterSepia(); } else if (filter_name == "grayscale") { - raw_image->filterGrayScale(); + filterGrayScale(); } else if (filter_name == "saturate") { - raw_image->filterSaturate((float)(mFilterData[i][1].asReal())); + filterSaturate((float)(mFilterData[i][1].asReal())); } else if (filter_name == "rotate") { - raw_image->filterRotate((float)(mFilterData[i][1].asReal())); + 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())); - raw_image->filterGamma((float)(mFilterData[i][1].asReal()),color); + 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())); - raw_image->filterColorize(color,alpha); + 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())); - raw_image->filterContrast((float)(mFilterData[i][1].asReal()),color); + 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())); - raw_image->filterBrightness((S32)(mFilterData[i][1].asReal()),color); + filterBrightness((S32)(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())); - raw_image->filterBrightness((S32)(-mFilterData[i][1].asReal()),color); + filterBrightness((S32)(-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())); - raw_image->filterLinearize((float)(mFilterData[i][1].asReal()),color); + 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())); - raw_image->filterEqualize((S32)(mFilterData[i][1].asReal()),color); + filterEqualize((S32)(mFilterData[i][1].asReal()),color); } else if (filter_name == "screen") { @@ -260,10 +198,525 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mode = SCREEN_MODE_LINE; } - raw_image->filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); + filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); } } } +// Filter Primitives +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++) + { + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = lut_red[dst_data[VRED]]; + dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; + dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; + dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = alpha * 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++) + { + LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); + LLVector3 dst = src * transform; + dst.clamp(0.0f,255.0f); + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = dst.mV[VRED]; + dst_data[VGREEN] = dst.mV[VGREEN]; + dst_data[VBLUE] = dst.mV[VBLUE]; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; + dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; + dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * dst.mV[VRED]; + dst_data[VGREEN] = alpha * dst.mV[VGREEN]; + dst_data[VBLUE] = alpha * dst.mV[VBLUE]; + } + } + dst_data += components; + } + } +} + +void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) +{ + const S32 components = mImage->getComponents(); + llassert( components >= 1 && components <= 4 ); + + S32 width = mImage->getWidth(); + S32 height = mImage->getHeight(); + + F32 sin = sinf(angle*DEG_TO_RAD); + F32 cos = cosf(angle*DEG_TO_RAD); + + U8* dst_data = mImage->getData(); + for (S32 j = 0; j < height; j++) + { + for (S32 i = 0; i < width; i++) + { + F32 value = 0.0; + F32 d = 0.0; + switch (mode) + { + case SCREEN_MODE_2DSINE: + value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + break; + case SCREEN_MODE_LINE: + d = sin*i - cos*j; + value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; + break; + } + U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); + + if (mVignetteMode == VIGNETTE_MODE_NONE) + { + dst_data[VRED] = dst_value; + dst_data[VGREEN] = dst_value; + dst_data[VBLUE] = dst_value; + } + else + { + F32 alpha = getVignetteAlpha(i,j); + if (mVignetteMode == VIGNETTE_MODE_BLEND) + { + // Blends with the source image on the edges + F32 inv_alpha = 1.0 - alpha; + dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; + dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; + dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; + } + else // VIGNETTE_MODE_FADE + { + // Fade to black on the edges + dst_data[VRED] = alpha * dst_value; + dst_data[VGREEN] = alpha * dst_value; + dst_data[VBLUE] = alpha * dst_value; + } + } + dst_data += components; + } + } +} + +// Procedural Stencils +void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) +{ + mVignetteMode = mode; + mVignetteType = type; + mVignetteGamma = gamma; + mVignetteMin = llclampf(min); + // We always center the vignette on the image and fits it in the image smallest dimension + mVignetteCenterX = mImage->getWidth()/2; + mVignetteCenterY = mImage->getHeight()/2; + mVignetteWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); +} + +F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j) +{ + F32 alpha = 1.0; + if (mVignetteType == VIGNETTE_TYPE_CENTER) + { + // 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 - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); + alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + } + else if (mVignetteType == VIGNETTE_TYPE_LINES) + { + // alpha varies according to a squared sine function vertically. + // gamma is interpreted as the wavelength (in pixels) of the sine in that case. + alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); + } + // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. + return (mVignetteMin + alpha * (1.0 - mVignetteMin)); +} + +// 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,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(S32 add, const LLColor3& alpha) +{ + U8 brightness_red_lut[256]; + U8 brightness_green_lut[256]; + U8 brightness_blue_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + U8 value_i = (U8)(llclampb((S32)((S32)(i) + add))); + // 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 index 5598fa69f5..c67789ede0 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -29,7 +29,6 @@ #include "llimage.h" -/* class LLImageRaw; class LLColor4U; class LLColor3; @@ -53,7 +52,7 @@ typedef enum e_screen_mode SCREEN_MODE_2DSINE = 0, SCREEN_MODE_LINE = 1 } EScreenMode; -*/ + //============================================================================ // Image Filter @@ -65,8 +64,55 @@ public: void loadFromFile(const std::string& file_path); 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(S32 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 S32 wave_length, const F32 angle); + + // Procedural Stencils + void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); + F32 getVignetteAlpha(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; + + // Vignette filtering + EVignetteMode mVignetteMode; + EVignetteType mVignetteType; + S32 mVignetteCenterX; + S32 mVignetteCenterY; + S32 mVignetteWidth; + F32 mVignetteGamma; + F32 mVignetteMin; }; -- cgit v1.3 From f1229912280fe67b272f5c1ba424524d738ed867 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 15 Jan 2014 09:24:06 -0800 Subject: ACME-1236 : Add comments to LLImageFilter --- indra/llimage/llimagefilter.cpp | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index ed97d9ae17..5c969001b7 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -62,6 +62,34 @@ LLImageFilter::~LLImageFilter() } /* + *TODO + * Rename vignette to stencil + * Separate shape from mode + * Add shapes : uniform and gradients + * Add modes + * Add stencil (min,max) range + * Suppress alpha from colorcorrect and use uniform alpha instead + * Refactor stencil composition in the filter primitives + + + stencil + shape + blend_mode + min + max + param1 + param2 + param3 + param4 + + + vignette : center_x, center_y, width, feather + sine : wavelength, angle + flat + gradient : start_x, start_y, end_x, end_y + + * Document all the admissible names in the wiki + " Apply the filter to the input images using the optional value. Admissible names:\n" " - 'grayscale' converts to grayscale (no param).\n" " - 'sepia' converts to sepia (no param).\n" @@ -85,7 +113,10 @@ LLImageFilter::~LLImageFilter() " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" */ +//============================================================================ // Load filter from file +//============================================================================ + void LLImageFilter::loadFromFile(const std::string& file_path) { //std::cout << "Loading filter settings from : " << file_path << std::endl; @@ -104,7 +135,10 @@ void LLImageFilter::loadFromFile(const std::string& file_path) } } +//============================================================================ // Apply the filter data to the image passed as parameter +//============================================================================ + void LLImageFilter::executeFilter(LLPointer raw_image) { mImage = raw_image; @@ -203,7 +237,10 @@ void LLImageFilter::executeFilter(LLPointer raw_image) } } +//============================================================================ // Filter Primitives +//============================================================================ + void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue) { const S32 components = mImage->getComponents(); @@ -353,7 +390,10 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const } } +//============================================================================ // Procedural Stencils +//============================================================================ + void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) { mVignetteMode = mode; @@ -386,7 +426,10 @@ F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j) return (mVignetteMin + alpha * (1.0 - mVignetteMin)); } +//============================================================================ // Histograms +//============================================================================ + U32* LLImageFilter::getBrightnessHistogram() { if (!mHistoBrightness) @@ -444,7 +487,10 @@ void LLImageFilter::computeHistograms() } } +//============================================================================ // Secondary Filters +//============================================================================ + void LLImageFilter::filterGrayScale() { LLMatrix3 gray_scale; -- cgit v1.3 From fda7b94f490564568dee0ba6d6516943b0fd82a0 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 16 Jan 2014 18:34:51 -0800 Subject: ACME-1236 : Small LLImageFilter clean up --- .../llimage_libtest/llimage_libtest.cpp | 14 ++++----- indra/llimage/llimagefilter.cpp | 33 +++++++--------------- indra/llimage/llimagefilter.h | 6 ++-- indra/newview/llfloaterflickr.cpp | 2 -- indra/newview/llsnapshotlivepreview.cpp | 6 ++-- 5 files changed, 21 insertions(+), 40 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index d3373a61f2..3d27b4a5b5 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -578,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(); @@ -594,13 +597,8 @@ int main(int argc, char** argv) continue; } - if (filter_name != "") - { - // We're interpreting the filter as a filter file name - LLImageFilter filter; - filter.loadFromFile(filter_name); - filter.executeFilter(raw_image); - } + // Apply the filter + filter.executeFilter(raw_image); // Save file if (out_file != out_end) diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 5c969001b7..cd03454cdd 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -39,7 +39,7 @@ // LLImageFilter //--------------------------------------------------------------------------- -LLImageFilter::LLImageFilter() : +LLImageFilter::LLImageFilter(const std::string& file_path) : mFilterData(LLSD::emptyArray()), mImage(NULL), mHistoRed(NULL), @@ -50,6 +50,15 @@ LLImageFilter::LLImageFilter() : mVignetteGamma(1.0), mVignetteMin(0.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() @@ -113,28 +122,6 @@ LLImageFilter::~LLImageFilter() " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" */ -//============================================================================ -// Load filter from file -//============================================================================ - -void LLImageFilter::loadFromFile(const std::string& file_path) -{ - //std::cout << "Loading filter settings from : " << file_path << std::endl; - 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(); - } - else - { - // File couldn't be open, reset the filter data - mFilterData = LLSD(); - } -} - //============================================================================ // Apply the filter data to the image passed as parameter //============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index c67789ede0..dc092a47a5 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -54,15 +54,15 @@ typedef enum e_screen_mode } EScreenMode; //============================================================================ -// Image Filter +// LLImageFilter +//============================================================================ class LLImageFilter { public: - LLImageFilter(); + LLImageFilter(const std::string& file_path); ~LLImageFilter(); - void loadFromFile(const std::string& file_path); void executeFilter(LLPointer raw_image); private: diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index cff57bfa13..c34124caf5 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -334,7 +334,6 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) S32 height = sdres[1]; const std::string& filter_name = filterbox->getSimple(); - llinfos << "Merov : filter name is : " << filter_name << llendl; LLSnapshotLivePreview * previewp = static_cast(mPreviewHandle.get()); if (previewp && combobox->getCurrentIndex() >= 0) @@ -358,7 +357,6 @@ void LLFlickrPhotoPanel::updateResolution(BOOL do_update) checkAspectRatio(width); previewp->getSize(width, height); - // Merov : // Get the old filter, compare to the current one "filter_name" and set if changed // If changed, also force the updateSnapshot() here under std::string original_filter = previewp->getFilter(); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 21abdd2675..ee74dbdb0f 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -594,8 +594,7 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); if (filter_path != "") { - LLImageFilter filter; - filter.loadFromFile(filter_path); + LLImageFilter filter(filter_path); filter.executeFilter(raw); } else @@ -713,8 +712,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(previewp->getFilter()); if (filter_path != "") { - LLImageFilter filter; - filter.loadFromFile(filter_path); + LLImageFilter filter(filter_path); filter.executeFilter(previewp->mPreviewImage); } else -- cgit v1.3 From 95bb14440e4e35c7cc5c44a2b836deadb54bfd1b Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 17 Jan 2014 16:50:35 -0800 Subject: ACME-1236 : Refactor vignette into stencil, implement uniform and gradient stencils, implement dodge and add blend modes --- indra/llimage/llimagefilter.cpp | 308 +++++++++++++++++++++++++--------------- indra/llimage/llimagefilter.h | 55 ++++--- 2 files changed, 226 insertions(+), 137 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index cd03454cdd..03eabce8e3 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -46,9 +46,11 @@ LLImageFilter::LLImageFilter(const std::string& file_path) : mHistoGreen(NULL), mHistoBlue(NULL), mHistoBrightness(NULL), - mVignetteMode(VIGNETTE_MODE_NONE), - mVignetteGamma(1.0), - mVignetteMin(0.0) + 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); @@ -79,23 +81,13 @@ LLImageFilter::~LLImageFilter() * Add stencil (min,max) range * Suppress alpha from colorcorrect and use uniform alpha instead * Refactor stencil composition in the filter primitives + * Make filter definition resolution independent (do not use pixel size anywhere) - - stencil - shape - blend_mode - min - max - param1 - param2 - param3 - param4 - - - vignette : center_x, center_y, width, feather - sine : wavelength, angle - flat - gradient : start_x, start_y, end_x, end_y + params: + * vignette : center_x, center_y, width, feather + * scan lines : wavelength, angle + * uniform + * gradient : start_x, start_y, end_x, end_y * Document all the admissible names in the wiki @@ -143,17 +135,86 @@ void LLImageFilter::executeFilter(LLPointer raw_image) //std::cout << std::endl; // Execute the filter described on this line - if (filter_name == "blend") + /* + + stencil + shape uniform / gradient / vignette / scanlines + blend_mode blend /add /dodge / fade + min -1.0 to 1.0 (mandatory though ignored for uniform shape) + max -1.0 to 1.0 (value for uniform) + param1 + param2 + param3 + param4 + + params: + * vignette : center_x, center_y, width, feather : positions between in float (0.0 is center, 1.0 is top), width in float in same unit, feather is a float + * scan lines : wavelength, angle : wavelength in float assuming (height/2 = 1), angle float in degree + * uniform : all parameters ignored + * gradient : start_x, start_y, end_x, end_y : position in float (0.0 is center, 1.0 is top) + */ + if (filter_name == "stencil") { - setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + // 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 alpha + 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 == "dodge") + { + mode = STENCIL_BLEND_MODE_DODGE; + } + 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 == "blend") + { + setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); } else if (filter_name == "fade") { - setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setStencil(STENCIL_BLEND_MODE_FADE,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); } else if (filter_name == "lines") { - setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal())); + setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_SCAN_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); } else if (filter_name == "sepia") { @@ -228,6 +289,38 @@ void LLImageFilter::executeFilter(LLPointer raw_image) // 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] = pixel[VRED] + alpha * red; + pixel[VGREEN] = pixel[VGREEN] + alpha * green; + pixel[VBLUE] = pixel[VBLUE] + alpha * blue; + break; + case STENCIL_BLEND_MODE_DODGE: + // Dodge/burn the incoming color onto the background image + pixel[VRED] = inv_alpha * pixel[VRED] + red; + pixel[VGREEN] = inv_alpha * pixel[VGREEN] + green; + pixel[VBLUE] = 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(); @@ -241,31 +334,8 @@ void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U { for (S32 i = 0; i < width; i++) { - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = lut_red[dst_data[VRED]]; - dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * lut_blue[dst_data[VBLUE]]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * lut_red[dst_data[VRED]]; - dst_data[VGREEN] = alpha * lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = alpha * lut_blue[dst_data[VBLUE]]; - } - } + // 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; } } @@ -284,34 +354,13 @@ void LLImageFilter::colorTransform(const LLMatrix3 &transform) { 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); - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst.mV[VRED]; - dst_data[VGREEN] = dst.mV[VGREEN]; - dst_data[VBLUE] = dst.mV[VBLUE]; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * src.mV[VRED] + alpha * dst.mV[VRED]; - dst_data[VGREEN] = inv_alpha * src.mV[VGREEN] + alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = inv_alpha * src.mV[VBLUE] + alpha * dst.mV[VBLUE]; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst.mV[VRED]; - dst_data[VGREEN] = alpha * dst.mV[VGREEN]; - dst_data[VBLUE] = alpha * dst.mV[VBLUE]; - } - } + + // Blend result + blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]); dst_data += components; } } @@ -333,6 +382,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const { for (S32 i = 0; i < width; i++) { + // Compute screen value F32 value = 0.0; F32 d = 0.0; switch (mode) @@ -347,31 +397,8 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const } U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); - if (mVignetteMode == VIGNETTE_MODE_NONE) - { - dst_data[VRED] = dst_value; - dst_data[VGREEN] = dst_value; - dst_data[VBLUE] = dst_value; - } - else - { - F32 alpha = getVignetteAlpha(i,j); - if (mVignetteMode == VIGNETTE_MODE_BLEND) - { - // Blends with the source image on the edges - F32 inv_alpha = 1.0 - alpha; - dst_data[VRED] = inv_alpha * dst_data[VRED] + alpha * dst_value; - dst_data[VGREEN] = inv_alpha * dst_data[VGREEN] + alpha * dst_value; - dst_data[VBLUE] = inv_alpha * dst_data[VBLUE] + alpha * dst_value; - } - else // VIGNETTE_MODE_FADE - { - // Fade to black on the edges - dst_data[VRED] = alpha * dst_value; - dst_data[VGREEN] = alpha * dst_value; - dst_data[VBLUE] = alpha * dst_value; - } - } + // Blend result + blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value); dst_data += components; } } @@ -381,36 +408,81 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const // Procedural Stencils //============================================================================ -void LLImageFilter::setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min) +void LLImageFilter::setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max) { - mVignetteMode = mode; - mVignetteType = type; - mVignetteGamma = gamma; - mVignetteMin = llclampf(min); - // We always center the vignette on the image and fits it in the image smallest dimension - mVignetteCenterX = mImage->getWidth()/2; - mVignetteCenterY = mImage->getHeight()/2; - mVignetteWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); + mStencilBlendMode = mode; + mStencilShape = type; + mStencilGamma = gamma; + mStencilMin = llmin(llmax(min, -1.0f), 1.0f); + mStencilMax = llmin(llmax(max, -1.0f), 1.0f); + + // We center the vignette on the image and fits it in the image smallest dimension + mStencilCenterX = mImage->getWidth()/2; + mStencilCenterY = mImage->getHeight()/2; + mStencilWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); + + mStencilWavelength = gamma; + mStencilSine = 0.0; + mStencilCosine = 1.0; + + mStencilStartX = 0.0; + mStencilStartY = 0.0; + mStencilGradX = 0.0; + mStencilGradY = (F32)(mImage->getHeight()); + mStencilGradN = (F32)(mImage->getHeight()*mImage->getHeight()); } -F32 LLImageFilter::getVignetteAlpha(S32 i, S32 j) +void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params) { - F32 alpha = 1.0; - if (mVignetteType == VIGNETTE_TYPE_CENTER) + 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 - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); - alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + 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 (mVignetteType == VIGNETTE_TYPE_LINES) + else if (mStencilShape == STENCIL_SHAPE_SCAN_LINES) { - // alpha varies according to a squared sine function vertically. - // gamma is interpreted as the wavelength (in pixels) of the sine in that case. - alpha = (sinf(2*F_PI*j/mVignetteGamma) > 0.0 ? 1.0 : 0.0); + // 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); } - // We rescale alpha between min and 1.0 so to avoid complete fading if so desired. - return (mVignetteMin + alpha * (1.0 - mVignetteMin)); + 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)); } //============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index dc092a47a5..19ac7e81d6 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -34,18 +34,21 @@ class LLColor4U; class LLColor3; class LLMatrix3; -typedef enum e_vignette_mode +typedef enum e_stencil_blend_mode { - VIGNETTE_MODE_NONE = 0, - VIGNETTE_MODE_BLEND = 1, - VIGNETTE_MODE_FADE = 2 -} EVignetteMode; + STENCIL_BLEND_MODE_BLEND = 0, + STENCIL_BLEND_MODE_ADD = 1, + STENCIL_BLEND_MODE_DODGE = 2, + STENCIL_BLEND_MODE_FADE = 3 +} EStencilBlendMode; -typedef enum e_vignette_type +typedef enum e_stencil_shape { - VIGNETTE_TYPE_CENTER = 0, - VIGNETTE_TYPE_LINES = 1 -} EVignetteType; + STENCIL_SHAPE_UNIFORM = 0, + STENCIL_SHAPE_GRADIENT = 1, + STENCIL_SHAPE_VIGNETTE = 2, + STENCIL_SHAPE_SCAN_LINES = 3 +} EStencilShape; typedef enum e_screen_mode { @@ -87,10 +90,12 @@ private: void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); + void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue); // Procedural Stencils - void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); - F32 getVignetteAlpha(S32 i, S32 j); + void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max); + void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params); + F32 getStencilAlpha(S32 i, S32 j); // Histograms U32* getBrightnessHistogram(); @@ -105,14 +110,26 @@ private: U32 *mHistoBlue; U32 *mHistoBrightness; - // Vignette filtering - EVignetteMode mVignetteMode; - EVignetteType mVignetteType; - S32 mVignetteCenterX; - S32 mVignetteCenterY; - S32 mVignetteWidth; - F32 mVignetteGamma; - F32 mVignetteMin; + // 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; }; -- cgit v1.3 From d14392f55f9c47ba121d5470a3deb153a16b1cfb Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 20 Jan 2014 19:52:27 -0800 Subject: ACME-1236 : Fix new blend modes, updated comments --- indra/llimage/llimagefilter.cpp | 43 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 03eabce8e3..0f11b1037f 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -74,14 +74,12 @@ LLImageFilter::~LLImageFilter() /* *TODO - * Rename vignette to stencil - * Separate shape from mode - * Add shapes : uniform and gradients - * Add modes - * Add stencil (min,max) range - * Suppress alpha from colorcorrect and use uniform alpha instead - * Refactor stencil composition in the filter primitives + * Test blend modes + * Improve perf: use LUT for alpha blending in uniform case + * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Make filter definition resolution independent (do not use pixel size anywhere) + * Add gradient coloring as a filter + * Add convolve3x3 params: * vignette : center_x, center_y, width, feather @@ -96,18 +94,19 @@ LLImageFilter::~LLImageFilter() " - 'sepia' converts to sepia (no param).\n" " - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" " - 'rotate' rotates the color hue according to (in degree, positive value only).\n" - " - 'gamma' applies gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" - " - 'colorize' applies a red tint to the image using as an alpha (transparency between 0.0 and 1.0) value.\n" + + " - 'gamma' applies a gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" + " - 'colorize' applies a colored tint to the image.\n" " - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" " - 'brighten' adds light to the image ( between 0 and 255).\n" " - 'darken' substracts light to the image ( between 0 and 255).\n" - " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of discarded tail of the histogram.\n" + " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of the discarded head and tail of the histogram.\n" " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" - " - 'newsscreen' applies a 2D sine screening to the red channel and output to black and white.\n" - " - 'horizontalscreen' applies a horizontal screening to the red channel and output to black and white.\n" - " - 'verticalscreen' applies a vertical screening to the red channel and output to black and white.\n" - " - 'slantedscreen' applies a 45 degrees slanted screening to the red channel and output to black and white.\n" - " - Any other value will be interpreted as a file name describing a sequence of filters and parameters to be applied to the input images.\n" + + " - 'screen' applies a screening filter to the red channel and output to black and white. This filter assumes that the input image has been converted to grayscale or that the red channel is somewhat meaningful. It takes 3 parameters: a mode, a wave length and an angle. Modes are:\n" + " - '2Dsine' applies a bidirectional (x,y) sine screen. has no influence on that mode.\n" + " - 'line' applies a linear sine screen. is the line generator angle with the horizontal.\n" + " is size between 2 peaks of the sine function in normalized image coordinates." " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" @@ -174,7 +173,7 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { shape = STENCIL_SHAPE_SCAN_LINES; } - // Get the blend mode of the stencil, that is how the effect is blended in the background through the alpha + // 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") @@ -302,15 +301,15 @@ void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue break; case STENCIL_BLEND_MODE_ADD: // Add incoming color to the background image - pixel[VRED] = pixel[VRED] + alpha * red; - pixel[VGREEN] = pixel[VGREEN] + alpha * green; - pixel[VBLUE] = pixel[VBLUE] + alpha * blue; + 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_DODGE: // Dodge/burn the incoming color onto the background image - pixel[VRED] = inv_alpha * pixel[VRED] + red; - pixel[VGREEN] = inv_alpha * pixel[VGREEN] + green; - pixel[VBLUE] = inv_alpha * pixel[VBLUE] + blue; + 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 -- cgit v1.3 From 6c630b73a825befb6eeef66d7ed0063b1b891df7 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 13:05:54 -0800 Subject: ACME-1240 : Implement convolve filter for 3x3 kernels. Implements sharpen, blur and edge detection as examples and tests. --- indra/integration_tests/llimage_libtest/blur.xml | 7 + indra/integration_tests/llimage_libtest/edges.xml | 24 +++ .../integration_tests/llimage_libtest/sharpen.xml | 7 + indra/llimage/llimagefilter.cpp | 164 +++++++++++++++++++++ indra/llimage/llimagefilter.h | 1 + 5 files changed, 203 insertions(+) create mode 100644 indra/integration_tests/llimage_libtest/blur.xml create mode 100644 indra/integration_tests/llimage_libtest/edges.xml create mode 100644 indra/integration_tests/llimage_libtest/sharpen.xml (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/integration_tests/llimage_libtest/blur.xml b/indra/integration_tests/llimage_libtest/blur.xml new file mode 100644 index 0000000000..addd056855 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/blur.xml @@ -0,0 +1,7 @@ + + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/edges.xml b/indra/integration_tests/llimage_libtest/edges.xml new file mode 100644 index 0000000000..a66b81d01e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/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/sharpen.xml b/indra/integration_tests/llimage_libtest/sharpen.xml new file mode 100644 index 0000000000..6d3f9ae1a2 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/sharpen.xml @@ -0,0 +1,7 @@ + + + + sharpen + + + diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 0f11b1037f..75661a6d4b 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -34,6 +34,7 @@ #include "m3math.h" #include "v3math.h" #include "llsdserialize.h" +#include "llstring.h" //--------------------------------------------------------------------------- // LLImageFilter @@ -281,6 +282,32 @@ void LLImageFilter::executeFilter(LLPointer raw_image) } filterScreen(mode,(S32)(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 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) + kernel.mMatrix[i][j] = -1.0; + kernel.mMatrix[1][1] = 9.0; + convolve(kernel,false,false); + } + else if (filter_name == "gradient") + { + 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; + kernel.mMatrix[1][1] = 8.0; + convolve(kernel,false,true); + } } } @@ -365,6 +392,143 @@ void LLImageFilter::colorTransform(const LLMatrix3 &transform) } } +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 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); + // 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; + dst_data += 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 S32 wave_length, const F32 angle) { const S32 components = mImage->getComponents(); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 19ac7e81d6..738c693686 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -91,6 +91,7 @@ private: void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); void filterScreen(EScreenMode mode, const S32 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(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max); -- cgit v1.3 From 4082d8ea27a6d386a01681e51e9776b552f6cb5c Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 16:39:23 -0800 Subject: ACME-1236 : Fixes gamma and brightness code. Also fixes example xml filter files. --- indra/integration_tests/llimage_libtest/brighten.xml | 2 +- indra/integration_tests/llimage_libtest/colorize.xml | 16 ++++++++++------ indra/integration_tests/llimage_libtest/contrast.xml | 7 ------- indra/integration_tests/llimage_libtest/darken.xml | 2 +- indra/integration_tests/llimage_libtest/gamma.xml | 9 +-------- indra/llimage/llimagefilter.cpp | 13 +++++++------ indra/llimage/llimagefilter.h | 2 +- 7 files changed, 21 insertions(+), 30 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml index d17b96d2d7..9b4232229f 100755 --- a/indra/integration_tests/llimage_libtest/brighten.xml +++ b/indra/integration_tests/llimage_libtest/brighten.xml @@ -2,7 +2,7 @@ brighten - 50.0 + 0.5 1.0 1.0 1.0 diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml index 18c6cd3425..72e58b0ffe 100644 --- a/indra/integration_tests/llimage_libtest/colorize.xml +++ b/indra/integration_tests/llimage_libtest/colorize.xml @@ -1,20 +1,24 @@ - linearize + stencil + vignette + blend 0.0 1.0 + 0.0 + 0.0 1.0 - 1.0 + 10.0 colorize 1.0 - 1.0 - 1.0 - 0.2 0.0 - 0.2 + 0.0 + 0.5 + 0.5 + 0.0 diff --git a/indra/integration_tests/llimage_libtest/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml index 8dcdd1a9a9..00746b8a9e 100644 --- a/indra/integration_tests/llimage_libtest/contrast.xml +++ b/indra/integration_tests/llimage_libtest/contrast.xml @@ -1,12 +1,5 @@ - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - contrast 1.5 diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml index 8d110452e9..5cec3589b6 100755 --- a/indra/integration_tests/llimage_libtest/darken.xml +++ b/indra/integration_tests/llimage_libtest/darken.xml @@ -2,7 +2,7 @@ darken - 50.0 + 0.5 1.0 1.0 1.0 diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml index 7505a03027..19af09b046 100644 --- a/indra/integration_tests/llimage_libtest/gamma.xml +++ b/indra/integration_tests/llimage_libtest/gamma.xml @@ -1,15 +1,8 @@ - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - gamma - 1.5 + 1.7 1.0 1.0 1.0 diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 75661a6d4b..c02679e04f 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -80,7 +80,6 @@ LLImageFilter::~LLImageFilter() * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Make filter definition resolution independent (do not use pixel size anywhere) * Add gradient coloring as a filter - * Add convolve3x3 params: * vignette : center_x, center_y, width, feather @@ -251,12 +250,12 @@ void LLImageFilter::executeFilter(LLPointer raw_image) else if (filter_name == "brighten") { LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal())); - filterBrightness((S32)(mFilterData[i][1].asReal()),color); + 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((S32)(-mFilterData[i][1].asReal()),color); + filterBrightness((float)(-mFilterData[i][1].asReal()),color); } else if (filter_name == "linearize") { @@ -807,7 +806,7 @@ void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha) for (S32 i = 0; i < 256; i++) { - F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,gamma))); + 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); @@ -969,15 +968,17 @@ void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha) colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut); } -void LLImageFilter::filterBrightness(S32 add, const LLColor3& alpha) +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((S32)((S32)(i) + add))); + 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); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 738c693686..3e3be3d88b 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -84,7 +84,7 @@ private: 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(S32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker + void filterBrightness(F32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.3 From c99e22e6740ebb3e39bc1b85000bd465676e60d1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 21 Jan 2014 21:17:57 -0800 Subject: ACME-1236 : Make all filters resolution independent, cleanup comments, move example filters to a sub folder in llimage_libtest --- .../llimage_libtest/1970colorize.xml | 41 ------------- indra/integration_tests/llimage_libtest/blur.xml | 7 --- .../integration_tests/llimage_libtest/brighten.xml | 11 ---- .../integration_tests/llimage_libtest/colorize.xml | 24 -------- .../integration_tests/llimage_libtest/contrast.xml | 11 ---- indra/integration_tests/llimage_libtest/darken.xml | 11 ---- indra/integration_tests/llimage_libtest/edges.xml | 24 -------- .../llimage_libtest/filters/1970colorize.xml | 41 +++++++++++++ .../llimage_libtest/filters/blur.xml | 7 +++ .../llimage_libtest/filters/brighten.xml | 11 ++++ .../llimage_libtest/filters/colorize.xml | 24 ++++++++ .../llimage_libtest/filters/contrast.xml | 11 ++++ .../llimage_libtest/filters/darken.xml | 11 ++++ .../llimage_libtest/filters/edges.xml | 24 ++++++++ .../llimage_libtest/filters/gamma.xml | 11 ++++ .../llimage_libtest/filters/grayscale.xml | 14 +++++ .../llimage_libtest/filters/horizontalscreen.xml | 20 +++++++ .../llimage_libtest/filters/linearize.xml | 11 ++++ .../llimage_libtest/filters/newsscreen.xml | 20 +++++++ .../llimage_libtest/filters/posterize.xml | 11 ++++ .../llimage_libtest/filters/rotatecolors180.xml | 8 +++ .../llimage_libtest/filters/saturate.xml | 8 +++ .../llimage_libtest/filters/sepia.xml | 14 +++++ .../llimage_libtest/filters/sharpen.xml | 7 +++ .../llimage_libtest/filters/slantedscreen.xml | 20 +++++++ .../llimage_libtest/filters/spotlight.xml | 45 ++++++++++++++ .../llimage_libtest/filters/stencilgradient.xml | 24 ++++++++ .../llimage_libtest/filters/stencilscanlines.xml | 22 +++++++ .../llimage_libtest/filters/stenciluniform.xml | 20 +++++++ .../llimage_libtest/filters/stencilvignette.xml | 24 ++++++++ .../llimage_libtest/filters/verticalscreen.xml | 20 +++++++ .../llimage_libtest/filters/video.xml | 23 +++++++ indra/integration_tests/llimage_libtest/gamma.xml | 11 ---- .../llimage_libtest/grayscale.xml | 14 ----- .../llimage_libtest/horizontalscreen.xml | 25 -------- .../llimage_libtest/linearize.xml | 11 ---- .../llimage_libtest/newsscreen.xml | 25 -------- .../llimage_libtest/posterize.xml | 18 ------ .../llimage_libtest/rotatecolors180.xml | 8 --- .../integration_tests/llimage_libtest/saturate.xml | 8 --- indra/integration_tests/llimage_libtest/sepia.xml | 14 ----- .../integration_tests/llimage_libtest/sharpen.xml | 7 --- .../llimage_libtest/slantedscreen.xml | 25 -------- .../llimage_libtest/spotlight.xml | 45 -------------- .../llimage_libtest/verticalscreen.xml | 25 -------- indra/integration_tests/llimage_libtest/video.xml | 23 ------- indra/llimage/llimagefilter.cpp | 70 ++++------------------ indra/llimage/llimagefilter.h | 4 +- 48 files changed, 464 insertions(+), 449 deletions(-) delete mode 100644 indra/integration_tests/llimage_libtest/1970colorize.xml delete mode 100644 indra/integration_tests/llimage_libtest/blur.xml delete mode 100755 indra/integration_tests/llimage_libtest/brighten.xml delete mode 100644 indra/integration_tests/llimage_libtest/colorize.xml delete mode 100644 indra/integration_tests/llimage_libtest/contrast.xml delete mode 100755 indra/integration_tests/llimage_libtest/darken.xml delete mode 100644 indra/integration_tests/llimage_libtest/edges.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/1970colorize.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/blur.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/brighten.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/colorize.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/contrast.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/darken.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/edges.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/gamma.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/grayscale.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/horizontalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/linearize.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/newsscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/posterize.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/rotatecolors180.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/saturate.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/sepia.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/sharpen.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/slantedscreen.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/spotlight.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilgradient.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilscanlines.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stenciluniform.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/stencilvignette.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/verticalscreen.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/video.xml delete mode 100644 indra/integration_tests/llimage_libtest/gamma.xml delete mode 100644 indra/integration_tests/llimage_libtest/grayscale.xml delete mode 100644 indra/integration_tests/llimage_libtest/horizontalscreen.xml delete mode 100755 indra/integration_tests/llimage_libtest/linearize.xml delete mode 100755 indra/integration_tests/llimage_libtest/newsscreen.xml delete mode 100755 indra/integration_tests/llimage_libtest/posterize.xml delete mode 100644 indra/integration_tests/llimage_libtest/rotatecolors180.xml delete mode 100644 indra/integration_tests/llimage_libtest/saturate.xml delete mode 100644 indra/integration_tests/llimage_libtest/sepia.xml delete mode 100644 indra/integration_tests/llimage_libtest/sharpen.xml delete mode 100644 indra/integration_tests/llimage_libtest/slantedscreen.xml delete mode 100644 indra/integration_tests/llimage_libtest/spotlight.xml delete mode 100644 indra/integration_tests/llimage_libtest/verticalscreen.xml delete mode 100755 indra/integration_tests/llimage_libtest/video.xml (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/integration_tests/llimage_libtest/1970colorize.xml b/indra/integration_tests/llimage_libtest/1970colorize.xml deleted file mode 100644 index 0dab2489a0..0000000000 --- a/indra/integration_tests/llimage_libtest/1970colorize.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - 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/blur.xml b/indra/integration_tests/llimage_libtest/blur.xml deleted file mode 100644 index addd056855..0000000000 --- a/indra/integration_tests/llimage_libtest/blur.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - blur - - - diff --git a/indra/integration_tests/llimage_libtest/brighten.xml b/indra/integration_tests/llimage_libtest/brighten.xml deleted file mode 100755 index 9b4232229f..0000000000 --- a/indra/integration_tests/llimage_libtest/brighten.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - brighten - 0.5 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/colorize.xml b/indra/integration_tests/llimage_libtest/colorize.xml deleted file mode 100644 index 72e58b0ffe..0000000000 --- a/indra/integration_tests/llimage_libtest/colorize.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - 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/contrast.xml b/indra/integration_tests/llimage_libtest/contrast.xml deleted file mode 100644 index 00746b8a9e..0000000000 --- a/indra/integration_tests/llimage_libtest/contrast.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - contrast - 1.5 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/darken.xml b/indra/integration_tests/llimage_libtest/darken.xml deleted file mode 100755 index 5cec3589b6..0000000000 --- a/indra/integration_tests/llimage_libtest/darken.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - darken - 0.5 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/edges.xml b/indra/integration_tests/llimage_libtest/edges.xml deleted file mode 100644 index a66b81d01e..0000000000 --- a/indra/integration_tests/llimage_libtest/edges.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - 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/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/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/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/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/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/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/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/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/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/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/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..8b10687ef5 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/video.xml @@ -0,0 +1,23 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + lines + 10.0 + 0.0 + + + brighten + 100.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/gamma.xml b/indra/integration_tests/llimage_libtest/gamma.xml deleted file mode 100644 index 19af09b046..0000000000 --- a/indra/integration_tests/llimage_libtest/gamma.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - gamma - 1.7 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/grayscale.xml b/indra/integration_tests/llimage_libtest/grayscale.xml deleted file mode 100644 index 984312c4fd..0000000000 --- a/indra/integration_tests/llimage_libtest/grayscale.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - grayscale - - - diff --git a/indra/integration_tests/llimage_libtest/horizontalscreen.xml b/indra/integration_tests/llimage_libtest/horizontalscreen.xml deleted file mode 100644 index ddff4d1977..0000000000 --- a/indra/integration_tests/llimage_libtest/horizontalscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 0.0 - - - diff --git a/indra/integration_tests/llimage_libtest/linearize.xml b/indra/integration_tests/llimage_libtest/linearize.xml deleted file mode 100755 index 23d0290e07..0000000000 --- a/indra/integration_tests/llimage_libtest/linearize.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/newsscreen.xml b/indra/integration_tests/llimage_libtest/newsscreen.xml deleted file mode 100755 index 8247c34500..0000000000 --- a/indra/integration_tests/llimage_libtest/newsscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - 2Dsine - 5.0 - 0.0 - - - diff --git a/indra/integration_tests/llimage_libtest/posterize.xml b/indra/integration_tests/llimage_libtest/posterize.xml deleted file mode 100755 index f026278f9e..0000000000 --- a/indra/integration_tests/llimage_libtest/posterize.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - posterize - 10.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/integration_tests/llimage_libtest/rotatecolors180.xml b/indra/integration_tests/llimage_libtest/rotatecolors180.xml deleted file mode 100644 index e25029720f..0000000000 --- a/indra/integration_tests/llimage_libtest/rotatecolors180.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - rotate - 180.0 - - - diff --git a/indra/integration_tests/llimage_libtest/saturate.xml b/indra/integration_tests/llimage_libtest/saturate.xml deleted file mode 100644 index b77f07a037..0000000000 --- a/indra/integration_tests/llimage_libtest/saturate.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - saturate - 3.0 - - - diff --git a/indra/integration_tests/llimage_libtest/sepia.xml b/indra/integration_tests/llimage_libtest/sepia.xml deleted file mode 100644 index 0304ead015..0000000000 --- a/indra/integration_tests/llimage_libtest/sepia.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - linearize - 0.0 - 1.0 - 1.0 - 1.0 - - - sepia - - - diff --git a/indra/integration_tests/llimage_libtest/sharpen.xml b/indra/integration_tests/llimage_libtest/sharpen.xml deleted file mode 100644 index 6d3f9ae1a2..0000000000 --- a/indra/integration_tests/llimage_libtest/sharpen.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - sharpen - - - diff --git a/indra/integration_tests/llimage_libtest/slantedscreen.xml b/indra/integration_tests/llimage_libtest/slantedscreen.xml deleted file mode 100644 index 63ad01d51d..0000000000 --- a/indra/integration_tests/llimage_libtest/slantedscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 45.0 - - - diff --git a/indra/integration_tests/llimage_libtest/spotlight.xml b/indra/integration_tests/llimage_libtest/spotlight.xml deleted file mode 100644 index 203130bdee..0000000000 --- a/indra/integration_tests/llimage_libtest/spotlight.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - 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/verticalscreen.xml b/indra/integration_tests/llimage_libtest/verticalscreen.xml deleted file mode 100644 index 71e48df656..0000000000 --- a/indra/integration_tests/llimage_libtest/verticalscreen.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - blend - 0.0 - 0.0 - - - screen - line - 5.0 - 90.0 - - - diff --git a/indra/integration_tests/llimage_libtest/video.xml b/indra/integration_tests/llimage_libtest/video.xml deleted file mode 100755 index 8b10687ef5..0000000000 --- a/indra/integration_tests/llimage_libtest/video.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - linearize - 0.01 - 1.0 - 1.0 - 1.0 - - - lines - 10.0 - 0.0 - - - brighten - 100.0 - 1.0 - 1.0 - 1.0 - - - diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index c02679e04f..4c6dd2faee 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -1,6 +1,6 @@ /** * @file llimagefilter.cpp - * @brief Simple Image Filtering. + * @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 @@ -75,42 +75,12 @@ LLImageFilter::~LLImageFilter() /* *TODO - * Test blend modes + * Rename stencil to mask + * Test blend modes and name them correctly + * Suppress old "blend", "fade" and "lines" stencil definition. Change all xml accordingly. * Improve perf: use LUT for alpha blending in uniform case * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) - * Make filter definition resolution independent (do not use pixel size anywhere) * Add gradient coloring as a filter - - params: - * vignette : center_x, center_y, width, feather - * scan lines : wavelength, angle - * uniform - * gradient : start_x, start_y, end_x, end_y - - * Document all the admissible names in the wiki - - " Apply the filter to the input images using the optional value. Admissible names:\n" - " - 'grayscale' converts to grayscale (no param).\n" - " - 'sepia' converts to sepia (no param).\n" - " - 'saturate' changes color saturation according to : < 1.0 will desaturate, > 1.0 will saturate.\n" - " - 'rotate' rotates the color hue according to (in degree, positive value only).\n" - - " - 'gamma' applies a gamma curve to all channels: > 1.0 will darken, < 1.0 will lighten.\n" - " - 'colorize' applies a colored tint to the image.\n" - " - 'contrast' modifies the contrast according to : > 1.0 will enhance the contrast, <1.0 will flatten it.\n" - " - 'brighten' adds light to the image ( between 0 and 255).\n" - " - 'darken' substracts light to the image ( between 0 and 255).\n" - " - 'linearize' optimizes the contrast using the brightness histogram. is the fraction (between 0.0 and 1.0) of the discarded head and tail of the histogram.\n" - " - 'posterize' redistributes the colors between classes per channel ( between 2 and 255).\n" - - " - 'screen' applies a screening filter to the red channel and output to black and white. This filter assumes that the input image has been converted to grayscale or that the red channel is somewhat meaningful. It takes 3 parameters: a mode, a wave length and an angle. Modes are:\n" - " - '2Dsine' applies a bidirectional (x,y) sine screen. has no influence on that mode.\n" - " - 'line' applies a linear sine screen. is the line generator angle with the horizontal.\n" - " is size between 2 peaks of the sine function in normalized image coordinates." - - " Apply a circular central vignette to the filter using the optional and values. Admissible names:\n" - " - 'blend' : the filter is applied with full intensity in the center and blends with the image to the periphery.\n" - " - 'fade' : the filter is applied with full intensity in the center and fades to black to the periphery.\n" */ //============================================================================ @@ -133,25 +103,6 @@ void LLImageFilter::executeFilter(LLPointer raw_image) //} //std::cout << std::endl; - // Execute the filter described on this line - /* - - stencil - shape uniform / gradient / vignette / scanlines - blend_mode blend /add /dodge / fade - min -1.0 to 1.0 (mandatory though ignored for uniform shape) - max -1.0 to 1.0 (value for uniform) - param1 - param2 - param3 - param4 - - params: - * vignette : center_x, center_y, width, feather : positions between in float (0.0 is center, 1.0 is top), width in float in same unit, feather is a float - * scan lines : wavelength, angle : wavelength in float assuming (height/2 = 1), angle float in degree - * uniform : all parameters ignored - * gradient : start_x, start_y, end_x, end_y : position in float (0.0 is center, 1.0 is top) - */ if (filter_name == "stencil") { // Get the shape of the stencil, that is how the procedural alpha is computed geometrically @@ -279,7 +230,7 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mode = SCREEN_MODE_LINE; } - filterScreen(mode,(S32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); + filterScreen(mode,(F32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal())); } else if (filter_name == "blur") { @@ -445,7 +396,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v // All other lines for (S32 j = 1; j < (height-1); j++) { - // We need to buffer 2 lines. We flip north and current to avoid moving too much memory around + // 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 */ @@ -460,6 +411,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v } // 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; @@ -470,7 +422,6 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v U8* SW = south_data; U8* S = SW+components; U8* SE = S+components; - dst_data += components; // All other pixels for (S32 i = 1; i < (width-1); i++) { @@ -528,7 +479,7 @@ void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_v } } -void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) +void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle) { const S32 components = mImage->getComponents(); llassert( components >= 1 && components <= 4 ); @@ -536,6 +487,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const 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); @@ -550,11 +502,11 @@ void LLImageFilter::filterScreen(EScreenMode mode, const S32 wave_length, const switch (mode) { case SCREEN_MODE_2DSINE: - value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + value = (sinf(2*F_PI*i/wave_length_pixels)*sinf(2*F_PI*j/wave_length_pixels)+1.0)*255.0/2.0; break; case SCREEN_MODE_LINE: d = sin*i - cos*j; - value = (sinf(2*F_PI*d/wave_length)+1.0)*255.0/2.0; + value = (sinf(2*F_PI*d/wave_length_pixels)+1.0)*255.0/2.0; break; } U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index 3e3be3d88b..e392d3215e 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -1,6 +1,6 @@ /** * @file llimagefilter.h - * @brief Simple Image Filtering. + * @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 @@ -89,7 +89,7 @@ private: // 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 S32 wave_length, const F32 angle); + 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); -- cgit v1.3 From ff3edd06d2c824a32753e689de3369abf593c684 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 23 Jan 2014 16:37:48 -0800 Subject: ACME-1275 : WIP : Clean up unwanted code and comments in image filter --- indra/llimage/llimagefilter.cpp | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 4c6dd2faee..e0dae9fab2 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -77,7 +77,6 @@ LLImageFilter::~LLImageFilter() *TODO * Rename stencil to mask * Test blend modes and name them correctly - * Suppress old "blend", "fade" and "lines" stencil definition. Change all xml accordingly. * Improve perf: use LUT for alpha blending in uniform case * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Add gradient coloring as a filter @@ -154,18 +153,6 @@ void LLImageFilter::executeFilter(LLPointer raw_image) // Set the stencil setStencil(shape,mode,min,max,params); } - else if (filter_name == "blend") - { - setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); - } - else if (filter_name == "fade") - { - setStencil(STENCIL_BLEND_MODE_FADE,STENCIL_SHAPE_VIGNETTE,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); - } - else if (filter_name == "lines") - { - setStencil(STENCIL_BLEND_MODE_BLEND,STENCIL_SHAPE_SCAN_LINES,(float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),1.0); - } else if (filter_name == "sepia") { filterSepia(); @@ -258,6 +245,10 @@ void LLImageFilter::executeFilter(LLPointer raw_image) kernel.mMatrix[1][1] = 8.0; convolve(kernel,false,true); } + else + { + llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl; + } } } -- cgit v1.3 From 225fb4e782108d83217b587188beb031afb04fef Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 5 Feb 2014 18:56:58 -0800 Subject: ACME-1300 : Rename blend mode dodge to add_back --- indra/llimage/llimagefilter.cpp | 8 ++++---- indra/llimage/llimagefilter.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index e0dae9fab2..7734b08c18 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -134,9 +134,9 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mode = STENCIL_BLEND_MODE_ADD; } - else if (filter_mode == "dodge") + else if (filter_mode == "add_back") { - mode = STENCIL_BLEND_MODE_DODGE; + mode = STENCIL_BLEND_MODE_ABACK; } else if (filter_mode == "fade") { @@ -273,8 +273,8 @@ void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green); pixel[VBLUE] = llclampb(pixel[VBLUE] + alpha * blue); break; - case STENCIL_BLEND_MODE_DODGE: - // Dodge/burn the incoming color onto the background image + 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); diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index e392d3215e..d2650c2539 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -38,7 +38,7 @@ typedef enum e_stencil_blend_mode { STENCIL_BLEND_MODE_BLEND = 0, STENCIL_BLEND_MODE_ADD = 1, - STENCIL_BLEND_MODE_DODGE = 2, + STENCIL_BLEND_MODE_ABACK = 2, STENCIL_BLEND_MODE_FADE = 3 } EStencilBlendMode; -- cgit v1.3 From 9112a47f9be023dd83bf4de72d490d21d85e6b5e Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 10:26:25 -0800 Subject: ACME-1301 : Add convolve as a secondary filter command --- .../llimage_libtest/filters/convolve.xml | 18 ++++++++++++++++++ indra/llimage/llimagefilter.cpp | 19 +++++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/filters/convolve.xml (limited to 'indra/llimage/llimagefilter.cpp') 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/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 7734b08c18..9093e4b59c 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -230,21 +230,32 @@ void LLImageFilter::executeFilter(LLPointer raw_image) else if (filter_name == "sharpen") { LLMatrix3 kernel; - for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++) for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) - kernel.mMatrix[i][j] = -1.0; + 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 i = 0; i < NUM_VALUES_IN_MAT3; i++) + for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++) for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++) - kernel.mMatrix[i][j] = -1.0; + 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 { llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl; -- cgit v1.3 From 2ba7552b9cd94b62c850365bcc537f0b3e344917 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 11:57:01 -0800 Subject: ACME-1301 : Add colortransform as a secondary filter command --- .../llimage_libtest/filters/colortransform.xml | 16 ++++++++++++++++ indra/llimage/llimagefilter.cpp | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 indra/integration_tests/llimage_libtest/filters/colortransform.xml (limited to 'indra/llimage/llimagefilter.cpp') 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/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 9093e4b59c..8f7e340d16 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -256,6 +256,16 @@ void LLImageFilter::executeFilter(LLPointer raw_image) 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; -- cgit v1.3 From 8ad37cec70be671809f317bbc558eed1b59be595 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 16:25:12 -0800 Subject: ACME-1278 : Allow angle to be used in 2D screen filter --- indra/llimage/llimagefilter.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 8f7e340d16..8bd7416f6a 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -510,15 +510,18 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const { // Compute screen value F32 value = 0.0; - F32 d = 0.0; + F32 di = 0.0; + F32 dj = 0.0; switch (mode) { case SCREEN_MODE_2DSINE: - value = (sinf(2*F_PI*i/wave_length_pixels)*sinf(2*F_PI*j/wave_length_pixels)+1.0)*255.0/2.0; + 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: - d = sin*i - cos*j; - value = (sinf(2*F_PI*d/wave_length_pixels)+1.0)*255.0/2.0; + 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) ? 255 : 0); -- cgit v1.3 From 99427b29ceb8c6a22755075679ae008a37a947ae Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 18:21:18 -0800 Subject: Clear up comments --- indra/llimage/llimagefilter.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 8bd7416f6a..a5b5888bb2 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -76,9 +76,7 @@ LLImageFilter::~LLImageFilter() /* *TODO * Rename stencil to mask - * Test blend modes and name them correctly * Improve perf: use LUT for alpha blending in uniform case - * Improve perf: make sure filter is not called more than necessary in viewer (seems to be called 3 times per change) * Add gradient coloring as a filter */ -- cgit v1.3 From 73c9e42fafc0ad21af1ed38735c0ed9212640dd2 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Feb 2014 16:27:42 -0800 Subject: ACME-1314 : Fix screen filter to make it less harsh on edges, modify Jules Verne and Newspaper filters as a result --- indra/llimage/llimagefilter.cpp | 10 +++++++++- indra/newview/app_settings/filters/JulesVerne.xml | 11 ----------- indra/newview/app_settings/filters/Newspaper.xml | 11 ----------- 3 files changed, 9 insertions(+), 23 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index a5b5888bb2..742b0ad802 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -500,6 +500,14 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const 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++) @@ -522,7 +530,7 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0; break; } - U8 dst_value = (dst_data[VRED] >= (U8)(value) ? 255 : 0); + 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); diff --git a/indra/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml index 35bc657c11..981e221da9 100644 --- a/indra/newview/app_settings/filters/JulesVerne.xml +++ b/indra/newview/app_settings/filters/JulesVerne.xml @@ -10,17 +10,6 @@ grayscale - - stencil - vignette - blend - 1.0 - 0.1 - 0.0 - 0.0 - 1.0 - 1.0 - screen line diff --git a/indra/newview/app_settings/filters/Newspaper.xml b/indra/newview/app_settings/filters/Newspaper.xml index 8441decf3b..6cfe319281 100755 --- a/indra/newview/app_settings/filters/Newspaper.xml +++ b/indra/newview/app_settings/filters/Newspaper.xml @@ -10,17 +10,6 @@ grayscale - - stencil - vignette - blend - 1.0 - 0.1 - 0.0 - 0.0 - 1.0 - 1.0 - screen 2Dsine -- cgit v1.3 From 51844473c00a7d620746c26af822aa7d41f53832 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 7 Feb 2014 18:35:46 -0800 Subject: ACME-1315 : Fix anisotropy in filters applied to thumbnail. Deleted some unused code --- indra/llimage/llimagefilter.cpp | 25 ------------------------- indra/llimage/llimagefilter.h | 1 - indra/newview/llsnapshotlivepreview.cpp | 13 +++++-------- 3 files changed, 5 insertions(+), 34 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 742b0ad802..3d0c488768 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -542,31 +542,6 @@ void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const //============================================================================ // Procedural Stencils //============================================================================ - -void LLImageFilter::setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max) -{ - mStencilBlendMode = mode; - mStencilShape = type; - mStencilGamma = gamma; - mStencilMin = llmin(llmax(min, -1.0f), 1.0f); - mStencilMax = llmin(llmax(max, -1.0f), 1.0f); - - // We center the vignette on the image and fits it in the image smallest dimension - mStencilCenterX = mImage->getWidth()/2; - mStencilCenterY = mImage->getHeight()/2; - mStencilWidth = llmin(mImage->getWidth()/2,mImage->getHeight()/2); - - mStencilWavelength = gamma; - mStencilSine = 0.0; - mStencilCosine = 1.0; - - mStencilStartX = 0.0; - mStencilStartY = 0.0; - mStencilGradX = 0.0; - mStencilGradY = (F32)(mImage->getHeight()); - mStencilGradN = (F32)(mImage->getHeight()*mImage->getHeight()); -} - void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params) { mStencilShape = shape; diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h index d2650c2539..0f1cbc3fb8 100755 --- a/indra/llimage/llimagefilter.h +++ b/indra/llimage/llimagefilter.h @@ -94,7 +94,6 @@ private: void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value); // Procedural Stencils - void setStencil(EStencilBlendMode mode, EStencilShape type, F32 gamma, F32 min, F32 max); void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params); F32 getStencilAlpha(S32 i, S32 j); diff --git a/indra/newview/llsnapshotlivepreview.cpp b/indra/newview/llsnapshotlivepreview.cpp index 2a5bd5d8bc..eef4ed78c8 100644 --- a/indra/newview/llsnapshotlivepreview.cpp +++ b/indra/newview/llsnapshotlivepreview.cpp @@ -556,10 +556,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) mPreviewImage->getHeight(), mPreviewImage->getComponents()); raw->copy(mPreviewImage); - // Scale to the thumbnal size modulo a power of 2 - S32 width = LLImageRaw::expandDimToPowerOfTwo(mThumbnailWidth,MAX_IMAGE_SIZE); - S32 height = LLImageRaw::expandDimToPowerOfTwo(mThumbnailHeight,MAX_IMAGE_SIZE); - if (!raw->scale(width, height)) + // Scale to the thumbnail size + if (!raw->scale(mThumbnailWidth, mThumbnailHeight)) { raw = NULL ; } @@ -575,15 +573,12 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) { raw = NULL ; } - else - { - raw->expandToPowerOfTwo(); - } } if (raw) { // Filter the thumbnail + // Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted if (getFilter() != "") { std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter()); @@ -597,6 +592,8 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update) llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl; } } + // Scale to a power of 2 so it can be mapped to a texture + raw->expandToPowerOfTwo(); mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); mThumbnailUpToDate = TRUE ; } -- cgit v1.3 From a5366f06edf5aa1b75328e26011989eba7c601ca Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 13 Feb 2014 15:15:05 -0800 Subject: ACME-1277 : Final set of filters, added a SnapshotFiltersEnabled debug setting --- .../llimage_libtest/filters/heatwave.xml | 38 ++++++ .../llimage_libtest/filters/julesverne.xml | 20 ++++ .../llimage_libtest/filters/lensflare.xml | 45 +++---- .../llimage_libtest/filters/overcast.xml | 24 ++++ indra/llimage/llimagefilter.cpp | 2 + .../newview/app_settings/filters/Autocontrast.xml | 11 ++ indra/newview/app_settings/filters/Heatwave.xml | 38 ------ indra/newview/app_settings/filters/JulesVerne.xml | 20 ---- indra/newview/app_settings/filters/LensFlare.xml | 131 +++++++++++++++++++++ indra/newview/app_settings/filters/Miniature.xml | 118 +++++++++++++++++++ indra/newview/app_settings/filters/Overcast.xml | 24 ---- indra/newview/app_settings/filters/Spotlight.xml | 38 +++--- indra/newview/app_settings/filters/Toycamera.xml | 46 ++++++++ indra/newview/app_settings/settings.xml | 11 ++ indra/newview/llfloatersnapshot.cpp | 41 +++++-- .../skins/default/xui/en/floater_snapshot.xml | 4 +- indra/newview/skins/default/xui/en/strings.xml | 13 +- 17 files changed, 473 insertions(+), 151 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/filters/heatwave.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/julesverne.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/overcast.xml create mode 100755 indra/newview/app_settings/filters/Autocontrast.xml delete mode 100644 indra/newview/app_settings/filters/Heatwave.xml delete mode 100644 indra/newview/app_settings/filters/JulesVerne.xml create mode 100644 indra/newview/app_settings/filters/LensFlare.xml create mode 100755 indra/newview/app_settings/filters/Miniature.xml delete mode 100644 indra/newview/app_settings/filters/Overcast.xml create mode 100755 indra/newview/app_settings/filters/Toycamera.xml (limited to 'indra/llimage/llimagefilter.cpp') 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/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 index ec8afc8daa..0b5af9c82b 100644 --- a/indra/integration_tests/llimage_libtest/filters/lensflare.xml +++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml @@ -7,43 +7,36 @@ 1.0 1.0 - - brighten - 0.1 - 1.0 - 1.0 - 1.0 - stencil - vignette + gradient add + 1.0 0.0 - 0.4 - -0.5 - 0.5 - 0.15 - 20.0 + -1.0 + 1.0 + 1.0 + -1.0 colorize 1.0 1.0 1.0 - 0.15 - 0.15 - 0.15 + 0.1 + 0.1 + 0.0 stencil vignette add 0.0 - 0.4 - -0.5 - 0.5 - 0.20 - 20.0 + 1.0 + -1.0 + 1.0 + 1.5 + 5.0 colorize @@ -59,11 +52,11 @@ vignette add 0.0 - 0.5 - -0.7 - 0.7 - 0.10 - 20.0 + 1.0 + -1.0 + 1.0 + 1.0 + 5.0 colorize 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/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 3d0c488768..6e9ea2f948 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -55,6 +55,7 @@ LLImageFilter::LLImageFilter(const std::string& file_path) : { // Load filter description from file llifstream filter_xml(file_path); + llinfos << "Merov : load filter : " << file_path << llendl; if (filter_xml.is_open()) { // Load and parse the file @@ -88,6 +89,7 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mImage = raw_image; + llinfos << "Merov : execute filter on image size " << mImage->getWidth() << "x" << mImage->getHeight() << llendl; //std::cout << "Filter : size = " << mFilterData.size() << std::endl; for (S32 i = 0; i < mFilterData.size(); ++i) { diff --git a/indra/newview/app_settings/filters/Autocontrast.xml b/indra/newview/app_settings/filters/Autocontrast.xml new file mode 100755 index 0000000000..ec3d7561bd --- /dev/null +++ b/indra/newview/app_settings/filters/Autocontrast.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/newview/app_settings/filters/Heatwave.xml b/indra/newview/app_settings/filters/Heatwave.xml deleted file mode 100644 index a99f41c833..0000000000 --- a/indra/newview/app_settings/filters/Heatwave.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - 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/newview/app_settings/filters/JulesVerne.xml b/indra/newview/app_settings/filters/JulesVerne.xml deleted file mode 100644 index 981e221da9..0000000000 --- a/indra/newview/app_settings/filters/JulesVerne.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - linearize - 0.1 - 1.0 - 1.0 - 1.0 - - - grayscale - - - screen - line - 0.02 - 0.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..0b5af9c82b --- /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 + 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/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/Overcast.xml b/indra/newview/app_settings/filters/Overcast.xml deleted file mode 100644 index dce5ab3e9e..0000000000 --- a/indra/newview/app_settings/filters/Overcast.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - 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/newview/app_settings/filters/Spotlight.xml b/indra/newview/app_settings/filters/Spotlight.xml index 044b2c0b3a..0e2e0ad68c 100644 --- a/indra/newview/app_settings/filters/Spotlight.xml +++ b/indra/newview/app_settings/filters/Spotlight.xml @@ -2,47 +2,43 @@ linearize - 0.1 + 0.0 + 1.0 1.0 1.0 + + + stencil + vignette + add + 0.0 + 0.4 + 0.0 + 0.0 1.0 + 2.0 contrast - 0.8 1.0 1.0 1.0 - - - saturate - 1.5 + 1.0 stencil vignette - fade - 0.75 - 1.0 + add + -0.8 + 0.0 0.0 0.0 1.0 - 5.0 - - - saturate - 0.8 + 2.0 contrast - 1.1 - 1.0 - 1.0 1.0 - - - brighten - 0.1 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/settings.xml b/indra/newview/app_settings/settings.xml index afc4ac617c..43c82c3005 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11268,6 +11268,17 @@ Value 0 + SnapshotFiltersEnabled + + Comment + Enable filters in the Snapshot Advanced panel (experimental). + Persist + 1 + Type + Boolean + Value + 0 + SnapshotFormat Comment diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 1d52ac5a69..8e48d35c1d 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -478,9 +478,6 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) previewp->setSnapshotType(shot_type); previewp->setSnapshotFormat(shot_format); previewp->setSnapshotBufferType(layer_type); - // Filters - //const std::string& filter_name = floater->getChild("filters_combobox")->getSimple(); - //previewp->setFilter(filter_name); } LLPanelSnapshot* current_panel = Impl::getActivePanel(floater); @@ -575,8 +572,17 @@ void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data) LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; if (view) { - checkAutoSnapshot(getPreviewView(view)); updateControls(view); + LLSnapshotLivePreview* previewp = getPreviewView(view); + if (previewp) + { + checkAutoSnapshot(previewp); + // Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale + LLComboBox* filterbox = static_cast(view->getChild("filters_combobox")); + std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : ""); + previewp->setFilter(filter_name); + previewp->updateSnapshot(FALSE, TRUE); + } } } @@ -1078,16 +1084,25 @@ BOOL LLFloaterSnapshot::postBuild() getChild("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); - // Update filter list - //std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); - //LLComboBox* filterbox = getChild("filters_combobox"); - //for (U32 i = 0; i < filter_list.size(); i++) - //{ - // filterbox->add(filter_list[i]); - //} - //childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + // Filters + LLComboBox* filterbox = getChild("filters_combobox"); + if (gSavedSettings.getBOOL("SnapshotFiltersEnabled")) + { + // Update filter list if setting is on (experimental) + std::vector filter_list = LLImageFiltersManager::getInstance()->getFiltersList(); + for (U32 i = 0; i < filter_list.size(); i++) + { + filterbox->add(filter_list[i]); + } + childSetCommitCallback("filters_combobox", Impl::onClickFilter, this); + } + else + { + // Hide Filter UI if setting is off (default) + getChild("filter_list_label")->setVisible(FALSE); + filterbox->setVisible(FALSE); + } - LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1)); LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1)); diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 5e3c7d4e3d..771035b40d 100755 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -381,7 +381,6 @@ top_pad="8" width="180" name="auto_snapshot_check" /> - diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 92913f678d..51576f71a8 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -171,16 +171,17 @@ Please try logging in again in a minute. Black & White 1970's Colors - Heat Wave Intense - Jules Verne - Newspaper - Overcast + Newsprint Sepia Spotlight Video - - + Autocontrast + Lens Flare + Miniature + Toy Camera + + Person (no name) Owner: -- cgit v1.3 From fc4efd18479f43766e7945d4ae8caf5e735f6563 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 14 Feb 2014 09:42:57 -0800 Subject: ACME-1277 : Delete debug printouts spamming the log --- indra/llimage/llimagefilter.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/llimage/llimagefilter.cpp') diff --git a/indra/llimage/llimagefilter.cpp b/indra/llimage/llimagefilter.cpp index 6e9ea2f948..3d0c488768 100755 --- a/indra/llimage/llimagefilter.cpp +++ b/indra/llimage/llimagefilter.cpp @@ -55,7 +55,6 @@ LLImageFilter::LLImageFilter(const std::string& file_path) : { // Load filter description from file llifstream filter_xml(file_path); - llinfos << "Merov : load filter : " << file_path << llendl; if (filter_xml.is_open()) { // Load and parse the file @@ -89,7 +88,6 @@ void LLImageFilter::executeFilter(LLPointer raw_image) { mImage = raw_image; - llinfos << "Merov : execute filter on image size " << mImage->getWidth() << "x" << mImage->getHeight() << llendl; //std::cout << "Filter : size = " << mFilterData.size() << std::endl; for (S32 i = 0; i < mFilterData.size(); ++i) { -- cgit v1.3