From 7372afaae4aa7097ffad1e9c070b8b9d9a611f62 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 20 Dec 2013 13:49:20 -0800 Subject: ACME-1236 : WIP : Implement colorTransform filter, grayscale and sepia using it, add parameter to llimage_libtest to use filters --- .../llimage_libtest/llimage_libtest.cpp | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 034c816742..e485136f58 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -83,6 +83,9 @@ static const char USAGE[] = "\n" " -rev, --reversible\n" " Set the compression to be lossless (reversible in j2c parlance).\n" " Only valid for output j2c images.\n" +" -f, --filter \n" +" Apply the filter to the input images.\n" +" Note: so far, only grayscale and sepia are supported.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -350,6 +353,7 @@ int main(int argc, char** argv) int blocks_size = -1; int levels = 0; bool reversible = false; + std::string filter_name = ""; // Init whatever is necessary ll_init_apr(); @@ -523,6 +527,26 @@ int main(int argc, char** argv) break; } } + else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f")) + { + // '--filter' needs to be specified with a named filter argument + // Note: for the moment, only sepia and grayscale are supported + if ((arg + 1) < argc) + { + filter_name = argv[arg+1]; + } + if (((arg + 1) >= argc) || (filter_name[0] == '-')) + { + // We don't have an argument left in the arg list or the next argument is another option + std::cout << "No --filter argument given, no filter will be applied" << std::endl; + } + else + { + arg += 1; // Skip that arg now we know it's a valid test name + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } + } else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) { analyze_performance = true; @@ -568,6 +592,16 @@ int main(int argc, char** argv) std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl; continue; } + + // Apply filter if any + if (filter_name == "sepia") + { + raw_image->filterSepia(); + } + else if (filter_name == "grayscale") + { + raw_image->filterGrayScale(); + } // Save file if (out_file != out_end) -- cgit v1.3 From 08a798bb1d88708765041adf21a784911842f101 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 30 Dec 2013 20:33:33 -0800 Subject: ACME-1236 : WIP : Implement saturation/desaturation transform filter, add it to llimage_libtest for testing --- .../llimage_libtest/llimage_libtest.cpp | 4 +++ indra/llimage/llimage.cpp | 31 ++++++++++++++++++++++ indra/llimage/llimage.h | 1 + 3 files changed, 36 insertions(+) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index e485136f58..cbd6ccebbf 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -602,6 +602,10 @@ int main(int argc, char** argv) { raw_image->filterGrayScale(); } + else if (filter_name == "saturate") + { + raw_image->filterSaturate(2.0f); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 73e6f48a8d..4028514898 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -955,6 +955,37 @@ void LLImageRaw::filterSepia() 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(0.7071, 0.7071, 0.0), + LLVector3(-0.7071, 0.7071, 0.0), + LLVector3(0.0, 0.0, 1.0)); + // 54.73 degre rotation around y + r_b.setRows(LLVector3(0.5773, 0.0, -0.8165), + LLVector3(0.0, 1.0, 0.0), + LLVector3(0.8165, 0.0, 0.5773)); + + // 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); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index d6b7e65c76..1742cf8a71 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -260,6 +260,7 @@ public: // Filter Operations void filterGrayScale(); void filterSepia(); + void filterSaturate(F32 s); // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.3 From 218d305c443d4e5ddba03c6f4a988924939d805d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 1 Jan 2014 17:13:06 -0800 Subject: ACME-1236 : WIP : add an optional filter parameter to llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 23 ++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index cbd6ccebbf..d1535bf3cf 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -83,9 +83,10 @@ static const char USAGE[] = "\n" " -rev, --reversible\n" " Set the compression to be lossless (reversible in j2c parlance).\n" " Only valid for output j2c images.\n" -" -f, --filter \n" -" Apply the filter to the input images.\n" -" Note: so far, only grayscale and sepia are supported.\n" +" -f, --filter []\n" +" Apply the filter to the input images using the optional param (float) value.\n" +" Notes: - 'grayscale' and 'sepia' are supported (no param).\n" +" - 'saturate' uses the param: param < 1.0 will desaturate the colors, param > 1.0 will saturate them.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -354,6 +355,7 @@ int main(int argc, char** argv) int levels = 0; bool reversible = false; std::string filter_name = ""; + double filter_param = 0.0; // Init whatever is necessary ll_init_apr(); @@ -530,7 +532,6 @@ int main(int argc, char** argv) else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f")) { // '--filter' needs to be specified with a named filter argument - // Note: for the moment, only sepia and grayscale are supported if ((arg + 1) < argc) { filter_name = argv[arg+1]; @@ -545,7 +546,17 @@ int main(int argc, char** argv) arg += 1; // Skip that arg now we know it's a valid test name if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; - } + // --filter can also have an optional parameter + std::string value_str; + value_str = argv[arg+1]; // Check the next arg + if (value_str[0] != '-') // If it's not another argument, it's a filter parameter value + { + filter_param = atof(value_str.c_str()); + arg += 1; // Skip that arg now we used it as a valid filter param + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } + } } else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) { @@ -604,7 +615,7 @@ int main(int argc, char** argv) } else if (filter_name == "saturate") { - raw_image->filterSaturate(2.0f); + raw_image->filterSaturate((float)(filter_param)); } // Save file -- cgit v1.3 From 9dca514c0b416c1b15e9a63e6f5af1b52df70b7e Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 1 Jan 2014 17:58:52 -0800 Subject: ACME-1236 : WIP : add filterRotate to rotate hue, add rotate as a valid argument to --filter in llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 11 +++-- indra/llimage/llimage.cpp | 48 +++++++++++++++++++--- indra/llimage/llimage.h | 3 +- 3 files changed, 52 insertions(+), 10 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index d1535bf3cf..1f9a5f0e18 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -84,9 +84,10 @@ static const char USAGE[] = "\n" " Set the compression to be lossless (reversible in j2c parlance).\n" " Only valid for output j2c images.\n" " -f, --filter []\n" -" Apply the filter to the input images using the optional param (float) value.\n" -" Notes: - 'grayscale' and 'sepia' are supported (no param).\n" -" - 'saturate' uses the param: param < 1.0 will desaturate the colors, param > 1.0 will saturate them.\n" +" Apply the filter to the input images using the optional param (float) value:\n" +" - 'grayscale' and 'sepia' just do that (no param).\n" +" - 'saturate' changes color saturation according to param: param < 1.0 will desaturate, param > 1.0 will saturate.\n" +" - 'rotate' rotates the color hue according to param (in degree, positive value only).\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -617,6 +618,10 @@ int main(int argc, char** argv) { raw_image->filterSaturate((float)(filter_param)); } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(filter_param)); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 4028514898..8b7c352437 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -962,13 +962,15 @@ void LLImageRaw::filterSaturate(F32 saturation) LLMatrix3 r_b; // 45 degre rotation around z - r_a.setRows(LLVector3(0.7071, 0.7071, 0.0), - LLVector3(-0.7071, 0.7071, 0.0), - LLVector3(0.0, 0.0, 1.0)); + 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 - r_b.setRows(LLVector3(0.5773, 0.0, -0.8165), - LLVector3(0.0, 1.0, 0.0), - LLVector3(0.8165, 0.0, 0.5773)); + 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; @@ -986,6 +988,40 @@ void LLImageRaw::filterSaturate(F32 saturation) colorTransform(transfo); } +void LLImageRaw::filterRotate(F32 alpha) +{ + // 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; + alpha *= DEG_TO_RAD; + r.setRows(LLVector3( cosf(alpha), sinf(alpha), 0.0), + LLVector3(-sinf(alpha), cosf(alpha), 0.0), + LLVector3( 0.0, 0.0, 1.0)); + + // Global color rotation transform + LLMatrix3 transfo = Lij_inv * r * Lij; + colorTransform(transfo); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 1742cf8a71..3a9c088dbd 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -260,7 +260,8 @@ public: // Filter Operations void filterGrayScale(); void filterSepia(); - void filterSaturate(F32 s); + void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates + void filterRotate(F32 alpha); // rotates hue, alpha in degrees // Filter Primitives void colorTransform(const LLMatrix3 &transform); -- cgit v1.3 From 205a4e3dc63c338c05e27a4806cdfd6f50bac2b6 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 1 Jan 2014 19:42:10 -0800 Subject: ACME-1236 : WIP : add filterGamma, computeHistograms, colorCorrect, implemented filter gamma to llimage_libtest for testing --- .../llimage_libtest/llimage_libtest.cpp | 4 + indra/llimage/llimage.cpp | 92 +++++++++++++++++++++- indra/llimage/llimage.h | 11 +++ 3 files changed, 103 insertions(+), 4 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 1f9a5f0e18..afd5e2ce98 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -622,6 +622,10 @@ int main(int argc, char** argv) { raw_image->filterRotate((float)(filter_param)); } + else if (filter_name == "gamma") + { + raw_image->filterGamma((float)(filter_param)); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 8b7c352437..d406995f3a 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -97,7 +97,11 @@ LLImageBase::LLImageBase() mHeight(0), mComponents(0), mBadBufferAllocation(false), - mAllowOverSize(false) + mAllowOverSize(false), + mHistoRed(NULL), + mHistoGreen(NULL), + mHistoBlue(NULL), + mHistoBrightness(NULL) { } @@ -105,10 +109,14 @@ 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 -void LLImageBase::createPrivatePool() +//static +void LLImageBase::createPrivatePool() { if(!sPrivatePoolp) { @@ -1022,6 +1030,18 @@ void LLImageRaw::filterRotate(F32 alpha) colorTransform(transfo); } +void LLImageRaw::filterGamma(F32 gamma) +{ + U8 gamma_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + gamma_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma))))); + } + + colorCorrect(gamma_lut,gamma_lut,gamma_lut); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { @@ -1030,7 +1050,7 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform) S32 pixels = getWidth() * getHeight(); U8* dst_data = getData(); - for( S32 i=0; i= 1 && components <= 4 ); + + S32 pixels = getWidth() * getHeight(); + U8* dst_data = getData(); + for (S32 i = 0; i < pixels; i++) + { + dst_data[VRED] = lut_red[dst_data[VRED]]; + dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; + dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; + dst_data += components; + } +} + +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 3a9c088dbd..89734693cc 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -151,6 +151,12 @@ 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; + public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -262,8 +268,11 @@ public: void filterSepia(); void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates void filterRotate(F32 alpha); // rotates hue, alpha in degrees + void filterGamma(F32 gamma); // Apply a gamma lookup to all channels + // Filter Primitives void colorTransform(const LLMatrix3 &transform); + void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); protected: // Create an image from a local file (generally used in tools) @@ -276,6 +285,8 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; + void computeHistograms(); + public: static S32 sGlobalRawMemory; static S32 sRawImageCount; -- cgit v1.3 From d28b92744ee0d4a19a5587585998e5c351f6d300 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 2 Jan 2014 16:14:38 -0800 Subject: ACME-1236 : WIP : added all the color correction filters: colorize, linarize, equalize, contrast, brightness --- .../llimage_libtest/CMakeLists.txt | 3 + .../llimage_libtest/llimage_libtest.cpp | 44 +++++- indra/llimage/llimage.cpp | 155 +++++++++++++++++++++ indra/llimage/llimage.h | 16 ++- 4 files changed, 209 insertions(+), 9 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt index 36a7d38bb7..8a83ac498f 100755 --- a/indra/integration_tests/llimage_libtest/CMakeLists.txt +++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt @@ -7,6 +7,7 @@ project (llimage_libtest) include(00-Common) include(LLCommon) include(LLImage) +include(LLMath) include(LLImageJ2COJ) include(LLKDU) include(LLVFS) @@ -15,6 +16,7 @@ include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLVFS_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} ) include_directories(SYSTEM ${LLCOMMON_SYSTEM_INCLUDE_DIRS} @@ -64,6 +66,7 @@ endif (DARWIN) target_link_libraries(llimage_libtest ${LLCOMMON_LIBRARIES} ${LLVFS_LIBRARIES} + ${LLMATH_LIBRARIES} ${LLIMAGE_LIBRARIES} ${LLKDU_LIBRARIES} ${KDU_LIBRARY} diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index afd5e2ce98..4d32282a0d 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -39,6 +39,7 @@ #include "llimagej2c.h" #include "lldir.h" #include "lldiriterator.h" +#include "v4coloru.h" // system libraries #include @@ -84,10 +85,18 @@ static const char USAGE[] = "\n" " Set the compression to be lossless (reversible in j2c parlance).\n" " Only valid for output j2c images.\n" " -f, --filter []\n" -" Apply the filter to the input images using the optional param (float) value:\n" -" - 'grayscale' and 'sepia' just do that (no param).\n" -" - 'saturate' changes color saturation according to param: param < 1.0 will desaturate, param > 1.0 will saturate.\n" -" - 'rotate' rotates the color hue according to param (in degree, positive value only).\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" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -626,6 +635,33 @@ int main(int argc, char** argv) { raw_image->filterGamma((float)(filter_param)); } + else if (filter_name == "colorize") + { + // For testing, we just colorize in red, modulate by the alpha passed as a parameter + LLColor4U color = LLColor4U::red; + color.setAlpha((U8)(filter_param * 255.0)); + raw_image->filterColorize(color); + } + else if (filter_name == "contrast") + { + raw_image->filterContrast((float)(filter_param)); + } + else if (filter_name == "brighten") + { + raw_image->filterBrightness((S32)(filter_param)); + } + else if (filter_name == "darken") + { + raw_image->filterBrightness((S32)(-filter_param)); + } + else if (filter_name == "linearize") + { + raw_image->filterLinearize((float)(filter_param)); + } + else if (filter_name == "posterize") + { + raw_image->filterEqualize((S32)(filter_param)); + } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index d406995f3a..5dc9c24f6c 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1042,6 +1042,152 @@ void LLImageRaw::filterGamma(F32 gamma) colorCorrect(gamma_lut,gamma_lut,gamma_lut); } +void LLImageRaw::filterLinearize(F32 tail) +{ + // 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_lut[256]; + if (max_v == min_v) + { + // Degenerated binary split case + for (S32 i = 0; i < 256; i++) + { + linear_lut[i] = (i < min_v ? 0 : 255); + } + } + 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++) + { + linear_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + } + } + + // Apply lookup table + colorCorrect(linear_lut,linear_lut,linear_lut); +} + +void LLImageRaw::filterEqualize(S32 nb_classes) +{ + // 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_lut[256]; + for (S32 i = 0; i < 256; i++) + { + equalize_lut[i] = (U8)(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_lut,equalize_lut,equalize_lut); +} + +void LLImageRaw::filterColorize(const LLColor4U& color) +{ + U8 red_lut[256]; + U8 green_lut[256]; + U8 blue_lut[256]; + + F32 alpha = (F32)(color.mV[3])/255.0; + F32 inv_alpha = 1.0 - alpha; + + F32 red_composite = alpha * (F32)(color.mV[0]); + F32 green_composite = alpha * (F32)(color.mV[1]); + F32 blue_composite = alpha * (F32)(color.mV[2]); + + for (S32 i = 0; i < 256; i++) + { + red_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + red_composite))); + green_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + green_composite))); + blue_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + blue_composite))); + } + + colorCorrect(red_lut,green_lut,blue_lut); +} + +void LLImageRaw::filterContrast(F32 slope) +{ + U8 contrast_lut[256]; + + F32 translate = 128.0 * (1.0 - slope); + + for (S32 i = 0; i < 256; i++) + { + contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + } + + colorCorrect(contrast_lut,contrast_lut,contrast_lut); +} + +void LLImageRaw::filterBrightness(S32 add) +{ + U8 brightness_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + brightness_lut[i] = (U8)(llclampb((S32)((S32)(i) + add))); + } + + colorCorrect(brightness_lut,brightness_lut,brightness_lut); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { @@ -1078,6 +1224,15 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } +U32* LLImageRaw::getBrightnessHistogram() +{ + if (!mHistoBrightness) + { + computeHistograms(); + } + return mHistoBrightness; +} + void LLImageRaw::computeHistograms() { const S32 components = getComponents(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 89734693cc..b62deadee0 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -264,15 +264,21 @@ public: void compositeUnscaled4onto3( LLImageRaw* src ); // Filter Operations - void filterGrayScale(); - void filterSepia(); - void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates - void filterRotate(F32 alpha); // rotates hue, alpha in degrees - void filterGamma(F32 gamma); // Apply a gamma lookup to all channels + void filterGrayScale(); // Convert to grayscale + void filterSepia(); // Convert to sepia + void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates + void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha in degrees + void filterGamma(F32 gamma); // Apply gamma to all channels + void filterLinearize(F32 tail); // Use histogram to linearize constrast between min and max values minus tail + void filterEqualize(S32 nb_classes); // Use histogram to equalize constrast throughout the image + void filterColorize(const LLColor4U& color); // Colorize with color. Alpha will be taken into account for colorization intensity. + void filterContrast(F32 slope); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast + void filterBrightness(S32 add); // 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); + U32* getBrightnessHistogram(); protected: // Create an image from a local file (generally used in tools) -- cgit v1.3 From 1b5fb662927ac84606cf767c8c9ec350e82b656f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 3 Jan 2014 14:19:29 -0800 Subject: ACME-1236 : WIP : Added the vignette mode. Can be applied to colorCorrect and color Transform. Added new -v argument to llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 47 ++++++++- indra/llimage/llimage.cpp | 106 +++++++++++++++++---- indra/llimage/llimage.h | 16 ++++ 3 files changed, 152 insertions(+), 17 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 4d32282a0d..45e60f64e6 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -97,6 +97,10 @@ static const char USAGE[] = "\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" +" -v, --vignette []\n" +" Apply a circular central vignette to the filter using the optional value. 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" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -366,6 +370,8 @@ int main(int argc, char** argv) bool reversible = false; std::string filter_name = ""; double filter_param = 0.0; + std::string vignette_name = ""; + double vignette_param = 1.0; // Init whatever is necessary ll_init_apr(); @@ -568,7 +574,36 @@ int main(int argc, char** argv) } } } - else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) + else if (!strcmp(argv[arg], "--vignette") || !strcmp(argv[arg], "-v")) + { + // '--vignette' needs to be specified with a named vignette argument + if ((arg + 1) < argc) + { + vignette_name = argv[arg+1]; + } + if (((arg + 1) >= argc) || (vignette_name[0] == '-')) + { + // We don't have an argument left in the arg list or the next argument is another option + std::cout << "No --vignette argument given, no vignette will be applied to filters" << std::endl; + } + else + { + arg += 1; // Skip that arg now we know it's a valid vignette name + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + // --vignette can also have an optional parameter + std::string value_str; + value_str = argv[arg+1]; // Check the next arg + if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value + { + vignette_param = atof(value_str.c_str()); + arg += 1; // Skip that arg now we used it as a valid vignette param + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } + } + } + else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) { analyze_performance = true; } @@ -614,6 +649,16 @@ int main(int argc, char** argv) continue; } + // Set the vignette if any + if (vignette_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param)); + } + else if (vignette_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param)); + } + // Apply filter if any if (filter_name == "sepia") { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 5dc9c24f6c..da22ed5e5b 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -101,7 +101,9 @@ LLImageBase::LLImageBase() mHistoRed(NULL), mHistoGreen(NULL), mHistoBlue(NULL), - mHistoBrightness(NULL) + mHistoBrightness(NULL), + mVignetteMode(VIGNETTE_MODE_NONE), + mVignetteGamma(1.0) { } @@ -1194,17 +1196,44 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform) const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); - S32 pixels = getWidth() * getHeight(); + S32 width = getWidth(); + S32 height = getHeight(); + U8* dst_data = getData(); - for (S32 i = 0; i < pixels; i++) + for (S32 j = 0; j < height; j++) { - LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE])); - LLVector3 dst = src * transform; - dst.clamp(0.0f,255.0f); - dst_data[VRED] = dst.mV[VRED]; - dst_data[VGREEN] = dst.mV[VGREEN]; - dst_data[VBLUE] = dst.mV[VBLUE]; - dst_data += components; + 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; + } } } @@ -1213,17 +1242,62 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); - S32 pixels = getWidth() * getHeight(); + S32 width = getWidth(); + S32 height = getHeight(); + U8* dst_data = getData(); - for (S32 i = 0; i < pixels; i++) + for (S32 j = 0; j < height; j++) { - dst_data[VRED] = lut_red[dst_data[VRED]]; - dst_data[VGREEN] = lut_green[dst_data[VGREEN]]; - dst_data[VBLUE] = lut_blue[dst_data[VBLUE]]; - dst_data += components; + 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::setVignette(EVignetteMode mode, F32 gamma) +{ + mVignetteMode = mode; + mVignetteGamma = gamma; + // 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) +{ + // 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 to 0.0 + F32 d_center_square = (i - mVignetteCenterX)*(i - mVignetteCenterX) + (j - mVignetteCenterY)*(j - mVignetteCenterY); + return powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); +} + U32* LLImageRaw::getBrightnessHistogram() { if (!mHistoBrightness) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index b62deadee0..b9f6a12bdd 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -87,6 +87,13 @@ 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; + //============================================================================ // library initialization class @@ -157,6 +164,13 @@ protected: U32 *mHistoBlue; U32 *mHistoBrightness; + // Vignette filtering + EVignetteMode mVignetteMode; + S32 mVignetteCenterX; + S32 mVignetteCenterY; + S32 mVignetteWidth; + F32 mVignetteGamma; + public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -278,6 +292,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); + void setVignette(EVignetteMode mode, F32 gamma); U32* getBrightnessHistogram(); protected: @@ -292,6 +307,7 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; void computeHistograms(); + F32 getVignetteAlpha(S32 i, S32 j); public: static S32 sGlobalRawMemory; -- cgit v1.3 From 35e30759c82e0fa425e2ee5ba235868a25b44169 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 3 Jan 2014 15:44:29 -0800 Subject: ACME-1236 : WIP : Added a min value to vignette --- .../llimage_libtest/llimage_libtest.cpp | 23 +++++++++++++++------- indra/llimage/llimage.cpp | 12 +++++++---- indra/llimage/llimage.h | 3 ++- 3 files changed, 26 insertions(+), 12 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 45e60f64e6..6c23a6a866 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -97,8 +97,8 @@ static const char USAGE[] = "\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" -" -v, --vignette []\n" -" Apply a circular central vignette to the filter using the optional value. Admissible names:\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" " -log, --logmetrics \n" @@ -371,7 +371,8 @@ int main(int argc, char** argv) std::string filter_name = ""; double filter_param = 0.0; std::string vignette_name = ""; - double vignette_param = 1.0; + double vignette_param_1 = 1.0; + double vignette_param_2 = 0.0; // Init whatever is necessary ll_init_apr(); @@ -591,15 +592,23 @@ int main(int argc, char** argv) arg += 1; // Skip that arg now we know it's a valid vignette name if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; - // --vignette can also have an optional parameter + // --vignette can also have optional parameters std::string value_str; value_str = argv[arg+1]; // Check the next arg if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value { - vignette_param = atof(value_str.c_str()); + vignette_param_1 = atof(value_str.c_str()); arg += 1; // Skip that arg now we used it as a valid vignette param if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; + value_str = argv[arg+1]; // Check the next arg + if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value + { + vignette_param_2 = atof(value_str.c_str()); + arg += 1; // Skip that arg now we used it as a valid vignette param + if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list + break; + } } } } @@ -652,11 +661,11 @@ int main(int argc, char** argv) // Set the vignette if any if (vignette_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param)); + raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param_1),(float)(vignette_param_2)); } else if (vignette_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param)); + raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(vignette_param_1),(float)(vignette_param_2)); } // Apply filter if any diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index da22ed5e5b..d84989f9c8 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -103,7 +103,8 @@ LLImageBase::LLImageBase() mHistoBlue(NULL), mHistoBrightness(NULL), mVignetteMode(VIGNETTE_MODE_NONE), - mVignetteGamma(1.0) + mVignetteGamma(1.0), + mVignetteMin(0.0) { } @@ -1280,10 +1281,11 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } -void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma) +void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) { mVignetteMode = mode; 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; @@ -1293,9 +1295,11 @@ void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma) F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) { // 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 to 0.0 + // 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); - return powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + F32 alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + // 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() diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index b9f6a12bdd..404f1c0769 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -170,6 +170,7 @@ protected: S32 mVignetteCenterY; S32 mVignetteWidth; F32 mVignetteGamma; + F32 mVignetteMin; public: static void generateMip(const U8 *indata, U8* mipdata, int width, int height, S32 nchannels); @@ -292,7 +293,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); - void setVignette(EVignetteMode mode, F32 gamma); + void setVignette(EVignetteMode mode, F32 gamma, F32 min); U32* getBrightnessHistogram(); protected: -- cgit v1.3 From 90cbda6db0d075dccc2369a68b02919b40f53cca Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 3 Jan 2014 17:31:04 -0800 Subject: ACME-1236 : WIP : Add 2 new color correction filters. Add a la Instagram composite filters for testing in llimage_libtest --- .../llimage_libtest/llimage_libtest.cpp | 40 +++++++++++++++++++++- indra/llimage/llimage.cpp | 33 ++++++++++++++++++ indra/llimage/llimage.h | 4 ++- 3 files changed, 75 insertions(+), 2 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 6c23a6a866..58d7f53dd1 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -716,7 +716,45 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param)); } - + // Test for some "a la Instagram" filters + else if (filter_name == "Lomofi") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0); + raw_image->filterLinearize(0.2); + } + else if (filter_name == "Sutro") + { + raw_image->filterLinearize(0.2); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterSepia(); + } + else if (filter_name == "Inkwell") + { + raw_image->filterLinearize(0.0); + raw_image->filterGrayScale(); + } + else if (filter_name == "Poprocket") + { + LLColor4U color = LLColor4U::red; + color.setAlpha((U8)(0.2 * 255.0)); + raw_image->filterLinearize(0.0); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterColorize(color); + } + else if (filter_name == "Gotham") + { + raw_image->filterLinearize(0.0); + raw_image->filterColorBalance(1.0,1.0,20.0); + raw_image->filterGrayScale(); + } + else if (filter_name == "Toaster") + { + raw_image->filterContrast(0.8); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterBrightness(10); + raw_image->filterColorBalance(0.5,1.0,1.0); + } + // Save file if (out_file != out_end) { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index d84989f9c8..3d86abb26d 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1045,6 +1045,22 @@ void LLImageRaw::filterGamma(F32 gamma) colorCorrect(gamma_lut,gamma_lut,gamma_lut); } +void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue) +{ + U8 gamma_red_lut[256]; + U8 gamma_green_lut[256]; + U8 gamma_blue_lut[256]; + + for (S32 i = 0; i < 256; i++) + { + gamma_red_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_red))))); + gamma_green_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_green))))); + gamma_blue_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_blue))))); + } + + colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut); +} + void LLImageRaw::filterLinearize(F32 tail) { // Get the histogram @@ -1191,6 +1207,23 @@ void LLImageRaw::filterBrightness(S32 add) colorCorrect(brightness_lut,brightness_lut,brightness_lut); } +void LLImageRaw::filterMinMax(S32 min, S32 max) +{ + U8 contrast_lut[256]; + min = llclampb(min); + max = llclampb(max); + + F32 slope = 255.0/(F32)(max - min); + F32 translate = -slope*min; + + for (S32 i = 0; i < 256; i++) + { + contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + } + + colorCorrect(contrast_lut,contrast_lut,contrast_lut); +} + // Filter Primitives void LLImageRaw::colorTransform(const LLMatrix3 &transform) { diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 404f1c0769..6e58453da5 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -289,7 +289,9 @@ public: void filterColorize(const LLColor4U& color); // Colorize with color. Alpha will be taken into account for colorization intensity. void filterContrast(F32 slope); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast void filterBrightness(S32 add); // Change brightness according to add: > 0 brighter, < 0 darker - + void filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue); // Change the color balance applying gammas to each channel + void filterMinMax(S32 min, S32 max); // Redistribute contrast / brightness between min and max in a linear way + // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); -- cgit v1.3 From 3cbd0dfd849a94a789ae70f4bdc176f85cf2ba34 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 6 Jan 2014 14:46:52 -0800 Subject: ACME-1236 : WIP : Make each color correct filter use a per channel alpha argument, tweak Instagram-like test filters for discussion --- .../llimage_libtest/llimage_libtest.cpp | 66 +++++++----- indra/llimage/llimage.cpp | 118 ++++++++++----------- indra/llimage/llimage.h | 24 +++-- 3 files changed, 111 insertions(+), 97 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 58d7f53dd1..6045ed321d 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -687,73 +687,85 @@ int main(int argc, char** argv) } else if (filter_name == "gamma") { - raw_image->filterGamma((float)(filter_param)); + raw_image->filterGamma((float)(filter_param),LLColor3::white); } else if (filter_name == "colorize") { - // For testing, we just colorize in red, modulate by the alpha passed as a parameter - LLColor4U color = LLColor4U::red; - color.setAlpha((U8)(filter_param * 255.0)); - raw_image->filterColorize(color); + // 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)); + raw_image->filterContrast((float)(filter_param),LLColor3::white); } else if (filter_name == "brighten") { - raw_image->filterBrightness((S32)(filter_param)); + raw_image->filterBrightness((S32)(filter_param),LLColor3::white); } else if (filter_name == "darken") { - raw_image->filterBrightness((S32)(-filter_param)); + raw_image->filterBrightness((S32)(-filter_param),LLColor3::white); } else if (filter_name == "linearize") { - raw_image->filterLinearize((float)(filter_param)); + raw_image->filterLinearize((float)(filter_param),LLColor3::white); } else if (filter_name == "posterize") { - raw_image->filterEqualize((S32)(filter_param)); + raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } // Test for some "a la Instagram" filters else if (filter_name == "Lomofi") { raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0); - raw_image->filterLinearize(0.2); + raw_image->filterLinearize(0.2,LLColor3::white); + raw_image->filterBrightness(20,LLColor3::white); + } + else if (filter_name == "Poprocket") + { + LLColor3 color(1.0,0.0,0.0); + LLColor3 alpha(0.5,0.0,0.0); + raw_image->filterLinearize(0.0,LLColor3::white); + raw_image->filterContrast(0.5,LLColor3::white); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterColorize(color,alpha); } else if (filter_name == "Sutro") { - raw_image->filterLinearize(0.2); + raw_image->filterLinearize(0.2,LLColor3::white); raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); raw_image->filterSepia(); } + else if (filter_name == "Toaster") + { + raw_image->filterContrast(0.8,LLColor3::white); + raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); + raw_image->filterBrightness(10,LLColor3::white); + //raw_image->filterColorBalance(0.5,1.0,1.0); + } else if (filter_name == "Inkwell") { - raw_image->filterLinearize(0.0); + raw_image->filterLinearize(0.0,LLColor3::white); raw_image->filterGrayScale(); } - else if (filter_name == "Poprocket") + else if (filter_name == "Hefe") { - LLColor4U color = LLColor4U::red; - color.setAlpha((U8)(0.2 * 255.0)); - raw_image->filterLinearize(0.0); + raw_image->filterLinearize(0.0,LLColor3::white); raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterColorize(color); + raw_image->filterContrast(1.5,LLColor3::white); } else if (filter_name == "Gotham") { - raw_image->filterLinearize(0.0); - raw_image->filterColorBalance(1.0,1.0,20.0); + raw_image->filterLinearize(0.0,LLColor3::white); + // Blow out the Blue + LLColor3 color(0.0,0.0,0.0); + LLColor3 alpha(0.0,0.0,1.0); + raw_image->filterColorize(color,alpha); + // Convert to Grayscale raw_image->filterGrayScale(); } - else if (filter_name == "Toaster") - { - raw_image->filterContrast(0.8); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterBrightness(10); - raw_image->filterColorBalance(0.5,1.0,1.0); - } // Save file if (out_file != out_end) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 3d86abb26d..977bb09b63 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -29,6 +29,7 @@ #include "llimage.h" #include "llmath.h" +#include "v3color.h" #include "v4coloru.h" #include "m3math.h" #include "v3math.h" @@ -1033,19 +1034,7 @@ void LLImageRaw::filterRotate(F32 alpha) colorTransform(transfo); } -void LLImageRaw::filterGamma(F32 gamma) -{ - U8 gamma_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - gamma_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma))))); - } - - colorCorrect(gamma_lut,gamma_lut,gamma_lut); -} - -void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue) +void LLImageRaw::filterGamma(F32 gamma, const LLColor3& alpha) { U8 gamma_red_lut[256]; U8 gamma_green_lut[256]; @@ -1053,15 +1042,17 @@ void LLImageRaw::filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_bl for (S32 i = 0; i < 256; i++) { - gamma_red_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_red))))); - gamma_green_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_green))))); - gamma_blue_lut[i] = (U8)(255.0 * (llclampf((float)(pow((float)(i)/255.0,gamma_blue))))); + F32 gamma_i = llclampf((float)(pow((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) +void LLImageRaw::filterLinearize(F32 tail, const LLColor3& alpha) { // Get the histogram U32* histo = getBrightnessHistogram(); @@ -1093,13 +1084,19 @@ void LLImageRaw::filterLinearize(F32 tail) } // Compute linear lookup table - U8 linear_lut[256]; + 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++) { - linear_lut[i] = (i < min_v ? 0 : 255); + 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 @@ -1109,15 +1106,19 @@ void LLImageRaw::filterLinearize(F32 tail) F32 translate = -min_v * slope; for (S32 i = 0; i < 256; i++) { - linear_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + 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_lut,linear_lut,linear_lut); + colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut); } -void LLImageRaw::filterEqualize(S32 nb_classes) +void LLImageRaw::filterEqualize(S32 nb_classes, const LLColor3& alpha) { // Regularize the parameter: must be between 2 and 255 nb_classes = llmax(nb_classes,2); @@ -1142,10 +1143,15 @@ void LLImageRaw::filterEqualize(S32 nb_classes) S32 current_value = 0; // Compute equalized lookup table - U8 equalize_lut[256]; + U8 equalize_red_lut[256]; + U8 equalize_green_lut[256]; + U8 equalize_blue_lut[256]; for (S32 i = 0; i < 256; i++) { - equalize_lut[i] = (U8)(current_value); + // 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; @@ -1155,73 +1161,65 @@ void LLImageRaw::filterEqualize(S32 nb_classes) } // Apply lookup table - colorCorrect(equalize_lut,equalize_lut,equalize_lut); + colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut); } -void LLImageRaw::filterColorize(const LLColor4U& color) +void LLImageRaw::filterColorize(const LLColor3& color, const LLColor3& alpha) { U8 red_lut[256]; U8 green_lut[256]; U8 blue_lut[256]; - F32 alpha = (F32)(color.mV[3])/255.0; - F32 inv_alpha = 1.0 - alpha; - - F32 red_composite = alpha * (F32)(color.mV[0]); - F32 green_composite = alpha * (F32)(color.mV[1]); - F32 blue_composite = alpha * (F32)(color.mV[2]); + 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)(inv_alpha*(F32)(i) + red_composite))); - green_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + green_composite))); - blue_lut[i] = (U8)(llclampb((S32)(inv_alpha*(F32)(i) + blue_composite))); + 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) +void LLImageRaw::filterContrast(F32 slope, const LLColor3& alpha) { - U8 contrast_lut[256]; + 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++) { - contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + 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_lut,contrast_lut,contrast_lut); + colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut); } -void LLImageRaw::filterBrightness(S32 add) +void LLImageRaw::filterBrightness(S32 add, const LLColor3& alpha) { - U8 brightness_lut[256]; - - for (S32 i = 0; i < 256; i++) - { - brightness_lut[i] = (U8)(llclampb((S32)((S32)(i) + add))); - } - - colorCorrect(brightness_lut,brightness_lut,brightness_lut); -} - -void LLImageRaw::filterMinMax(S32 min, S32 max) -{ - U8 contrast_lut[256]; - min = llclampb(min); - max = llclampb(max); - - F32 slope = 255.0/(F32)(max - min); - F32 translate = -slope*min; + U8 brightness_red_lut[256]; + U8 brightness_green_lut[256]; + U8 brightness_blue_lut[256]; for (S32 i = 0; i < 256; i++) { - contrast_lut[i] = (U8)(llclampb((S32)(slope*i + translate))); + 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(contrast_lut,contrast_lut,contrast_lut); + colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut); } // Filter Primitives diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 6e58453da5..cc91f95624 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -71,6 +71,7 @@ const S32 HTTP_PACKET_SIZE = 1496; class LLImageFormatted; class LLImageRaw; class LLColor4U; +class LLColor3; class LLMatrix3; class LLPrivateMemoryPool; @@ -278,19 +279,22 @@ public: // Src and dst are same size. Src has 4 components. Dst has 3 components. void compositeUnscaled4onto3( LLImageRaw* src ); - // Filter Operations + // 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 alpha); // Rotates hue according to alpha, alpha in degrees - void filterGamma(F32 gamma); // Apply gamma to all channels - void filterLinearize(F32 tail); // Use histogram to linearize constrast between min and max values minus tail - void filterEqualize(S32 nb_classes); // Use histogram to equalize constrast throughout the image - void filterColorize(const LLColor4U& color); // Colorize with color. Alpha will be taken into account for colorization intensity. - void filterContrast(F32 slope); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast - void filterBrightness(S32 add); // Change brightness according to add: > 0 brighter, < 0 darker - void filterColorBalance(F32 gamma_red, F32 gamma_green, F32 gamma_blue); // Change the color balance applying gammas to each channel - void filterMinMax(S32 min, S32 max); // Redistribute contrast / brightness between min and max in a linear way + void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha is an 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); -- cgit v1.3 From 5187e709c923429554ab89600a0b27cb9cedd567 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 7 Jan 2014 16:17:25 -0800 Subject: ACME-1236 : WIP : Add filter file loading and execution to llimage_libtest, suppress the a la Instagram tests as a result --- .../llimage_libtest/llimage_libtest.cpp | 156 ++++++++++++++------- 1 file changed, 107 insertions(+), 49 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 6045ed321d..009be0941e 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -40,6 +40,7 @@ #include "lldir.h" #include "lldiriterator.h" #include "v4coloru.h" +#include "llsdserialize.h" // system libraries #include @@ -97,6 +98,7 @@ static const char USAGE[] = "\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" +" - 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" @@ -114,10 +116,110 @@ static const char USAGE[] = "\n" // true when all image loading is done. Used by metric logging thread to know when to stop the thread. static bool sAllDone = false; +// Load filter from file +LLSD load_filter_from_file(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 it + LLSD filter_data(LLSD::emptyArray()); + LLPointer parser = new LLSDXMLParser(); + parser->parse(filter_xml, filter_data, LLSDSerialize::SIZE_UNLIMITED); + filter_xml.close(); + return filter_data; + } + else + { + return LLSD(); + } +} + +// Apply the filter data to the image passed as parameter +void execute_filter(const LLSD& filter_data, LLPointer raw_image) +{ + //std::cout << "Filter : size = " << filter_data.size() << std::endl; + for (S32 i = 0; i < filter_data.size(); ++i) + { + std::string filter_name = filter_data[i][0].asString(); + // Dump out the filter values (for debug) + //std::cout << "Filter : name = " << filter_data[i][0].asString() << ", params = "; + //for (S32 j = 1; j < filter_data[i].size(); ++j) + //{ + // std::cout << filter_data[i][j].asString() << ", "; + //} + //std::cout << std::endl; + + // Execute the filter described on this line + if (filter_name == "blend") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + } + else if (filter_name == "fade") + { + raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(filter_data[i][1].asReal()),(float)(filter_data[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)(filter_data[i][1].asReal())); + } + else if (filter_name == "rotate") + { + raw_image->filterRotate((float)(filter_data[i][1].asReal())); + } + else if (filter_name == "gamma") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterGamma((float)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "colorize") + { + LLColor3 color((float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal())); + LLColor3 alpha((F32)(filter_data[i][4].asReal()),(float)(filter_data[i][5].asReal()),(float)(filter_data[i][6].asReal())); + raw_image->filterColorize(color,alpha); + } + else if (filter_name == "contrast") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterContrast((float)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "brighten") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterBrightness((S32)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "darken") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterBrightness((S32)(-filter_data[i][1].asReal()),color); + } + else if (filter_name == "linearize") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterLinearize((float)(filter_data[i][1].asReal()),color); + } + else if (filter_name == "posterize") + { + LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); + raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color); + } + } +} + // Create an empty formatted image instance of the correct type from the filename LLPointer create_image(const std::string &filename) { - std::string exten = gDirUtilp->getExtension(filename); + std::string exten = gDirUtilp->getExtension(filename); LLPointer image = LLImageFormatted::createFromExtension(exten); return image; } @@ -716,55 +818,11 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } - // Test for some "a la Instagram" filters - else if (filter_name == "Lomofi") + else if (filter_name != "") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,4.0,0.0); - raw_image->filterLinearize(0.2,LLColor3::white); - raw_image->filterBrightness(20,LLColor3::white); - } - else if (filter_name == "Poprocket") - { - LLColor3 color(1.0,0.0,0.0); - LLColor3 alpha(0.5,0.0,0.0); - raw_image->filterLinearize(0.0,LLColor3::white); - raw_image->filterContrast(0.5,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "Sutro") - { - raw_image->filterLinearize(0.2,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterSepia(); - } - else if (filter_name == "Toaster") - { - raw_image->filterContrast(0.8,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterBrightness(10,LLColor3::white); - //raw_image->filterColorBalance(0.5,1.0,1.0); - } - else if (filter_name == "Inkwell") - { - raw_image->filterLinearize(0.0,LLColor3::white); - raw_image->filterGrayScale(); - } - else if (filter_name == "Hefe") - { - raw_image->filterLinearize(0.0,LLColor3::white); - raw_image->setVignette(VIGNETTE_MODE_FADE,4.0,0.5); - raw_image->filterContrast(1.5,LLColor3::white); - } - else if (filter_name == "Gotham") - { - raw_image->filterLinearize(0.0,LLColor3::white); - // Blow out the Blue - LLColor3 color(0.0,0.0,0.0); - LLColor3 alpha(0.0,0.0,1.0); - raw_image->filterColorize(color,alpha); - // Convert to Grayscale - raw_image->filterGrayScale(); + // We're interpreting the filter as a filter file name + LLSD filter_data = load_filter_from_file(filter_name); + execute_filter(filter_data,raw_image); } // Save file -- cgit v1.3 From c2a974f1556906f6ca69afb5942378c8dbf85169 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Tue, 7 Jan 2014 22:10:23 -0800 Subject: ACME-1236 : WIP : Introduced screenFilter, simple creative screening filter --- .../llimage_libtest/llimage_libtest.cpp | 11 +++++- indra/llimage/llimage.cpp | 46 ++++++++++++++++++++++ indra/llimage/llimage.h | 1 + 3 files changed, 56 insertions(+), 2 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 009be0941e..69cea33911 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -119,8 +119,7 @@ static bool sAllDone = false; // Load filter from file LLSD load_filter_from_file(const std::string& file_path) { - std::cout << "Loading filter settings from : " << file_path << std::endl; - + //std::cout << "Loading filter settings from : " << file_path << std::endl; llifstream filter_xml(file_path); if (filter_xml.is_open()) { @@ -213,6 +212,10 @@ void execute_filter(const LLSD& filter_data, LLPointer raw_image) LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color); } + else if (filter_name == "screen") + { + raw_image->screenFilter((S32)(filter_data[i][1].asReal())); + } } } @@ -818,6 +821,10 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } + else if (filter_name == "screen") + { + raw_image->screenFilter((S32)(filter_param)); + } else if (filter_name != "") { // We're interpreting the filter as a filter file name diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 977bb09b63..ae3de32788 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1312,6 +1312,52 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } +void LLImageRaw::screenFilter(const S32 wave_length) +{ + 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++) + { + F32 value = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; + //F32 value = (sinf(2*F_PI*i/wave_length)+1.0)*255.0/2.0; // will do line + 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, F32 gamma, F32 min) { mVignetteMode = mode; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index cc91f95624..ed17f1af21 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -299,6 +299,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); + void screenFilter(const S32 wave_length); void setVignette(EVignetteMode mode, F32 gamma, F32 min); U32* getBrightnessHistogram(); -- cgit v1.3 From 3161d822ab1336a347f1bb34574b5c4b8e747799 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 8 Jan 2014 15:41:42 -0800 Subject: ACME-1236 : WIP : Added mode and angle parameter to filterScreen (renamed for consistency) --- .../llimage_libtest/llimage_libtest.cpp | 34 +++++++++++++++++++--- indra/llimage/llimage.cpp | 28 +++++++++++++----- indra/llimage/llimage.h | 10 +++++-- 3 files changed, 59 insertions(+), 13 deletions(-) (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 69cea33911..90a7c09442 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -98,7 +98,11 @@ static const char USAGE[] = "\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" -" - 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" +" - '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" @@ -214,7 +218,17 @@ void execute_filter(const LLSD& filter_data, LLPointer raw_image) } else if (filter_name == "screen") { - raw_image->screenFilter((S32)(filter_data[i][1].asReal())); + std::string screen_name = filter_data[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)(filter_data[i][2].asReal()),(F32)(filter_data[i][3].asReal())); } } } @@ -821,9 +835,21 @@ int main(int argc, char** argv) { raw_image->filterEqualize((S32)(filter_param),LLColor3::white); } - else if (filter_name == "screen") + 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->screenFilter((S32)(filter_param)); + raw_image->filterScreen(SCREEN_MODE_LINE,(S32)(filter_param),45.0); } else if (filter_name != "") { diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index ae3de32788..a30646d846 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1000,7 +1000,7 @@ void LLImageRaw::filterSaturate(F32 saturation) colorTransform(transfo); } -void LLImageRaw::filterRotate(F32 alpha) +void LLImageRaw::filterRotate(F32 angle) { // Matrix to Lij LLMatrix3 r_a; @@ -1024,9 +1024,9 @@ void LLImageRaw::filterRotate(F32 alpha) // Local color rotation transform LLMatrix3 r; - alpha *= DEG_TO_RAD; - r.setRows(LLVector3( cosf(alpha), sinf(alpha), 0.0), - LLVector3(-sinf(alpha), cosf(alpha), 0.0), + 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 @@ -1312,7 +1312,7 @@ void LLImageRaw::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* } } -void LLImageRaw::screenFilter(const S32 wave_length) +void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle) { const S32 components = getComponents(); llassert( components >= 1 && components <= 4 ); @@ -1320,14 +1320,28 @@ void LLImageRaw::screenFilter(const S32 wave_length) 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 = (sinf(2*F_PI*i/wave_length)*sinf(2*F_PI*j/wave_length)+1.0)*255.0/2.0; - //F32 value = (sinf(2*F_PI*i/wave_length)+1.0)*255.0/2.0; // will do line + 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; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index ed17f1af21..f2bb91a329 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -95,6 +95,12 @@ typedef enum e_vignette_mode VIGNETTE_MODE_FADE = 2 } EVignetteMode; +typedef enum e_screen_mode +{ + SCREEN_MODE_2DSINE = 0, + SCREEN_MODE_LINE = 1 +} EScreenMode; + //============================================================================ // library initialization class @@ -283,7 +289,7 @@ public: void filterGrayScale(); // Convert to grayscale void filterSepia(); // Convert to sepia void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates - void filterRotate(F32 alpha); // Rotates hue according to alpha, alpha is an angle in degrees + 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 @@ -299,7 +305,7 @@ public: // Filter Primitives void colorTransform(const LLMatrix3 &transform); void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue); - void screenFilter(const S32 wave_length); + void filterScreen(EScreenMode mode, const S32 wave_length, const F32 angle); void setVignette(EVignetteMode mode, F32 gamma, F32 min); U32* getBrightnessHistogram(); -- cgit v1.3 From 0c7cab771cb7972ed44eedf0c16133ef082eb9e1 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 9 Jan 2014 21:58:30 -0800 Subject: ACME-1236 : Add lines as a new type of vignette and Brightscan as an example --- .../llimage_libtest/llimage_libtest.cpp | 12 +++++++---- indra/llimage/llimage.cpp | 21 +++++++++++++++----- indra/llimage/llimage.h | 9 ++++++++- indra/newview/app_settings/filters/Brightscan.xml | 23 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) create mode 100755 indra/newview/app_settings/filters/Brightscan.xml (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 90a7c09442..2447e00028 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -158,11 +158,15 @@ void execute_filter(const LLSD& filter_data, LLPointer raw_image) // Execute the filter described on this line if (filter_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); } else if (filter_name == "fade") { - raw_image->setVignette(VIGNETTE_MODE_FADE,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); + } + else if (filter_name == "lines") + { + raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); } else if (filter_name == "sepia") { @@ -780,11 +784,11 @@ int main(int argc, char** argv) // Set the vignette if any if (vignette_name == "blend") { - raw_image->setVignette(VIGNETTE_MODE_BLEND,(float)(vignette_param_1),(float)(vignette_param_2)); + 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,(float)(vignette_param_1),(float)(vignette_param_2)); + raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(vignette_param_1),(float)(vignette_param_2)); } // Apply filter if any diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 14fa71d828..3105fe3746 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -1372,9 +1372,10 @@ void LLImageRaw::filterScreen(EScreenMode mode, const S32 wave_length, const F32 } } -void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) +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 @@ -1385,10 +1386,20 @@ void LLImageRaw::setVignette(EVignetteMode mode, F32 gamma, F32 min) F32 LLImageRaw::getVignetteAlpha(S32 i, S32 j) { - // 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); - F32 alpha = powf(F_E, -(powf((d_center_square/(mVignetteWidth*mVignetteWidth)),mVignetteGamma)/2.0f)); + 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)); } diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index f2bb91a329..a600f2e4a6 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -95,6 +95,12 @@ typedef enum e_vignette_mode 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, @@ -173,6 +179,7 @@ protected: // Vignette filtering EVignetteMode mVignetteMode; + EVignetteType mVignetteType; S32 mVignetteCenterX; S32 mVignetteCenterY; S32 mVignetteWidth; @@ -306,7 +313,7 @@ public: 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, F32 gamma, F32 min); + void setVignette(EVignetteMode mode, EVignetteType type, F32 gamma, F32 min); U32* getBrightnessHistogram(); protected: diff --git a/indra/newview/app_settings/filters/Brightscan.xml b/indra/newview/app_settings/filters/Brightscan.xml new file mode 100755 index 0000000000..8b10687ef5 --- /dev/null +++ b/indra/newview/app_settings/filters/Brightscan.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 + + + -- cgit v1.3 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 --- .../llimage_libtest/llimage_libtest.cpp | 274 +-------------------- indra/llimage/CMakeLists.txt | 2 + indra/llimage/llimagefilter.cpp | 269 ++++++++++++++++++++ indra/llimage/llimagefilter.h | 73 ++++++ 4 files changed, 351 insertions(+), 267 deletions(-) create mode 100755 indra/llimage/llimagefilter.cpp create mode 100755 indra/llimage/llimagefilter.h (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 2447e00028..d3373a61f2 100755 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -32,6 +32,7 @@ // Linden library includes #include "llimage.h" +#include "llimagefilter.h" #include "llimagejpeg.h" #include "llimagepng.h" #include "llimagebmp.h" @@ -85,28 +86,8 @@ static const char USAGE[] = "\n" " -rev, --reversible\n" " Set the compression to be lossless (reversible in j2c parlance).\n" " Only valid for output j2c images.\n" -" -f, --filter []\n" -" Apply the filter to the input images 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" +" -f, --filter \n" +" Apply the filter to the input images.\n" " -log, --logmetrics \n" " Log performance data for . Results in .slp\n" " Note: so far, only ImageCompressionTester has been tested.\n" @@ -120,123 +101,6 @@ static const char USAGE[] = "\n" // true when all image loading is done. Used by metric logging thread to know when to stop the thread. static bool sAllDone = false; -// Load filter from file -LLSD load_filter_from_file(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 it - LLSD filter_data(LLSD::emptyArray()); - LLPointer parser = new LLSDXMLParser(); - parser->parse(filter_xml, filter_data, LLSDSerialize::SIZE_UNLIMITED); - filter_xml.close(); - return filter_data; - } - else - { - return LLSD(); - } -} - -// Apply the filter data to the image passed as parameter -void execute_filter(const LLSD& filter_data, LLPointer raw_image) -{ - //std::cout << "Filter : size = " << filter_data.size() << std::endl; - for (S32 i = 0; i < filter_data.size(); ++i) - { - std::string filter_name = filter_data[i][0].asString(); - // Dump out the filter values (for debug) - //std::cout << "Filter : name = " << filter_data[i][0].asString() << ", params = "; - //for (S32 j = 1; j < filter_data[i].size(); ++j) - //{ - // std::cout << filter_data[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)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); - } - else if (filter_name == "fade") - { - raw_image->setVignette(VIGNETTE_MODE_FADE,VIGNETTE_TYPE_CENTER,(float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal())); - } - else if (filter_name == "lines") - { - raw_image->setVignette(VIGNETTE_MODE_BLEND,VIGNETTE_TYPE_LINES,(float)(filter_data[i][1].asReal()),(float)(filter_data[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)(filter_data[i][1].asReal())); - } - else if (filter_name == "rotate") - { - raw_image->filterRotate((float)(filter_data[i][1].asReal())); - } - else if (filter_name == "gamma") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterGamma((float)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "colorize") - { - LLColor3 color((float)(filter_data[i][1].asReal()),(float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal())); - LLColor3 alpha((F32)(filter_data[i][4].asReal()),(float)(filter_data[i][5].asReal()),(float)(filter_data[i][6].asReal())); - raw_image->filterColorize(color,alpha); - } - else if (filter_name == "contrast") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterContrast((float)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "brighten") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterBrightness((S32)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "darken") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterBrightness((S32)(-filter_data[i][1].asReal()),color); - } - else if (filter_name == "linearize") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterLinearize((float)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "posterize") - { - LLColor3 color((float)(filter_data[i][2].asReal()),(float)(filter_data[i][3].asReal()),(float)(filter_data[i][4].asReal())); - raw_image->filterEqualize((S32)(filter_data[i][1].asReal()),color); - } - else if (filter_name == "screen") - { - std::string screen_name = filter_data[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)(filter_data[i][2].asReal()),(F32)(filter_data[i][3].asReal())); - } - } -} - // Create an empty formatted image instance of the correct type from the filename LLPointer create_image(const std::string &filename) { @@ -492,10 +356,6 @@ int main(int argc, char** argv) int levels = 0; bool reversible = false; std::string filter_name = ""; - double filter_param = 0.0; - std::string vignette_name = ""; - double vignette_param_1 = 1.0; - double vignette_param_2 = 0.0; // Init whatever is necessary ll_init_apr(); @@ -686,53 +546,6 @@ int main(int argc, char** argv) arg += 1; // Skip that arg now we know it's a valid test name if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list break; - // --filter can also have an optional parameter - std::string value_str; - value_str = argv[arg+1]; // Check the next arg - if (value_str[0] != '-') // If it's not another argument, it's a filter parameter value - { - filter_param = atof(value_str.c_str()); - arg += 1; // Skip that arg now we used it as a valid filter param - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - } - } - } - else if (!strcmp(argv[arg], "--vignette") || !strcmp(argv[arg], "-v")) - { - // '--vignette' needs to be specified with a named vignette argument - if ((arg + 1) < argc) - { - vignette_name = argv[arg+1]; - } - if (((arg + 1) >= argc) || (vignette_name[0] == '-')) - { - // We don't have an argument left in the arg list or the next argument is another option - std::cout << "No --vignette argument given, no vignette will be applied to filters" << std::endl; - } - else - { - arg += 1; // Skip that arg now we know it's a valid vignette name - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - // --vignette can also have optional parameters - std::string value_str; - value_str = argv[arg+1]; // Check the next arg - if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value - { - vignette_param_1 = atof(value_str.c_str()); - arg += 1; // Skip that arg now we used it as a valid vignette param - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - value_str = argv[arg+1]; // Check the next arg - if (value_str[0] != '-') // If it's not another argument, it's a vignette parameter value - { - vignette_param_2 = atof(value_str.c_str()); - arg += 1; // Skip that arg now we used it as a valid vignette param - if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list - break; - } - } } } else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a")) @@ -781,85 +594,12 @@ int main(int argc, char** argv) continue; } - // 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); - } - else if (filter_name != "") + if (filter_name != "") { // We're interpreting the filter as a filter file name - LLSD filter_data = load_filter_from_file(filter_name); - execute_filter(filter_data,raw_image); + LLImageFilter filter; + filter.loadFromFile(filter_name); + filter.executeFilter(raw_image); } // Save file diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index e837b0cac2..293ada7548 100755 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -27,6 +27,7 @@ set(llimage_SOURCE_FILES llimage.cpp llimagedimensionsinfo.cpp llimagedxt.cpp + llimagefilter.cpp llimagej2c.cpp llimagejpeg.cpp llimagepng.cpp @@ -42,6 +43,7 @@ set(llimage_HEADER_FILES llimagebmp.h llimagedimensionsinfo.h llimagedxt.h + llimagefilter.h llimagej2c.h llimagejpeg.h llimagepng.h diff --git a/indra/llimage/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())); + } + } +} + + +//============================================================================ diff --git a/indra/llimage/llimagefilter.h b/indra/llimage/llimagefilter.h new file mode 100755 index 0000000000..5598fa69f5 --- /dev/null +++ b/indra/llimage/llimagefilter.h @@ -0,0 +1,73 @@ +/** + * @file llimagefilter.h + * @brief Simple Image Filtering. + * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2014, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLIMAGEFILTER_H +#define LL_LLIMAGEFILTER_H + +#include "llimage.h" + +/* +class LLImageRaw; +class LLColor4U; +class LLColor3; +class LLMatrix3; + +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; +*/ +//============================================================================ +// Image Filter + +class LLImageFilter +{ +public: + LLImageFilter(); + ~LLImageFilter(); + + void loadFromFile(const std::string& file_path); + void executeFilter(LLPointer raw_image); +private: + LLSD mFilterData; +}; + + +#endif -- 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/integration_tests') 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 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/integration_tests') 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 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/integration_tests') 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/integration_tests') 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/integration_tests') 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 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/integration_tests') 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/integration_tests') 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 23727d02c8c941051a1aef8a51ecb493b65a2063 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 6 Feb 2014 18:23:54 -0800 Subject: ACME-1277 : Add a set of creative filters to the llimage_libtest/filters examples --- .../llimage_libtest/filters/badtrip.xml | 36 ++++++ .../llimage_libtest/filters/blowhighlights.xml | 25 ++++ .../llimage_libtest/filters/dodgeandburn.xml | 47 +++++++ .../llimage_libtest/filters/focus.xml | 39 ++++++ .../llimage_libtest/filters/lensflare.xml | 138 +++++++++++++++++++++ 5 files changed, 285 insertions(+) create mode 100755 indra/integration_tests/llimage_libtest/filters/badtrip.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/blowhighlights.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/focus.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/lensflare.xml (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/filters/badtrip.xml b/indra/integration_tests/llimage_libtest/filters/badtrip.xml new file mode 100755 index 0000000000..14ee0baff3 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/badtrip.xml @@ -0,0 +1,36 @@ + + + + grayscale + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + posterize + 10.0 + 1.0 + 1.0 + 1.0 + + + gradient + + + colorize + 0.0 + 0.0 + 1.0 + 0.0 + 0.0 + 0.15 + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml new file mode 100644 index 0000000000..2474a1b953 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/blowhighlights.xml @@ -0,0 +1,25 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + stencil + uniform + add + 0.0 + 1.0 + + + gamma + 0.25 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml new file mode 100644 index 0000000000..0e2e0ad68c --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/dodgeandburn.xml @@ -0,0 +1,47 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + add + 0.0 + 0.4 + 0.0 + 0.0 + 1.0 + 2.0 + + + contrast + 1.0 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + add + -0.8 + 0.0 + 0.0 + 0.0 + 1.0 + 2.0 + + + contrast + 1.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/focus.xml b/indra/integration_tests/llimage_libtest/filters/focus.xml new file mode 100644 index 0000000000..d8525fea62 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/focus.xml @@ -0,0 +1,39 @@ + + + + linearize + 0.0 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + blend + 0.0 + 0.4 + 0.0 + 0.0 + 0.5 + 2.0 + + + sharpen + + + stencil + vignette + blend + 1.0 + 0.0 + 0.0 + 0.0 + 0.5 + 2.0 + + + blur + + + diff --git a/indra/integration_tests/llimage_libtest/filters/lensflare.xml b/indra/integration_tests/llimage_libtest/filters/lensflare.xml new file mode 100644 index 0000000000..ec8afc8daa --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/lensflare.xml @@ -0,0 +1,138 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + brighten + 0.1 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + add + 0.0 + 0.4 + -0.5 + 0.5 + 0.15 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.15 + 0.15 + 0.15 + + + stencil + vignette + add + 0.0 + 0.4 + -0.5 + 0.5 + 0.20 + 20.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.6 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 0.5 + -0.7 + 0.7 + 0.10 + 20.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 + + + -- cgit v1.3 From 2887d191ebd8bd9fff2a163e8b20acdeb4a82b5a Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 12 Feb 2014 17:05:03 -0800 Subject: ACME-1277 : Add new example filter scripts --- .../llimage_libtest/filters/autocontrast.xml | 11 ++ .../llimage_libtest/filters/lightleak.xml | 78 ++++++++++++++ .../llimage_libtest/filters/miniature.xml | 118 +++++++++++++++++++++ .../llimage_libtest/filters/pixelate.xml | 18 ++++ .../llimage_libtest/filters/thematrix.xml | 42 ++++++++ .../llimage_libtest/filters/toycamera.xml | 46 ++++++++ 6 files changed, 313 insertions(+) create mode 100755 indra/integration_tests/llimage_libtest/filters/autocontrast.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/lightleak.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/miniature.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/pixelate.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/thematrix.xml create mode 100755 indra/integration_tests/llimage_libtest/filters/toycamera.xml (limited to 'indra/integration_tests') diff --git a/indra/integration_tests/llimage_libtest/filters/autocontrast.xml b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml new file mode 100755 index 0000000000..ec3d7561bd --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/autocontrast.xml @@ -0,0 +1,11 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/lightleak.xml b/indra/integration_tests/llimage_libtest/filters/lightleak.xml new file mode 100755 index 0000000000..6fe496506e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/lightleak.xml @@ -0,0 +1,78 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + brighten + 0.1 + 1.0 + 1.0 + 1.0 + + + stencil + gradient + add + 1.0 + 0.0 + -1.0 + 1.0 + 1.0 + -1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.1 + 0.1 + 0.0 + + + stencil + vignette + add + 0.0 + 1.0 + -1.0 + 1.0 + 1.5 + 5.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.8 + 0.0 + 0.0 + + + stencil + vignette + add + 0.0 + 1.0 + -1.0 + 1.0 + 1.0 + 5.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.8 + 0.8 + 0.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/miniature.xml b/indra/integration_tests/llimage_libtest/filters/miniature.xml new file mode 100755 index 0000000000..9aa8a87c6f --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/miniature.xml @@ -0,0 +1,118 @@ + + + + linearize + 0.02 + 1.0 + 1.0 + 1.0 + + + contrast + 1.02 + 1.0 + 1.0 + 1.0 + + + saturate + 1.2 + + + stencil + vignette + blend + 0.0 + 0.25 + 0.0 + 0.0 + 0.25 + 2.0 + + + sharpen + + + stencil + gradient + blend + 1.0 + 0.0 + 0.0 + -1.0 + 0.0 + -0.25 + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + stencil + gradient + blend + 1.0 + 0.0 + 0.0 + 1.0 + 0.0 + 0.25 + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + blur + + + \ No newline at end of file diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml new file mode 100755 index 0000000000..4c9e8255fe --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml @@ -0,0 +1,18 @@ + + + + linearize + 0.01 + 1.0 + 1.0 + 1.0 + + + posterize + 5.0 + 1.0 + 1.0 + 1.0 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/thematrix.xml b/indra/integration_tests/llimage_libtest/filters/thematrix.xml new file mode 100755 index 0000000000..af9a5eced8 --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/thematrix.xml @@ -0,0 +1,42 @@ + + + + grayscale + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + posterize + 50.0 + 1.0 + 1.0 + 1.0 + + + gradient + + + screen + line + 0.025 + 90.0 + + + colorize + 0.0 + 1.0 + 0.0 + 0.1 + 0.2 + 0.2 + + + blur + + + \ No newline at end of file diff --git a/indra/integration_tests/llimage_libtest/filters/toycamera.xml b/indra/integration_tests/llimage_libtest/filters/toycamera.xml new file mode 100755 index 0000000000..4e76f6b2fb --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/toycamera.xml @@ -0,0 +1,46 @@ + + + + stencil + vignette + fade + 0.0 + 1.0 + 0.0 + 0.0 + 1.2 + 3.0 + + + linearize + 0.05 + 1.0 + 1.0 + 1.0 + + + grayscale + + + contrast + 1.1 + 1.0 + 1.0 + 1.0 + + + stencil + vignette + blend + 1.0 + 0.0 + 0.0 + 0.0 + 0.5 + 2.0 + + + blur + + + \ No newline at end of file -- cgit v1.3 From 170b5aed71446bf891ef4095812ccbfba7f4bab1 Mon Sep 17 00:00:00 2001 From: Cho Date: Thu, 13 Feb 2014 19:54:58 +0000 Subject: Updated test filters --- .../llimage_libtest/filters/heatwave.xml | 38 ++++++++++++++++++++++ .../llimage_libtest/filters/overcast.xml | 24 ++++++++++++++ .../llimage_libtest/filters/pixelate.xml | 21 ++++++++++-- .../llimage_libtest/filters/video.xml | 31 +++++++++++++++--- 4 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 indra/integration_tests/llimage_libtest/filters/heatwave.xml create mode 100644 indra/integration_tests/llimage_libtest/filters/overcast.xml (limited to 'indra/integration_tests') 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/overcast.xml b/indra/integration_tests/llimage_libtest/filters/overcast.xml new file mode 100644 index 0000000000..dce5ab3e9e --- /dev/null +++ b/indra/integration_tests/llimage_libtest/filters/overcast.xml @@ -0,0 +1,24 @@ + + + + linearize + 0.1 + 1.0 + 1.0 + 1.0 + + + colorize + 1.0 + 1.0 + 1.0 + 0.0 + 0.3 + 0.0 + + + saturate + 0.35 + + + diff --git a/indra/integration_tests/llimage_libtest/filters/pixelate.xml b/indra/integration_tests/llimage_libtest/filters/pixelate.xml index 4c9e8255fe..f643419aa0 100755 --- a/indra/integration_tests/llimage_libtest/filters/pixelate.xml +++ b/indra/integration_tests/llimage_libtest/filters/pixelate.xml @@ -1,5 +1,22 @@ + + blur + + + darken + 0.1 + 1.0 + 1.0 + 1.0 + + + contrast + 0.9 + 1.0 + 1.0 + 1.0 + linearize 0.01 @@ -9,10 +26,10 @@ posterize - 5.0 + 4.0 1.0 1.0 1.0 - + \ No newline at end of file diff --git a/indra/integration_tests/llimage_libtest/filters/video.xml b/indra/integration_tests/llimage_libtest/filters/video.xml index 8b10687ef5..fe17f3950a 100755 --- a/indra/integration_tests/llimage_libtest/filters/video.xml +++ b/indra/integration_tests/llimage_libtest/filters/video.xml @@ -2,22 +2,43 @@ linearize - 0.01 + 0.0 1.0 1.0 1.0 - lines - 10.0 + darken + 0.15 + 1.0 + 1.0 + 1.0 + + + stencil + uniform + add 0.0 + 0.5 - brighten - 100.0 + screen + line + 0.02 + 0.0 + + + gamma + 0.25 1.0 1.0 1.0 + + blur + + + blur + -- 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/integration_tests') 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