2013-08-12 1 views
3

빠른 실시간 이미지 흐림을 수행해야합니다. 코드 샘플vImageBoxConvolve_ARGB8888 사용에 대한 CGImageGetBytesPerRow 값이 잘못되었습니다.

-(UIImage *)boxblurImage:(UIImage *)image boxSize:(int)boxSize { 
    CGImageRef img = image.CGImage; 

    vImage_Buffer inBuffer, outBuffer; 

    vImage_Error error; 
    void *pixelBuffer; 

    //create vImage_Buffer with data from CGImageRef 

    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); 

    //create vImage_Buffer for output 

    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); 

    //perform convolution 
    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend); 

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

    //create CGImageRef from vImage_Buffer output 
    //1 - CGBitmapContextCreateImage - 

    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); 

    CGImageRelease(imageRef); 

    return returnImage; 
} 

문제는 그 기능은 일부 이미지에 예외가 발생 여기서 유용한 가이드 Perform a blur using vImage.

발견된다. 하나의 이미지 "Broken image" (JPEG, PNG가 아님) 만 있습니다.

내가 그것을 구글 시작을 제외하고

<Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; kCGImageAlphaNoneSkipLast; 538 bytes/row. 
<Error>: CGBitmapContextCreateImage: invalid context 0x0 

있습니다. 해결책 몇 개를 찾았습니다. 디버깅 시간이 지나면 CGImageGetBytesPerRow이 "깨진 이미지"에 대해 잘못된 값을 반환한다는 것을 발견했습니다. 원래의 이미지 너비에 맞게 4 배를 초과하지 않아도됩니다.

rowBytes을 수동으로 CGBitmapContextCreate으로 변경하려고 시도했지만 이미지에 많은 아티팩트가 표시되기 시작했습니다. 요점은 버그는 신비스럽고 때로는 나타나지만 여전히 그렇다는 것입니다.

버퍼의 rowBytes을 확인하지 않고 어떻게 해결할 수 있습니까? rowBytes 값의 사전 검사를 수행하고 원본 이미지를 반환 할 수 있지만 해킹처럼 보입니다. 그리고 우리의 이미지처럼 일부 이미지가 잘못 rowBytes 값을 반환하도록 어떻게 됐습니까?

답변

0

vImageBuffer_InitWithCGImage/vImageCreateCGImageFromBuffer 보셨습니까?

vImage_Buffer buf = {0}; 
vImage_CGImageFormat fmt = { 
    .bitsPerComponent = 8, 
    .bitsPerPixel = 32, 
    .colorSpace = CGImageGetColorSpace(image), 
    .bitmapInfo = kCGImageAlphaLast | kCGBitmapByteOrderDefault 
}; 

vImage_Error err = vImageBuffer_InitWithCGImage(&buf, &fmt, NULL, image, kvImageNoFlags); // allocates buf.data 

vImage_Buffer outBuffer; 
vImageBuffer_Init(&outBuffer, buf.height, buf.width, fmt.bitsPerPixel, kvImageNoFlags); 
vImageBoxConvolve_ARGB8888(&buf, &outBuffer, ...); 
free(buf.data); 

CGImageRef newImage = vImageCreateCGImageFromBuffer(&outBuffer, &fmt, NULL, NULL, kvImageNoAllocate, &err); // outBuffer.data will be freed when the CGImageRef is released. 
관련 문제