Data returned by LockBits is incorrect

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi

I need to get the color of some pixels from an image (png file). I am using
CF 2.0 and have noticed that the data returned by LockBits is not 100%
correct. For example if the pixel color is #232323. LockBits will return
#212021, if #040404 LockBits will return #000400. Is there a bug with
LockBits?

Help

Gavin
 
No, there's no bug. Bitmaps are stored in 16 bit format, so 3 LSB in red and
blue channels and 2 LSB in green are always set to zero.



Example:

#040404 = 00000100 00000100 00000100

& 11111000 11111100 11111000

= 00000000 00000100 00000000 = #000400

--
Best regards,

Ilya

This posting is provided "AS IS" with no warranties, and confers no rights.

*** Want to find answers instantly? Here's how... ***

1. Go to
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.compactframework?hl=en
2. Type your question in the text box near "Search this group" button.
3. Hit "Search this group" button.
4. Read answer(s).
 
Thank Ilya but if "Bitmaps are stored in 16 bit format" what is the
purpose of Bitmap.LockBits PixelFormat parameter? Also, I tired the
code on the Framework and it worked fine so on the CF are the images
stored differently?

Regards

Gavin
 
Also your example seems to be only valid for certain colors. From your
example, if the image has magenta #FF00FF

#FF00FF = 11111111 00000000 11111111


& 11111000 11111100 11111000


= 11111000 000000 11111000 = #F800F8

But for this color LockBits it correctly returns #FF00FF
 
Let me clarify:



1. Bitmap is loaded into memory and internally stored in 16 bit format. All
LSBs are gone at this point.

2. LockBits is called; data from internal buffer is copied into another
memory area and converted to requested format.



I'm not sure why Magenta is treated differently, I suspect that's because it
commonly used as transparent color.


--
Best regards,

Ilya

This posting is provided "AS IS" with no warranties, and confers no rights.

*** Want to find answers instantly? Here's how... ***

1. Go to
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.compactframework?hl=en
2. Type your question in the text box near "Search this group" button.
3. Hit "Search this group" button.
4. Read answer(s).
 
Below is some code that will create a 4 pixel bitmap with 4
differentcolors. If I use Format24bppRgb the colors returned by
LockBits are correct, but if I use Format16bppRgb565 the results are
all wrong: #FFFF00, #840000, #420000, #EF8E94. This time no transparent
color is used ;) so is it a bug?

Dim bmp As New Bitmap(4, 1,
Imaging.PixelFormat.Format16bppRgb565)
Dim gBMP As Graphics = Graphics.FromImage(bmp)
gBMP.Clear(Color.FromArgb(&HFF, &HFF, &H0))
Dim pen As New Pen(Color.FromArgb(&H40, &H0, &H0))
gBMP.DrawRectangle(pen, 1, 0, 1, 1)
pen.Color = Color.FromArgb(&H80, &H0, &H0)
gBMP.DrawRectangle(pen, 2, 0, 1, 1)
pen.Color = Color.FromArgb(&HE7, &H8F, &H91)
gBMP.DrawRectangle(pen, 3, 0, 1, 1)

Dim bmpData As System.Drawing.Imaging.BitmapData =
bmp.LockBits(New Rectangle(0, 0, 4, 1), Imaging.ImageLockMode.ReadOnly,
Imaging.PixelFormat.Format24bppRgb)
Dim ptrBMP As IntPtr = bmpData.Scan0

Dim b(4 * 1 * 3 - 1) As Byte
System.Runtime.InteropServices.Marshal.Copy(ptrBMP, b, 0,
b.Length)
bmp.UnlockBits(bmpData)

Regards

Gavin
 
As Ilya said there is no bug here.

First of all you have to know that Bitmap represented in reverse order
and in you case each pixel has 2 bytes length. It means that:

the first 5bits - red MSBs bits
next 6bits - green MSBs bits
the last 5bits - blue MSBs bits

Try to create image 1x1 and put there Color.Magenta (0xff 0x00 0xff)
pixel, use LockBits Format16bppRgb565 to get picture bits. And you will
see the first 2 bytes:

0x1f 0xf8 - 00011111 11111000

Reverse bytes:

11111000 00011111 => 0x1f 0x00 0x1f:

Shift 0x1f on 3 bits left => 0xf7
Shift 0x0 on 2 bits left => 0x0
Shift 0x1f on 3 bits left => 0xf7

It's not easy to work with 565 pixel representation. I'd recommend you
to work with 24bpp instead - then all pixels will have 3 bytes per pixel.

And one more thing - the Bitmap has an alignment with 4 bytes - if pixel
has the length 3 bytes and you have a picture with dimension 1x2 one
byte will be added for each line. Thus instead off

Dim b(4 * 1 * 3 - 1) As Byte

you should write something like this:

Dim b(bmpData.Stride * bmpData.Height) As Byte

HTH
 
Back
Top