2010-02-14 18 views
13

Cargar un CGImage o NSImage de un archivo usando un formato de imagen estándar (jpeg, gif, png et.) Es muy simple.CGImage from byte array

Sin embargo, ahora necesito crear una CGImage desde una matriz en bytes en la memoria generada usando libfreetype. Es realmente fácil crear texturas OpenGL a partir de una matriz de bytes formateados, y puedo ver cómo crear un CGBitmapContext para escribir en. Pero parece que no puedo encontrar una manera fácil de crear una CGImage desde una matriz de píxeles en bruto.

Respuesta

6

Puede crear un CGDataProvider y dejar que CG solicite los datos necesarios de su proveedor, en lugar de escribir en un búfer de imagen.

Aquí hay un ejemplo muy simple que genera un CGImage negro de tamaño 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); 

y getBytes se define así:

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

por supuesto, tendrá que poner en práctica las otras devoluciones de llamada (skipForward, rewind, releaseInfo), y el uso de una estructura u objeto adecuado para info. Para obtener más información, consulte las referencias CGImage y CGDataProvider.

+1

ha. la función correcta estaba justo debajo de mi nariz. Parece bastante simple envolver mis datos en un objeto CFData, y luego CGDataProviderCreateWithCFData. –

+0

@ChrisBecke - ¿Me puede dar más información? Estoy teniendo un problema similar. – Patricia

9

El uso de CFData puede hacer que el código anterior sea más simple. Aquí está el código.

// 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); 
+0

Lo que ocurre con las API básicas de base, CFData, etc., es que parecen diseñadas para transportar instancias refinanciadas de datos inmutables. Pero en la práctica parecen crear nuevas asignaciones y memcpy mucho. –

+0

¿Por qué los espacios de color 64 * 3 en la llamada CGImageCreate? De acuerdo con los documentos de Apple "espacio de color = el espacio de color de destino. El número de componentes en este espacio de color debe ser el mismo que el número en la imagen especificada". ¿Cómo determina la cantidad de componentes para el espacio de color? – Praxiteles

+0

¿Cómo podría hacer que la variable 64s sea variable? – achi

0

Pregunta anterior, pero sigue siendo útil. Swift 4 equivalentes de la respuesta del parque chansuk:

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)