簡體   English   中英

如何使用帶有核心圖形的Accelerate Framework?

[英]How do I use the Accelerate Framework With Core Graphics?

我有一個項目。 它基本上是從iPhone相機拍照並對照片應用了一些效果。 在我應用效果之前,我使用核心圖形將圖像縮放到合適的大小。 縮放和旋轉圖像后,我使用Accelerate框架(vImage)來創建效果。 我的問題是在應用效果之后它最終變成了一些藍色的圖像。 但是,如果我不使用核心圖形縮放圖像,則這種偏藍的外觀不會發生。

我使用的縮放代碼來自這篇文章。

這是我的代碼應用效果:

- (UIImage *)applyFiltertoImage:(UIImage *)img
{
    CGImageRef image = img.CGImage;
    vImage_Buffer inBuffer, outBuffer;
    void *pixelBuffer;

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

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

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

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

    if (pixelBuffer == NULL) {
        NSLog(@"No buffer");
    }

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

    vImageConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, self.kernel, self.size, self.size, self.divisor, NULL, kvImageEdgeExtend);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
                                             outBuffer.width,
                                             outBuffer.height,
                                             8,
                                             outBuffer.rowBytes,
                                             colorSpace,
                                             kCGImageAlphaNoneSkipLast);

    CGImageRef imageRef = CGBitmapContextCreateImage(ctx);

    UIImage *blurredImage = [UIImage imageWithCGImage:imageRef];

    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);
    free(pixelBuffer);
    CFRelease(inBitmapData);
    CGImageRelease(imageRef);

    return blurredImage;
}

避免手動重新定義CGContext

嘗試讓vImage為您初始化值。 vImageBuffer_InitWithCGImage可以幫助您避免一些痛苦。

直截了當的版本

- (UIImage *)applyFiltertoImage:(UIImage *)image
    CGImageRef originalImageRef = image.CGImage;
    CGColorSpaceRef originalColorSpace = CGColorSpaceRetain(CGImageGetColorSpace(originalImageRef));

    if (_pixelBuffer == NULL) {
        _pixelBuffer = malloc(CGImageGetBytesPerRow(originalImageRef) * CGImageGetHeight(originalImageRef));
    }

    vImage_CGImageFormat inputImageFormat =
    {
        .bitsPerComponent = (uint32_t) CGImageGetBitsPerComponent(originalImageRef),
        .bitsPerPixel = (uint32_t) CGImageGetBitsPerComponent(originalImageRef) * (uint32_t)(CGColorSpaceGetNumberOfComponents(originalColorSpace) + (kCGImageAlphaNone != CGImageGetAlphaInfo(originalImageRef))),
        .colorSpace = originalColorSpace,
        .bitmapInfo = CGImageGetBitmapInfo(originalImageRef),
        .version = 0,
        .decode = NULL,
        .renderingIntent = kCGRenderingIntentDefault
    };
    vImage_Buffer inputImageBuffer;
    vImageBuffer_InitWithCGImage(&inputImageBuffer, &inputImageFormat, NULL, originalImageRef, kvImageNoFlags);

    vImage_Buffer outputImageBuffer = {
        .data = _pixelBuffer,
        .width = CGImageGetWidth(originalImageRef),
        .height = CGImageGetHeight(originalImageRef),
        .rowBytes = CGImageGetBytesPerRow(originalImageRef)
    };

    vImage_Error error;
    error = vImageConvolve_ARGB8888(&inputImageBuffer,
                                    &outputImageBuffer,
                                    NULL,
                                    0,
                                    0,
                                    self.kernel,
                                    self.size,
                                    self.divisor,
                                    NULL,
                                    kvImageEdgeExtend);
    if (error) {
        NSLog(@"vImage error %zd", error);
    }
    free(inputImageBuffer.data);

    vImage_CGImageFormat outFormat =
    {
        .bitsPerComponent = (uint32_t) CGImageGetBitsPerComponent(originalImageRef),
        .bitsPerPixel = (uint32_t) CGImageGetBitsPerComponent(originalImageRef) * (uint32_t)(CGColorSpaceGetNumberOfComponents(originalColorSpace) + (kCGImageAlphaNone != CGImageGetAlphaInfo(originalImageRef))),
        .colorSpace = originalColorSpace,
        .bitmapInfo = CGImageGetBitmapInfo(originalImageRef),
        .version = 0,
        .decode = NULL,
        .renderingIntent = kCGRenderingIntentDefault
    };
    CGImageRef modifiedImageRef = vImageCreateCGImageFromBuffer(&outputImageBuffer,
                                                                &outFormat,
                                                                NULL,
                                                                NULL,
                                                                kvImageNoFlags,
                                                                &error);
    CGColorSpaceRelease(originalColorSpace);

    UIImage *returnImage = [UIImage imageWithCGImage:modifiedImageRef];
    CGImageRelease(modifiedImageRef);

    return returnImage;
}

更高性能的版本

每個圖像一次創建_inputImageBuffer,_outputImageBuffer和_outputImageFormat,然后只需將過濾器重新應用到源圖像。 一旦vImage變暖,它將從呼叫開始削減幾毫秒。

- (UIImage *)applyFilter
    vImage_Error error;
    error = vImageConvolve_ARGB8888(&_inputImageBuffer,
                                    &_outputImageBuffer,
                                    NULL,
                                    0,
                                    0,
                                    self.kernel,
                                    self.size,
                                    self.divisor,
                                    NULL,
                                    kvImageEdgeExtend);
    if (error) {
        NSLog(@"vImage error %zd", error);
    }

    CGImageRef modifiedImageRef = vImageCreateCGImageFromBuffer(&_outputImageBuffer,
                          &_outputImageFormat,
                          NULL,
                          NULL,
                          kvImageNoFlags,
                          &error);    
    UIImage *returnImage = [UIImage imageWithCGImage:modifiedImageRef];
    CGImageRelease(modifiedImageRef);

    return returnImage;
}

通常,強烈的色調意味着顏色通道順序在沿途的某處翻譯時丟失,例如您創建了帶有BGRA數據的CG圖像,但它實際上是ARGB。

你看過vImage_Utilities.h嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM