summaryrefslogtreecommitdiff
path: root/indra/llimage/llimage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llimage/llimage.cpp')
-rwxr-xr-xindra/llimage/llimage.cpp527
1 files changed, 1 insertions, 526 deletions
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();