Image Pixel-weise selber zeichnen

  • Image Pixel-weise selber zeichnen

    Hallo Zusammen!

    Ich möchte ein Image Pixel für Pixel selber zeichnen (die Farbe für jeden Pixel muss einzelnd berechnet werden).

    Da ich (bis jetzt) keine Möglichkeit gefunden habe, wie man in Cocoa nur genau einen Pixel mit einer bestimmten Farbe zeichnet, habe ich eine Lösung mittels QuickDraw gefunden:
    1. Mittels "NewGWorld" eine off-screen QuickDraw GWorld erzeugen
    2. Die gewünschten QuickDraw-Zeichenoperationen in diese GWorld machen (in meinem Fall jeden Punkt mit "SetCPixel" setzten).
    3. Über "CopyBits" das erstellte Bild (also den Inhalt der GWorld) in eine NSQuickDrawView kopieren.

    Das läuft soweit und ist auch einigermaßen schnell (viel, viel schneller, als wenn ich direkt in die NSQuickDrawView zeichnen würde)

    Jetzt kommt aber das Problem:
    Wie bekomme ich dieses erzeugte Bild in einen anderen Context z.B. in eine Zelle einer NSTableView?

    Man kann sich zwar ein Bild mit Cocoa, ähnlich wie in QuickDraw oben beschrieben, selbst erzeugen (und zwar über ein NSCachedImageRep-Objekt), aber dann habe ich wieder das Problem, dass ich nicht weiß, wie ich jeden Pixel einzeln setzen kann.

    Eine Lösung wäre es, wenn man der QuickDraw-Umgebung mitteilen könnte, doch bitte seine Zeichen-Funktionen auf den CoreGraphics-Context zu beziehen (den erhält man über [[NSGraphicsContext currentContext] graphicsPort]).
    Wenn man den aber mit SetGWorld setzt, bleibt das Programm bei der ersten QuickDraw-Zeichenfunktion stehen.

    Also, das einfachste wäre, wenn man mittels Cocoa/CoreGraphics einen einzelnen Punkt mit einer bestimmten Farbe malen könnte (ohne dass man jür jeden Punkt ein eigenes NSColor-Objekt anlegen muss).

    Ich bin für jede Hilfe dankbar!
  • RE: Image Pixel-weise selber zeichnen

    Vielen Dank für den Link!

    Habe gerade mal den dort gelistetet Quelltext angeschaut und es scheint, dass damit mein Problem gelöst ist!

    Dort wird es so gemacht: Speicherbereich für das Bild anlegen und dann direkt in diesen Speicherbreich schreiben.
    Das ist konzeptionell nicht so schön - weil man genau wissen muss, wie der Speicher organisiert ist. Besser wäre ist, wenn man den Speicherbreich als aktuellen Zeichen-Kontext deklarieren könnte und dann mit regulären Zeichenoperationen zechnet.

    Aber wie heißt es so schön: Das Leben ist kein Wunschkonzert!
  • RE: Image Pixel-weise selber zeichnen

    Also, ich bin gerade dabei, ein Programm zu schreiben, dass die Festplattenbelegung grafisch darstellt à la SequoiaView (Windows) bzw. KDirStat (Linux).

    Leider muss die Farbe für jeden Pixel einzelnd berechnet werden. Mit Cocoa/CoreGraphics kann man zwar sehr leicht komplexe Grafiken Zeichnen, aber ich habe noch keinen guten Weg gefunden, ein BitMap-Image Pixel-für-Pixel selber zu erzeugen.
    Wie oben beschrieben, gibt's unter QuickDraw "SetCPixel".

    Hast Du einen Tip? (die Möglichkeit von dem Link oben ist zwar machbar, aber nicht schön).
  • RE: Image Pixel-weise selber zeichnen

    Mir fällt auch nur die genannte Methode ein, ich finde das auch nicht so problematisch- Ich würde mir eine Sub-Klasse bilden, die ihr Datenlayout kennt und mir eine setPixelatPoint withColor oder so Methode dazuschreiben, dann ist das doch einigermassen sauber. Wenn man wirklich an die rohen Daten ran will ist das am Einfachsten. Der andere Weg geht über OpneGL, das eignet sich auch hervorragend für 2D Graphik.
    Du könntest natürlich auch eine Linie mit selben Start und Endpunkt zeichnen, das gäbe dann auch einen Punk ;)
  • RE: Image Pixel-weise selber zeichnen

    Ich habe gerade noch ein bisschen im Netz gestöbert und bin durch einen Post in der OmniGroup Mailinglist auf die Programmbeispiele des Buches "Cocoa Programming" gekommen (herunterladbar unter cocoaprogramming.net).

    Dort gibt es ein Beispiel wo eine View mit Punkten gefüllt wird. Auf 3 verschiedene Weisen:
    1. Direkt mit NSRectFill (Höhe = Breite = 1)
    2. Mit NSRectFillList
    3. Mit anlegen von Speicher, direktes festlegen der Farben der Pixel und dann per NSBitmapImageRep in View malen (also wie bereits oben beschrieben)

    Wie man sich vorstellen kann, ist die 3. Methode die BEI WEITEM die schnellste...

    Ich muss sagen, wenn man eher eine Bitmap-orientierte Bilderzeugung braucht, ist man mit QuickTime besser bedient. Denn leider kann man so einen Speicherbereich nicht gleichzeitig benutzten, um direkt Pixel über Speicherzugriff zu manipulieren und mittels Cocoa/CoreGraphics in diesen Speicher zu zeichnen.
    Das geht nur nacheinander.
    Das geht unter QuickDraw schon (direktes Setzten von einzelnen Pixel geschieht auch nicht über direkten Speicherzugriff, sondern über entsprechende Funktionen - sehr schön).

    Vielleicht sollte ich mir wirklich mal anschauen, wie man OpenGL benutzt. Soll ja unter Cocoa sehr einfach sein.
    Dann kann man gleich beim Live-Resizing die Grafikkarte das Verzerren des Bildes übernehmen lassen und erst am Ende des Resizing Vorhangs das Bild neu berechnen ?
  • RE: Image Pixel-weise selber zeichnen

    Um noch auf deinen Vorschlag mit der eigenen Klasse zurückzukommen:
    Ich bin auch schon am Überlegen, wie ich das Codetechnisch einigermassen sauber hinbekomme. Das Problem dabei ist, dass die View das Zeichnen nicht selber übernimmt, sondern es an andere Objekte (plural) delegiert (wie es sich unter OO gehört ;-).
    Bis jetzt konnten diese Objekte lustig drauf loszeichnen, weil der Grafikkontext vorher in der View initialisiert wurde.
    Wenn diese Zeichenobjekte aber nun in einzelne Pixel über direkten Speicherzugriff malen müssen, ist es nicht mehr so schön einfach. Und wenn sie auch noch über Cocoa/CoreGraphics etwas zeichnen wollen (z.B. Text), wirds noch unschöner...
  • RE: Image Pixel-weise selber zeichnen

    Normal wäre doch, das der View jedem Objekt einen (beschränkten) Zugriff auf die Zeichenumgebung einräumt, mit der Aufforderung, sich dort darzustellen. In diesem komplexeren Fall würde ich für den View ein Callback-Interface definieren, das das Setzen einzelner Pixel erlaubt. Bzw. die Clients des View einfach ihre 'Pixel-Wünsche' dem View ohne direkten Zugriff zu melden, und dieser übernimmt dann die Darstellung. Müsste SPÄTER mal meine OO-Bible zücken und nach einem Pattern suchen. Freut mich aber, das sich mal jmd Gedanken über Design macht.