2016-06-29 21 views
0

Ich arbeite an einer OSX-App, die Bildbearbeitung auf Pixelebene durchführt. Ich verwende den folgenden Code, um auf die Pixel-Farbkomponenten (RGBA) als reguläre Bytes zuzugreifen, die als uint8-Zeiger umgewandelt werden.Zugriff auf CGImageRef zugrunde liegenden Bytes und ändern?

NSImage *image = self.iv.image; 
NSRect imageRect = NSMakeRect(0, 0, image.size.width, image.size.height); 
CGImageRef cgImage = [image CGImageForProposedRect:&imageRect context:NULL hints:nil]; 
NSData *data = (NSData *)CFBridgingRelease(CGDataProviderCopyData(CGImageGetDataProvider(cgImage))); 
    uint8 *pixels = (uint8 *)[data bytes]; 

An diesem Punkt wende ich einige Byte-Ebene Änderungen:

for (int i = 0; i < [data length]; i += 4) { ... } 

diesen Bereich des Speichers ändern scheint keine Auswirkungen auf die ursprünglichen CGImageRef zu haben (die zu der Zeit in eine angezeigte NSImageView). Ich muß die folgenden Punkte entsprechend das Bild Update zu sehen:

CGImageRef newImageRef = CGImageCreate (width, 
              height, 
              bitsPerComponent, 
              bitsPerPixel, 
              bytesPerRow, 
              colorspace, 
              bitmapInfo, 
              provider, 
              NULL, 
              false, 
              kCGRenderingIntentDefault); 

    NSSize size = NSMakeSize(CGImageGetWidth(newImageRef), 
          CGImageGetHeight(newImageRef)); 

    NSImage * newIm = [[NSImage alloc] initWithCGImage:newImageRef size:size]; 

    self.iv.image = newIm; 

Mit anderen Worten, die Bytes ich zurück zu modifizieren, ist nur eine Kopie des ursprünglichen Bytes, vermutlich als Folge von CGDataProviderCopyData(CGImageGetDataProvider(cgImage).

Meine Frage ist wie folgt. Gibt es eine Möglichkeit, auf die zugrunde liegenden Bytes von CGImageRef direkt zuzugreifen, so dass das Bild bei der Änderung auf dem Bildschirm aktualisiert wird, wenn ich sie manipuliere?

Antwort

2

Nr. CGImage s sind unveränderlich. Sie können sie nicht mehr ändern, sobald sie erstellt wurden. In Ihrem Code gibt der Aufruf an [data bytes] einen Zeiger auf constvoid. Sie haben die const weggeworfen, die es ohne Warnungen kompiliert, aber das ist ein Verstoß gegen den Design-Vertrag. Das Schreiben in den Puffer, der den Datenprovider unterstützt, ist nicht zulässig und funktioniert nicht garantiert, selbst wenn Sie einen neuen CGImage daraus erstellen.

Ich werde auch darauf hinweisen, dass das Format der Daten im Puffer möglicherweise ganz anders als erwartet ist. Es gibt keinen guten Grund zu erwarten, dass die Daten 32 Bit pro Pixel sind, RGBA gegen BGRA vs. ARGB vs. ... oder irgendetwas anderes.

Ich empfehle dringend, dass Sie die Abschnitte über die verschiedenen Bildobjekte in der 10.6 AppKit release notes lesen. Scrollen Sie nach unten zu "NSImage, CGImage und CoreGraphics Impedanzanpassung" und lesen Sie alle folgenden bildbezogenen Abschnitte durch, bis Sie "NSComboBox" drücken. Der Abschnitt "NSBitmapImageRep: CoreGraphics Impedanzanpassung und Leistungshinweise" ist einer der wichtigsten für Ihre Zwecke.

Darüber hinaus können Sie nur einen Pixelpuffer verwalten, den Sie selbst zugewiesen haben, in dem von Ihnen bevorzugten Format. Dann, wenn Sie eine CGImage davon wollen, erstellen Sie es aus dem Puffer, zeichnen Sie mit ihm und verwerfen Sie es. Irgendwelche Pixelmanipulationen würden in diesem Puffer durchgeführt werden.