Question

J'ai créé un objet NSImage et voudrais idéalement déterminer combien de pixels chaque couleur qu'il contient. Est-ce possible?

Était-ce utile?

La solution

Je suggère de créer votre propre contexte bitmap href="http://developer.apple.com/mac/library/documentation/GraphicsImaging/Reference/CGBitmapContext/" , emballage dans un graphiques contexte et paramètre comme le contexte actuel, dire l'image à se dessiner , puis accéder aux données de pixels derrière le contexte de bitmap directement

Ce sera plus de code, mais vous permettra d'économiser à la fois un voyage à travers une représentation TIFF et la création de milliers ou des millions d'objets NSColor. Si vous travaillez avec des images de taille appréciable, ces dépenses ajouteront rapidement.

Autres conseils

Ce code rend le NSImage dans un 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);
}

Dans un contexte donné bitmap, on peut accéder aux données d'images brutes directement, et calculer les histogrammes pour chaque canal de couleur:

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

J'ai publié un projet complet, un exemple d'application de cacao, qui comprend ce qui précède.

Obtenez NSBitmapImageRep de votre NSImage. Ensuite, vous pouvez accéder aux pixels.

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

peut-être une approche plus rationnelle pour certains et réduire la complexité de tomber dans la gestion de la mémoire.

https://github.com/koher/EasyImagy

Code de l'échantillon https://github.com/koher/EasyImagyCameraSample

import EasyImagy

let image = Image<RGBA<UInt8>>(nsImage: "test.png") // N.B. init with nsImage 

print(image[x, y])
image[x, y] = RGBA(red: 255, green: 0, blue: 0, alpha: 127)
image[x, y] = RGBA(0xFF00007F) // red: 255, green: 0, blue: 0, alpha: 127

// Iterates over all pixels
for pixel in image {
    // ...
}



//// Gets a pixel by subscripts Gets a pixel by  
let pixel = image[x, y]
// Sets a pixel by subscripts
image[x, y] = RGBA(0xFF0000FF)
image[x, y].alpha = 127
// Safe get for a pixel
if let pixel = image.pixelAt(x: x, y: y) {
    print(pixel.red)
    print(pixel.green)
    print(pixel.blue)
    print(pixel.alpha)

    print(pixel.gray) // (red + green + blue) / 3
    print(pixel) // formatted like "#FF0000FF"
} else {
    // `pixel` is safe: `nil` is returned when out of bounds
    print("Out of bounds")
}

Recherchez "histogramme" dans la documentation de l'image de base.

Utilisation colorAtX avec NSBitmapImageRep ne conduit pas toujours à la bonne couleur exacte.

J'ai réussi à obtenir la couleur correcte avec ce code simple:

[yourImage lockFocus]; // yourImage is just your NSImage variable
NSColor *pixelColor = NSReadPixel(NSMakePoint(1, 1)); // Or another point
[yourImage unlockFocus];
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top