Seite 1 von 3
SaveImageToMemory() [Windows-Only]
Verfasst: 14.04.2009 20:13
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.
Verfasst: 15.04.2009 00:32
von KeyKon
Klasse
Lass mich raten, das ganze läuft auch in deinem DesktopStreamer^^
Verfasst: 15.04.2009 06:35
von cxAlex
KeyKon hat geschrieben:Klasse
Lass mich raten, das ganze läuft auch in deinem DesktopStreamer^^
exakt, in der nächsten Version ists drin ^^
Verfasst: 15.04.2009 11:34
von KeyKon
Btw, ich bin zwar kein Englisch-Guru, aber ich meine der Topic müsste Sa
veImageToMemory() heißen

Verfasst: 15.04.2009 11:47
von DarkDragon
Hmm... das müsste so ähnlich sicher auch unter Linux gehen.
Verfasst: 15.04.2009 16:29
von Andesdaf
KeyKon hat geschrieben:Btw, ich bin zwar kein Englisch-Guru, aber ich meine der Topic müsste Sa
veImageToMemory() heißen

Nur der Threadtitel ist falsch (meiner Meinung nach), die Procedure an sich ist richtig.
Verfasst: 15.04.2009 16:43
von cxAlex
Jo mein Fehler

.
Beim Programmieren kam mir PB mit der Autovervollständigung entgegen, im Titel hat sich mein schlechtes Englisch durchgesetzt

.
Verfasst: 15.04.2009 18:11
von Andesdaf
allgemein zur Procedure

Verfasst: 25.04.2009 00:17
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
Verfasst: 25.04.2009 22:04
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