Frage

Ich wünschte, ich hätte eine Antwort für diese finden. Ich habe gesucht und gesucht und konnte nicht die richtige Antwort. Hier ist meine Situation:

In einer Mac OS Cocoa-Anwendung, ich möchte, um ein Pixel zeichnen (tatsächlich ein paar Pixel) auf einen speziellen Bereich auf meinem Fenster. Ich dachte, es wäre schöner, ein NSImageView dort platziert zu haben (ich habe so mit IB und verbunden, um den Ausgang zu meinem AppDelegate) und ziehen auf, dass statt meiner NSWindow.

Wie in der Welt kann ich das tun? Mac OS scheint Angebot NSBezierPath als das grundlegendste Zeichenwerkzeug - ist das wahr? Das ist schockierend vollständig zu mir. Ich komme aus einer langen Geschichte der Windows-Programmierung und ein Pixel auf eine Leinwand Zeichnung ist die einfachste Sache, in der Regel.

Ich möchte nicht, OpenGL verwenden, und ich bin nicht sicher, inwieweit Quarz in dieser beteiligt ist.

Alles, was ich will, ist etwas Hilfe, wie ich Objective-C / Cocoa diesen Pseudo-Code in Echt abziehen kann:

imageObj.drawPixel(10,10,blackColor);

Ich würde gerne Ihre Antworten auf diese hören, und ich bin sicher, dass dies eine Menge Leute helfen mit Cocoa beginnen.

Danke!

War es hilfreich?

Lösung

ist NSBezierPath das einzige Werkzeug in Cocoa zum Zeichnen primitivsten Formen und für viele komplexen Formen. Detailbeschreibung finden Sie hier: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaDrawingGuide/Paths/Paths.html%23//apple_ref/doc/uid/TP40003290-CH206-BBCHFJJG http://en.wikibooks.org/wiki/Programming_Mac_OS_X_with_Cocoa_for_Beginners/Graphics_-_Drawing_with_Quartz

Andere Tipps

Was Sie fordern ist eine dieser beiden Methoden:

NSBitmapRep setColor: atX: y:. ändert die Farbe des Pixels an den angegebenen Koordinaten

NSBitmapRep setPixel: atX: y:. Legt die Pixel des Empfängers an den angegebenen Koordinaten auf die angegebenen rohen Pixelwerte

Beachten Sie, dass diese auf iOS nicht verfügbar sind. Auf iOS, scheint es, dass die Art und Weise, dies zu tun, ist einen rohen Puffer von Pixeldaten für einen bestimmten Farbraum (wahrscheinlich RGB), füllt, die mit Farbdaten (schreiben eine wenig setPixel Methode, dies zu tun) und dann ruft CGImageCreate () zu erstellen etwa so:

    //Create a raw buffer to hold pixel data which we will fill algorithmically
    NSInteger width = theWidthYouWant;
    NSInteger height = theHeightYouWant;
    NSInteger dataLength = width * height * 4;
    UInt8 *data = (UInt8*)malloc(dataLength * sizeof(UInt8));

    //Fill pixel buffer with color data
    for (int j=0; j<height; j++) {
        for (int i=0; i<width; i++) {

            //Here I'm just filling every pixel with red
            float red   = 1.0f;
            float green = 0.0f;
            float blue  = 0.0f;
            float alpha = 1.0f;

            int index = 4*(i+j*width);
            data[index]  =255*red;
            data[++index]=255*green;
            data[++index]=255*blue;
            data[++index]=255*alpha;

        }
    }

    // Create a CGImage with the pixel data
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
    CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
    CGImageRef image = CGImageCreate(width, height, 8, 32, width * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,

                            provider, NULL, true, kCGRenderingIntentDefault);

    //Clean up
    CGColorSpaceRelease(colorspace);
    CGDataProviderRelease(provider);
    // Don't forget to free(data) when you are done with the CGImage

Schließlich könnten wollen Sie Pixel in einem Bild zu manipulieren, haben Sie bereits in eine CGImage geladen. Es gibt Beispielcode dafür, dass in einem Apple Technical Q & A betitelte QA1509 die Erste Pixeldaten von einem CGImage Objekt .

Cocoa Low-Level-API Zeichnung ist Core Graphics (Quarz). Sie erhalten eine Zeichnung Kontext und Ausgabe-Befehle auf diesen Zusammenhang zu ziehen. Die API ist so konzipiert, dass geräteunabhängige (Sie die gleichen Befehle auf den Bildschirm zu zeichnen, wie man es auf Papier zu zeichnen, wenn das Drucken). Daher gibt es keine Befehle für in einzelnen Pixeln füllen, weil es als ein Pixel auf dem Papier nicht so etwas ist. Auch auf dem Bildschirm, Ihrer Ansicht nach in irgendeiner Art und Weise verändert worden sein, so dass ein einzelner Punkt auf einem einzelnen Gerät Pixel abbilden nicht.

Wenn Sie ein einzelnes Pixel zeichnen möchten, müssen Sie ein Rechteck spezifizieren, die die Größe eines einzelnen Pixels ist, dann füllen Sie es in. Für das Pixel bei (x, y), ein Rechteck mit Ursprung wollen würde (x-0,5, y-0,5) und eine Größe von (1,1).

Sie können das tun mit NSBezierPath, oder Sie können einen Core Graphics Kontext (CGContextRef) aus [[NSGraphicsContext currentContext] graphicsPort] und Nutzungsfunktionen wie CGContextFillRect() erhalten.

Dies wird sich natürlich nicht sehr schnell sein, wenn Sie viele Pixel zeichnen; das ist nicht das, was die API ausgelegt ist. Wenn das, was Sie tun müssen, sollten Sie einen Puffer mit malloc das Erstellen und das Schreiben der Pixeldaten an das, dann Core Graphics mit in ein CGImageRef umzuwandeln, die auf dem Bildschirm gezeichnet werden kann.

Für Zeichnung Pixel, wie Sie beschreiben, gibt es keine Notwendigkeit, einen Weg zu schaffen oder zu dem Quartz 2D oder OpenGL API zurückgreifen.

Siehe NSRectFill() und verwandte Funktionen wie NSRectFillList() und NSRectFillUsingOperation().

Wenn Sie eine Menge von einzelnen Pixeln sind zeichnen, ist NSRectFillList() etwa so schnell, wie Sie es, ohne auf rollen Sie Ihre eigenen Bildpuffer tun können.

Vielleicht bin ich Missverständnis der Frage, aber Quarz hat die Fähigkeit, Rechtecke zu füllen:

void CGContextFillRect (CGContextRef c, CGRect rect);

Hier ist ein schneller Weg, Pixel auf OS X zu ziehen:

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    NSBitmapImageRep *rep = [[NSBitmapImageRep alloc]
                             initWithFocusedViewRect:dirtyRect];

    for (int x = 0; x < [rep pixelsWide]; x++) {
        for (int y = 0; y < [rep pixelsHigh]; y++) {
            NSUInteger pixel[4] = { 0, 255, 0, 255 };
            [rep setPixel:pixel atX:x y:y];
        }
    }

    [rep drawInRect:dirtyRect];
}

fand ich Ihre Frage hier ein bisschen spät, weil ich das gleiche Problem haben. Vielleicht kann Apples Entwickler-Dokumentation Ihnen dabei helfen. Ich habe es selbst nicht getestet, aber einen Blick auf dieses Dokument übernehmen:

http://developer.apple .com / library / mac / # Dokumentation / Kakao / konzeptuelle / CocoaDrawingGuide / Bilder / images.html

Etwa in der Mitte des Dokuments Sie den Abschnitt finden „Erstellen einer Bitmap“. Es sagt Ihnen, verschiedene Arten von Pixeldaten zu schaffen.

class CMKViewController: NSViewController {


  override func viewDidLoad() {
        super.viewDidLoad()

         let testIV = TestImageView(image: NSImage(named: "test.png")!)
         // testIV.frame = CGRect(x:0,y:0,width:100,height:100)
          self.view.addSubview(testIV)
          testIV.myPixels = [CGPoint(x:10,y:10)]

    }


}

class TestImageView:NSImageView{

    var myPixels:[CGPoint] = []

    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)

        guard let context: CGContext = NSGraphicsContext.current()?.cgContext else {
            consolePrint("Cannot get graphics context")
            return
        }

        // Fill background to white
        context.setFillColor(.white)
        context.fill(bounds)
        context.setFillColor(NSColor.red.cgColor)


        // Draw pixels
        context.fillPixels(myPixels)


    }
}



extension CGContext {

    func fillPixels(_ pixels: [CGPoint]) {
        var size:CGSize?
        if Screen.retinaScale > 1{
            size = CGSize(width: 1.5, height: 1.5)
        }else{
            size = CGSize(width: 1.0, height: 1.0)
        }

        for pixel in pixels{
          fill(CGRect(origin: pixel, size: size!))
        }
    }

    func fill(_ pixel: CGPoint) {
        fill(CGRect(origin: pixel, size: CGSize(width: 1.0, height: 1.0)))
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top