7

I have tried gaussian blur and checked out all the questions on stackoverflow but no one of them solved my crash issue.Please help is there is any other way to blur image other than gaussian blur algorithm. My image size is 768x1024 and the loops iterates for 2*1024*768 times and this is not feasible.

CGContextRef NYXImageCreateARGBBitmapContext(const size_t width, const size_t height, const size_t bytesPerRow)
{
/// Use the generic RGB color space
/// We avoid the NULL check because CGColorSpaceRelease() NULL check the value anyway, and worst case scenario = fail to create context
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

/// Create the bitmap context, we want pre-multiplied ARGB, 8-bits per component
CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8/*Bits per component*/, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst);

CGColorSpaceRelease(colorSpace);

return bmContext;
}



 -(UIImage*)blurredImageUsingGaussFactor:(NSUInteger)gaussFactor andPixelRadius:(NSUInteger)pixelRadius
{
CGImageRef cgImage = self.CGImage;
const size_t originalWidth = CGImageGetWidth(cgImage);
const size_t originalHeight = CGImageGetHeight(cgImage);
const size_t bytesPerRow = originalWidth * 4;
CGContextRef context = NYXImageCreateARGBBitmapContext(originalWidth, originalHeight, bytesPerRow);
if (!context) 
    return nil;

unsigned char *srcData, *destData, *finalData;

size_t width = CGBitmapContextGetWidth(context);
size_t height = CGBitmapContextGetHeight(context);
size_t bpr = CGBitmapContextGetBytesPerRow(context);
size_t bpp = CGBitmapContextGetBitsPerPixel(context) / 8;
CGRect rect = {{0.0f, 0.0f}, {width, height}}; 

CGContextDrawImage(context, rect, cgImage); 

// Now we can get a pointer to the image data associated with the bitmap
// context.
srcData = (unsigned char*)CGBitmapContextGetData(context);
if (srcData != NULL)
{
    size_t dataSize = bpr * height;
    finalData = malloc(dataSize);
    destData = malloc(dataSize);
    memcpy(finalData, srcData, dataSize);
    memcpy(destData, srcData, dataSize);

    int sums[gaussFactor];
    size_t i, /*x, y,*/ k;
    int gauss_sum = 0;
    size_t radius = pixelRadius * 2 + 1;
    int *gauss_fact = malloc(radius * sizeof(int));

    for (i = 0; i < pixelRadius; i++)
    {
        gauss_fact[i] = 1 + (gaussFactor * i);
        gauss_fact[radius - (i + 1)] = 1 + (gaussFactor * i);
        gauss_sum += (gauss_fact[i] + gauss_fact[radius - (i + 1)]);
    }
    gauss_fact[(radius - 1) / 2] = 1 + (gaussFactor*pixelRadius);
    gauss_sum += gauss_fact[(radius - 1) / 2];

    unsigned char *p1, *p2, *p3;

    for (size_t y = 0; y < height; y++) 
    {
        for (size_t x = 0; x < width; x++) 
        {
            p1 = srcData + bpp * (y * width + x); 
            p2 = destData + bpp * (y * width + x);

            for (i = 0; i < gaussFactor; i++)
                sums[i] = 0;

            for (k = 0; k < radius ; k++)
            {
                if ((y - ((radius - 1) >> 1) + k) < height)
                    p1 = srcData + bpp * ((y - ((radius - 1) >> 1) + k) * width + x); 
                else
                    p1 = srcData + bpp * (y * width + x);

                for (i = 0; i < bpp; i++)
                    sums[i] += p1[i] * gauss_fact[k];

            }
            for (i = 0; i < bpp; i++)
                p2[i] = sums[i] / gauss_sum;
        }
    }
    for (size_t y = 0; y < height; y++) 
    {
        for (size_t x = 0; x < width; x++) 
        {
            p2 = destData + bpp * (y * width + x);
            p3 = finalData + bpp * (y * width + x);

            for (i = 0; i < gaussFactor; i++)
                sums[i] = 0;

            for(k = 0; k < radius ; k++)
            {
                if ((x - ((radius - 1) >> 1) + k) < width)
                    p1 = srcData + bpp * ( y * width + (x - ((radius - 1) >> 1) + k)); 
                else
                    p1 = srcData + bpp * (y * width + x);

                for (i = 0; i < bpp; i++)
                    sums[i] += p2[i] * gauss_fact[k];

            }
            for (i = 0; i < bpp; i++)
            {
                p3[i] = sums[i] / gauss_sum;
            }
        }
    }
}

size_t bitmapByteCount = bpr * height;

///////Here was the problem.. you had given srcData instead of destData.. Rest all 
//were perfect...
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, destData, bitmapByteCount, NULL);

CGImageRef blurredImageRef = CGImageCreate(width, height, CGBitmapContextGetBitsPerComponent(context), CGBitmapContextGetBitsPerPixel(context), CGBitmapContextGetBytesPerRow(context), CGBitmapContextGetColorSpace(context), CGBitmapContextGetBitmapInfo(context), dataProvider, NULL, true, kCGRenderingIntentDefault);

CGDataProviderRelease(dataProvider);
CGContextRelease(context); 
if (destData)
    free(destData);
if (finalData)
    free(finalData);

UIImage* retUIImage = [UIImage imageWithCGImage:blurredImageRef];

CGImageRelease(blurredImageRef);

return retUIImage;
}
Leena
  • 2,678
  • 1
  • 30
  • 43

3 Answers3

15

I've made a small StackBlur extension to UIImage. StackBlur is close to GaussianBlur but much faster.

Check it at: https://github.com/tomsoft1/StackBluriOS


tiny note... there's a typo just on that ReadMe, "normalized" for "normalize"

Fattie
  • 27,874
  • 70
  • 431
  • 719
tomsoft
  • 4,448
  • 5
  • 28
  • 35
  • 1
    Works great, do you know of any StackBlur implementations on iOS that handle transparency? – mmc Jun 07 '12 at 22:41
  • I am getting crash when I run above stackBlur code. – Uttam Mar 31 '17 at 05:43
  • @tomsoft: a typo/bug report has been edited into this answer, but I am not sure it belongs here. Can it be actioned on the repo so it can be removed here? – halfer Nov 03 '19 at 09:14
2

Not sure about how to blur an image. This may help is you want to blur an UIImageView or any view.

   UIView *myView = self.theImageView;
    CALayer *layer = [myView layer];
    [layer setRasterizationScale:0.25];
    [layer setShouldRasterize:YES];

You can undo it by setting the rasterization scale back to 1.

[layer setRasterizationScale:1.0];

UPDATE:

The below Apple sample code includes a blur/sharp effect. (using Open GL) See if it helps, http://developer.apple.com/library/ios/#samplecode/GLImageProcessing/Introduction/Intro.html

WrightsCS
  • 50,551
  • 22
  • 134
  • 186
sElanthiraiyan
  • 6,000
  • 1
  • 31
  • 38
1

What you probably want is a Box Blur algorithm. It is about 10 times faster than Gaussian blur and produces nice results. I have the code running on Android, I just haven't ported it to iOS yet. Here is the source.

Should only take about 10 minutes to port to iOS. The functions will work as is, you just need to access the image bytes (as you are doing in the source code above) and feed them to functions.

Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58
  • Box Blur is available as part of Core Image. – Abizern Jan 07 '12 at 11:43
  • 1
    box blur is available only for mac check this link:-http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/uid/TP30000136-SW69 – Leena Jan 07 '12 at 11:54
  • You could try vImageBoxConvolve_ARGB8888. There is also a tent filter that looks nicer. – Ian Ollmann Jan 21 '14 at 02:25