从NSImage获取像素和颜色

Nip*_*rus 9 cocoa nsimage

我创建了一个NSImage对象,理想情况下,它想确定它包含的每个像素颜色的数量.这可能吗?

Pet*_*sey 10

我建议创建自己的位图上下文,将其包装在图形上下文中并将其设置为当前上下文,告诉图像绘制自己,然后直接访问位图上下文后面的像素数据.

这将是更多的代码,但将通过TIFF表示和创建数千或数百万个NSColor对象来节省您的旅程.如果您正在使用任何可观尺寸的图像,这些费用将很快增加.


gav*_*inb 9

此代码呈现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);
}
Run Code Online (Sandbox Code Playgroud)

给定位图上下文,我们可以直接访问原始图像数据,并计算每个颜色通道的直方图:

- (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
Run Code Online (Sandbox Code Playgroud)

我发布了一个完整的项目,一个Cocoa示例应用程序,其中包括上述内容.


iam*_*mac 7

获取一个NSBitmapImageRep从你的NSImage.然后,您可以访问像素.

NSImage* img = ...;
NSBitmapImageRep* raw_img = [NSBitmapImageRep imageRepWithData:[img TIFFRepresentation]];
NSColor* color = [raw_img colorAtX:0 y:0];
Run Code Online (Sandbox Code Playgroud)

  • 这是一种非常昂贵的方法,因为`colorAtX:y:`将涉及为每个像素创建一个`NSColor`实例,正如Peter Hosey所说.获取原始数据缓冲区并使用指针计算直方图更有效. (3认同)
  • 嗨gavinb,你有这方面的任何指示(获取原始数据缓冲区并使用指针)?谢谢! (3认同)