0

While testing my app for any bugs I noticed that in the simulator when I call one of my functions to set an image to an UIImageView, a bunch of CGContext errors are thrown and the image never gets set. However on my devices (I have tested on iPhone 5, iPhone 3GS and iPad 3), none of these CGContext errors come up and the image gets set fine.

Anyway I looked for any CGContext code that could make this happen and the following are the only methods that involve 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;
}

These are the CGContext errors:

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

Those are the only methods in my app that use CGContexts. But like I said, this only occurs in the simulator and not on the devices I have tested on.

Anyway, is there any particular reason for this or is there any way I can fix this?

Thanks all!

CGContextRef context = CGBitmapContextCreate(NULL,
                                                 size.width,
                                                 size.height,
                                                 CGImageGetBitsPerComponent(source), //8,
                                                 0,
                                                 CGImageGetColorSpace(source),
                                                 CGImageGetBitmapInfo //kCGImageAlphaNoneSkipFirst(source)
                                                 );
SimplyKiwi
  • 12,376
  • 22
  • 105
  • 191

2 Answers2

1

Most likely, your first call to CGBitmapContextCreate is failing, because you are asking it to do something it cannot do. You can see that in the first error message:

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

CGBitmapContextCreate returns NULL, and the rest of the failures cascade from there. (You cannot operate on a NULL context, and calling CGBitmapContextGetImage() on a NULL context gives you a NULL image, which you similarly can't do anything useful with.)

The documentation for CGBitmapContextCreate states:

For the list of supported pixel formats, see “Supported Pixel Formats” in the “Graphics Contexts” chapter of Quartz 2D Programming Guide.

Here's the direct link to that list.

Kurt Revis
  • 27,695
  • 5
  • 68
  • 74
  • Ah okay. I am not that familiar with CGContexts so you probably would know more than me, but would the second answer in this question: http://stackoverflow.com/questions/5545600/iphone-cgcontextref-cgbitmapcontextcreate-unsupported-parameter-combination fix this issue and accomplish the same as the code I have now? – SimplyKiwi Aug 01 '13 at 04:51
  • SO doesn't always show answers in the same order, so I don't know which one you think is second. If you mean [this one](http://stackoverflow.com/a/8455299/1218876), the code is bad: it specifies part of the format (RGB colorspace) but still takes some parts from the original image (bits per component, bitmapInfo), so you could still end up with a similar error. [This answer](http://stackoverflow.com/a/17039624/1218876) is probably better. In fact, you are almost there, just use the code that is commented-out in the lines where you hardcode 8 bits/pixel and kCGImageAlphaNoneSkipFirst. – Kurt Revis Aug 01 '13 at 05:07
  • Thanks for helping me out here but doing what you recommended didn't fix the issue. I posted what I interpreted from your response at the end of my original question, but it resulted in the same CGContext errors. – SimplyKiwi Aug 01 '13 at 05:23
  • You mean `CGImageGetBitmapInfo(source)`, not just `CGImageGetBitmapInfo`, correct? (Your way should not even compile, or should at least give a compiler warning.) – Kurt Revis Aug 01 '13 at 05:32
  • But why this error happens in the simulator and not on the device? Did you find out? – Julia Jan 22 '15 at 13:32
0

Your two calls to CGBitmapContextCreate both use unsupported bits/component - bits/pixel combinations (as the CGContext errors tell you).

See Table 2.1 in Quartz 2D Programming Guide for a list of supported pixel formats

Quentin
  • 3,971
  • 2
  • 26
  • 29