2010-01-03 123 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];