仅在模拟器中出现 CGContext 错误?

Posted

技术标签:

【中文标题】仅在模拟器中出现 CGContext 错误?【英文标题】:CGContext Errors only in simulator? 【发布时间】:2013-08-01 04:12:28 【问题描述】:

在测试我的应用程序是否存在任何错误时,我注意到在模拟器中,当我调用我的一个函数将图像设置为 UIImageView 时,会引发一堆 CGContext 错误并且图像永远不会被设置。但是在我的设备上(我在 iPhone 5、iPhone 3GS 和 iPad 3 上进行了测试),这些 CGContext 错误都没有出现,并且图像设置正常。

无论如何,我都在寻找任何可以实现这一点的 CGContext 代码,以下是唯一涉及 CGContext 的方法:

- (void)setCropRect:(CGRect)cropRect

    if(!CGRectEqualToRect(_cropRect,cropRect))
        _cropRect = cropRect;
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.f);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [[UIColor blackColor] setFill];
        UIRectFill(self.bounds);
        CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] colorWithAlphaComponent:0.5].CGColor);
        CGContextStrokeRect(context, _cropRect);
        [[UIColor clearColor] setFill];
        UIRectFill(CGRectInset(_cropRect, 1, 1));
        self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();
    


- (CGImageRef)newScaledImage:(CGImageRef)source withOrientation:(UIImageOrientation)orientation toSize:(CGSize)size withQuality:(CGInterpolationQuality)quality

    CGSize srcSize = size;
    CGFloat rotation = 0.0;

    switch(orientation)
    
        case UIImageOrientationUp: 
            rotation = 0;
         break;
        case UIImageOrientationDown: 
            rotation = M_PI;
         break;
        case UIImageOrientationLeft:
            rotation = M_PI_2;
            srcSize = CGSizeMake(size.height, size.width);
         break;
        case UIImageOrientationRight: 
            rotation = -M_PI_2;
            srcSize = CGSizeMake(size.height, size.width);
         break;
        default:
            break;
    

    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 size.width,
                                                 size.height,
                                                 8, //CGImageGetBitsPerComponent(source),
                                                 0,
                                                 CGImageGetColorSpace(source),
                                                 kCGImageAlphaNoneSkipFirst//CGImageGetBitmapInfo(source)
                                                 );

    CGContextSetInterpolationQuality(context, quality);
    CGContextTranslateCTM(context,  size.width/2,  size.height/2);
    CGContextRotateCTM(context,rotation);

    CGContextDrawImage(context, CGRectMake(-srcSize.width/2 ,
                                           -srcSize.height/2,
                                           srcSize.width,
                                           srcSize.height),
                       source);

    CGImageRef resultRef = CGBitmapContextCreateImage(context);
    CGContextRelease(context);

    return resultRef;


- (CGImageRef)newTransformedImage:(CGAffineTransform)transform
                      sourceImage:(CGImageRef)sourceImage
                       sourceSize:(CGSize)sourceSize
                sourceOrientation:(UIImageOrientation)sourceOrientation
                      outputWidth:(CGFloat)outputWidth
                         cropSize:(CGSize)cropSize
                    imageViewSize:(CGSize)imageViewSize

    CGImageRef source = [self newScaledImage:sourceImage
                             withOrientation:sourceOrientation
                                      toSize:sourceSize
                                 withQuality:kCGInterpolationNone];

    CGFloat aspect = cropSize.height/cropSize.width;
    CGSize outputSize = CGSizeMake(outputWidth, outputWidth*aspect);

    CGContextRef context = CGBitmapContextCreate(NULL,
                                                 outputSize.width,
                                                 outputSize.height,
                                                 CGImageGetBitsPerComponent(source),
                                                 0,
                                                 CGImageGetColorSpace(source),
                                                 CGImageGetBitmapInfo(source));
    CGContextSetFillColorWithColor(context,  [[UIColor clearColor] CGColor]);
    CGContextFillRect(context, CGRectMake(0, 0, outputSize.width, outputSize.height));

    CGAffineTransform uiCoords = CGAffineTransformMakeScale(outputSize.width/cropSize.width,
                                                            outputSize.height/cropSize.height);
    uiCoords = CGAffineTransformTranslate(uiCoords, cropSize.width/2.0, cropSize.height/2.0);
    uiCoords = CGAffineTransformScale(uiCoords, 1.0, -1.0);
    CGContextConcatCTM(context, uiCoords);

    CGContextConcatCTM(context, transform);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextDrawImage(context, CGRectMake(-imageViewSize.width/2.0,
                                           -imageViewSize.height/2.0,
                                           imageViewSize.width,
                                           imageViewSize.height)
                       ,source);

    CGImageRef resultRef = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    CGImageRelease(source);
    return resultRef;

这些是 CGContext 错误:

Jul 31 23:37:37 app[10190] <Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 16 bits/pixel; 1-component color space; kCGImageAlphaNoneSkipFirst; 1504 bytes/row.
Jul 31 23:37:37 app[10190] <Error>: CGContextSetInterpolationQuality: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextTranslateCTM: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextRotateCTM: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextDrawImage: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGBitmapContextCreateImage: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGBitmapContextCreate: unsupported parameter combination: 0 integer bits/component; 0 bits/pixel; 0-component color space; kCGImageAlphaNone; 0 bytes/row.
Jul 31 23:37:37 app[10190] <Error>: CGContextSetFillColorWithColor: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextFillRects: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextConcatCTM: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextConcatCTM: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextScaleCTM: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGContextDrawImage: invalid context 0x0
Jul 31 23:37:37 app[10190] <Error>: CGBitmapContextCreateImage: invalid context 0x0

这些是我的应用程序中唯一使用 CGContexts 的方法。但就像我说的,这只发生在模拟器中,而不是我测试过的设备上。

无论如何,这有什么特别的原因吗?或者有什么办法可以解决这个问题?

谢谢大家!

CGContextRef context = CGBitmapContextCreate(NULL,
                                                 size.width,
                                                 size.height,
                                                 CGImageGetBitsPerComponent(source), //8,
                                                 0,
                                                 CGImageGetColorSpace(source),
                                                 CGImageGetBitmapInfo //kCGImageAlphaNoneSkipFirst(source)
                                                 );

【问题讨论】:

如果您告诉我们“一堆 CGContext 错误”是什么会有所帮助。 抱歉,我添加了它们。 【参考方案1】:

很可能,您对CGBitmapContextCreate 的第一次调用失败了,因为您要求它做一些它不能做的事情。您可以在第一条错误消息中看到:

CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 16 bits/pixel; 1-component color space; kCGImageAlphaNoneSkipFirst; 1504 bytes/row.

CGBitmapContextCreate 返回 NULL,其余故障从那里级联。 (您不能对 NULL 上下文进行操作,并且在 NULL 上下文上调用 CGBitmapContextGetImage() 会给您一个 NULL 图像,您同样无法对它做任何有用的事情。)

CGBitmapContextCreate 的文档指出:

有关支持的像素格式列表,请参阅Quartz 2D Programming Guide 的“Graphics Contexts” 章节中的“支持的像素格式”。

这是该列表中的direct link。

【讨论】:

啊,好吧。我对 CGContexts 不是很熟悉,所以你可能比我知道的更多,但是这个问题的第二个答案:***.com/questions/5545600/… 会解决这个问题并完成与我现在的代码相同的操作吗? SO 并不总是以相同的顺序显示答案,所以我不知道您认为哪个是第二个。如果你的意思是this one,代码是错误的:它指定了格式的一部分(RGB 颜色空间),但仍然从原始图像中获取一些部分(每个组件的位数,bitmapInfo),所以你仍然可能会遇到类似的错误。 This answer 可能更好。事实上,你几乎就在那里,只需使用在硬编码 8 位/像素和 kCGImageAlphaNoneSkipFirst 的行中注释掉的代码。 感谢您在这里帮助我,但按照您的建议进行操作并不能解决问题。我在原始问题的末尾发布了我从您的回复中解释的内容,但它导致了相同的 CGContext 错误。 您的意思是CGImageGetBitmapInfo(source),而不仅仅是CGImageGetBitmapInfo,对吗? (你的方式甚至不应该编译,或者至少应该给出编译器警告。) 但是为什么这个错误发生在模拟器而不是设备上呢?你发现了吗?【参考方案2】:

您对CGBitmapContextCreate 的两次调用都使用了不受支持的位/组件 - 位/像素组合(正如 CGContext 错误告诉您的那样)。

有关支持的像素格式列表,请参阅Quartz 2D Programming Guide 中的表 2.1

【讨论】:

以上是关于仅在模拟器中出现 CGContext 错误?的主要内容,如果未能解决你的问题,请参考以下文章

仅在某些设备上出现核心数据标量错误

仅在某些 iPhone 5 和 6 上出现网站错误

从 drawRect 调用的方法中出现无效的 CGContext 错误

解析推送通知仅在模拟器中工作

ListFragment 在手机上出现两次

读取 NSFetchedResultsController 的 fetchedObjects 属性时出现 EXC_BAD_ACCESS 错误(仅在模拟器上)