2010-01-03 15 views

Respuesta

9

que sugieren la creación de su propia bitmap context, envolviéndolo en una graphics context y establecer que a medida que el contexto actual, telling the image to draw itself, y luego acceder a los datos de píxeles detrás del marco de mapa de bits directamente.

Esto será más código, pero le ahorrará un viaje a través de una representación TIFF y la creación de miles o millones de objetos NSColor. Si está trabajando con imágenes de cualquier tamaño apreciable, estos gastos se acumularán rápidamente.

6

Obtenga NSBitmapImageRep de su NSImage. Luego puede obtener acceso a los píxeles.

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

Este es un enfoque muy caro, ya que 'colorAtX: y:' implicará la creación de una instancia de 'NSColor' para cada píxel, como Peter Notas de Hosey. Es mucho más eficiente obtener el buffer de datos en bruto y caminar usando punteros para calcular el histograma. – gavinb

+3

Hola gavinb, ¿tienes alguna dirección (obtén el búfer de datos brutos y recorres el uso de punteros) en este caso? ¡Gracias! – RickON

+0

@clearlight Bueno, no me di cuenta de que mantenía a nadie en suspenso. Escribí una aplicación de muestra que hace exactamente lo que se describe arriba, y agregué el código en una respuesta a esta pregunta. Lo publiqué en github también. ¡Disfrutar! – gavinb

1

Busque "histograma" en la documentación de Core Image.

2

Este código hace que la NSImage en 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); 
} 

Dado un contexto de mapa de bits, se puede acceder a los datos de imágenes en bruto directamente, y calcular los histogramas para cada canal de color:

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

Publiqué un proyecto completo, una aplicación de muestra Cocoa, que incluye lo anterior.

0

Usando colorAtX con NSBitmapImageRep no siempre conduce al color correcto.

me las arreglé para obtener el color correcto con este simple código:

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