Eine Linie zeichnen und ein Pixel setzen.

  • Eine Linie zeichnen und ein Pixel setzen.

    Hallo zusammen,

    es grüßt Euch die neue. Habe noch nicht lange einen Mac. Bin aber von Linux und PC vorbelastet.
    Die Programmierung von Grafik scheint kompliziert zu sein mit Objective C. Bei C++ und QT war alles viel einfacher.

    Nun zu XCode, Cocoa Objective C und solchen Gemeinheiten.

    Ich möchte nur einfach eine Linie zeichnen und ein Pixel setzen, und das ohne hunderte Zeilen Code einzugeben und komplizierte Konzepte verstehen zu müssen, die ich nicht nutze.

    Das Buch Obkective C und Cocoa von Rodewig sagt nichts darüber. X(

    Kann mir jemand ein paar einfache Zeilen posten ? Muss ich die Methode DrawRect überschreiben ?
    Welche View muss erzeugt werden ? Gibt es da keine einfachen Grafikbefehle? Muss ich auf einen Gerätekontext zugreifen ? Wenn ja, auf welchen ?

    Ich komme mir als Anfängerin vor. Es glaubt mir sicher niemand, dass ich mal Raytracer und Fraktalprogramme entwickelt habe.

    Oder soll ich weiter in Python enwickeln ? Sehr langsam, aber tut.

    Viele Grüße

    Andrea
  • Hm...
    Falsches Buch?
    <Werbeeinblendung>
    Objective-C und Cocoa, 2. erweiterte Auflage
    </Werbeeinblendung>

    Fertige Beispiele diesbezüglich findest du auf der Website zum Buch.

    1.) du brauchst ein eigenes View
    2.) du malst in der drawRect-Methode
    3.) es gibt keine einfachen Pixel, die man zeichnen kann.
    4.) eine Linie beginnst du mit [NSBezierPath moveToPoint:NSPoint] (Startpunkt setzen)
    5.) dann malst du mit [NSBezierPath lineToPoint:NSPoint] (zu absolutem Punkt malen) oder [NSBezierPath relativeLineToPoint:NSPoint] (zu Punkt relativ des Startpunktes malen)

    Hier ein kleines Codebeispiel aus dem Buch:

    Quellcode

    1. - (void)drawRect:(NSRect)rect
    2. {
    3. // Hintergrund und Rahmen zeichnen
    4. [[NSColor blackColor] set];
    5. NSEraseRect( rect );
    6. NSFrameRect( [self bounds] );
    7. }
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • RE: Eine Linie zeichnen und ein Pixel setzen.

    Hallo erst einmal!

    Ich möchte nur einfach eine Linie zeichnen und ein Pixel setzen, und das ohne hunderte Zeilen Code einzugeben und komplizierte Konzepte verstehen zu müssen, die ich nicht nutze.

    Nicht auf Dauer.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • RE: Eine Linie zeichnen und ein Pixel setzen.

    nicht gleich die flinte ins korn werfen. so schlimm ist das gar nicht. du brauchst auch keine hunderte zeilen code schreiben.
    und bevor ich hier ein paar aus dem zusammenhang gerissene zeilen poste schau dir mal diesen thread an und lad dir das zip am ende des threads herunter. damit solltest du eine ganz gute idee bekommen wie das funktioniert.

    sascha
  • RE: Eine Linie zeichnen und ein Pixel setzen.

    Nicht zu vergessen die Beispiele in den 'DevTools':

    /Developer/Examples/AppKit/BezierPathLab
    /Developer/Examples/AppKit/CompositeLab
    /Developer/Examples/AppKit/Sketch
    I would be embarrassed if they did not spy on me.
  • Hallo zusammen,

    vielen Danke für Eure Hilfe. Lucas: das Buch hab ich grad bestellt. ( Mein Buch heisst fast genauso; da fehlt alles über Grafik)

    Das Beispiel ist vielleicht ein Anfang.
    Jedoch möchte ich Grafik nicht nur Vektororientiert erzeugen, sondern, auch Pixelorientiert. D.H einzelne Pixel eines Bildes ändern/setzen/färben usw. Für meine Entwicklungen wäre das Voraussetzung.

    Es muss doch irgendwie möglich sein Pixel zu setzen ??

    Oder muss ich ein Bild in ein Array laden und dieses von Hand ändern und zurückschreiben, das wäre dann Mittelalterprogrammierung a la C=64 ( aber einfacher) *fg*

    Tom: Ein Pixel hat eine Ausdehnung ! Und ist sichtbar, es sei denn es ist transparent. :D

    macuser: Danke für das Beispiel. werds mir ansehen.

    longW: Die DevTools Beispiele hab ich mir angesehen, aber so richtg schlau wurde ich daraus nicht.

    Viele Grüße

    Andrea

    PS: bis jetzt fand ich Windoof-Api Programmierung umständlich !
  • Ich hatte Punkt gelesen.

    Wie in dem Buch (Du hast einfach die erste Auflage) ziemlich genau ausgeführt wird, sprichst du in Cocoa üblicherweise in der Tat keine Pixel an. Du kannst aber freilich Rechtecke mit der Ausdehnung 1.0/1.0 zeichnen. Wie das Ganze mit Koordinaten und Anti-Aliasing zusammenhängt wird ziemlich umfangreich erläutert.

    Ich bin übrigens der Negm-Awad.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Andrea
    Hallo zusammen,

    vielen Danke für Eure Hilfe. Lucas: das Buch hab ich grad bestellt. ( Mein Buch heisst fast genauso; da fehlt alles über Grafik)

    Das Beispiel ist vielleicht ein Anfang.
    Jedoch möchte ich Grafik nicht nur Vektororientiert erzeugen, sondern, auch Pixelorientiert. D.H einzelne Pixel eines Bildes ändern/setzen/färben usw. Für meine Entwicklungen wäre das Voraussetzung.

    Es muss doch irgendwie möglich sein Pixel zu setzen ??

    Oder muss ich ein Bild in ein Array laden und dieses von Hand ändern und zurückschreiben, das wäre dann Mittelalterprogrammierung a la C=64 ( aber einfacher) *fg*

    Tom: Ein Pixel hat eine Ausdehnung ! Und ist sichtbar, es sei denn es ist transparent. :D

    macuser: Danke für das Beispiel. werds mir ansehen.

    longW: Die DevTools Beispiele hab ich mir angesehen, aber so richtg schlau wurde ich daraus nicht.

    Viele Grüße

    Andrea

    PS: bis jetzt fand ich Windoof-Api Programmierung umständlich !

    Statt Verweisen auf ein paar Bücher vielleicht ein paar Tips wenn Du schon Raytracer programmiert hast:

    1) das Cocoa-Dreawing-Modell geht davon aus, daß immer mal wieder Events vorkommen, die sagen daß auf dem Bildschirm ein Rechteck neu gemalt werden muß. Das geht aber nicht direkt auf den Bildschirm sondern über mehrere Zwischenspeicher.
    2) das "Male-Neu-Event" wird automatisch auf einen NSView (oder Subklasse) übersetzt
    3) dort wird dann drawRect aufgerufen und der View höflich gebeten (mindestens) das angegebene Rechteck neu zu malen
    4) dort den ganzen Raytracer-Algorithmus unterzubringen wäre wahrscheinlich nicht sinnvoll (das blockiert nämlich das ganze Fenster)
    5) einzelne Pixel kann man sehr wohl lesen&schreiben, aber nicht direkt auf dem Bildschirm sondern in einem Objekt der Klasse NSBitmapImageRep
    6) das hat Breite, Höhe und Tiefe (Farbkanäle)
    7) es gibt ein "Vermittlerobjekt" NSImage, das von einer Bitmap abstrahiert (und auch Vektorgrafikformate verwaltet)
    8) und schließlich den NSImageView der ein NSImage (also auch eine Bitmap) ggf. gedreht, verkleinert, usw. auf den Bildschirm kopieren kann

    Am besten macht man deshalb einen NSImageView der ein NSImage anzeigt, das eine solche NSBitmapImageRep enthält. Dann kümmert sich der ImageView um das oben genannte drawRect und holt den jeweils zu malenden Bereich aus der ImageRep.

    Nun braucht es sicher einen Thread (damit das UI nicht hängt), in dem dann wirklich gemalt wird. Die Mal-Schleife ruft dann regelmäßig [imageView setNeedsDisplayInRect:rect] auf und das Kopieren auf den Bildschirm geht dann automatisch.

    Ja, das ist kompliziert wenn man gewohnt ist einfach setPixel(x, y, color) aufzurufen.

    -- hns
  • Hallo hns,

    danke für die Hilfe.
    Folgende Vorgehensweise für zeilenweise Berechnungen eines Bildes in einem Event - orientiertem OS:
    [list]
    Grafik in einem extra-Thread zeilenweise berechnen.

    Nach eine vorbestimmten Anzahl von Zeilen, das Rechteck dieser Zeilen als ungültig erklären.

    Der Hauptthread braucht nur noch aus der Hilfs-Bitmap die entsprechenden Pixel kopieren.

    Nach Fertigstellung kann die Hilfs-Bitmap als Resultat abgespeichert werden.
    [/list]
    Das ist im Prinzip Double-Buffering , jedoch effektiver.


    In der Doku find ich jedoch nur Abstraktionen. Kein einziger Befehl, wo wirklich etwas passiert.

    Oder ist der ganze Tiger nur ein Sammelwerk von abstrakten Interfaces?

    Ich möchte am Anfang erstmal nur eine Einfache Linie von Punkt A nach B zeichnen und nicht Bezier Approximationen ausführen. Ausserdem soll der "Kram" auch abgespeichert werden um ihn später weiterzuverarbeiten, drucken, etc. ( als GIF,PNG, PDF,PS oder so)

    7) es gibt ein "Vermittlerobjekt" NSImage, das von einer Bitmap abstrahiert (und auch Vektorgrafikformate verwaltet)


    Aber wo sind die Implementationen ? Wie müssen die geartet werden ?

    In der Doku find ich immer nur eine rekursive Kette von abstrakten Methoden.

    ich wünsche mir vom Osterhasen, Weihnachtsmann usw ein: "setPixel( x,y,R,G,B)" und
    zum Geburtstag dann ein "getPixel(x,y)" denn das brauch ich auch.

    viele Grüße

    Andrea
  • -lineToPoint: (NSBezierpath) führt keine Bezier-Approximation aus, sondern zeichnet eine Linie zum Zielpunkt.
    Discussion
    This method creates a straight line segment starting at the current point and ending at the point specified by the aPoint parameter. The current point is the last point in the receiver’s most recently added segment.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Andrea
    Folgende Vorgehensweise für zeilenweise Berechnungen eines Bildes in einem Event - orientiertem OS:
    [list]
    Grafik in einem extra-Thread zeilenweise berechnen.

    Nach eine vorbestimmten Anzahl von Zeilen, das Rechteck dieser Zeilen als ungültig erklären.

    Der Hauptthread braucht nur noch aus der Hilfs-Bitmap die entsprechenden Pixel kopieren.

    Nach Fertigstellung kann die Hilfs-Bitmap als Resultat abgespeichert werden.
    [/list]
    Das ist im Prinzip Double-Buffering , jedoch effektiver.
    Ja, genau.

    In der Doku find ich jedoch nur Abstraktionen. Kein einziger Befehl, wo wirklich etwas passiert.

    Oder ist der ganze Tiger nur ein Sammelwerk von abstrakten Interfaces?

    Ich möchte am Anfang erstmal nur eine Einfache Linie von Punkt A nach B zeichnen und nicht Bezier Approximationen ausführen. Ausserdem soll der "Kram" auch abgespeichert werden um ihn später weiterzuverarbeiten, drucken, etc. ( als GIF,PNG, PDF,PS oder so)

    7) es gibt ein "Vermittlerobjekt" NSImage, das von einer Bitmap abstrahiert (und auch Vektorgrafikformate verwaltet)


    Aber wo sind die Implementationen ? Wie müssen die geartet werden ?

    In der Doku find ich immer nur eine rekursive Kette von abstrakten Methoden.
    Vielleicht an der falschen Stelle?

    Nun, Cocoa ist ein Framework, das viele Primitive Objektklassen anbietet sowie Methoden um die zu bearbeiten. Sie sind halt so primitiv, daß man sich das Double-Buffering selber zusammenbauen kann/muß.

    Vielleicht folgender Anfang - nämlich erst mal etwas zu malen:

    1) In Xcode ein neues Cocoa-Application-Projekt anfangen (bei New Project...)
    2) dann die Datei MainMenu.nib im Interface Builder öffnen
    3) Dort einen NSImageView in das Fenster legen (Das ist der "Schneeberg" unter Custom Views)

    Übersetzen und ausprobieren. Da kann man dann (wenn der ImageView auf enabled steht) schon per Drag&Drop Bilder reinziehen.

    4) Eine Objective-C-NSView Class hinzufügen (bei New File...)
    5) In der Header-Datei aus NSView ein NSImageView machen, den View passend benennen
    6) drawRect: mal wie von anderen oben vorgeschlagen mit Code füllen (keine Sorge vor NSBezierPath - diese Klasse kann Kurven, aber auch Linien und Linien der Länge 0 = Punkte)
    7) und im Interface Builder den ImageView anwählen, dann das Info-Fenster öffnen und unter CustomView auf den eigenen View (Unterklasse) einstellen
    8) damit das geht, muß man vorher die Header-Datei aus dem Xcode-Projekt per Drag&Drop auf das Interface-Builder-File ziehen (man kann im IB auch den Menüpunkt Classes/Read File... nehmen)

    Das macht zwar noch kein Double Buffering, aber gibt schon mal einen ersten Einblick, wie ein Mac-GUI-Programm aussieht, das etwas Eigenes malt.
    ich wünsche mir vom Osterhasen, Weihnachtsmann usw ein: "setPixel( x,y,R,G,B)" und
    zum Geburtstag dann ein "getPixel(x,y)" denn das brauch ich auch.

    Die gibt es hier:
    developer.apple.com/documentat…itmapImageRep/colorAtX:y:
    developer.apple.com/documentat…pImageRep/setColor:atX:y:

    Apple ist also Osterhase und Weihnachtsmann zusammen :)

    -- hns
  • Tiger reicht als Geschenkebringer, 'NSBitmapImageRep' hat seit Tiger 2 neue Methoden:

    Quellcode

    1. - (void)setPixel:(unsigned int[])pixelData atX:(int)x y:(int)y
    2. - (void)getPixel:(unsigned int[])pixelData atX:(int)x y:(int)y


    Zum Zeichen von "NSBezierPath" in "NSImage", als Rastergrafik:

    Quellcode

    1. - (NSImage *) drawBezierPathInImage {
    2. NSSize size = NSMakeSize(100,100);
    3. NSImage *image = [[NSImage alloc] initWithSize: size];
    4. [image lockFocus];
    5. [[NSColor whiteColor] set]; //clears the background
    6. [NSBezierPath fillRect: NSMakeRect (0.0, 0.0, size.width, size.height)];
    7. // more drawing here
    8. [image unlockFocus];
    9. return [image autorelease];
    10. }
    Man braucht in der Regel eine Instanz von NSImage, in die gezeichnet werden kann.

    Zeichnen von Bildern in neuen Bilder:

    Quellcode

    1. [newImage lockFocus];
    2. [sourceImage compositeToPoint:locationInNewImage fromRect:rectToCopy operation:NSCompositeSourceOver];
    3. [otherImage compositeToPoint:locationInNewImage fromRect:rectToCopy operation:NSCompositeSourceOver];
    4. ...
    5. [newImage unlockFocus];


    Die "abstrakte" Doku von NSImage und begleitenden Objekten sollte man sich dazu anschauen, hier insbesondere eben 'NSBitmapImageRep'.
    I would be embarrassed if they did not spy on me.
  • Hallo hns, Negm-Awad

    danke für die Beiträge.

    vielleicht jetzt etwas OT
    der Mac hat mich schon fasziniert, Stabilität und Geschwindigkeit.

    Bisherige Grafikexperimente sind auf meiner HP zu sehen. Nichts weltbewegendes, aber alles selbst erdacht und programmiert. Gerne würde ich sowas auf dem mac entwickeln.
    Da dachte ich Cocoa (Quartz?) ist die richtige Wahl.


    Gruß

    Andrea
  • Cocoa ist zunächst für typische GUI-Apps entwickelt worden. Du kannst es schmerzfrei mit dem Graphik-System von OS X kombinieren, auch dann, wenn die entsprechenden Funktionen nicht bis Cocoa "hochgewrappt" wurden. Du kannst dich also gerne bei Quartz bedienen.

    Es gibt übrigens eine Quartz 2D API für Python.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Original von Andrea
    Jedoch möchte ich Grafik nicht nur Vektororientiert erzeugen, sondern, auch Pixelorientiert. D.H einzelne Pixel eines Bildes ändern/setzen/färben usw. Für meine Entwicklungen wäre das Voraussetzung.

    Es muss doch irgendwie möglich sein Pixel zu setzen ??


    GANZ schlechte Idee. Apple wird innerhalb des nächsten Jahres HiRes Bildschirme einführen. Sprich das sind Monitore mit der 4- oder 9- fachen Ausflösung bei gleicher Größe. Stichwort Resolution Independence. Auf der letzten WWDC hat Apple das ganz offensiv proklammiert. Du wirst also mittelfristig Probleme mit Pixelzeichnungen bekommen.

    Die kompletten Zeichen-Routinen unter OS X sind vektorbasiert. Wenn du ein Pixel haben willst, dann mal doch ein Rechteck, dass du auf genau auf die koordinaten packst, dann hast du dein pixel. Und wenn du mal auf 200% zoomst, dann bleibt es trotzdem scharf...

    Max
  • Hallo zusammen,

    nach vielem Probieren hab ich nun, dank Eurer Hilfe es hinbekommen eine Linie zu zeichnen.
    hpandrea.de/mac/xcode/Ansicht.zip

    Ich glaub ich hab das irgendwie anders gemacht. Der Umgang mit IB und XCode ist noch nicht so flüssig bei mir.

    M.A.X:

    Ich kenn diese Art von Grundsatzdisskussion Vektor versus Pixel. ;) ( Erinnert mich an meinen Ex Dozenten; ewig ists her)
    Unabhängig davon, dass ich sowieso meinen eigenen Stil habe und auch praktiziere geht es bei einigen Anwendugen halt um ganz bestimmte Eigenschaften.

    Bei einem SIRD ( Stereogramm) z.B. darf keine Skalierung stattfinden. Denn die gesammte Geometrie würde nicht mehr stimmen.
    Beim Drucken darf auch keine Skalierung stattfinden.
    Eine Vorlage . z. B. Ein Schnittmuster muss auf dem Papier die Genauen Maße ( cm, mm ) haben.
    Fraktale Grafiken ( siehe Peitgen Richter Science of Fraktal Images) werden meistens Pixelweise berechnet, da so die Fläche lückenlos geometrisch aufgeteilt wird. Eine Vektorisierung wäre da sinnlos und kontraproduktiv.

    Natürlich gibt es auch sinvolle Anwendungen für Vektorgrafik. Wie z. B. die Visualisierung von Firmendaten. Aber sowas brauch ich nicht. Da ich kein Geld für mein Progerei bekomm, tu ich Dinge die ich schön finde, also schöne Bilder erzeugen.

    Es gibt unzählig viele Rasterformate, GIF, PNG, JPG etc etc . Das WWW ist voll davon. Wenn diese Bilder nicht mehr verwertbar sind, werden Benutzer das nicht hinnehmen. Apple wird also dafür sorgen, dass auch diese Formate weiterhin eingesetzt werden können.

    Es ist also absolut keine schlechte Idee pixelorientiert zu arbeiten. Und Vektorbildschirme gab es auch schon früher. ( und viel Software in Fortran)

    viele Grüße

    Andrea