【问题标题】:UIImage Gaussian Blur with vImageUIImage 高斯模糊与 vImage
【发布时间】:2016-07-07 00:25:30
【问题描述】:

我正在尝试寻找一种更快的方法来生成Gaussian Blur 图像,这个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;
}

我尝试了另一种方法来制作Gaussian Blur 效果,
通过使用Apple WWDC 2013 UIImage-ImageEffects 类别,
但是这个分类的效果更像Frosted glass而不是Gaussian Blur。

Blur in Core Image 工作正常,但比 vImage 方式慢。

GPUImage 也比 vImage 方式慢。

请帮我修改上面的vImage代码, 我已经尝试了很多,并使用演示here发布代码;

:)

【问题讨论】:

  • 最后,我通过简单的将图像转换为 .png 来移除 alpha 通道来解决它UIImage *inputImage = [UIImage imageWithData:UIImageJPEGRepresentation(img, 1.0)];
  • 透明图片,模糊结果在这里i.stack.imgur.com/o1iVy.png,对不起,我没有足够的声誉来发布图片
  • 我希望结果是这样的,i.stack.imgur.com/RZJ6V.png

标签: ios blur gaussian core-image vimage


【解决方案1】:

看看有什么不好的地方会很有用。

如果只是透明区域附近的区域,您可以尝试先对图像进行预乘。这将使完全透明区域中的无意义颜色不会渗入图像的其余部分。

【讨论】:

  • 我为我的问题添加了图像,我尝试通过使用UIGraphicsBeginImageContextWithOptions 重绘它来删除透明区域,以创建一个具有白色背景颜色的新图像,但仍然无法正常工作。然后我尝试使用[UIImage imageWithData:UIImageJPEGRepresentation(img, 1.0)]; 将图像从png 格式传输到jpeg 格式以删除任何alpha 通道,这可行但看起来效率不高。期待您的回复~
  • 有一系列 vImageFlatten... 函数旨在使图像不透明。但是,我真的认为您应该先尝试将图像与其 alpha 通道预乘以查看是否可以解决问题。更少的 alpha 信息会以这种方式被破坏。参见 vImagePremultiplyData...
【解决方案2】:

你也可以这样做:

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

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

摆脱阿尔法。如果您需要与其他CIFilters 链接,这将更有效。

【讨论】:

  • 感谢您的回复,我用图片更新了我的问题。我试过你的答案,但没有用,我正在使用[UIImage imageWithData:UIImageJPEGRepresentation(img, 1.0)]; 使图像不透明,这有效但效率不高,有更好的主意吗? ~
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 2016-04-30
  • 2011-12-07
  • 2023-03-22
  • 1970-01-01
相关资源
最近更新 更多