2010-01-03 8 views

Antwort

9

Ich schlage vor, Ihre eigenen bitmap context zu schaffen, ist es in einem graphics context Einwickeln und Einstellung, die als aktuellen Kontext, telling the image to draw itself und dann hinter dem Bitmap-Kontext direkt die Pixeldaten zugreifen.

Dies wird mehr Code sein, aber sparen Sie sowohl eine Reise durch eine TIFF-Darstellung und die Schaffung von Tausenden oder Millionen von NSColor-Objekten. Wenn Sie mit Bildern von beträchtlicher Größe arbeiten, summieren sich diese Ausgaben schnell.

6

Holen Sie sich eine NSBitmapImageRep von Ihrem NSImage. Dann können Sie auf die Pixel zugreifen.

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

Dies ist eine sehr teure Ansatz, wie 'colorAtX: y:' 'wird eine NSColor' Instanz für jedes Pixel umfassen die Erstellung, als Peter Hosey Notizen. Es ist viel effizienter, den Rohdatenpuffer zu erhalten und mit Hilfe von Zeigern das Histogramm zu berechnen. – gavinb

+3

Hallo Gavinb, haben Sie irgendwelche Anweisungen (Holen Sie sich den Rohdatenpuffer und gehen Sie mit Zeigern durch) auf diesem einen? Vielen Dank! – RickON

+0

@clearlight Nun, ich wusste nicht, dass ich jemanden in der Schwebe halte. Ich schrieb eine Beispiel-App, die genau das tut, was oben beschrieben ist, und fügte den Code in einer Antwort zu dieser Frage hinzu. Ich habe es auch auf GitHub veröffentlicht. Genießen! – gavinb

1

Suchen Sie in der Core Image-Dokumentation nach "Histogramm".

2

Dieser Code macht die NSImage in ein 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); 
} 

eine Bitmap Kontext Gegeben, können wir die Rohbilddaten direkt zuzugreifen, und berechnen die Histogramme für jeden Farbkanal:

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

Ich habe ein komplettes Projekt veröffentlicht, eine Cocoa-Beispiel-App, die das oben genannte enthält.

0

Mit colorAtX mit NSBitmapImageRep führt nicht immer auf die genaue richtige Farbe.

ich es geschafft, die richtige Farbe mit diesem einfachen Code zu erhalten:

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