Save Bitmap

J

Jon Brunson

After doing a LOT of research into saving Bitmaps and/or getting byte
arrays out of them, I finally found the "Graphic Object Internals"
article on the OpenNETCF forum
(http://www.opennetcf.org/Forums/forum.asp?FORUM_ID=22). Unfortunately,
this method doesn't work for Bitmap's created using the width-height
contstructor, only those loaded from file.

I did find a thread which discusses this problem, and found a potential
solution - http://www.opennetcf.org/Forums/topic.asp?TOPIC_ID=385

After converting the code posted to VB.NET (see end of post) so I could
use it in my project, I got an OverflowException on the line:

BitmapData(2) = CByte(nBytes)


which makes sence, because nBytes is in the region of 54,000, and bytes
only go up to 255.

But surely bitmaps can be larger than 256 bytes?

Am I missing something?



Code (be careful of word-wrap):

Public Shared Sub SaveBitmap(ByVal Image As System.Drawing.Image, ByVal
Path As String)
Dim fs As FileStream = File.Create(Path)
SaveBitmap(Image, fs)
fs.Close()
End Sub

Public Shared Sub SaveBitmap(ByVal Image As System.Drawing.Image, ByVal
Stream As System.IO.Stream)

' This should probably be done a little more carefully
Dim bm As Bitmap = CType(Image, Bitmap)
Const BYTES_PER_PIXEL As Integer = 3

' Need 0x36 bytes for the headers, plus all of the pixel data, so
round up to nearest 4
Dim nBytes As Integer = 54 + (bm.Height * ((BYTES_PER_PIXEL *
bm.Width) + 3) And Not 3)

Dim BitmapData(nBytes) As Byte
BitmapData(0) = System.Text.Encoding.UTF8.GetBytes(New Char() {"B"c})(0)
BitmapData(1) = System.Text.Encoding.UTF8.GetBytes(New Char() {"M"c})(0)

' I'm sure there's a better way to do this but I didn't look up the C#
equiv of memcpy
BitmapData(2) = CByte(nBytes)
BitmapData(3) = CByte((nBytes >> 8))
BitmapData(4) = CByte((nBytes >> 16))
BitmapData(5) = CByte((nBytes >> 24))

BitmapData(10) = 54
BitmapData(14) = 40

BitmapData(18) = CByte(bm.Width)
BitmapData(19) = CByte((bm.Width >> 8))
BitmapData(20) = CByte((bm.Width >> 16))
BitmapData(21) = CByte((bm.Width >> 24))

BitmapData(22) = CByte(bm.Height)
BitmapData(23) = CByte((bm.Height >> 8))
BitmapData(24) = CByte((bm.Height >> 16))
BitmapData(25) = CByte((bm.Height >> 24))

BitmapData(26) = 1
BitmapData(28) = 24

BitmapData(34) = CByte((nBytes - 54))
BitmapData(35) = CByte(((nBytes - 54) >> 8))
BitmapData(36) = CByte(((nBytes - 54) >> 16))
BitmapData(37) = CByte(((nBytes - 54) >> 24))

' Stripping bitmap from bottom left, moving right through the row,
then up to the next row
Dim index As Integer = 54
Dim h As Integer = bm.Height - 1
While h >= 0
Dim w As Integer = 0
While w < bm.Width
Dim c As Integer = bm.GetPixel(w, h).ToArgb

BitmapData(System.Math.Min(System.Threading.Interlocked.Increment(index),
index - 1)) = CType(c, Byte)

BitmapData(System.Math.Min(System.Threading.Interlocked.Increment(index),
index - 1)) = CType((c >> 8), Byte)

BitmapData(System.Math.Min(System.Threading.Interlocked.Increment(index),
index - 1)) = CType((c >> 16), Byte)
System.Math.Min(System.Threading.Interlocked.Increment(w), w - 1)
End While

' Padding the end of the row
' (if I RTFM'd this wouldn't have taken so long to figure out :)
Dim xtra As Integer = (bm.Width * 3) Mod 4
If Not (xtra = 0) Then
index += 4 - xtra
End If
System.Math.Max(System.Threading.Interlocked.Decrement(h), h + 1)
End While

' Write the bytes to the stream
Stream.Write(BitmapData, 0, BitmapData.Length)

End Sub
 
J

Jon Brunson

Well, after a few more hours of digging, I found a small tutorial on The
Code Project which describes saving Bitmaps in VB.NET on
PocketPC/CompactFramework. You can find the article here:

http://www.codeproject.com/netcf/VBPocketPCBitmaps.asp

It would appear there is *no* way to do it all in VB.NET as it uses
unsafe code, which C# supports, but VB.NET does not. The only way to do
it is to have a second project (assembly) in your solution
(application), which does all the unsafe stuff, and which your VB.NET
code can call. It's all in the article, and it works.

I seriously hope they add .Save in .NET 2.0!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top