CIImage rendered to CVPixelBuffer (with CIContext help) changes color

1

I create a CIImage from an IOSurface. Then I render it to a CVPixelBuffer. If I skip the CIImage step the color is fine, however I intend to crop the image with CIImage/CIContext functions. However the problem is that the CIImage/CIContext step introduces color changes. See the example image, left is the intended colors and right is what I end up with.

enter image description here

I am pretty sure (although not certain) that it has to do with color spaces, and the fact that the iPhone uses a .. wide? .. color space? However I've tried countless of configurations, both in the CIContext and the render step. For example:

CIContext *cicontext = [CIContext contextWithOptions:@{
    kCIContextWorkingColorSpace: (id)CGColorSpaceCreateWithName(kCGColorSpaceSRGB)
}];

And

[cicontext render:ciimage 
  toCVPixelBuffer:pixelBuffer 
           bounds:CGRectMake(0, 0, 1125, 2436) 
       colorSpace:CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearSRGB)];

But I never get any different result. My full code is:

CIImage *ciimage = [CIImage imageWithIOSurface:surface];
CIContext *cicontext = [CIContext context];
CVPixelBufferRef pixelBuffer = NULL;
NSDictionary *pixelAttributes = @{(id)kCVPixelBufferCGImageCompatibilityKey: (id)kCFBooleanTrue,
                                  (id)kCVPixelBufferBytesPerRowAlignmentKey: @(16),
                                  (id)kCVPixelBufferCGBitmapContextCompatibilityKey: (id)kCFBooleanTrue};
CVPixelBufferCreate(kCFAllocatorDefault, 
                    1125, 
                    2436, 
                    kCVPixelFormatType_32BGRA, 
                    (__bridge CFDictionaryRef _Nullable)(pixelAttributes),
                    &pixelBuffer);
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
[cicontext render:ciimage 
  toCVPixelBuffer:pixelBuffer 
           bounds:CGRectMake(0, 0, 1125, 2436) 
       colorSpace:CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearSRGB)];
[writerAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:presentTime];
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);    
CVPixelBufferRelease(pixelBuffer);
CFRelease(surface);

And below are the NSLogs from the CIImage, CIContext, CVPixelBuffer, in case that helps. I have had configurations where I set the CIContext CGColorSpace to the same as the CIImage, without any change in output. CIImage:

<CIImage: 0x28191cbf0 extent [0 0 1125 2436]>
<CGColorSpace 0x283f5c240> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)

CIContext

<CIContext: 0x28191dff0 (metal 24) MTLDevice=0x104738000>
    priority: default
    workingSpace: <CGColorSpace 0x283f71500> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB Linear)
    workingFormat: RGBAh
    downsampleQuality: Low

Pixel Buffer

<CVPixelBuffer 0x282a7b2a0 width=1125 height=2436 bytesPerRow=4544 pixelFormat=BGRA iosurface=0x0 attributes={
    BytesPerRowAlignment = 16;
    CGBitmapContextCompatibility = 1;
    CGImageCompatibility = 1;
    PixelFormatDescription =     {
        BitsPerBlock = 32;
        BitsPerComponent = 8;
        BlackBlock = {length = 4, bytes = 0x000000ff};
        CGBitmapContextCompatibility = 1;
        CGBitmapInfo = 8196;
        CGImageCompatibility = 1;
        ComponentRange = FullRange;
        ContainsAlpha = 1;
        ContainsGrayscale = 0;
        ContainsRGB = 1;
        ContainsYCbCr = 0;
        FillExtendedPixelsCallback = {length = 24, bytes = 0x00000000000000008cfcbea8010000000000000000000000};
        IOSurfaceCoreAnimationCompatibility = 1;
        IOSurfaceOpenGLESFBOCompatibility = 1;
        IOSurfaceOpenGLESTextureCompatibility = 1;
        OpenGLESCompatibility = 1;
        PixelFormat = 1111970369;
    };
} propagatedAttachments={
} nonPropagatedAttac
ios
objective-c
ciimage
iosurface
asked on Stack Overflow Apr 27, 2021 by jontelang • edited Apr 28, 2021 by aheze

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0