CVPixelBuffer created from CGImage has different attributes

282 views Asked by At

EDIT: I worked around this issue but to rephrase my question - is it possible to create the CVPixelBuffer to match the CGImage? For example I would like to have 16 bits per component instead of 8.


As the title says. For example, when I NSLog my buffer it has 4544 bytes per row. But when I NSLog the actual CGImage it has 9000. This is the logs:

buffer: <CVPixelBuffer 0x282b8b020 width=1125 height=2436 bytesPerRow=4544 pixelFormat=BGRA iosurface=0x0 attributes={    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 = 0x00000000000000008c3c1da7010000000000000000000000};
IOSurfaceCoreAnimationCompatibility = 1;
IOSurfaceOpenGLESFBOCompatibility = 1;
IOSurfaceOpenGLESTextureCompatibility = 1;
OpenGLESCompatibility = 1;
PixelFormat = 1111970369;
};
} propagatedAttachments={
} nonPropagatedAttachments={
}>

And the image

image: <CGImage 0x1044625d0> (IP)   <<CGColorSpace 0x283e9ea60> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; Display P3)>
        width = 1125, height = 2436, bpc = 16, bpp = 64, row bytes = 9000
        kCGImageAlphaNoneSkipLast | kCGImageByteOrder16Little  | kCGImagePixelFormatPacked
        is mask? No, has masking color? No, has soft mask? No, has matte? No, should interpolate? Yes

This is the code I use

CGImageRef cgImageRef = [image CGImage];
CGImageRetain(cgImageRef);
CVPixelBufferRef pixelBuffer = NULL;
size_t w = CGImageGetWidth(cgImageRef);
size_t h = CGImageGetHeight(cgImageRef);
CGDataProviderRef x = CGImageGetDataProvider(cgImageRef);
CGDataProviderRetain(x);
CFDataRef da = CGDataProviderCopyData(x);
CFIndex len = CFDataGetLength(da);
const uint8_t* src = CFDataGetBytePtr(da);
CVPixelBufferCreate(kCFAllocatorDefault,
                    w,
                    h,
                    kCVPixelFormatType_32BGRA,
                    nil,
                    &pixelBuffer);
CVPixelBufferLockBaseAddress( pixelBuffer, 0 );
void* base = CVPixelBufferGetBaseAddress(pixelBuffer);

SNLog(@"buffer: %@", pixelBuffer);
SNLog(@"image: %@", cgImageRef);

I am later trying to go through the CGImage address and manually copy the bytes into the destination pixel buffer. But it crashes and I assume it is because I am at some point trying to read from "after" the actual image.

1

There are 1 answers

0
jontelang On

I guess my initial question was not exactly clear, or perhaps I should have rephrased it slightly. The problem is more like - I would like to create my buffer to match the image - with the same amount of bytes/bits per component.

I worked around this by looping through the buffer and picking individually bytes I want from the image. Basically ignoring some bits of each pixel.

In the end the image looks fine still, I suspect the increased amount of bits is used for better quality on more capable screens. Although I am not sure.