Encode in memory?

Just starting out? Need help? Post your questions and find answers here.
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Encode in memory?

Post by Shannara »

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?
User avatar
Deeem2031
Enthusiast
Enthusiast
Posts: 216
Joined: Sat Sep 20, 2003 3:57 pm
Location: Germany
Contact:

Post by Deeem2031 »

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
localmotion34
Enthusiast
Enthusiast
Posts: 665
Joined: Fri Sep 12, 2003 10:40 pm
Location: Tallahassee, Florida

Post by localmotion34 »

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

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
User avatar
Deeem2031
Enthusiast
Enthusiast
Posts: 216
Joined: Sat Sep 20, 2003 3:57 pm
Location: Germany
Contact:

Post by Deeem2031 »

Hm, my way with SaveImage() and Pipes looks a little bit easier, dont u think? ;)
irc://irc.freenode.org/#purebasic
localmotion34
Enthusiast
Enthusiast
Posts: 665
Joined: Fri Sep 12, 2003 10:40 pm
Location: Tallahassee, Florida

Post by localmotion34 »

Deeem2031 wrote:Hm, my way with SaveImage() and Pipes looks a little bit easier, dont u think? ;)
true, but what if he wants to encode to a format PB doesnt support?

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
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

@Deeem2031: very nice work, thanks for posting that.
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

Thanks for sharing, tight code for sure.

Nice.
Intrigued - Registered PureBasic, lifetime updates user
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

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 :D

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!
Dreglor
Enthusiast
Enthusiast
Posts: 759
Joined: Sat Aug 02, 2003 11:22 pm
Location: OR, USA

Post by Dreglor »

using a JPG is probably the best way to go it tends to save around 200k - 150k for a 1024x768 image in higher quality levels

if you want to get fancy you could send image blocks, section of where the image has changed
~Dreglor
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

Dreglor: Thats not a bad idea :) The only problem Im getting atm, is that I would have to go by each pixel and see if the rgb is different by a certain threshold, which isnt much by itself. But webcams do get quite messy :)
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Great code Deeem2031. 8)

I always wondered if this was possible? Now I know!

Thanks.
I may look like a mule, but I'm not a complete ass.
User avatar
Deeem2031
Enthusiast
Enthusiast
Posts: 216
Joined: Sat Sep 20, 2003 3:57 pm
Location: Germany
Contact:

Post by Deeem2031 »

You can also send the Data directly to the other computer, which saves memory and time. "SaveImage(0,"\\192.168.0.6\pipe\ImageDataPipe",#PB_ImagePlugin_PNG) "
irc://irc.freenode.org/#purebasic
Baldrick
Addict
Addict
Posts: 860
Joined: Fri Jul 02, 2004 6:49 pm
Location: Australia

Post by Baldrick »

@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.
Shannara
Addict
Addict
Posts: 1808
Joined: Thu Oct 30, 2003 11:19 pm
Location: Emerald Cove, Unformed

Post by Shannara »

Thanks for the link, I'll take a look :) I actually hate Linux with a passion.
lexvictory
Addict
Addict
Posts: 1027
Joined: Sun May 15, 2005 5:15 am
Location: Australia
Contact:

Post by lexvictory »

is there a way to make it so that i can repeatedly write data to the pipe and then read and send on?

im trying to do that, but it doesnt seem to be doing it properly....
Demonio Ardente

Currently managing Linux & OS X Tailbite
OS X TailBite now up to date with Windows!
Post Reply