Eine Array von nicht zusammenhängenden Pixeln zeichnen?
-
Moin,
zur Zeit mach ich das so:
static void drawpoints(struct state *st) { for (int i = 0; i < st->npoints; i++) { // Punktebuffer in den Grafikbuffer SetPixel( myBackBuffer, // HDC via SelectObject ... st->pointbuf[i].x, // int st->pointbuf[i].y, // int st->colorbuf[i] // COLORREF ); } // Pointbuffer zurücksetzen st->npoints = 0; }Die Anzahl der Colorrefs entspricht immer der Anzahl von Punkten.
Herrjeh, geht das nicht schneller?
-
timmix schrieb:
Herrjeh, geht das nicht schneller?
Nein, solange Du uns nicht sagst, was eigentlich Dein Problem ist... :p
-
Elektronix schrieb:
Nein, solange Du uns nicht sagst, was eigentlich Dein Problem ist... :p
Ok. ich machs mal deutlicher:

Also ich habe mir einen (Bildschirm-) Buffer mit CreatCompatibleDC() erzeugt und dort auch ein kompatibles Bitmap in der richtigen Größe eingefügt.
GetWindowRect(hWnd, &myScreenSize); myDevCon = GetDC(hWnd); myBitmap = CreateCompatibleBitmap(myDevCon, myScreenSize.right, myScreenSize.bottom); myBackBuffer = CreateCompatibleDC(myDevCon); ReleaseDC(hWnd, myDevCon); SelectObject(myBackBuffer, myBitmap);In oben genannter Schleife setze ich, sagen wir mal 30.000 Pixel mit SetPixel in eben diesen Buffer (hier: myBackbuffer). Ist der Punktbuffer (Zeiger auf ein POINT[] und COLORREF[]) komplett in myBuffer gelandet mache ich ein BitBlt().
Klappt klasse, allerdings nicht sehr performant. Ich hatte gehofft einer von euch Freaks könnte mir auf Anhieb sagen: "mmh, mach das doch so und so!"
Meine Vermutung ist, dass der Flaschenhals sich in det SetPixel() gemütlich gemacht hat.
Unter X11 gibt es XDrawPixel(), das genau das gleiche macht wie SetPixel(); es gibt aber auch eine Funktion XDrawPixels() [man beachte den Plural] die neben anderen Sachen einen Pointer auf einen Punktebuffer übernimmt und diesen wahnsinnig schnell verarbeitet - das ist das was ich brauche ...

--
Beste Grüße
Timmix
-
Erstmal vorweg: Die GDI ist langsam, egal welche Funktion du benutzt.
Was soll denn das Resultat sein ...? Ein Farbverlauf ? Das hast du nämlich nicht geschrieben! Was soll denn das Resultat später präsentieren ?
-
CodeFinder schrieb:
Erstmal vorweg: Die GDI ist langsam, egal welche Funktion du benutzt.
Toll, hilft ja nun wirklich nicht weiter!
CodeFinder schrieb:
Was soll denn das Resultat sein ...? Ein Farbverlauf ? Das hast du nämlich nicht geschrieben! Was soll denn das Resultat später präsentieren ?
Mmh, ich dachte ich hätte geschrieben, ich würde die Punkte aus einen Punktbuffer von sagen wir mal 30.000 Punkten mal hier hin mal dorthin gesetzt haben. Das wird dann schlussendlich ein animiertes IFS-Fraktal (schnell und schön!)
Try it: http://ticore.de/share/ifs.zip
-
timmix schrieb:
Toll, hilft ja nun wirklich nicht weiter!
Das aber schade, ...mir hätte es nämlich weitergeholfen.
CodeFinder schrieb:
Was soll denn das Resultat sein ...? Ein Farbverlauf ? Das hast du nämlich nicht geschrieben! Was soll denn das Resultat später präsentieren ?
[...]ein animiertes IFS-Fraktal (schnell und schön!)
[/quote]
Ahh, na geht doch!...Gut und wo ist nun dein Problem ? Es läuft doch.
-
[überflüssig]
-
Nimm eine Device Independend Bitmap (DIB) und setze direkt Pixel via Byte-Array (da gibts glaube ich CreateDIBSection() oder sowas in der WinAPI...)
Das dürfte deutlich schneller sein.
Das fertige Resultat dann z.B. mit DrawDib() anzeigen lassen.Bei codeproject.com oder hier im Board lässt sich dazu bestimmt etwas finden.
Die Pixel alle mit SetPixel() zu setzen ist auf jedenfall sau lahmarschig.
-
CodeFinder schrieb:
Ahh, na geht doch!...Gut und wo ist nun dein Problem ? Es läuft doch.
Na ja, ich kann mein Mittagessen wohl auch mit Hilfe eines Baggers essen; das wäre sehr effektiv! Mir geht es aber nicht um Effektivität sondern um Effizienz. Bedeutet: Weniger Rechenpower für ebensoviel Leistung. Sprich: Unter Linux und X11 läuft das Programm mit ca. 3-4% Rechenleistung meines 1,6 GHz P6. Unter Windows läuft das Ganze mit ca. 25 - 30 Prozent. Ergo, gehe ich davon aus, dass ich das schneller hinbekommmen kann, weil ich falsch programmiert habe. Deswegen meine Frage an das geschätzte Publikum dieses Forums.

Es ist einfach total uncool, wenn ich vor meinem Rechner sitze und mein Rechner glaubt er müsse jetzt mal den Lüfter anschmeißen, weil er sonst sterben würde. Ich weiß das dass anders geht, und ich werde das auch noch hinbiegen ...

Die Sache mit den DIB-Dingsda werde ich mal angehen, wenn jemand noch Tipps hat für mich, immer her damit.
Im übrigen ist das Ganze mein erstes C-Program. Schonmal nicht ganz unbeachtlich, oder?

-
geeky schrieb:
Nimm eine Device Independend Bitmap (DIB) und setze direkt Pixel via Byte-Array (da gibts glaube ich CreateDIBSection() oder sowas in der WinAPI...)
Das dürfte deutlich schneller sein.
Das fertige Resultat dann z.B. mit DrawDib() anzeigen lassen.Also, dass hört sich doch mal nach einem heißen Tipp an! Schade nur dass mein Englisch nicht das Beste ist. Dennoch, das SDK sagt DI-Bitmaps wären meine Freunde. Herrlich! Schon jemand viel Erfahrung damit gemacht?
-
timmix schrieb:
[...]Effizienz. Bedeutet: [...]
LOL ich weiß was Effizienz bedeutet.
timmix schrieb:
Schade nur dass mein Englisch nicht das Beste ist
Ist bei der Programmierung aber das A und O.
Naja du kannst ja auch DX nutzen, aber da braucht man auch English
.
-
Generell:
Du nimmst CreateDIBSection() und fütterst es so:
hdc - Der DC auf den du später blitten wirst
CONST BITMAPINFO *pbmi - Hier den Pointer einer BITMAPINFO-Struktur übergeben. Mit der BITMAPINFO-Struktur legst du Höhe, Breite, Farbtiefe etc. der Bitmap fest.
UINT iUsage - Wirst du auf DIB_RGB_COLORS setzen wollen.
ppvBits - Pointer auf eine Variable die den Pointer für die Pixeldaten bekommt.
Sprich über die befüllte Variable kannst du hinterher die Pixel direkt im Speicher setzen.
hSection - FileMapping wirste vermutl. nicht brauchen (also NULL)
dwOffset - Wird bei hSection=NULL eh ignoriert.Wenn der Funktionsaufruf funktioniert hat, kriegste ne HBITMAP zurück, die du auch ganz normal in nen DC selektieren und blitten kannst (BitBlt()...)
Die Pixel kannst du dann über den ppvBits-Pointer selbst setzen.
-
geeky schrieb:
Generell:
Du nimmst (...)Ok, die Richtung hab ich verstanden!

Ich zieh dann jetzt mal los und werde genanntes böhmisches Dorf erobern. Kann 'ne Woche dauern, oder so - ich bin ja lernwillig

Ich melde mich mit Resultaten oder neuen Fragen. Bis dahin!
-
geeky schrieb:
( ... schnipp ... )
Wenn der Funktionsaufruf funktioniert hat, kriegste ne HBITMAP zurück, die du auch ganz normal in nen DC selektieren und blitten kannst (BitBlt()...)
Die Pixel kannst du dann über den ppvBits-Pointer selbst setzen.Folgendes scheint erstmal zu funktionieren!
// DISection bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = myScreenSize.right; bmih.biHeight = myScreenSize.bottom; bmih.biPlanes = 1; bmih.biBitCount = 24; bmih.biCompression = BI_RGB; bmih.biSizeImage = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3) * bmih.biHeight; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; hBitmap = CreateDIBSection(NULL, (BITMAPINFO *) &bmih, 0, (void**)&pBits, NULL, 0); // DISectionWie schreibe ich jetzt meine Punkte wie in folgender Schleife in die DIBSection?
static void drawpoints(struct state *st) { for (int i = 0; i < st->npoints; i++) { SetPixelV(myBackBuffer, st->pointbuf[i].x, st->pointbuf[i].y, st->colours[st->ccolour]); } // Pointbuffer zurücksetzen st->npoints = 0; }Auch auf die Gefahr hin mich lächerlich zu machen, etwas wie dieses?
Zeile = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3); Adresse = &pBits + (Zeile * y) + x;Und vor allem wie schreibe ich jetzt mein COLORREF an diese Adresse?
Mmmh: Merkt man dass ich gerade C und WinAPI lerne? Wahrscheinlich!
-
Habs selbst rausgefunden:
static void drawpoints(struct state *st) { int Zeile = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3); for (int i = 0; i < st->npoints; i++) { pBits[ Zeile * st->pointbuf[i].y + st->pointbuf[i].x * sizeof(COLORREF) ] = RGB(255,255,255); } }Funktioniert, außer, dass statt weiß wie angegeben blau gezeichnet wird - verstehe ich nicht! Jemand einen Tipp!
-
timmix schrieb:
Habs selbst rausgefunden:
static void drawpoints(struct state *st) { int Zeile = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3); for (int i = 0; i < st->npoints; i++) { pBits[ Zeile * st->pointbuf[i].y + st->pointbuf[i].x * sizeof(COLORREF) ] = RGB(255,255,255); } }Funktioniert, außer, dass statt weiß wie angegeben blau gezeichnet wird - verstehe ich nicht! Jemand einen Tipp!
Selbst gelöst, immerhin:
static void drawpoints(struct state *st) { int offset; int cxScanLine = ((((bmih.biWidth * bmih.biBitCount) + 31) & ~31) >> 3); for (int i = 0; i < st->npoints; i++) { offset = (cxScanLine * st->pointbuf[i].y) + (st->pointbuf[i].x * (sizeof(BYTE)) * 4); pBits[offset] = 0x00; // 0x00bbggrr (!) pBits[offset++] = st->b[st->ccolour]; pBits[offset++] = st->g[st->ccolour]; pBits[offset++] = st->r[st->ccolour]; } // Pointbuffer zurücksetzen st->npoints = 0; }Verstehen tu ich das noch nicht, aber wird schon!
