0

I am trying to find a faster way to generate Gaussian Blur image, this blog works great with most of the image.

But when image has transparent backgroudcolor, the blured image looks bad

The code below is copied from the blog:

-(UIImage *)vImageBlurWithNumber:(CGFloat)blur
{
    if (blur < 0.f || blur > 1.f) {
        blur = 0.5f;
    }
    int boxSize = (int)(blur * 100);
    boxSize = boxSize - (boxSize % 2) + 1;

    CGImageRef img = self.CGImage;

    vImage_Buffer inBuffer, outBuffer;
    vImage_Error error;

    void *pixelBuffer;

    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);

    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);

    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);

    pixelBuffer = malloc(CGImageGetBytesPerRow(img) *
                     CGImageGetHeight(img));

    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");

    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);

    // may be i should modify last 2 parameter below ,how ?
    error = vImageBoxConvolve_ARGB8888(&inBuffer,
                                   &outBuffer,
                                   NULL,
                                   0,
                                   0,
                                   boxSize,
                                   boxSize,
                                   NULL,
                                   kvImageEdgeExtend); //        kvImageBackgroundColorFill ?



    if (error) {
        NSLog(@"error from convolution %ld", error);
    }

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(
                                         outBuffer.data,
                                         outBuffer.width,
                                         outBuffer.height,
                                         8,
                                         outBuffer.rowBytes,
                                         colorSpace,
                                         kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];

    //clean up
//    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);

    free(pixelBuffer);
    CFRelease(inBitmapData);

    CGColorSpaceRelease(colorSpace);
    CGImageRelease(imageRef);

    return returnImage;
}

I have tried another way to make Gaussian Blur Effect ,
by using Apple WWDC 2013 UIImage-ImageEffects category,
but the effect of this category is more like Frosted glass instead of Gaussian Blur.

Blur in Core Image works fine, but it is so slow than the vImage way.

GPUImage also slower than vImage way.

Please help me to modified the vImage code above, i have tried a lot ,and post the code with demo here;

:)

Shawn Wang
  • 2,314
  • 1
  • 16
  • 19
  • Finally, i solve it by simple transform image to .png to remove alpha channel `UIImage *inputImage = [UIImage imageWithData:UIImageJPEGRepresentation(img, 1.0)];` – Shawn Wang Jul 03 '16 at 14:06
  • Transparent image with blur result here http://i.stack.imgur.com/o1iVy.png ,pardon me,i have't enough reputation to post image – Shawn Wang Jul 07 '16 at 03:54
  • I hoping the result will be like this , http://i.stack.imgur.com/RZJ6V.png – Shawn Wang Jul 07 '16 at 03:57

2 Answers2

0

It would be useful to see what looks bad about it.

If it is just regions near the transparent areas, you might try to premultiply the image first. That will keep the meaningless colors in the fully transparent areas from bleeding into the rest of the image.

Ian Ollmann
  • 1,592
  • 9
  • 16
  • I add image for my question, i tried to remove transparent areas by redraw it using `UIGraphicsBeginImageContextWithOptions` to create a new Image with white background color, still not wok. Then i tried using `[UIImage imageWithData:UIImageJPEGRepresentation(img, 1.0)];` to transfer image from `png` format to `jpeg` format to remove any alpha channel , this works but looks not efficient . Looking forward to your reply ~ – Shawn Wang Jul 07 '16 at 04:03
  • There are a series of vImageFlatten... functions which are intended to make images opaque. However, I really think you should try just pre-multiplying the image by its alpha channel first to see if that solves the problem. Less alpha information is destroyed that way. See vImagePremultiplyData... – Ian Ollmann Jul 07 '16 at 15:10
0

You could also do something like:

var noAlpha = CIVector(x: 0, y: 0, z: 0, w: 1)

image.imageByApplyingFilter("CIColorMatrix", 
    withInputParameters: ["inputAVector": noAlpha])

to get rid of the alpha. If you need to chain with other CIFilters this would be more efficient.

henrikstroem
  • 2,978
  • 4
  • 35
  • 51
  • Thank you for your reply, I update my question with images. I tried your answer, but not work, i am using `[UIImage imageWithData:UIImageJPEGRepresentation(img, 1.0)];` to make image opaque , this works but not efficient , any better idea ? ~ – Shawn Wang Jul 07 '16 at 04:11