ACME-1236 : WIP : add filterGamma, computeHistograms, colorCorrect, implemented filter gamma to llimage_libtest for testing
parent
9dca514c0b
commit
205a4e3dc6
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue