SaveImageToMemory() [Windows-Only]

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

SaveImageToMemory() [Windows-Only]

Beitrag von cxAlex »

Nachdem ich eine Featurerequest im englishen Forum gemacht hab, Bilder direkt in den Speicher zu sichern, hat mir srod einen Tip gegeben, den ich nun zu einer Procedure verwurstet hab:

http://www.purebasic.fr/english/viewtop ... 247#283247

Code: Alles auswählen

Procedure SaveImageToMemory(Image, *MemSize, Format = #PB_ImagePlugin_BMP, Compression = 7)
  Protected *Mem, MemSize, ImageDataPipe
  MemSize = ImageDepth(Image)*ImageHeight(Image)*ImageWidth(Image)
  *Mem = AllocateMemory(MemSize)
  ImageDataPipe = CreateNamedPipe_("\\.\pipe\ImageDataPipe", #PIPE_ACCESS_INBOUND | #FILE_FLAG_OVERLAPPED, #PIPE_TYPE_BYTE | #PIPE_READMODE_BYTE | #PIPE_NOWAIT, 1, MemSize, MemSize, #NMPWAIT_USE_DEFAULT_WAIT, #Null)
  SaveImage(Image, "\\.\pipe\ImageDataPipe", Format, Compression)
  ReadFile_(ImageDataPipe, *Mem, MemSize, *MemSize, #Null)
  CloseHandle_(ImageDataPipe)
  ProcedureReturn *Mem
EndProcedure
Ich brauch sowas immer wieder, ganz nützlich.
Zuletzt geändert von cxAlex am 15.04.2009 16:42, insgesamt 1-mal geändert.
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Beitrag von KeyKon »

Klasse :allright:
Lass mich raten, das ganze läuft auch in deinem DesktopStreamer^^
(\/) (°,,,°) (\/)
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

KeyKon hat geschrieben:Klasse :allright:
Lass mich raten, das ganze läuft auch in deinem DesktopStreamer^^
exakt, in der nächsten Version ists drin ^^
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Beitrag von KeyKon »

Btw, ich bin zwar kein Englisch-Guru, aber ich meine der Topic müsste SaveImageToMemory() heißen ;-)
(\/) (°,,,°) (\/)
DarkDragon
Beiträge: 6291
Registriert: 29.08.2004 08:37
Computerausstattung: Hoffentlich bald keine mehr
Kontaktdaten:

Beitrag von DarkDragon »

Hmm... das müsste so ähnlich sicher auch unter Linux gehen.
Angenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
Andesdaf
Moderator
Beiträge: 2671
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Beitrag von Andesdaf »

KeyKon hat geschrieben:Btw, ich bin zwar kein Englisch-Guru, aber ich meine der Topic müsste SaveImageToMemory() heißen ;-)
Nur der Threadtitel ist falsch (meiner Meinung nach), die Procedure an sich ist richtig.
Win11 x64 | PB 6.20
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Jo mein Fehler :oops:.

Beim Programmieren kam mir PB mit der Autovervollständigung entgegen, im Titel hat sich mein schlechtes Englisch durchgesetzt :mrgreen: .
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Andesdaf
Moderator
Beiträge: 2671
Registriert: 15.06.2008 18:22
Wohnort: Dresden

Beitrag von Andesdaf »

allgemein zur Procedure :allright:
Benutzeravatar
cxAlex
Beiträge: 2111
Registriert: 26.06.2008 10:42

Beitrag von cxAlex »

Update:

Das ganze ist nun Thread-Safe, bei massiver verwendung in Threads konnte es zu Kollisionen mit der Pipe kommen:

Code: Alles auswählen

Procedure SaveImageToMemory(Image, *MemSize, Format = #PB_ImagePlugin_JPEG, Compression = 9)
  Protected *Mem, MemSize, ImageDataPipe, PipeName$
  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
Projekte: IO.pbi, vcpu
Pausierte Projekte: Easy Network Manager, µC Emulator
Aufgegebene Projekte: ECluster

Bild

PB 5.1 x64/x86; OS: Win7 x64/Ubuntu 10.x x86
Benutzeravatar
mpz
Beiträge: 505
Registriert: 14.06.2005 15:53
Computerausstattung: Win 11 Pro, 48 GB Ram, Intel I7 CPU und RX4070 Grafikkarte, PB (4/5) 6.12LT
Wohnort: Berlin, Tempelhof

Beitrag von mpz »

Hi cxAlex,

der Code sieht gut aus. Wie genau wende ich Ihn den Code praktisch an? Ich weis nicht wie ich den Wert "*MemSize" ermitteln muss den ich der Prozedur übergebe. Wenn ich meine Code durch Deinen ersetze kommt immer eine Fehlermeldung in der folgender Zeile:

> ReadFile_(ImageDataPipe, *Mem, MemSize, *MemSize, #Null) > invalid memory access

Mein Code zur Übergabe eines Image in einen Speicherbereich:

Code: Alles auswählen


 w = ImageWidth(Img) 
  h = ImageHeight(Img) 
  hBmp = ImageID(Img) 
  
  bmi\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER) 
  bmi\bmiHeader\biWidth       =  w 

  If direction = 0
     bmi\bmiHeader\biHeight      =  h ; -h dreht das Bild als Textur
  Else
     bmi\bmiHeader\biHeight      =  -h 
  EndIf

  bmi\bmiHeader\biPlanes      =  1 
  bmi\bmiHeader\biBitCount    = 32 
  bmi\bmiHeader\biCompression = #BI_RGB 
  

  width = w 
  height = h 

  bitcount = 32 ; Should be 24 bits for this example 
  ; Rows need to be a multiple of 4 bytes so calculate extra bytes needed 
  extrabytesperrow = (4 - (width * bitcount / 8) % 4) % 4 

  ; Allocate memory for bitmap 
  sizeheaders = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER) 
  sizeimage = (width * bitcount / 8 + extrabytesperrow) * height 

  *bitmap = AllocateMemory(sizeheaders + sizeimage) 

  If *bitmap = 0
    ProcedureReturn #False 
    ;Debug("Couldn't allocate memory for bitmap") 
    ;End 
  EndIf 

  ; Set bitmap headers 
  *bitmapfile.BITMAPFILEHEADER = *bitmap 
  *bitmapfile\bfType = Asc("B") + Asc("M") << 8 
  *bitmapfile\bfSize = sizeheaders +sizeall 
  *bitmapfile\bfOffBits = sizeheaders 

  *bitmapinfo.BITMAPINFOHEADER = *bitmap + SizeOf(BITMAPFILEHEADER) 
  *bitmapinfo\biSize = SizeOf(BITMAPINFOHEADER) 
  *bitmapinfo\biWidth = width 
  *bitmapinfo\biHeight = height 
  *bitmapinfo\biPlanes = 1 
  *bitmapinfo\biBitCount = bitcount 
  *bitmapinfo\biCompression = 0 
  *bitmapinfo\biSizeImage = sizeimage 

  *bitmapdata = *bitmap + sizeheaders 

; Create 24 bit image in bitmap 
  *bitmapdatapos = *bitmapdata 


  hDC  = StartDrawing( ImageOutput(Img) ) 
  If GetDIBits_(hDC, hBmp, 0, h, *bitmapdatapos , bmi, #DIB_RGB_COLORS) 
     StopDrawing() 
  Else 
     StopDrawing()  
  EndIf 
Working on :lol: - LibSGD - MP3D Engine - 8)
Antworten