From 205a4e3dc63c338c05e27a4806cdfd6f50bac2b6 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 1 Jan 2014 19:42:10 -0800
Subject: [PATCH] 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(-)

diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 1f9a5f0e18f..afd5e2ce98e 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 8b7c352437e..d406995f3a2 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<pixels; i++ )
+	for (S32 i = 0; i < pixels; i++)
 	{
         LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
         LLVector3 dst = src * transform;
@@ -1042,6 +1062,70 @@ void LLImageRaw::colorTransform(const LLMatrix3 &transform)
 	}
 }
 
+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 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 3a9c088dbd3..89734693ccf 100755
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -151,6 +151,12 @@ class LLImageBase : public LLThreadSafeRefCount
 	// 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 @@ class LLImageRaw : public LLImageBase
     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 @@ class LLImageRaw : public LLImageBase
 
 	void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ;
 
+    void computeHistograms();
+
 public:
 	static S32 sGlobalRawMemory;
 	static S32 sRawImageCount;
-- 
GitLab