Encode in memory?
Encode in memory?
For example, I loaded a bmp into a memory location (*). Now I want to convert it over to png or jpg in memory (no hard drive use). How do I do that? Will the result allow me to use CatchImage on that new format?
Code: Select all
UsePNGImageEncoder()
UsePNGImageDecoder()
UseJPEGImageEncoder()
ImageSize = ?image_end-?image
CatchImage(0,?image,ImageSize)
ImageDataPipe = CreateNamedPipe_("\\.\pipe\ImageDataPipe",#PIPE_ACCESS_INBOUND|#FILE_FLAG_OVERLAPPED,#PIPE_TYPE_BYTE|#PIPE_READMODE_BYTE|#PIPE_NOWAIT,1,ImageSize,ImageSize,#NMPWAIT_USE_DEFAULT_WAIT,#Null)
PNGImageData = AllocateMemory(ImageSize) ;The Size of the png is smaller, but we dont know yet how much exactly
SaveImage(0,"\\.\pipe\ImageDataPipe",#PB_ImagePlugin_PNG)
ReadFile_(ImageDataPipe,PNGImageData,ImageSize,@PNGImageSize,#Null)
CloseHandle_(ImageDataPipe)
;Just to test the new image we save it as jpeg :D
If CatchImage(1,PNGImageData,PNGImageSize)
SaveImage(1,"c:\test.jpeg",#PB_ImagePlugin_JPEG)
EndIf
DataSection
image:
IncludeBinary "C:\windows\Angler.bmp"
image_end:
EndDataSection
irc://irc.freenode.org/#purebasic
-
- Enthusiast
- Posts: 665
- Joined: Fri Sep 12, 2003 10:40 pm
- Location: Tallahassee, Florida
look at my example of the TGA encoder i just posted.
what i do is take the hbitmap, figure out the size of the headers, the size of the image and extra bytes per row, then run through the actual pixel data starting one byte after the headers in memory. i write a single byte for each RGB/A color to a file.
however, you can go byte by byte in memory just like i do, but just write the data to a different format while still in memory.
here is a theoretical example: note it wont actually work, but it shows you how to get the bitmap data of the hbitmap and then look at the pixel data
what i do is take the hbitmap, figure out the size of the headers, the size of the image and extra bytes per row, then run through the actual pixel data starting one byte after the headers in memory. i write a single byte for each RGB/A color to a file.
however, you can go byte by byte in memory just like i do, but just write the data to a different format while still in memory.
here is a theoretical example: note it wont actually work, but it shows you how to get the bitmap data of the hbitmap and then look at the pixel data
Code: Select all
GetObject_(hBitmap, SizeOf(BITMAP), BM.BITMAP) ; get our bitmap, imageid(image), loadimage ect
bitcount = BM\bmBitsPixel ; get the bitcount
width=BM\bmWidth
height=BM\bmHeight
extrabytesperrow = (4 - (width * bitcount / 8) % 4) % 4
sizeheaders = SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER)
sizeimage = (width * bitcount / 8 + extrabytesperrow) * height ;calculate the total image size
Debug sizeimage
*bitmap = AllocateMemory(sizeheaders + sizeimage);allocate a memory block
*bitmapfile.BITMAPFILEHEADER = *bitmap ;here we set all out headers
*bitmapfile\bfType = Asc("B") + Asc("M") << 8
*bitmapfile\bfSize = sizeheaders +sizeimage
*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 ; *bitmap is the pointer to the ACTUAL hbitmap in memory
;;; so we drive right past ALL the headers to get to the pixel data
*bitmapdatapos = *bitmapdata ; use a DIFFERENT variable for our position
hdc = GetDC_(#Null)
GetDIBits_(hdc, hBitmap, 0, height, *bitmap+sizeheaders, *bitmapinfo, #DIB_RGB_COLORS )
;;;get the ACTUAL BITS of the original hbitmap so we dont destroy it by accident
For j= 0 To height - 1 ; j = 0 corresponds to bottom of image ;;;HUH?
For i = 0 To width - 1
WriteByte(0,PeekB(*bitmapdatapos)) ; Blue
WriteByte(0,PeekB(*bitmapdatapos + 1)) ; Green
WriteByte(0,PeekB(*bitmapdatapos + 2)) ; Red
;;;hmm, but here we can take each byte and do whatever
PokeB(*yourbuffer,PeekB(*bitmapdatapos))
;;or transform the bitmapdata
;;compress it ect
For a=0 To whatever
*thisdata=*thisdata+PeekB(*bitmapdata+a)
Next
Compress(*thisdata,*yourbuffer)
*bitmapdatapos + bitcount / 8;;skip to the next RGB/A
Next
*bitmapdatapos + extrabytesperrow;;skip extra bytes per row
Next
EndIf
Code: Select all
!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
-
- Enthusiast
- Posts: 665
- Joined: Fri Sep 12, 2003 10:40 pm
- Location: Tallahassee, Florida
true, but what if he wants to encode to a format PB doesnt support?Deeem2031 wrote:Hm, my way with SaveImage() and Pipes looks a little bit easier, dont u think?
then you really need the actual pixel data in memory.
Code: Select all
!.WHILE status != dwPassedOut
! Invoke AllocateDrink, dwBeerAmount
!MOV Mug, Beer
!Invoke Drink, Mug, dwBeerAmount
!.endw
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
Thanks both of you, very much!
I will try out both methods actually. I am streaming video across the network (LAN), and need the quickest and highest compression possible. I want to be able to push about 30fps on a 8MB connection (basically 10Mbit lan card). I figure if the video frames are at a max of about 500K each, I can push 16FPS across the lan. If it was around 100K each, I can push 80fps (more then what I need) across the LAN.
This is the reason I asked the question. BMP files are too fricken huge. At least 1MB per frame is insane and only good if you have a 100Mbit (80MB) connection (most Ethernet cards support this) for full 30 fps with no compression
While I have a 100Mbit connection around the house, and a 54Mbit connection via wireless, I want to hit the lowest common denominator which is 10Mbit. Thus the reason I asked the encode question..
Good thing though, the client only need to decode (which it can do with CatchImage and CatchSprite), while the server only needs to Encode and push the frame across multiple connections
I'm trying to push the envelop here so if there are any faster and higher ways to do so, I am all for it. Even if it means not encoding a BMP to PNG or JPG, but pure compression, that would rule as well.
Again, thank you guys for your help!
I will try out both methods actually. I am streaming video across the network (LAN), and need the quickest and highest compression possible. I want to be able to push about 30fps on a 8MB connection (basically 10Mbit lan card). I figure if the video frames are at a max of about 500K each, I can push 16FPS across the lan. If it was around 100K each, I can push 80fps (more then what I need) across the LAN.
This is the reason I asked the question. BMP files are too fricken huge. At least 1MB per frame is insane and only good if you have a 100Mbit (80MB) connection (most Ethernet cards support this) for full 30 fps with no compression

While I have a 100Mbit connection around the house, and a 54Mbit connection via wireless, I want to hit the lowest common denominator which is 10Mbit. Thus the reason I asked the encode question..
Good thing though, the client only need to decode (which it can do with CatchImage and CatchSprite), while the server only needs to Encode and push the frame across multiple connections

I'm trying to push the envelop here so if there are any faster and higher ways to do so, I am all for it. Even if it means not encoding a BMP to PNG or JPG, but pure compression, that would rule as well.
Again, thank you guys for your help!
@Shannara,
From what I read from you here it sounds to me like you are wanting something along the lines of an mpeg4 codec.
You being a bit of a guru & somewhat familiar with Linux, you might take a look at this link http://mpeg4ip.sourceforge.net/index.php
Fwiw, I have a 4 camera DVR here at home which uses a proprietry mpeg4 streaming codec & it runs full live imaging using between 2.3Mb up to 5.5Mb's over my LAN depending on settings requiring high frame rate or high resolution. ( I would estimate displayed images @ around 640 x 480 )
I would dearly love to be able to write some streaming stuff like this of my own, but unfortunately this is way out of my league.
From what I read from you here it sounds to me like you are wanting something along the lines of an mpeg4 codec.
You being a bit of a guru & somewhat familiar with Linux, you might take a look at this link http://mpeg4ip.sourceforge.net/index.php
Fwiw, I have a 4 camera DVR here at home which uses a proprietry mpeg4 streaming codec & it runs full live imaging using between 2.3Mb up to 5.5Mb's over my LAN depending on settings requiring high frame rate or high resolution. ( I would estimate displayed images @ around 640 x 480 )
I would dearly love to be able to write some streaming stuff like this of my own, but unfortunately this is way out of my league.
-
- Addict
- Posts: 1027
- Joined: Sun May 15, 2005 5:15 am
- Location: Australia
- Contact: