【问题标题】:CGImage from byte array来自字节数组的 CGImage
【发布时间】:2010-02-14 13:25:44
【问题描述】:

使用标准图像格式(jpeg、gif、png 等)从文件中加载 CGImage 或 NSImage 非常简单。

但是,我现在需要从使用 libfreetype 生成的内存中的字节数组创建一个 CGImage。从格式化的字节数组创建 OpenGL 纹理真的很容易,我可以看到如何创建一个 CGBitmapContext 来写入。但我似乎找不到从原始像素数组创建 CGImage 的简单方法。

【问题讨论】:

    标签: cocoa cgimage freetype


    【解决方案1】:

    使用 CFData 可以使上面的代码更简单。 这是代码。

    // raw pixel data memory of 64 * 64 pixel size
    
    UInt8 pixelData[64 * 64 * 3];
    
    // fill the raw pixel buffer with arbitrary gray color for test
    
    for(size_t ui = 0; ui < 64 * 64 * 3; ui++)
      pixelData[ui] = 210;
    
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    
    CFDataRef rgbData = CFDataCreate(NULL, pixelData, 64 * 64 * 3);
    
    CGDataProviderRef provider = CGDataProviderCreateWithCFData(rgbData);
    
    CGImageRef rgbImageRef = CGImageCreate(64, 64, 8, 24, 64 * 3, colorspace, kCGBitmapByteOrderDefault, provider, NULL, true, kCGRenderingIntentDefault); 
    
    CFRelease(rgbData);
    
    CGDataProviderRelease(provider);
    
    CGColorSpaceRelease(colorspace);
    
    // use the created CGImage
    
    CGImageRelease(rgbImageRef);
    

    【讨论】:

    • 核心基础 API - CFData 等的问题是它们看起来像是被设计用来携带不可变数据的引用计数实例。但在实践中,它们似乎确实创建了很多新的分配和 memcpy。
    • 为什么在CGImageCreate调用中colorspace 64 * 3?根据Apple docs“颜色空间=目标颜色空间。此颜色空间中的组件数量必须与指定图像中的数量相同。”您如何确定颜色空间的组件数量?
    • 我怎样才能使 64s 可变?
    【解决方案2】:

    老问题,但仍然有用! Swift 4 相当于 chansuk park 的回答:

    let height = 64
    let width = 64
    let numComponents = 3
    let numBytes = height * width * numComponents
    let pixelData = [UInt8](repeating: 210, count: numBytes)
    let colorspace = CGColorSpaceCreateDeviceRGB()
    let rgbData = CFDataCreate(nil, pixelData, numBytes)!
    let provider = CGDataProvider(data: rgbData)!
    let rgbImageRef = CGImage(width: width,
                              height: height,
                              bitsPerComponent: 8,
                              bitsPerPixel: 8 * numComponents,
                              bytesPerRow: width * numComponents,
                              space: colorspace,
                              bitmapInfo: CGBitmapInfo(rawValue: 0),
                              provider: provider,
                              decode: nil,
                              shouldInterpolate: true,
                              intent: CGColorRenderingIntent.defaultIntent)!
    // Do something with rgbImageRef, or for UIImage:
    let outputImage = UIImage(cgImage: rgbImageRef)
    

    【讨论】:

    • 你不需要在swift 4中发布东西吗?
    【解决方案3】:

    您可以创建一个CGDataProvider,并让 CG 向您的提供者请求必要的数据,而不是写入图像缓冲区。

    这是一个非常简单的示例,它生成大小为 64x64 的黑色 CGImage

    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);
    

    getBytes 是这样定义的:

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

    当然,您需要实现其他回调(skipForwardrewindreleaseInfo),并为info 使用适当的结构或对象。

    有关详细信息,请查看 CGImageCGDataProvider 参考资料。

    【讨论】:

    • 哈哈。正确的功能就在我的眼皮底下。将我的数据包装在 CFData 对象中,然后 CGDataProviderCreateWithCFData 看起来很简单。
    • @ChrisBecke - 你能给我更多信息吗?我有类似的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多