Get pixels and colours from NSImage

后端 未结 6 1282
南方客
南方客 2021-02-06 03:10

I have created an NSImage object, and ideally would like to determine how many of each pixels colour it contains. Is this possible?

6条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-02-06 03:50

    This code renders the NSImage into a CGBitmapContext:

    - (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);
    }
    

    Given a bitmap context, we can access the raw image data directly, and compute the histograms for each colour channel:

    - (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
    

    I've published a complete project, a Cocoa sample app, which includes the above.

    • https://github.com/gavinb/CocoaImageHistogram.git

提交回复
热议问题