Bitmap context for wide color range

1.1k views Asked by At

I am trying to create an image mask with kCGColorSpaceDisplayP3 colorspace to support the iPhone 7's wide color range.

I am able to create image mask correctly when using sRGB colorspace on iPhone 6 and earlier devices using iOS 10 and earlier iOS. But I have no clue where I am going wrong when creating colorspace using kCGColorSpaceDisplayP3:

CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);

CGContextRef context = CGBitmapContextCreate(NULL, 320.0, 320.0, 32, 320.0*16, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents);

CGFloat radius = 10.0;
CGFloat components[] = {1.0,1.0,1.0,1.0,   1.0,1.0,1.0,1.0,    1.0,1.0,1.0,1.0,     1.0,1.0,1.0,1.0,    1.0,1.0,1.0,0.5,    1.0,1.0,1.0,0.0};
CGFloat locations[] = {0.0, 0.1, 0.2, 0.8, 0.9, 1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 6); //colorSpaceP3
CGPoint center = CGPointMake(100.0, 100.0);
CGContextDrawRadialGradient(context, gradient, center, 0.1, center, radius, 0);

CGGradientRelease(gradient);

CGImageRef imageHole = CGBitmapContextCreateImage(context);
CGImageRef maskHole = CGImageMaskCreate(CGImageGetWidth(imageHole), CGImageGetHeight(imageHole), CGImageGetBitsPerComponent(imageHole), CGImageGetBitsPerPixel(imageHole), CGImageGetBytesPerRow(imageHole), CGImageGetDataProvider(imageHole), NULL, FALSE);

CGImageRelease(imageHole);

CGImageRef image = [UIImage imageNamed:@"prosbo_hires.jpg"].CGImage;
CGImageRef masked = CGImageCreateWithMask(image, maskHole);

CGImageRelease(maskHole);
UIImage *img = [UIImage imageWithCGImage:masked];
CGImageRelease(masked);

CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

The log says:

: CGImageMaskCreate: invalid mask bits/component: 32.

I don't have much experience with Core Graphics. Can anyone please suggest something here.

Thanks.

2

There are 2 answers

0
Alej priv On

this fixed my issue:

contextRef = CGBitmapContextCreate(
    m.data,
    m.cols,
    m.rows,
    8,
    m.step[0], 
    CGColorSpaceCreateDeviceRGB(),
    bitmapInfo);

https://developer.apple.com/search/?q=CGColorSpaceCreate

1
Ken Thomases On

The documentation for the bitsPerComponent parameter of CGImageMaskCreate() says:

Image masks must be 1, 2, 4, or 8 bits per component.

You're passing CGImageGetBitsPerComponent(imageHole), which is 32 bits per component. As per both the documentation and the log message, that's not valid.

The implication is that image masks don't support floating point bitmap formats.

It should be possible to create the bitmap context and the mask using 8 bits per component. More or less, just leave out kCGBitmapFloatComponents. I expect that will result in reduced granularity of the opacity of the mask, but won't affect the color range of masked images.