Seite 2 von 3
Verfasst: 25.04.2009 22:17
von cxAlex
Ich hab dir mal ein Demo gemacht, hoffentlich hilft die das:
Code: Alles auswählen
UseJPEGImageEncoder()
Procedure SaveImageToMemory(Image, *MemSize, Format = #PB_ImagePlugin_JPEG, Compression = 9)
Protected *Mem, MemSize, ImageDataPipe, PipeName$, RealMemSize
PipeName$ = "\\.\pipe\ImageDataPipe_" + Str(GetCurrentThreadId_()) ; <- Threadsicher
MemSize = ImageDepth(Image)*ImageHeight(Image)*ImageWidth(Image)
*Mem = AllocateMemory(MemSize)
ImageDataPipe = CreateNamedPipe_(PipeName$, #PIPE_ACCESS_INBOUND | #FILE_FLAG_OVERLAPPED, #PIPE_TYPE_BYTE | #PIPE_READMODE_BYTE | #PIPE_NOWAIT, 1, MemSize, MemSize, #NMPWAIT_USE_DEFAULT_WAIT, #Null)
SaveImage(Image, PipeName$, Format, Compression)
ReadFile_(ImageDataPipe, *Mem, MemSize, *MemSize, #Null)
CloseHandle_(ImageDataPipe)
ProcedureReturn *Mem
EndProcedure
Define Image, MemSize, *ImageMemory
; Image erstellen
Image = CreateImage(#PB_Any, 1024, 768, 32)
; Image in Speicher sichern
*ImageMemory = SaveImageToMemory(Image, @MemSize)
; Größe des Speichers
Debug MemSize
Verfasst: 25.04.2009 22:40
von mpz
Hi cxAlex,
Ja jetzt habe ich es verstanden und gleich richtig eingesetzt. Funktioniert super, Danke.
Ich muss nur noch ermitteln ob die erzeugte Exe damit kleiner und schneller ist als mit meinem Code...
Gruß Michael
Verfasst: 25.04.2009 23:01
von mpz
Hi cxAlex,
kleines Messprotokoll:
Pipemethode
bei 1000 Durchgängen 13,2 S Dauer, +600 Bytes mehr in der Exe Datei
GetDIBits_ Methode
bei 1000 Durchgängen 12,3 S Dauer
Vorteil der Pipemethode: Image kann auch als jpg und Png Datei in den Speicher gelegt werden. Übersichtlicher Code
Nachteil der Pipemethode, Geringfügig langsamer und grössere Exe
Gruß Michael
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 25.04.2010 10:36
von davidpsd
Hallo!
Ich habe Probleme, das im Memory gespeicherte Image wieder zu laden. Ich habe das Beispiel von oben benutzt und dann noch meinen Code dazu:
Code: Alles auswählen
Img2 = CatchImage(#PB_Any, *ImageMemory, MemSize)
If OpenWindow(0, 10, 10, 1280, 1024, "Screenshot", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
ImageGadget(0, 0, 0, 1280, 1024, ImageID(Img2))
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
CloseWindow(0)
EndIf
Bei ImgageID(Img2) sagt der Debugger, das angegebene #Image wurde nicht initialisiert!
Wie kann ich dann das Image wieder auslesen?
lG davidpsd
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 25.04.2010 11:58
von Christian+
Hast du auch eine UseJPEGImageDecoder() eingebaut denn sonst geht es nicht mit habe ich keine Probleme funktioniert dann super.
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 25.04.2010 12:11
von davidpsd
Ja habe ich. Mein ganzer Code:
Code: Alles auswählen
UseJPEGImageDecoder()
Procedure SaveImageToMemory(Image, *MemSize, Format = #PB_ImagePlugin_JPEG, Compression = 9)
Protected *Mem, MemSize, ImageDataPipe, PipeName$, RealMemSize
PipeName$ = "\\.\pipe\ImageDataPipe_" + Str(GetCurrentThreadId_()) ; <- Threadsicher
MemSize = ImageDepth(Image)*ImageHeight(Image)*ImageWidth(Image)
*Mem = AllocateMemory(MemSize)
ImageDataPipe = CreateNamedPipe_(PipeName$, #PIPE_ACCESS_INBOUND | #FILE_FLAG_OVERLAPPED, #PIPE_TYPE_BYTE | #PIPE_READMODE_BYTE | #PIPE_NOWAIT, 1, MemSize, MemSize, #NMPWAIT_USE_DEFAULT_WAIT, #Null)
SaveImage(Image, PipeName$, Format, Compression)
ReadFile_(ImageDataPipe, *Mem, MemSize, *MemSize, #Null)
CloseHandle_(ImageDataPipe)
ProcedureReturn *Mem
EndProcedure
Define Image, MemSize, *ImageMemory
; Image erstellen
Image = CreateImage(#PB_Any, 1024, 768, 32)
; Image in Speicher sichern
*ImageMemory = SaveImageToMemory(Image, @MemSize)
; Größe des Speichers
Debug MemSize
Img2 = CatchImage(#PB_Any, *ImageMemory, MemSize)
If OpenWindow(0, 10, 10, 1280, 1024, "Screenshot", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
ImageGadget(0, 0, 0, 1280, 1024, ImageID(Img2))
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
CloseWindow(0)
EndIf
Fehler bei: ImageGadget(0, 0, 0, 1280, 1024, ImageID(Img2))
lG davidpsd
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 25.04.2010 12:17
von Christian+
Mach noch ein UseJPEGImageEncoder() rein, denn zum in Memory speichern braucht man den Encoder und zum auslesen dann den Decoder du hast jetzt aber nur den Decoder eingebaut.
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 25.04.2010 14:38
von davidpsd
ah, danke das wars
jetzt hab ich nur noch probleme, nach dem versenden des memory-teils an einen client das bild komplett darzustellen (hab nur ein halbes bild)
mal schauen, ob ich den fehler finde...
lG davidpsd
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 25.04.2010 18:12
von davidpsd
Was mach ich falsch?
Es kommt nur 1/4 des Screenshots an.
Ich mach den Screenshot, speicher ihn in den Memory und sende ihn an den Client:
Code: Alles auswählen
Define MemSize, *ImageMemory
;Screenshot machen
hImage = CreateImage(0,1280,1024)
hdc = StartDrawing(ImageOutput(0))
DeskDC = GetDC_(GetDesktopWindow_())
BitBlt_(hdc,0,0,1280,1024,DeskDC,0,0,#SRCCOPY)
StopDrawing()
ReleaseDC_(GetDesktopWindow_(),DeskDC)
ResizeImage(0, 1280/2, 1024/2)
;Screenshot in Memory speichern
*ImageMemory = SaveImageToMemory(0, @MemSize)
;sendet die Größe an den Client ( Eigene Funktion, vereinfacht SendNetworkString() )
sendmsg(ClientIP$, "screenshot|"+Str(MemSize))
ConnectionID = OpenNetworkConnection(ClientIP$, 6832)
If ConnectionID
SendNetworkData(ConnectionID, *ImageMemory, MemSize)
CloseNetworkConnection(ConnectionID)
PrintN("Screenshot gesendet! (Groesse: "+Str(MemSize)+")")
Else
PrintN("ERROR: Konnte den Client nicht finden!")
EndIf
und der Client empfängt mit:
Code: Alles auswählen
;screensize ist die Größe des Bildes, wurde vorher empfangen
ReceiveNetworkData(ClientID, *Buffer, screensize)
CatchImage(0,*Buffer,screensize)
CatchImage beim Server liefert das ganze Bild, beim Client nur mehr 1/4.
Warum??
lG davidpsd
Re: SaveImageToMemory() [Windows-Only]
Verfasst: 10.04.2012 03:45
von pyromane
Hallo cxAlex,
echt eine gute Funktion die mir schon oft gefehlt hat. Allerdings hat sie einen Nachteil.
Code: Alles auswählen
MemSize = ImageDepth(Image)*ImageHeight(Image)*ImageWidth(Image)
Das macht aus meinem Bild, welches als PNG ~ 200kb groß ist 52 MB im Ram. Das du dir die 52 MB reservierst macht ja Sinn, da das Bild ja auch unkomprimiert sein kann. Das aber nach dem Abspeichern der Rest nicht freigegeben wird stört etwas. In dem Code wird RealMemSize definiert aber nie verwendet (Wahrscheinlich hattest du genau das oben beschriebene vor). Allerdings fällt mir gerade auch nicht ein, wie ich ermittle, wieviel davon nun effektiv genutzt wurden. Bzw ich könnte schauen ab wann nur noch Nullen im Ram stehen aber das ist wahrscheinlich enorm ineffizent.
Aber ich bin mir ganz sicher das es einige aus dem Forum wissen.
Lg,
pyromane