Canvas auslesen? (was nicht von BMax reingeschrieben wurde)

Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

 

#Reaper

Newsposter

Betreff: Canvas auslesen? (was nicht von BMax reingeschrieben wurde)

BeitragDo, Aug 16, 2007 16:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Also ich versuche nun schon länger den Desktop (von Windows) auszulesen. Mit BPlus geht das ja ganz einfach, und vorallem sehr schnell.
Für BMax habe ich nun auch schon einige sachen gefunden, mit denen man zwar auch ein Bild bekommt, welche aber doch extrem langsamm sind.

Also einmal habe ich diese Funktion hier, welche ~60ms braucht:

Code: [AUSKLAPPEN]
Function GetDesktopPixmap:TPixmap()

   Extern "Win32"
      Function GetDIBits(hdc:Int, bitmap:Int, Start:Int, Num:Int, bits:Byte Ptr, lpbi:Byte Ptr, usage:Int)
      Function CreateCompatibleBitmap(hdc:Int, Width:Int, Height:Int)
      Function CreateDIBSection(hdc:Int, pbmi:Byte Ptr, usage:Int, Bits:Byte Ptr, hSection:Int, Offset:Int)
      Function SelectObject(hdc:Int, obj:Int)
      Function CreateCompatibleDC(hdc:Int)
      Function GetDesktopWindow()
      Function GetWindowDC(hwnd:Int)
      Function GetDeviceCaps(hdc:Int, index:Int)
      Function DeleteDC(hdc:Int)
      Function DeleteObject(obj:Int)
      Function ReleaseDC(hwdn:Int, hdc:Int)
      Function BitBlt(hdc:Int,x:Int,y:Int,w:Int,h:Int,src_dc:Int,src_x:Int,src_y:Int,dwrop:Int)
   End Extern

   ?Win32
   
      Type BITMAPINFO
         Field biSize:Int
         Field biWidth:Int
         Field biHeight:Int
         Field biPlanes:Short
         Field biBitCount:Short
         Field biCompression:Int
         Field biSizeImage:Int
         Field biXPelsPerMeter:Int
         Field biYPelsPerMeter:Int
         Field biClrUsed:Int
         Field biClrImportant:Int
         
         Field R:Byte
         Field G:Byte
         Field B:Byte
         Field Res:Byte
      End Type
       
       
      Const HORZRES:Int = 8
      Const VERTRES:Int = 10
   
      Local HwndDesktop:Int
      Local hdcDesktop:Int
      Local hdcMem:Int
      Local DesktopWidth:Int
      Local DesktopHeight:Int
      Local bmpMem:Int
      Local INFO:BITMAPINFO
      Local FinalPixmap:TPixmap
   
      HwndDesktop = GetDesktopWindow()
   
      If Not HwndDesktop
         Return Null
      EndIf
       
       
      hdcDesktop = GetWindowDC(HwndDesktop)
       
      If Not HdcDesktop
         Return Null
      EndIf
       
       
      hdcMem = CreateCompatibleDC(hdcDesktop)
       
      If Not HdcMem
         Return Null
      EndIf
       
       
      DesktopWidth = GetDeviceCaps(hdcDesktop, HORZRES)
      DesktopHeight = GetDeviceCaps(hdcDesktop, VERTRES)
   
      If DesktopWidth = 0 Or DesktopHeight = 0
         Return Null
      EndIf
       
       
      bmpMem  = CreateCompatibleBitmap(hdcDesktop, DesktopWidth, DesktopHeight)
   
      If Not BmpMem
         Return Null
      EndIf
       
       
      If Not SelectObject(HdcMem, bmpMem)
         Return Null
      EndIf
       
      Info                = New BITMAPINFO
      Info.bisize         = SizeOf(INFO)
      info.BiWidth        = DesktopWidth
      Info.biHeight       = DesktopHeight
      Info.biPlanes       = 1
      info.biBitCount     = 32
      Info.biCompression  = 0
       
       
      If Not BitBlt(hdcMem,0,0,Info.biWidth,Info.biHeight, hdcDesktop,0,0,ROP_SRCCOPY)   
         Return Null
      EndIf
       
      FinalPixmap = CreatePixmap(info.biWidth, info.biHeight, PF_BGRA8888)
       
      If Not GetDIBits(hdcMem, bmpMem, 10, Info.biHeight, FinalPixmap.PixelPtr(0,0), info, 0)
         Return Null
      EndIf
       
      FinalPixmap = YFlipPixmap(FinalPixmap)
       
      DeleteDC(HdcMem)
      DeleteObject(bmpMem)
      ReleaseDC(hwndDesktop, hdcDesktop)
       
      Return FinalPixmap
       
   ?
   
   ?Linux
      Return Null
   ?
   
   ?MacOs
      Return Null
   ?
End Function



Das langsammste an dieser geschichte ist die Funktion GetDIBits().

Nun geht das ganze auch noch etwas kürzer (und auch schneller):
Code: [AUSKLAPPEN]
Window:TGadget = CreateWindow("Desktop", 250, 250, ClientWidth(Desktop()), ClientHeight(Desktop()))
canvas:TGadget = CreateCanvas(0,0,1024,768, Window)

dsDC = GetDC(QueryGadget(canvas, QUERY_HWND_CLIENT))
dhWnd = GetDesktopWindow()

BitBlt dsDC, 0, 0, ClientWidth(Desktop()), ClientHeight(Desktop()), GetDC(dhWnd), 0, 0, $00CC0020


Nun befindet sich bei dem Code sogar der Screenshot vom Desktop in dem Canvas, aber wenn ich versuche irgend etwas aus dem Canvas zu lesen, ist es leer. Ich vermute einfach mal, das es insofern auch an Max2D liegt.
Weiß vielleicht jemand eine Funktion (von Windows oder so) mit der man direkt den Inhalt vom Canvas auslesen kann? Hab auch schonmal versucht das ganze in eine Bank zu hauen, geht aber leider auch nicht (bleibt leer) Sad
Oder weiß so noch jemand etwas?
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7
 

Dreamora

BeitragDo, Aug 16, 2007 16:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Aus einem Canvas zu lesen macht keinen Sinn.
Was da drin angezeigt wird ist der aktuelle Frontbuffer()
Was du also auslesen musst ist dieser.
Davon würd ich aber eigentlich abraten, da belässt du die Desktop Daten lieber in einem Pixmap und liest sie aus dem Pixmap aus mit den ReadPixel Befehlen oder durch die Abfrage des DatenPtr des Pixmaps und direkten Array Zugriffen auf diesen. (via Bank is zwar net nette Idee, jedoch ist ein Pixmap schon nichts anderes als ein Array mit Farbinformationen)

Der Grund ist recht simpel: Ausm Frontbuffer auslesen heisst FrontBuffer lock, was nicht gerade die schnellste Operation ist und auch net wirklich sinnvoll ist zu nutzen, denn es gibt keine Anwendung dafür (alles geht auch via Backbuffer)

Was willst du denn damit genau machen?
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

#Reaper

Newsposter

BeitragDo, Aug 16, 2007 18:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Also das Desktopimage will ich (zu mindestens teilweise) über das Netzwerk verschicken, deshalb ist es auch nicht so wichtig, als was mit die Daten vorliegen (also ob Pixmap oder Bank).
Und im erstem Code schreibt die Funktion GetDIBits() die Bilddaten in die Pixmap. Und ausgerechnet diese Funktion braucht rund 50ms dafür Sad
Ich hab noch keine andere Funktion für GetDIBits() gefunden :-/
Aber irgendetwas muss es ja geben, schließlich geht es mit BPlus ja mit weniger als 1ms Confused
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7
 

Dreamora

BeitragDo, Aug 16, 2007 19:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würd ma sagen da gibts 2 Möglichkeiten wie das geht:

1. Umleitung des Renderns in eine DirectSurface (nicht möglich in BM sofern du das nicht von Grund auf selbst implementierst)

2. Es gibt ne möglichkeit direkt an den Desktop Buffer ran zu kommen, also an den Byte Ptr davon und es auszulesen.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

d-bug

BeitragDo, Aug 16, 2007 19:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Bei deiner Funktion da oben sind 2 kleinere Fehler drin:

1.
Gehst du davon aus, dass jeder Desktop eine Farbtiefe von 32bit hat.

Ändere mal:
Code: [AUSKLAPPEN]
info.biBitCount     = 32

nach:
Code: [AUSKLAPPEN]
Const BITSPIXEL:Int = 12
info.biBitCount      = GetDeviceCaps (hdcDesktop, BITSPIXEL)



2.
Das Format was du bei der Pixmap zurück gibst sorgt schon mal für lustige Effekte.
Bei Beschwerden solltest du die Pixmap nach PF_BGR888 konvertieren.


und noch ein letztes...
Durch importieren des Modules pub.win32 bekommst du den Type BITMAPINFOHEADER und 90% deiner API-Calls (außer ReleaseDC, glaube ich) und Konstanten gratis dazu. Aber ich denke mal, dass weißt du bereits. Wink


Hatte jetzt nichts mit dem Kern des Threads zu tun, aber ich dachte mir, ich weise dich mal darauf hin!
 

#Reaper

Newsposter

BeitragDo, Aug 16, 2007 21:44
Antworten mit Zitat
Benutzer-Profile anzeigen
d-bug hat Folgendes geschrieben:

und noch ein letztes...
Durch importieren des Modules pub.win32 bekommst du den Type BITMAPINFOHEADER und 90% deiner API-Calls (außer ReleaseDC, glaube ich) und Konstanten gratis dazu. Aber ich denke mal, dass weißt du bereits. Wink


Danke für die Hinweise. Hatte den Code wo gefunden Wink
Und..mhh... Pub.Win32? Mhh..^^ Ok, ich gebs zu, wuste ich noch nicht Embarassed

Und ich frage mich aber immernoch, warum die nicht einfach alle RGB nehmen.... grml.. -.- naja..
Ich mag lustige Effekte Very Happy


@Dreamora:
Also zu 1.: Ich würde mal sagen, dass das noch zu hoch für mich ist Sad Crying or Very sad
Zu 2: Ok, das könnte mir dann doch vielleicht weiter helfen Smile
Aber habe bislang den Befehl noch nicht gefunden. Also falls du ihn rein zufällig weist, fände ich das auch toll Wink ^^
Ich schätze mal, dass der Befehl nämlich eh nichts mit Desktop und Buffer heißt, wodurch ich ihn bislang dann auch noch nicht gefunden habe, naja, ich such mal weiter Wink Danke Smile

PS: Meint ihr, es würde was bringen, wenn man Sibly fragen würde. Er müsste es ja wissen, angesichts BlitzPlus. Aber ob er da irgendetwas rausrückt..?
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Suco-X

Betreff: ......

BeitragSa, Aug 18, 2007 14:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Zeig mir bitte mal, wie du in Bplus den Desktop in weniger als einer MS ausliest.

@D-Bug: Die Desktop Screen Funktion habe ich damals geschrieben. Da war noch vieles anders mit BlitzMax.
Mfg
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB
 

#Reaper

Newsposter

BeitragSa, Aug 18, 2007 16:48
Antworten mit Zitat
Benutzer-Profile anzeigen
So z.B.:

Code: [AUSKLAPPEN]
img = CreateImage(ClientWidth(Desktop()), ClientHeight(Desktop()))

ms = MilliSecs()
CopyRect 0,0,ClientWidth(Desktop())-1, ClientHeight(Desktop())-1,0,0, DesktopBuffer(),ImageBuffer(img)
ms = MilliSecs()-ms

Graphics 800, 600, 32, 2
Color 255,0,0
DebugLog "MilliSecs: " + ms

While Not KeyHit(1)
   DrawImage img, 0,0
   Text 10, 10, "MilliSecs: " + ms
   Flip 0
   Cls
   Delay 10
Wend
End


Braucht bei mir sogar 0 ms Smile
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

d-bug

BeitragSa, Aug 18, 2007 16:53
Antworten mit Zitat
Benutzer-Profile anzeigen
@Suco-X

Ich weiß, dass es deine ist, hab sie schließlich für DesktopExtension auch übernommen. Hab sie allerdings
dann ein wenig modifiziert. Ist zwar auch nicht schneller, aber die Punkte die ich #Reaper aufzeigte sind eliminiert.
 

Dreamora

BeitragSo, Aug 19, 2007 6:36
Antworten mit Zitat
Benutzer-Profile anzeigen
Dein BB Code erinnert mich an was: Kick das Blit ma und versuchs mit MemCopy und kopiere es in den Pixmapbuffer (der gleich gross sein muss wie der Desktop und die gleiche Farbtiefe!)

denn evtl ist es auch der Blit der derart absäuft.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

#Reaper

Newsposter

BeitragSo, Aug 19, 2007 13:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Blit? Den gibt es doch garnicht? :-/ Wink
Also ich hab nochmals nachgemessen, es ist GetDIBits() welcher geschlagene ~50ms braucht.
Leider weiß ich nicht, wie ich MemCopy() richtig verwenden soll Sad Komme nie so gut mit Pointern zurecht Embarassed
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7
 

Dreamora

BeitragSo, Aug 19, 2007 14:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Gibts nicht?

BitBlt ist also eine Einbildung? Smile


Und MemCopy ist recht einfach zu verwenden, Es kopiert eine gewisse Anzahl Bytes vom Source ab Position Offset zum Zielbuffer an Position 0
Er vermute, schneller sein als der BitBlt wenn ich mich nicht irre.
Denn WinAPI Grafik Befehle sind nicht auf Geschwindigkeit ausgelegt.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.
 

#Reaper

Newsposter

BeitragSo, Aug 19, 2007 15:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Mhh.. Sad
Meinst du das vielleicht so..?
Code: [AUSKLAPPEN]
MemCopy(FinalPixmap.PixelPtr(0,0), hdcDesktop, Info.biHeight*Info.biWidth*4)


Also richtig testen kann ich das noch nichtmal, da ich nicht weiß, wie ich aus dem Integer von hdcDesktop ein Byte Ptr machen soll :-/
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Suco-X

Betreff: ....

BeitragMo, Aug 27, 2007 14:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Hups, habe nicht mehr an den Thread gedacht.
@Reaper: Was du da im BPlus Code gemacht hast, war eine einfache Kopieraktion von einem zum anderen Buffer. Wenn du die Pixel ausliest (Und das musst du ja, wenn du es übers Netzwerk verschicken willst), erweist sich die Bplus Lösung auch nicht als schnell.
Mfg
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB
 

#Reaper

Newsposter

BeitragMo, Aug 27, 2007 16:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja, doch, sie ist schon schneller, bei dem bisherigem BMax Code sind es ja ~60ms + Pixelauslesezeit fürs Netzwerk. Aber ein doch sehr großes Problem am BMax Code ist, das es seltsamer weiße den PC ein wenig zum "laggen" bringt, zu mindestens was die Grafik angeht.
Mhh.. kann mir einer vielleicht auch einen Tipp geben, wie ich auf den DesktopBuffer zugreifen kann? In BMax gibt es ja insofern keine Buffer mehr Sad
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7
 

Dreamora

BeitragMo, Aug 27, 2007 17:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich denke die MSDN wird da gewiss eine Lösung dafür haben, wird bloss seine Zeit brauchen bis du sie dort vermutlich finden wirst.

Eine andere Lösung: nein, vermutlich nicht.
Ihr findet die aktuellen Projekte unter Gayasoft und könnt mich unter @gayasoft auf Twitter erreichen.

Suco-X

Betreff: ....

BeitragMo, Aug 27, 2007 19:43
Antworten mit Zitat
Benutzer-Profile anzeigen
Bin schon etwas raus aus BB, aber wenn ich hier keinen Fehler eingebaut habe, bist du in BMX mit 60 ms noch sehr gut bedient.

Code: [AUSKLAPPEN]

img = CreateImage(ClientWidth(Desktop()), ClientHeight(Desktop()))
ms = MilliSecs()

CopyRect 0,0,ClientWidth(Desktop())-1, ClientHeight(Desktop())-1,0,0, DesktopBuffer(),ImageBuffer(img)

LockBuffer(ImageBuffer(img))

For x = 0 To ImageWidth(img)-1
   For y = 0 To ImageHeight(img)-1
      ReadPixelFast(x,y, ImageBuffer(img))
   Next
Next

UnlockBuffer(ImageBuffer(img))
ms = MilliSecs()-ms

Notify("Zeit: "+ms)


kriege hier 780 ms, alleine fürs auslesen der Pixel.

Die GetDesktopPixmap Funktion greift übrigens schon auf den Desktopbuffer zu. Die MSDN kannst du 10 Jahre durchsuchen, am besten gehst du mal in ein Deutsches WinAPI Forum und fragst da nach einer alternative. Gewisse Programme können ja schließlich sehr flott Videos vom Desktop aufnehmen, also muss es noch was anderes geben.
Mfg
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB
 

#Reaper

Newsposter

BeitragMo, Aug 27, 2007 20:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Mhh... ok, Danke, daran habe ich nun auch nicht mehr gedacht. Das PixelMap auslesen ist in BMax vermutlich schneller als in B+? (Bei mir braucht es sogar rund 1000ms ^^° Embarassed )
Dann werde ich mal irgendwelche anderen Foren dazu quälen Wink Very Happy

MfG
#Reaper
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Suco-X

Betreff: ....

BeitragDi, Aug 28, 2007 14:05
Antworten mit Zitat
Benutzer-Profile anzeigen
Habe mich nochmal dran gehängt und mir ist was aufgefallen. Du versendest die Daten ja sowieso per Netzwerk, also kannst du dir den Schritt mit der Pixmap sparen.
Erst die Desktop Daten auslesen, in eine Pixmap hauen und danach aus der Pixmap auslesen, sind zwei Schritte zu viel. Du kannst das z.b so machen:

Code: [AUSKLAPPEN]

     Local mem:Byte Ptr = MemAlloc((DesktopWidth*DesktopHeight)*3)

      If Not GetDIBits(hdcMem, bmpMem, 0, Info.biHeight, Mem, info, 0)
         Return Null
      EndIf


Du rerservierst also einfach den nötigen Speicher und lässt ihn von der GetDIBits Funktion mit den Farbdaten des Desktops füllen. Diesen Speicherblock Mem lässt du dir von der Funktion statt der Pixmap zurückgeben. Danach gehst du den Speicherblock wie ein Array durch und schickst die Daten ab. Drüben angekommen, benutzt den CreateStaticPixmap Befehl, um die Daten wieder in eine brauchbare Pixmap zu wandeln.
Ohne verschickung übers Netzwerk geht das hier in 30ms, also noch eine brauchbare Zeit. Wenn du mit der Pixmap arbeitest und die zum senden ausliest, dauert es hier z.b. 280 ms.
Solltest du trotzdem noch eine alternative in irgendeinem Forum entdeckt haben, sag hier bitte bescheid.
Mfg
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB
 

#Reaper

Newsposter

BeitragDi, Aug 28, 2007 16:55
Antworten mit Zitat
Benutzer-Profile anzeigen
Oh, danke Very Happy
Aber es ist bei mir leider nur rund ~10 ms schneller als vorher (nach deinen Zeiten wäre es etwa doppelt so schnell). Aber ich glaube, dass ich wohl irgendetwas falsch gemacht habe. Denn seltsamer weise ist Mem immer Leer :-/

Hast du deinen Code vielleicht noch? Wundert mich nun auch, dass aufeinmal GetDIBits() so langsam ist, vorher war es ja immernoch BitBlt() :-/

Aber danke nochmals/schonmals Very Happy
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group