Как использовать Accelerate Framework с базовой графикой?

У меня есть проект. Он в основном берет фотографию с камеры iPhone и применяет к фотографии некоторые эффекты. Прежде чем применить эффект, я использую основную графику для масштабирования изображения до нужного размера. После масштабирования и поворота изображения я использую Accelerate framework (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;
}

person mustafa    schedule 05.12.2013    source источник


Ответы (2)


Как избежать ручного переопределения 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;
}
person Cameron Lowell Palmer    schedule 26.02.2015

Обычно сильный цветовой оттенок означает, что порядок цветовых каналов был потерян при переводе где-то по пути, например, вы создали компьютерную графику с данными BGRA, но на самом деле это был ARGB.

Вы смотрели vImage_Utilities.h?

person Ian Ollmann    schedule 06.01.2014