2010-01-03 167 views

回答

9

我建議創建自己的bitmap context,在graphics context包裝,並設置作爲當前背景下,telling the image to draw itself,然後直接訪問位圖背景後面的像素數據。

這將是更多的代碼,但會爲您節省TIFF表示以及創建數千或數百萬個NSColor對象。如果您正在處理任何可觀尺寸的圖片,這些費用將快速增加。

6

NSImage獲取NSBitmapImageRep。然後你可以訪問像素。

NSImage* img = ...; 
NSBitmapImageRep* raw_img = [NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]]; 
NSColor* color = [raw_img colorAtX:0 y:0]; 
+3

這是一個非常昂貴的方法,如'colorAtX:Y:'將涉及每個像素創建'NSColor'實例,如彼得Hosey筆記。獲得原始數據緩衝區並通過使用指針來計算直方圖是非常有效的。 – gavinb 2010-01-03 10:28:58

+3

嗨gavinb,你有任何方向(獲取原始數據緩衝區,並通過使用指針走過)在這一個?謝謝! – RickON 2014-01-05 10:22:45

+0

@clearlight嗯,我沒有意識到我讓任何人處於懸念狀態。我寫了一個示例應用程序,它執行上面描述的內容,並將代碼添加到對此問題的答案中。我也在github上發佈了它。請享用! – gavinb 2017-04-05 13:21:17

1

在Core Image文檔中查找「直方圖」。

2

此代碼呈現NSImageCGBitmapContext

- (void)updateImageData { 

    if (!_image) 
     return; 

    // Dimensions - source image determines context size 

    NSSize imageSize = _image.size; 
    NSRect imageRect = NSMakeRect(0, 0, imageSize.width, imageSize.height); 

    // Create a context to hold the image data 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 

    CGContextRef ctx = CGBitmapContextCreate(NULL, 
              imageSize.width, 
              imageSize.height, 
              8, 
              0, 
              colorSpace, 
              kCGImageAlphaPremultipliedLast); 

    // Wrap graphics context 

    NSGraphicsContext* gctx = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:NO]; 

    // Make our bitmap context current and render the NSImage into it 

    [NSGraphicsContext setCurrentContext:gctx]; 
    [_image drawInRect:imageRect]; 

    // Calculate the histogram 

    [self computeHistogramFromBitmap:ctx]; 

    // Clean up 

    [NSGraphicsContext setCurrentContext:nil]; 
    CGContextRelease(ctx); 
    CGColorSpaceRelease(colorSpace); 
} 

給定一個位圖情況下,我們可以直接訪問原始圖像數據,並計算直方圖對於每個顏色通道:

- (void)computeHistogramFromBitmap:(CGContextRef)bitmap { 

    // NB: Assumes RGBA 8bpp 

    size_t width = CGBitmapContextGetWidth(bitmap); 
    size_t height = CGBitmapContextGetHeight(bitmap); 

    uint32_t* pixel = (uint32_t*)CGBitmapContextGetData(bitmap); 

    for (unsigned y = 0; y < height; y++) 
    { 
     for (unsigned x = 0; x < width; x++) 
     { 
      uint32_t rgba = *pixel; 

      // Extract colour components 
      uint8_t red = (rgba & 0x000000ff) >> 0; 
      uint8_t green = (rgba & 0x0000ff00) >> 8; 
      uint8_t blue = (rgba & 0x00ff0000) >> 16; 

      // Accumulate each colour 
      _histogram[kRedChannel][red]++; 
      _histogram[kGreenChannel][green]++; 
      _histogram[kBlueChannel][blue]++; 

      // Next pixel! 
      pixel++; 
     } 
    } 
} 

@end 

我已經發布了一個完整的項目,一個Cocoa示例應用程序,其中包括上述。

0

使用colorAtXNSBitmapImageRep並不總是導致確切正確的顏色。

我設法得到正確的顏色與這個簡單的代碼:

[yourImage lockFocus]; // yourImage is just your NSImage variable 
NSColor *pixelColor = NSReadPixel(NSMakePoint(1, 1)); // Or another point 
[yourImage unlockFocus];