Page 1 of 2
send Image over network (netmaestro)
Posted: Fri Mar 23, 2007 12:41 am
by Tomio
on Fri Sep 08, 2006 netmaestro answered to the Post subject: Image - Mem:
Will you be receiving this image with a PB program on the other end of a network connection? If so, I can show you how to do that without save/loading it first.
Well, unfortunately your offer was not needed then. So, may I ask you to show me now? I can't figure it out! How to send an image straight away from memory to the PB-client?
Thanks in advance .../tomio
Posted: Fri Mar 23, 2007 1:04 am
by srod
Deeem2031's post in the following thread could be one way:
http://www.purebasic.fr/english/viewtop ... light=pipe
Basically he creates a named pipe in order to use PB's SaveImage() with the result that the image saved ends up in memory rather than in a disk file. From here you can simply use PB's network commands to transfer the image, although I would probably compress the saved image first. The good thing is that you are transferring an entire bitmap file without first saving to disk and without having to pull out the bitmap's colour table or pixel bits etc. This can be easily adapted to jpegs and png's etc.
I guess the alternative is that you'd need to create the BITMAPINFOHEADER structure yourself and pull out the colour table and DIbits etc. and transmit these separately. And this would not actually save that much bandwidth over the above method.
I use a variation of Deeem's code to embed compressed images from memory into my own application files and I don't have to worry about putting the images back together with SetDIBits etc, I just use CatchImage(). Such files contain multiple images, fonts etc. It all works very well.
I guess there might be a good way of accessing the image data more efficiently using gdi+, and for that netmaestro is definitely the person to ask.
**EDIT: later in in the thread mentioned above, Deeem comments how to easily adapt the code to send the image directly to another computer. I've not tested this part though.
Posted: Fri Mar 23, 2007 1:36 am
by netmaestro
That's good advice from srod, if you're still stuck tomorrow I can post something. It's too late for any more coding today. It's probably better if someone beats me to it though. If I do it, it'll work all right but the friggin' thing will probably come out the other end transparent and rotating.
Posted: Fri Mar 23, 2007 5:02 am
by rsts
netmaestro wrote:That's good advice from srod, if you're still stuck tomorrow I can post something. It's too late for any more coding today. It's probably better if someone beats me to it though. If I do it, it'll work all right but the friggin' thing will probably come out the other end transparent and rotating.

- but at least it would come out.
For some of the rest of us it either would get stuck in transit or never even make it in

And
Posted: Fri Mar 23, 2007 5:09 am
by Fangbeast
And what's wrong with "transparent and rotating" anyway?
If I did it, it would come out looking like a violent zit (american word inserted) on a pimply, adolescent cheerleader's bum!
Yours would look much better!
Re: And
Posted: Fri Mar 23, 2007 5:18 am
by rsts
Fangbeast wrote:
snip
looking like a violent zit (american word inserted) on a pimply, adolescent cheerleader's bum!
Yours would look much better!
I'll take the cheerleaders bum over netmaestro's
cheer(leader)s
Re: And
Posted: Fri Mar 23, 2007 6:38 am
by Fangbeast
rsts wrote:Fangbeast wrote:
snip
looking like a violent zit (american word inserted) on a pimply, adolescent cheerleader's bum!
Yours would look much better!
I'll take the cheerleaders bum over netmaestro's
cheer(leader)s
Oh my, my face is now hurting from trying not to scream with laughter. rsts, you always manage to top my evil sense of tumour!
Posted: Fri Mar 23, 2007 1:52 pm
by Tomio
Thanks for info and humorous contributions.
What I see is: it's not as simple as I was hoping.
My problem is: the tool is to run on XP and several Win98.
And it must run at 100% !
But I can't even manage to CreateNamedPipe_() successfully on a Win98 using the examples I found in the forum.
Perhaps someone can confirm this?
I'm about to switch to saveimage(),...
../tomio
Posted: Fri Mar 23, 2007 2:17 pm
by srod
Ah, Tomio you can't create named pipes with win 98.
Instead, you may have to opt for an anonymous pipe using CreatePipe_(). Note that this cannot be used to communicate over a network, so you'll have to save the image to the pipe and then use Readfile_() to get ahold of the data.
Here's a (heavily edited) version of the code I use to grab a hold of a PB image and save it to a named pipe. From here I then write it to a file which already contains other images etc. but you can instead think about transferring the data over a network. Of course you'll need to use CreatePipe_() in place of CreateNamedPipe_():
Code: Select all
;Calculate the size of memory required.
imagesize = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)
imagesize + 4*((ImageWidth(image)*24+31)/32)*ImageHeight(image)
;Create a named pipe in order to save the image to memory,
imagedatapipe = CreateNamedPipe_("\\.\pipe\ImageDataPipe",#PIPE_ACCESS_INBOUND,#PIPE_TYPE_BYTE|#PIPE_READMODE_BYTE|#PIPE_NOWAIT,1,imagesize,imagesize,#NMPWAIT_USE_DEFAULT_WAIT,#Null)
If imagedatapipe <> #INVALID_HANDLE_VALUE
;Allocate sufficient memory to receive the image data,
imagemem = AllocateMemory(imagesize)
If imagemem
;Save the image to the pipe.
SaveImage(image,"\\.\pipe\ImageDataPipe")
;Retrieve the Data.
result=ReadFile_(imagedatapipe,imagemem,imagesize,@byteswritten,#Null)
If result And byteswritten=imagesize
;Write the image data to file. HERE IS WHERE YOU CAN WRITE TO A NETWORK etc.
WriteData(fileid, imagemem, imagesize)
EndIf
FreeMemory(imagemem)
EndIf
CloseHandle_(imagedatapipe)
EndIf
**EDIT: further investigation suggests that we cannot use CreatePipe_() as there doesn't appear to be any way of then pointing SaveImage() to the pipe so created!
I'll keep looking because the fact that named pipes can't be used in Win 98 does blight my current application somewhat! Bugger! If I can't find an alternative then I will simply ditch support for Win 98/Me etc.
Posted: Fri Mar 23, 2007 2:50 pm
by srod
Huh, reading more on named pipes; the damn things link to a disk file anyhow!
You may as well just use SaveImage() with a temporary file name and then transfer byte by byte etc. I'm going to alter my program to use this method so that it will run on Win 98.
Unless netmaestro can find a better way!

Come on lad, pull your finger out and get some work done!
**EDIT: actually, in the thread indicated in my first post above, localmotion34 gives some code which takes any bitmap and constructs, in memory, a corresponding 24 or 32-bit bitmap file (i.e. those without a colour table). This would be identical to that created by SaveImage() etc. From here you can do what you want with the image. And all without having to use a temporary disk file. I think I'm going to use this code. It needs a little adjusting.
Posted: Fri Mar 23, 2007 3:29 pm
by netmaestro
Code: Select all
;****************************************************************
; Program: Send/Receive image over network Demo
; Author: netmaestro
; Date: March 23, 2007
; Target OS: Microsoft Windows All
; Target Compiler: PureBasic 4.xx
; License: Free, unrestricted, credit appreciated
; but not required
;****************************************************************
; ***************************************************
; Off-Topic: Image to test with
; ***************************************************
UseJPEGImageDecoder()
ProcedureDLL Read_File(file.s)
#INTERNET_FLAG_RELOAD = $80000000
Bytes.l = 0
*html = AllocateMemory(50000)
hInet.l = InternetOpen_("lloydsplace.com", 1, #Null, #Null, 0)
If hInet
hURL.l = InternetOpenUrl_(hInet, file, #Null, 0, #INTERNET_FLAG_RELOAD, 0)
If hURL
If InternetReadFile_(hURL, *html, 50000, @Bytes)
hBmp = CatchImage(#PB_Any,*html, bytes)
InternetCloseHandle_(hURL)
Else
ProcedureReturn 0
EndIf
Else
ProcedureReturn 0
EndIf
InternetCloseHandle_(hInet)
Else
ProcedureReturn 0
EndIf
ProcedureReturn hBmp
EndProcedure
hBmp = Read_File("http://lloydsplace.com/kylie-minogue.jpg")
If IsImage(hBmp)
MessageRequester("", "Image is downloaded, click to test image prep/reconstitution",$C0)
Else
MessageRequester("oops", "problem downloading the image - try with something else", $C0)
End
EndIf
;**************************************************************
; End of Off-Topic Section - Start paying attention now
;**************************************************************
Global BmiInfo.BITMAPINFOHEADER, bmpWidth.w, bmpHeight.w
Procedure Get24BitColors(pBitmap)
GetObject_(pBitmap, SizeOf(BITMAP), @bmp.BITMAP)
bytesperrow = 4*((3*bmpWidth+3)/4)
*pPixels = AllocateMemory(bytesperrow*bmpHeight)
hDC = GetWindowDC_(#Null)
iRes = GetDIBits_(hDC, pBitmap, 0, bmpHeight, *pPixels, @bmiInfo, #DIB_RGB_COLORS)
ReleaseDC_(#Null, hDC)
ProcedureReturn *pPixels
EndProcedure
;*************** Prepare image for sending ********************
GetObject_(ImageID(hBmp), SizeOf(BITMAP), @Bmp.BITMAP)
bmpWidth = Bmp\bmWidth
bmpHeight = Bmp\bmHeight
With BmiInfo
\biSize = SizeOf(BITMAPINFOHEADER)
\biWidth = bmpWidth
\biHeight = bmpHeight
\biPlanes = 1
\biBitCount = 24
\biCompression = #BI_RGB
EndWith
*_24bitColors = Get24BitColors(ImageID(hBmp))
ImageSize = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER) + MemorySize(*_24bitColors)
*rawimage = AllocateMemory(ImageSize)
*fileheader.BITMAPFILEHEADER = *rawimage
*header.BITMAPINFOHEADER = *rawimage + SizeOf(BITMAPFILEHEADER)
With *fileheader
\bfType = 19778 ; word containing 2 bytes, 'BM' for 'BIT' 'MAP' ;)
\bfSize = ImageSize
\bfOffBits = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)
EndWith
CopyMemory(@BmiInfo, *header, SizeOf(BITMAPINFOHEADER))
CopyMemory(*_24bitColors, *rawimage + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER), MemorySize(*_24bitColors))
*PackedImage = AllocateMemory(ImageSize+8)
PackSize = PackMemory(*rawimage, *PackedImage, ImageSize)
;******** All ready to go now, send *PackedImage data and ImageSize *********
; Send image from *PackedImage
; Send ImageSize
; [..]
; Receive image to *PackedImage
; Receive imagesize to ImageSize.l
; ********* Image is here now, unpack it ************
*UnPacked = AllocateMemory(ImageSize)
UnpackMemory(*PackedImage, *UnPacked)
;********** How'd we do? Catch and display **********
CatchImage(0, *unpacked)
OpenWindow(0,0,0,ImageWidth(0),ImageHeight(0),"Reconstituted Image",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ImageGadget(0,0,0,0,0,ImageID(0))
Repeat:Until WaitWindowEvent() = #WM_CLOSE
Posted: Fri Mar 23, 2007 4:50 pm
by srod
Nice.
Practically identical to my own.
If I'd known named pipes were using disk space, I'd have gone straight for this method in my own app. Anyhow, I've now removed the pipes and saved the image directly into my own file along with other images and fonts. It works well and of course it will run on win 98.
(Are the forums playing up again; it's taken me ages to be able to post this?)
Posted: Fri Mar 23, 2007 4:53 pm
by Brice Manuel
srod wrote:(Are the forums playing up again; it's taken me ages to be able to post this?)
Buggier than Bamberware
Posted: Fri Mar 23, 2007 4:58 pm
by netmaestro
I personally think someone's attacking the forum server with some kind of DOS attack, as the difficulties seem to mimic an overloaded server, even though usage is light.
Posted: Fri Mar 23, 2007 5:03 pm
by srod
@netmaestro: looking again at your code, I'm not sure you're allocating enough memory for the GetDIBits. This function, when asked to create a 24 bit DIB, will pad each row out so that it is a multiple of 4 bytes. I think that some images might cause a memory problem with your code.
I had this with my code until I adjusted it.
Unless I've misinterpreted your code.
