Search code examples
cocoacgimagefreetype

CGImage from byte array


Loading a CGImage or NSImage from a file using a standard image format (jpeg, gif, png et.) is all very simple.

However, I now need to create a CGImage from an array in bytes in memory generated using libfreetype. Its really easy to create OpenGL textures from an array of formatted bytes, and I can see how to create a CGBitmapContext to write to. But I can't seem to find an easy way to create a CGImage from a raw pixel array.


Solution

  • You can create a CGDataProvider, and let CG request the necessary data from your provider, instead of writing to an image buffer.

    Here's a very simple example that generates a black CGImage of size 64x64.

    CGDataProviderSequentialCallbacks callbacks;
    callbacks.getBytes = getBytes;
    
    CGDataProviderRef provider = CGDataProviderCreateSequential(NULL, &callbacks);
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGImageRef img = CGImageCreate(64,                         // width
                                   64,                         // height
                                   8,                          // bitsPerComponent
                                   24,                         // bitsPerPixel
                                   64*3,                       // bytesPerRow
                                   space,                      // colorspace
                                   kCGBitmapByteOrderDefault,  // bitmapInfo
                                   provider,                   // CGDataProvider
                                   NULL,                       // decode array
                                   NO,                         // shouldInterpolate
                                   kCGRenderingIntentDefault); // intent
    
    CGColorSpaceRelease(space);
    CGDataProviderRelease(provider);
    
    // use the created CGImage
    
    CGImageRelease(img);
    

    and getBytes is defined like this:

    size_t getBytes(void *info, void *buffer, size_t count) {
        memset(buffer, 0x00, count);
        return count;
    }
    

    of course, you will want to implement the other callbacks (skipForward, rewind, releaseInfo), and use a proper structure or object for info.

    For more information, check out the CGImage and CGDataProvider references.