1. fixed many warnings about implicit double to int conversions in newly

checked in "advanced" image manipulation stuff
   (could we please avoid checking in the code with warnings?)
2. tried to simplify the new code a little, but much remains to be done,
   in particular it seems obvious that BlurVertical/Horizontal() must be
   refactored to avoid duplicating each other
3. reformatted (avoid jumbo lines, removed unnecessary double casts, declare
   the variables at the point of use, ...)

Hope this didn't break anything but as there are no tests it's really hard to
find out how was this supposed to behave.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41418 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2006-09-24 13:58:52 +00:00
parent 8d37334f0e
commit 30f27c00d6

View File

@@ -429,22 +429,25 @@ wxImage wxImage::Scale( int width, int height, int quality ) const
wxCHECK_MSG( (old_height > 0) && (old_width > 0), image, wxCHECK_MSG( (old_height > 0) && (old_width > 0), image,
wxT("invalid old image size") ); wxT("invalid old image size") );
// If the image's new width and height are the same as the original, no need to waste time or CPU cycles // If the image's new width and height are the same as the original, no
if(old_width == width && old_height == height) // need to waste time or CPU cycles
if ( old_width == width && old_height == height )
return *this; return *this;
// Scale the image (...or more appropriately, resample the image) using either the high-quality or normal method as specified // Scale the image (...or more appropriately, resample the image) using
if(quality == wxIMAGE_QUALITY_HIGH) // either the high-quality or normal method as specified
if ( quality == wxIMAGE_QUALITY_HIGH )
{ {
// We need to check whether we are downsampling or upsampling the image // We need to check whether we are downsampling or upsampling the image
if(width < old_width && height < old_height) if ( width < old_width && height < old_height )
{ {
// Downsample the image using the box averaging method for best results // Downsample the image using the box averaging method for best results
image = ResampleBox(width, height); image = ResampleBox(width, height);
} }
else else
{ {
// For upsampling or other random/wierd image dimensions we'll use a bicubic b-spline scaling method // For upsampling or other random/wierd image dimensions we'll use
// a bicubic b-spline scaling method
image = ResampleBicubic(width, height); image = ResampleBicubic(width, height);
} }
} }
@@ -524,59 +527,66 @@ wxImage wxImage::Scale( int width, int height, int quality ) const
wxImage wxImage::ResampleBox(int width, int height) const wxImage wxImage::ResampleBox(int width, int height) const
{ {
// This function implements a simple pre-blur/box averaging method for downsampling that gives reasonably smooth results // This function implements a simple pre-blur/box averaging method for
// To scale the image down we will need to gather a grid of pixels of the size of the scale factor in each direction // downsampling that gives reasonably smooth results To scale the image
// and then do an averaging of the pixels. // down we will need to gather a grid of pixels of the size of the scale
// factor in each direction and then do an averaging of the pixels.
wxImage ret_image(width, height, false); wxImage ret_image(width, height, false);
double scale_factor_x = double(M_IMGDATA->m_width) / width; const double scale_factor_x = double(M_IMGDATA->m_width) / width;
double scale_factor_y = double(M_IMGDATA->m_height) / height; const double scale_factor_y = double(M_IMGDATA->m_height) / height;
const int scale_factor_x_2 = (int)(scale_factor_x / 2);
const int scale_factor_y_2 = (int)(scale_factor_y / 2);
// If we want good-looking results we need to pre-blur the image a bit first // If we want good-looking results we need to pre-blur the image a bit first
wxImage src_image(*this); wxImage src_image(*this);
src_image = src_image.BlurHorizontal(scale_factor_x / 2); src_image = src_image.BlurHorizontal(scale_factor_x_2);
src_image = src_image.BlurVertical(scale_factor_y / 2); src_image = src_image.BlurVertical(scale_factor_y_2);
unsigned char* src_data = src_image.GetData(); unsigned char* src_data = src_image.GetData();
unsigned char* src_alpha = src_image.GetAlpha(); unsigned char* src_alpha = src_image.GetAlpha();
unsigned char* dst_data = ret_image.GetData(); unsigned char* dst_data = ret_image.GetData();
unsigned char* dst_alpha = NULL; unsigned char* dst_alpha = NULL;
if(src_alpha) if ( src_alpha )
{ {
ret_image.SetAlpha(); ret_image.SetAlpha();
dst_alpha = ret_image.GetAlpha(); dst_alpha = ret_image.GetAlpha();
} }
int x, y, i, j; int averaged_pixels, src_pixel_index;
int averaged_pixels, src_pixel_index, src_x, src_y;
double sum_r, sum_g, sum_b, sum_a; double sum_r, sum_g, sum_b, sum_a;
for(y = 0; y < height; y++) // Destination image - Y direction for ( int y = 0; y < height; y++ ) // Destination image - Y direction
{ {
// Source pixel in the Y direction // Source pixel in the Y direction
src_y = y * scale_factor_y; int src_y = (int)(y * scale_factor_y);
for(x = 0; x < width; x++) // Destination image - X direction for ( int x = 0; x < width; x++ ) // Destination image - X direction
{ {
// Source pixel in the X direction // Source pixel in the X direction
src_x = x * scale_factor_x; int src_x = (int)(x * scale_factor_x);
// Box of pixels to average // Box of pixels to average
averaged_pixels = 0; averaged_pixels = 0;
sum_r = sum_g = sum_b = sum_a = 0.0; sum_r = sum_g = sum_b = sum_a = 0.0;
for(j = src_y - scale_factor_y / 2 + 1; j <= int(src_y + scale_factor_y / 2); j++) // Y direction for ( int j = src_y - scale_factor_y_2 + 1;
j <= int(src_y + scale_factor_y_2);
j++ )
{ {
// We don't care to average pixels that don't exist (edges) // We don't care to average pixels that don't exist (edges)
if(j < 0 || j > M_IMGDATA->m_height) if ( j < 0 || j > M_IMGDATA->m_height )
continue; continue;
for(i = src_x - scale_factor_x / 2 + 1; i <= int(src_x + scale_factor_x / 2); i++) // X direction for ( int i = src_x - scale_factor_x_2 + 1;
i <= src_x + scale_factor_x_2;
i++ )
{ {
// Don't average edge pixels // Don't average edge pixels
if(i < 0 || i > M_IMGDATA->m_width) if ( i < 0 || i > M_IMGDATA->m_width )
continue; continue;
// Calculate the actual index in our source pixels // Calculate the actual index in our source pixels
@@ -585,7 +595,7 @@ wxImage wxImage::ResampleBox(int width, int height) const
sum_r += src_data[src_pixel_index * 3 + 0]; sum_r += src_data[src_pixel_index * 3 + 0];
sum_g += src_data[src_pixel_index * 3 + 1]; sum_g += src_data[src_pixel_index * 3 + 1];
sum_b += src_data[src_pixel_index * 3 + 2]; sum_b += src_data[src_pixel_index * 3 + 2];
if(src_alpha) if ( src_alpha )
sum_a += src_alpha[src_pixel_index]; sum_a += src_alpha[src_pixel_index];
averaged_pixels++; averaged_pixels++;
@@ -593,19 +603,20 @@ wxImage wxImage::ResampleBox(int width, int height) const
} }
// Calculate the average from the sum and number of averaged pixels // Calculate the average from the sum and number of averaged pixels
dst_data[0] = int(sum_r / averaged_pixels); dst_data[0] = (unsigned char)(sum_r / averaged_pixels);
dst_data[1] = int(sum_g / averaged_pixels); dst_data[1] = (unsigned char)(sum_g / averaged_pixels);
dst_data[2] = int(sum_b / averaged_pixels); dst_data[2] = (unsigned char)(sum_b / averaged_pixels);
dst_data += 3; dst_data += 3;
if(src_alpha) if ( src_alpha )
*dst_alpha++ = sum_a / averaged_pixels; *dst_alpha++ = (unsigned char)(sum_a / averaged_pixels);
} }
} }
return ret_image; return ret_image;
} }
// The following two local functions are for the B-spline weighting of the bicubic sampling algorithm // The following two local functions are for the B-spline weighting of the
// bicubic sampling algorithm
static inline double spline_cube(double value) static inline double spline_cube(double value)
{ {
return value <= 0.0 ? 0.0 : value * value * value; return value <= 0.0 ? 0.0 : value * value * value;
@@ -613,27 +624,40 @@ static inline double spline_cube(double value)
static inline double spline_weight(double value) static inline double spline_weight(double value)
{ {
return (spline_cube(value + 2) - 4 * spline_cube(value + 1) + 6 * spline_cube(value) - 4 * spline_cube(value - 1)) / 6; return (spline_cube(value + 2) -
4 * spline_cube(value + 1) +
6 * spline_cube(value) -
4 * spline_cube(value - 1)) / 6;
} }
// This is the bicubic resampling algorithm // This is the bicubic resampling algorithm
wxImage wxImage::ResampleBicubic(int width, int height) const wxImage wxImage::ResampleBicubic(int width, int height) const
{ {
// This function implements a Bicubic B-Spline algorithm for resampling. This method is certainly a little slower than wxImage's default // This function implements a Bicubic B-Spline algorithm for resampling.
// pixel replication method, however for most reasonably sized images not being upsampled too much on a fairly average CPU this // This method is certainly a little slower than wxImage's default pixel
// difference is hardly noticeable and the results are far more pleasing to look at. // replication method, however for most reasonably sized images not being
// upsampled too much on a fairly average CPU this difference is hardly
// noticeable and the results are far more pleasing to look at.
// //
// This particular bicubic algorithm does pixel weighting according to a B-Spline that basically implements a Gaussian bell-like // This particular bicubic algorithm does pixel weighting according to a
// weighting kernel. Because of this method the results may appear a bit blurry when upsampling by large factors. This is basically // B-Spline that basically implements a Gaussian bell-like weighting
// because a slight gaussian blur is being performed to get the smooth look of the upsampled image. // kernel. Because of this method the results may appear a bit blurry when
// upsampling by large factors. This is basically because a slight
// gaussian blur is being performed to get the smooth look of the upsampled
// image.
// Edge pixels: 3-4 possible solutions // Edge pixels: 3-4 possible solutions
// - (Wrap/tile) Wrap the image, take the color value from the opposite side of the image. // - (Wrap/tile) Wrap the image, take the color value from the opposite
// - (Mirror) Duplicate edge pixels, so that pixel at coordinate (2, n), where n is nonpositive, will have the value of (2, 1). // side of the image.
// - (Ignore) Simply ignore the edge pixels and apply the kernel only to pixels which do have all neighbours. // - (Mirror) Duplicate edge pixels, so that pixel at coordinate (2, n),
// - (Clamp) Choose the nearest pixel along the border. This takes the border pixels and extends them out to infinity. // where n is nonpositive, will have the value of (2, 1).
// - (Ignore) Simply ignore the edge pixels and apply the kernel only to
// pixels which do have all neighbours.
// - (Clamp) Choose the nearest pixel along the border. This takes the
// border pixels and extends them out to infinity.
// //
// NOTE: below the y_offset and x_offset variables are being set for edge pixels using the "Mirror" method mentioned above // NOTE: below the y_offset and x_offset variables are being set for edge
// pixels using the "Mirror" method mentioned above
wxImage ret_image; wxImage ret_image;
@@ -644,70 +668,76 @@ wxImage wxImage::ResampleBicubic(int width, int height) const
unsigned char* dst_data = ret_image.GetData(); unsigned char* dst_data = ret_image.GetData();
unsigned char* dst_alpha = NULL; unsigned char* dst_alpha = NULL;
if(src_alpha) if ( src_alpha )
{ {
ret_image.SetAlpha(); ret_image.SetAlpha();
dst_alpha = ret_image.GetAlpha(); dst_alpha = ret_image.GetAlpha();
} }
int k, i; for ( int dsty = 0; dsty < height; dsty++ )
double srcpixx, srcpixy, dx, dy;
int dstx, dsty;
double sum_r = 0, sum_g = 0, sum_b = 0, sum_a = 0; // Sums for each color channel
int x_offset = 0, y_offset = 0;
double pixel_weight;
long src_pixel_index;
for(dsty = 0; dsty < height; dsty++)
{ {
// We need to calculate the source pixel to interpolate from - Y-axis // We need to calculate the source pixel to interpolate from - Y-axis
srcpixy = double(dsty) * M_IMGDATA->m_height / height; double srcpixy = dsty * M_IMGDATA->m_height / height;
dy = srcpixy - (int)srcpixy; double dy = srcpixy - (int)srcpixy;
for(dstx = 0; dstx < width; dstx++) for ( int dstx = 0; dstx < width; dstx++ )
{ {
// X-axis of pixel to interpolate from // X-axis of pixel to interpolate from
srcpixx = double(dstx) * M_IMGDATA->m_width / width; double srcpixx = dstx * M_IMGDATA->m_width / width;
dx = srcpixx - (int)srcpixx; double dx = srcpixx - (int)srcpixx;
// Clear all the RGBA sum values // Sums for each color channel
sum_r = sum_g = sum_b = sum_a = 0; double sum_r = 0, sum_g = 0, sum_b = 0, sum_a = 0;
// Here we actually determine the RGBA values for the destination pixel // Here we actually determine the RGBA values for the destination pixel
for(k = -1; k <= 2; k++) for ( int k = -1; k <= 2; k++ )
{ {
// Y offset // Y offset
y_offset = srcpixy + double(k) < 0.0 ? 0 : (srcpixy + double(k) >= M_IMGDATA->m_height ? M_IMGDATA->m_height - 1 : srcpixy + k); int y_offset = srcpixy + k < 0.0
? 0
: srcpixy + k >= M_IMGDATA->m_height
? M_IMGDATA->m_height - 1
: (int)(srcpixy + k);
// Loop across the X axis // Loop across the X axis
for(i = -1; i <= 2; i++) for ( int i = -1; i <= 2; i++ )
{ {
// X offset // X offset
x_offset = srcpixx + double(i) < 0.0 ? 0 : (srcpixx + double(i) >= M_IMGDATA->m_width ? M_IMGDATA->m_width - 1 : srcpixx + i); int x_offset = srcpixx + i < 0.0
? 0
: srcpixx + i >= M_IMGDATA->m_width
? M_IMGDATA->m_width - 1
: (int)(srcpixx + i);
// Calculate the exact position where the source data should be pulled from based on the x_offset and y_offset // Calculate the exact position where the source data
src_pixel_index = (y_offset * M_IMGDATA->m_width) + x_offset; // should be pulled from based on the x_offset and y_offset
int src_pixel_index = y_offset*M_IMGDATA->m_width + x_offset;
// Calculate the weight for the specified pixel according to the bicubic b-spline kernel we're using for interpolation // Calculate the weight for the specified pixel according
pixel_weight = spline_weight(double(i) - dx) * spline_weight(double(k) - dy); // to the bicubic b-spline kernel we're using for
// interpolation
double
pixel_weight = spline_weight(i - dx)*spline_weight(k - dy);
// Create a sum of all velues for each color channel adjusted for the pixel's calculated weight // Create a sum of all velues for each color channel
sum_r += double(src_data[src_pixel_index * 3 + 0]) * pixel_weight; // adjusted for the pixel's calculated weight
sum_g += double(src_data[src_pixel_index * 3 + 1]) * pixel_weight; sum_r += src_data[src_pixel_index * 3 + 0] * pixel_weight;
sum_b += double(src_data[src_pixel_index * 3 + 2]) * pixel_weight; sum_g += src_data[src_pixel_index * 3 + 1] * pixel_weight;
if(src_alpha) sum_b += src_data[src_pixel_index * 3 + 2] * pixel_weight;
sum_a += double(src_alpha[src_pixel_index]) * pixel_weight; if ( src_alpha )
sum_a += src_alpha[src_pixel_index] * pixel_weight;
} }
} }
// Put the data into the destination image. The summed values are of double data type and are rounded here for accuracy // Put the data into the destination image. The summed values are
dst_data[0] = int(sum_r + 0.5); // of double data type and are rounded here for accuracy
dst_data[1] = int(sum_g + 0.5); dst_data[0] = (unsigned char)(sum_r + 0.5);
dst_data[2] = int(sum_b + 0.5); dst_data[1] = (unsigned char)(sum_g + 0.5);
dst_data[2] = (unsigned char)(sum_b + 0.5);
dst_data += 3; dst_data += 3;
if(src_alpha) if ( src_alpha )
*dst_alpha++ = sum_a; *dst_alpha++ = (unsigned char)sum_a;
} }
} }
@@ -726,79 +756,106 @@ wxImage wxImage::BlurHorizontal(int blurRadius)
unsigned char* dst_alpha = NULL; unsigned char* dst_alpha = NULL;
// Check for a mask or alpha // Check for a mask or alpha
if(M_IMGDATA->m_hasMask) if ( M_IMGDATA->m_hasMask )
ret_image.SetMaskColour(M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue); {
ret_image.SetMaskColour(M_IMGDATA->m_maskRed,
M_IMGDATA->m_maskGreen,
M_IMGDATA->m_maskBlue);
}
else else
if(src_alpha) {
if ( src_alpha )
{ {
ret_image.SetAlpha(); ret_image.SetAlpha();
dst_alpha = ret_image.GetAlpha(); dst_alpha = ret_image.GetAlpha();
} }
}
// Variables used in the blurring algorithm // number of pixels we average over
int x, y; const int blurArea = blurRadius*2 + 1;
int kernel_x;
long sum_r, sum_g, sum_b, sum_a;
long pixel_idx;
// Horizontal blurring algorithm - average all pixels in the specified blur radius in the X or horizontal direction // Horizontal blurring algorithm - average all pixels in the specified blur
for(y = 0; y < M_IMGDATA->m_height; y++) // radius in the X or horizontal direction
for ( int y = 0; y < M_IMGDATA->m_height; y++ )
{ {
sum_r = sum_g = sum_b = sum_a = 0; // Variables used in the blurring algorithm
long sum_r = 0,
sum_g = 0,
sum_b = 0,
sum_a = 0;
// Calculate the average of all pixels in the blur radius for the first pixel of the row long pixel_idx;
for(kernel_x = -blurRadius; kernel_x <= blurRadius; kernel_x++) const unsigned char *src;
unsigned char *dst;
// Calculate the average of all pixels in the blur radius for the first
// pixel of the row
for ( int kernel_x = -blurRadius; kernel_x <= blurRadius; kernel_x++ )
{ {
// To deal with the pixels at the start of a row so it's not grabbing GOK values from memory at negative indices of the image's data or grabbing from the previous row // To deal with the pixels at the start of a row so it's not
if(kernel_x < 0) // grabbing GOK values from memory at negative indices of the
// image's data or grabbing from the previous row
if ( kernel_x < 0 )
pixel_idx = y * M_IMGDATA->m_width; pixel_idx = y * M_IMGDATA->m_width;
else else
pixel_idx = kernel_x + y * M_IMGDATA->m_width; pixel_idx = kernel_x + y * M_IMGDATA->m_width;
sum_r += src_data[pixel_idx * 3 + 0]; src = src_data + pixel_idx*3;
sum_g += src_data[pixel_idx * 3 + 1]; sum_r += src[0];
sum_b += src_data[pixel_idx * 3 + 2]; sum_g += src[1];
sum_a += src_alpha ? src_alpha[pixel_idx] : 0; sum_b += src[2];
if ( src_alpha )
sum_a += src_alpha[pixel_idx];
} }
dst_data[y * M_IMGDATA->m_width * 3 + 0] = sum_r / (blurRadius * 2 + 1);
dst_data[y * M_IMGDATA->m_width * 3 + 1] = sum_g / (blurRadius * 2 + 1);
dst_data[y * M_IMGDATA->m_width * 3 + 2] = sum_b / (blurRadius * 2 + 1);
if(src_alpha)
dst_alpha[y * M_IMGDATA->m_width] = sum_a / (blurRadius * 2 + 1);
// Now average the values of the rest of the pixels by just moving the blur radius box along the row dst = dst_data + y * M_IMGDATA->m_width*3;
for(x = 1; x < M_IMGDATA->m_width; x++) dst[0] = sum_r / blurArea;
dst[1] = sum_g / blurArea;
dst[2] = sum_b / blurArea;
if ( src_alpha )
dst_alpha[y * M_IMGDATA->m_width] = sum_a / blurArea;
// Now average the values of the rest of the pixels by just moving the
// blur radius box along the row
for ( int x = 1; x < M_IMGDATA->m_width; x++ )
{ {
// Take care of edge pixels on the left edge by essentially duplicating the edge pixel // Take care of edge pixels on the left edge by essentially
if(x - blurRadius - 1 < 0) // duplicating the edge pixel
if ( x - blurRadius - 1 < 0 )
pixel_idx = y * M_IMGDATA->m_width; pixel_idx = y * M_IMGDATA->m_width;
else else
pixel_idx = (x - blurRadius - 1) + y * M_IMGDATA->m_width; pixel_idx = (x - blurRadius - 1) + y * M_IMGDATA->m_width;
// Subtract the value of the pixel at the left side of the blur radius box // Subtract the value of the pixel at the left side of the blur
sum_r -= src_data[pixel_idx * 3 + 0]; // radius box
sum_g -= src_data[pixel_idx * 3 + 1]; src = src_data + pixel_idx*3;
sum_b -= src_data[pixel_idx * 3 + 2]; sum_r -= src[0];
sum_a -= src_alpha ? src_alpha[pixel_idx] : 0; sum_g -= src[1];
sum_b -= src[2];
if ( src_alpha )
sum_a -= src_alpha[pixel_idx];
// Take care of edge pixels on the right edge // Take care of edge pixels on the right edge
if(x + blurRadius > M_IMGDATA->m_width - 1) if ( x + blurRadius > M_IMGDATA->m_width - 1 )
pixel_idx = M_IMGDATA->m_width - 1 + y * M_IMGDATA->m_width; pixel_idx = M_IMGDATA->m_width - 1 + y * M_IMGDATA->m_width;
else else
pixel_idx = x + blurRadius + y * M_IMGDATA->m_width; pixel_idx = x + blurRadius + y * M_IMGDATA->m_width;
// Add the value of the pixel being added to the end of our box // Add the value of the pixel being added to the end of our box
sum_r += src_data[pixel_idx * 3 + 0]; src = src_data + pixel_idx*3;
sum_g += src_data[pixel_idx * 3 + 1]; sum_r += src[0];
sum_b += src_data[pixel_idx * 3 + 2]; sum_g += src[1];
sum_a += src_alpha ? src_alpha[pixel_idx] : 0; sum_b += src[2];
if ( src_alpha )
sum_a += src_alpha[pixel_idx];
// Save off the averaged data // Save off the averaged data
dst_data[x * 3 + y * M_IMGDATA->m_width * 3 + 0] = sum_r / (blurRadius * 2 + 1); dst = dst_data + x*3 + y*M_IMGDATA->m_width;
dst_data[x * 3 + y * M_IMGDATA->m_width * 3 + 1] = sum_g / (blurRadius * 2 + 1); dst[0] = sum_r / blurArea;
dst_data[x * 3 + y * M_IMGDATA->m_width * 3 + 2] = sum_b / (blurRadius * 2 + 1); dst[1] = sum_g / blurArea;
if(src_alpha) dst[2] = sum_b / blurArea;
dst_alpha[x + y * M_IMGDATA->m_width] = sum_a / (blurRadius * 2 + 1); if ( src_alpha )
dst_alpha[x + y * M_IMGDATA->m_width] = sum_a / blurArea;
} }
} }
@@ -817,79 +874,106 @@ wxImage wxImage::BlurVertical(int blurRadius)
unsigned char* dst_alpha = NULL; unsigned char* dst_alpha = NULL;
// Check for a mask or alpha // Check for a mask or alpha
if(M_IMGDATA->m_hasMask) if ( M_IMGDATA->m_hasMask )
ret_image.SetMaskColour(M_IMGDATA->m_maskRed, M_IMGDATA->m_maskGreen, M_IMGDATA->m_maskBlue); {
ret_image.SetMaskColour(M_IMGDATA->m_maskRed,
M_IMGDATA->m_maskGreen,
M_IMGDATA->m_maskBlue);
}
else else
if(src_alpha) {
if ( src_alpha )
{ {
ret_image.SetAlpha(); ret_image.SetAlpha();
dst_alpha = ret_image.GetAlpha(); dst_alpha = ret_image.GetAlpha();
} }
}
// Variables used in the blurring algorithm // number of pixels we average over
int x, y; const int blurArea = blurRadius*2 + 1;
int kernel_y;
long sum_r, sum_g, sum_b, sum_a;
long pixel_idx;
// Vertical blurring algorithm - same as horizontal but switched the opposite direction // Vertical blurring algorithm - same as horizontal but switched the
for(x = 0; x < M_IMGDATA->m_width; x++) // opposite direction
for ( int x = 0; x < M_IMGDATA->m_width; x++ )
{ {
sum_r = sum_g = sum_b = sum_a = 0; // Variables used in the blurring algorithm
long sum_r = 0,
sum_g = 0,
sum_b = 0,
sum_a = 0;
// Calculate the average of all pixels in our blur radius box for the first pixel of the column long pixel_idx;
for(kernel_y = -blurRadius; kernel_y <= blurRadius; kernel_y++) const unsigned char *src;
unsigned char *dst;
// Calculate the average of all pixels in our blur radius box for the
// first pixel of the column
for ( int kernel_y = -blurRadius; kernel_y <= blurRadius; kernel_y++ )
{ {
// To deal with the pixels at the start of a column so it's not grabbing GOK values from memory at negative indices of the image's data or grabbing from the previous column // To deal with the pixels at the start of a column so it's not
if(kernel_y < 0) // grabbing GOK values from memory at negative indices of the
// image's data or grabbing from the previous column
if ( kernel_y < 0 )
pixel_idx = x; pixel_idx = x;
else else
pixel_idx = x + kernel_y * M_IMGDATA->m_width; pixel_idx = x + kernel_y * M_IMGDATA->m_width;
sum_r += src_data[pixel_idx * 3 + 0]; src = src_data + pixel_idx*3;
sum_g += src_data[pixel_idx * 3 + 1]; sum_r += src[0];
sum_b += src_data[pixel_idx * 3 + 2]; sum_g += src[1];
sum_a += src_alpha ? src_alpha[pixel_idx] : 0; sum_b += src[2];
if ( src_alpha )
sum_a += src_alpha[pixel_idx];
} }
dst_data[x * 3 + 0] = sum_r / (blurRadius * 2 + 1);
dst_data[x * 3 + 1] = sum_g / (blurRadius * 2 + 1);
dst_data[x * 3 + 2] = sum_b / (blurRadius * 2 + 1);
if(src_alpha)
dst_alpha[x] = sum_a / (blurRadius * 2 + 1);
// Now average the values of the rest of the pixels by just moving the box along the column from top to bottom dst = dst_data + x*3;
for(y = 1; y < M_IMGDATA->m_height; y++) dst[0] = sum_r / blurArea;
dst[1] = sum_g / blurArea;
dst[2] = sum_b / blurArea;
if ( src_alpha )
dst_alpha[x] = sum_a / blurArea;
// Now average the values of the rest of the pixels by just moving the
// box along the column from top to bottom
for ( int y = 1; y < M_IMGDATA->m_height; y++ )
{ {
// Take care of pixels that would be beyond the top edge by duplicating the top edge pixel for the column // Take care of pixels that would be beyond the top edge by
if(y - blurRadius - 1 < 0) // duplicating the top edge pixel for the column
if ( y - blurRadius - 1 < 0 )
pixel_idx = x; pixel_idx = x;
else else
pixel_idx = x + (y - blurRadius - 1) * M_IMGDATA->m_width; pixel_idx = x + (y - blurRadius - 1) * M_IMGDATA->m_width;
// Subtract the value of the pixel at the top of our blur radius box // Subtract the value of the pixel at the top of our blur radius box
sum_r -= src_data[pixel_idx * 3 + 0]; src = src_data + pixel_idx*3;
sum_g -= src_data[pixel_idx * 3 + 1]; sum_r -= src[0];
sum_b -= src_data[pixel_idx * 3 + 2]; sum_g -= src[1];
sum_a -= src_alpha ? src_alpha[pixel_idx] : 0; sum_b -= src[2];
if ( src_alpha )
sum_a -= src_alpha[pixel_idx];
// Take care of the pixels that would be beyond the bottom edge of the image similar to the top edge // Take care of the pixels that would be beyond the bottom edge of
if(y + blurRadius > M_IMGDATA->m_height - 1) // the image similar to the top edge
if ( y + blurRadius > M_IMGDATA->m_height - 1 )
pixel_idx = x + (M_IMGDATA->m_height - 1) * M_IMGDATA->m_width; pixel_idx = x + (M_IMGDATA->m_height - 1) * M_IMGDATA->m_width;
else else
pixel_idx = x + (blurRadius + y) * M_IMGDATA->m_width; pixel_idx = x + (blurRadius + y) * M_IMGDATA->m_width;
// Add the value of the pixel being added to the end of our box // Add the value of the pixel being added to the end of our box
sum_r += src_data[pixel_idx * 3 + 0]; src = src_data + pixel_idx*3;
sum_g += src_data[pixel_idx * 3 + 1]; sum_r += src[0];
sum_b += src_data[pixel_idx * 3 + 2]; sum_g += src[1];
sum_a += src_alpha ? src_alpha[pixel_idx] : 0; sum_b += src[2];
if ( src_alpha )
sum_a += src_alpha[pixel_idx];
// Save off the averaged data // Save off the averaged data
dst_data[(x + y * M_IMGDATA->m_width) * 3 + 0] = sum_r / (blurRadius * 2 + 1); dst = dst_data + (x + y * M_IMGDATA->m_width) * 3;
dst_data[(x + y * M_IMGDATA->m_width) * 3 + 1] = sum_g / (blurRadius * 2 + 1); dst[0] = sum_r / blurArea;
dst_data[(x + y * M_IMGDATA->m_width) * 3 + 2] = sum_b / (blurRadius * 2 + 1); dst[1] = sum_g / blurArea;
if(src_alpha) dst[2] = sum_b / blurArea;
dst_alpha[x + y * M_IMGDATA->m_width] = sum_a / (blurRadius * 2 + 1); if ( src_alpha )
dst_alpha[x + y * M_IMGDATA->m_width] = sum_a / blurArea;
} }
} }