【问题标题】:Error using sepia image effect in iOS?在 iOS 中使用棕褐色图像效果时出错?
【发布时间】:2014-02-20 09:45:23
【问题描述】:

在我的应用程序中,我有一个imageViewimageView 中的图像应该有一些效果,如棕褐色、黑色和白色。
为了做棕褐色效果,我使用了以下代码,

 -(UIImage*)makeSepiaScale:(UIImage*)image
{
    CGImageRef cgImage = [image CGImage];
    CGDataProviderRef provider = CGImageGetDataProvider(cgImage);
    CFDataRef bitmapData = CGDataProviderCopyData(provider);
    UInt8* data = (UInt8*)CFDataGetBytePtr(bitmapData);

    int imagWidth = image.size.width;
    int imageheight = image.size.height;
    NSInteger myDataLength = imagWidth * imageheight * 4;


    for (int i = 0; i < myDataLength; i+=4)
    {
        UInt8 r_pixel = data[i];
        UInt8 g_pixel = data[i+1];
        UInt8 b_pixel = data[i+2];

        int outputRed = (r_pixel * .393) + (g_pixel *.769) + (b_pixel * .189);
        int outputGreen = (r_pixel * .349) + (g_pixel *.686) + (b_pixel * .168);
        int outputBlue = (r_pixel * .272) + (g_pixel *.534) + (b_pixel * .131);

        if(outputRed>255)outputRed=255;
        if(outputGreen>255)outputGreen=255;
        if(outputBlue>255)outputBlue=255;


        data[i] = outputRed;
        data[i+1] = outputGreen;
        data[i+2] = outputBlue;
    }

    CGDataProviderRef provider2 = CGDataProviderCreateWithData(NULL, data, myDataLength, NULL);
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * imagWidth;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    CGImageRef imageRef = CGImageCreate(imagWidth, imageheight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider2, NULL, NO, renderingIntent);

    CGColorSpaceRelease(colorSpaceRef); // YOU CAN RELEASE THIS NOW
    CGDataProviderRelease(provider2); // YOU CAN RELEASE THIS NOW
    CFRelease(bitmapData);

    UIImage *sepiaImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef); // YOU CAN RELEASE THIS NOW
    return sepiaImage;
}

它运行良好,但仅适用于 .png 图像,当我使用 .jpg 图像时,它只会为 imageView 显示黑色视图。任何帮助将不胜感激

【问题讨论】:

  • jpg 不支持每像素 32 位最大为 24 位,即 R、G、B(无 Alpha)各 8 位,因为您没有将数据转换为 RGBA,请执行以下更改:int imagWidth = image.size.width; int imageheight = image.size.height; NSInteger myDataLength = imagWidth * imageheight * 3; for (int i = 0; i

标签: ios uiimageview effects


【解决方案1】:

使用核心图像处理,

 -(void)makeSepiaScale
{
CIImage *beginImage =[[CIImage alloc]initWithImage:imageForView];

    CIContext * context=[CIContext contextWithOptions:nil];

    CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"
                                  keysAndValues: kCIInputImageKey, beginImage,
                        @"inputIntensity", @0.8, nil];
    CIImage *outImage = [filter outputImage];

    CGImageRef cgimg=[context createCGImage:outImage fromRect:[outImage extent]];


[imageView setImage:[UIImage imageWithCGImage:cgimg]];

}

【讨论】:

    【解决方案2】:

    使用 CGImageCreateWithJPEGDataProvider 从 JPEG 中获取位图:

    -(UIImage*)makeSepiaScale:(UIImage*)image {
    
        CGImageRef cgJpegImage = [image CGImage];
        CGDataProviderRef jpegProvider = CGImageGetDataProvider(cgJpegImage);
    
        CGImageRef cgBitmapImage = CGImageCreateWithJPEGDataProvider(jpegProvider, nil, NO, kCGRenderingIntentRelativeColorimetric);
        CGDataProviderRef bitmapProvider = CGImageGetDataProvider(cgBitmapImage);
    
        CFDataRef bitmapData = CGDataProviderCopyData(bitmapProvider);
        UInt8* data = (UInt8*)CFDataGetBytePtr(bitmapData);
    
        // other code to make sepia effect
    }
    

    您不能像普通 RGB 那样使用 JPEG 编码图像。所以,先用 CGImageCreateWithJPEGDataProvider 解码吧。

    【讨论】:

    • 我已经发布了用于 JPEG 图像的代码。对于 PNG,请使用现在有效的解决方案。
    • 它在 UInt8* 数据 ebad 访问时崩溃
    【解决方案3】:

    我怀疑您正在处理非 RGBA 格式的数据.... JPG 没有 Alpha 通道。我建议您考虑使用 Core Image 过滤器,而不是处理复杂的数据,而是将它们与 jpg 和 PNG 一起使用,没有任何问题。

    有多种核心图像滤镜,包括一种用于棕褐色,另一种用于灰度/黑白这是棕褐色的代码:

    -(UIImage*)makeSepiaScale:(UIImage*)input_image output:(UIImage *)output
    {
    
     CIImage *cimage = [[CIImage alloc] initWithImage:input_image];  
    CIFilter *myFilter = [CIFilter filterWithName:@"CISepiaTone"];
    
    [myFilter setDefaults];
    [myFilter setValue:cimage forKey:@"inputImage"];
    [myFilter setValue:[NSNumber numberWithFloat:0.8f] forKey:@"inputIntensity"];
    
    CIImage *image = [myFilter outputImage];
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:image fromRect:image.extent];
    output = [UIImage imageWithCGImage:cgImage];  
    CGImageRelease(cgImage);
    return (output);}
    

    PS Apple 关于 CoreImage 的文档很好,我建议你阅读它。

    【讨论】:

    • JPG 使用 8 位灰度图像或 24 位颜色 - 对于 r、g 和蓝色分别为 8 位。您的例程假定 PNG 使用的称为 RBGA8888 的 32 位颜色格式。 (注意灰度 PNG 也存在)。我相信有一些例程可以检查正在使用的 CGColorSpaceRef 或将其转换为 RGBA,因此您的例程可能会起作用,但如果 CoreImage 等更高级别的框架已经为您完成了所有繁重的工作,为什么还要处理它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多