2010-02-14 49 views
13

使用標準圖像格式(jpeg,gif,png等)從文件加載CGImage或NSImage都非常簡單。來自字節數組的CGImage

但是,我現在需要在數組中使用libfreetype生成的內存中的字節數組中創建CGImage。它很容易從一組格式化的字節創建OpenGL紋理,我可以看到如何創建一個CGBitmapContext到,編寫即可。但我似乎無法找到從原始像素數組創建CGImage的簡單方法。

回答

6

您可以創建一個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參考。

+1

ha。正確的功能正好在我的鼻子下面。它看起來很簡單,我的數據包裝在一個CFData對象,然後CGDataProviderCreateWithCFData。 – 2010-02-14 16:14:11

+0

@ChrisBecke - 你能給我更多的信息嗎?我有類似的問題。 – Patricia 2014-07-03 22:37:32

9

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

核心基礎API - CFData等的東西是,它們看起來像它們被設計用來攜帶不可變數據的ref計數實例。但實際上,他們確實似乎創造了新的分配和memcpy很多。 – 2010-09-26 16:46:41

+0

爲什麼CGImageCreate調用中的colorspace 64 * 3?根據Apple文檔「colorspace =目標色彩空間,此色彩空間中的組件數量必須與指定圖像中的數量相同」。你如何確定色彩空間的組件數量? – Praxiteles 2012-12-12 07:51:25

+0

我怎樣才能使64s變量? – achi 2014-07-16 23:59:33

0

老問題,但仍然有用!雨斯公園回答:

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)