Writing a bitmap from a byte array

RcSepp
06-25-2006, 02:59 AM
Hi everyone

Is there anyway to speed this code up:

Dim bmp As Bitmap = New Bitmap(pic.Width, pic.Height)

For i As Integer = 0 To SkinBytes_count Step 2
Dim r As Byte = Convert.ToInt16((Convert.ToString(GetSkinByte(i + 1), 2).PadLeft(8, "0"c) & Convert.ToString(GetSkinByte(i), 2).PadLeft(8, "0"c)).Substring(0, 5), 2) * 255 / 31
Dim g As Byte = Convert.ToInt16((Convert.ToString(GetSkinByte(i + 1), 2).PadLeft(8, "0"c) & Convert.ToString(GetSkinByte(i), 2).PadLeft(8, "0"c)).Substring(5, 6), 2) * 255 / 63
Dim b As Byte = Convert.ToInt16((Convert.ToString(GetSkinByte(i + 1), 2).PadLeft(8, "0"c) & Convert.ToString(GetSkinByte(i), 2).PadLeft(8, "0"c)).Substring(11, 5), 2) * 255 / 31

bmp.SetPixel(i / 2 Mod pic.Width, Int(i / 2 / pic.Width), Color.FromArgb(255, r, g, b))
Next

pic.Image = bmp


What it does:
Get data from the array GetSkinByte()
Two Bytes are used for every pixel
The colorformat is 565 so in binary: the first 5 bits are red, the second 6 bits are green and the last 5 are blue

The code is working correctly but it's far to slow.

Any ideas are welcome.

OnErr0r
06-25-2006, 09:23 AM
There are several things you can do to speed that along.

1) Do your bit manipulations and store the data in another array (or alter the original), then use LockBits on the destination bmp and copy the array using Marshal.Copy.

2) Bitmask and shift with math only, no string manipulations

3) Use integer division (backslash)

Btw, if you need even more speed, consider creating an assembly in C# and using unsafe to alter Scan0 with pointers. This prevents the two array copies necessary with VB.

RcSepp
06-27-2006, 01:13 AM
Thanks for all the hints.
That's a lot of new stuff to learn and I can't hold myself back :)
For example: I hadn't known, that it's possible to bind assembly into C#

Thanks a lot!

RcSepp
06-27-2006, 08:28 AM
Thanks a lot OnErr0r!

I think now it's faster :D


Dim bmp As New Bitmap(1667, 323, PixelFormat.Format16bppRgb565)
Dim bmpData As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format16bppRgb565)

For i As Integer = 0 To SkinBytes_count
Marshal.WriteByte(bmpData.Scan0, i, GetSkinByte(i))
Next

bmp.UnlockBits(bmpData)
pic.Image = bmp


Programing would get a new meaning if everything goes so easy!

OnErr0r
06-27-2006, 09:29 AM
You don't need a loop if you use Marshal.Copy. Use this code in place of the loop in between Lock and UnlockBits:

Marshal.Copy(GetSkinByte, 0, bmpData.Scan0, GetSkinByte.Length)

How are you bitmasking now? :)

RcSepp
06-27-2006, 10:00 AM
Marshal.Copy(GetSkinByte, 0, bmpData.Scan0, GetSkinByte.Length)


Speeeeeed :p

With that methode I decreased processing time from 0.29 to 0.17!

Awesome!!!

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum