CGImage da array di byte
Domanda
Caricamento di un CGImage o NSImage da un file utilizzando un formato standard di immagini (jpeg, gif, png et.) È tutto molto semplice.
Tuttavia, ora bisogno di creare un CGImage da una matrice in byte di memoria generato utilizzando libfreetype. La sua veramente facile da creare texture OpenGL da un array di byte formattati, e posso vedere come creare un CGBitmapContext per di scrittura a. Ma io non riesco a trovare un modo semplice per creare un CGImage da una matrice di pixel crudo.
Soluzione
È possibile creare un CGDataProvider
, e lasciare richiesta CG i dati necessari dal vostro provider, invece di scrivere in un buffer di immagini.
Ecco un esempio molto semplice che genera un CGImage
nero di dimensioni 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);
e getBytes è definito in questo modo:
size_t getBytes(void *info, void *buffer, size_t count) {
memset(buffer, 0x00, count);
return count;
}
Naturalmente, si vuole attuare le altre callback (skipForward
, rewind
, releaseInfo
), e utilizzare una struttura adeguata o un oggetto per info
.
Per ulteriori informazioni, consulta la CGImage e CGDataProvider riferimenti .
Altri suggerimenti
Utilizzando CFData può rendere il codice di cui sopra più semplice. Ecco il codice.
// 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);
vecchia questione, ma sempre utile! Swift 4 equivalente della risposta di parco 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)