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