Bitmap.GetPixel(x, y) dosen't return the right color

M

Max Bolingbroke

Hi,

I'm trying to get the color of a palette-based BMP image at a certain
point, using Bitmap.GetPixel. However, the method call isnt returning
the correct color! Every editing program on my computer agrees that the
pixel in question is, for instance #00CC00, but GetPixel insists that
the pixel is actually #00C800.

Does anyone know why this might be the case?

Thanks in advance!

Max Bolingbroke

The image in question is here (104kb download):
http://www.omega-prime.co.uk/images/Map.bmp

And here is a demo app that demonstrates the problem:
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Data;

namespace PocketDebug
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{

private Bitmap bitmap;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

bitmap = new Bitmap("/Program Files/PocketDebug/Map.bmp");


}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// Form1
//
this.Text = "Form1";
this.Paint += new
System.Windows.Forms.PaintEventHandler(this.Form1_Paint);

}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>

static void Main()
{
Application.Run(new Form1());
}

private void Form1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
Brush brush = new SolidBrush(Color.Black);
Font font = new Font("Tahoma", 10.0f, FontStyle.Regular);
Color color = bitmap.GetPixel(89, 115);
e.Graphics.DrawString(color.R.ToString() + ", " + color.G.ToString()
+ ", " + color.B.ToString(), font, brush, 0.0f, 0.0f);
}
}
}
 
I

Ilya Tumanov [MS]

That's because screens on devices are not 24 bits, but 15 or 16 bits.

That means you only get 5 or 6 bits from 8 bit color.

For example: 0xCC = 11001100

Take 5 MSB, set others to zero: 11001_000 = 0xC8

If you have 15 bit screen, all colors will be 5 bits.

For 16 bit screens in most cases Green channel is 6 bit, Red and Blue are 5
bits.



Best regards,



Ilya



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

Max Bolingbroke

Ilya said:
That's because screens on devices are not 24 bits, but 15 or 16 bits.

That means you only get 5 or 6 bits from 8 bit color.

For example: 0xCC = 11001100

Take 5 MSB, set others to zero: 11001_000 = 0xC8

If you have 15 bit screen, all colors will be 5 bits.

For 16 bit screens in most cases Green channel is 6 bit, Red and Blue are 5
bits.

So even bitmaps that you never display on a screen but are only held in
memory are made to conform to the standards of the screen? Madness :)
Now I'm going to have to write my own BMP access code..

Thanks for the help..

Max Bolingbroke
 
I

Ilya Tumanov [MS]

I would not bet on it, but I can speculate it has something to do with
screen compatible DC.
In most cases if you have a bitmap, you're intended to show it on the
screen, right?

Best regards,

Ilya

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

Max Bolingbroke

Ilya said:
I would not bet on it, but I can speculate it has something to do with
screen compatible DC.
In most cases if you have a bitmap, you're intended to show it on the
screen, right?

This is counter intuitive to me. The thing is, you can go from original
image to screen compatiable but you cannot take a screen compatiable
image and infer any original data, so by making screen compatiable the
only option you cut off people who want non-compatiable bitmaps, whereas
using non-compatiable bitmaps would have accomodated both parties.

I suppose it made the process of bitmap displaying faster by doing the
screen-compatability processing only once (when the bitmap was loaded),
which is why they chose to do it this way. This would also have reduced
memory requirements (you only need to hold screen compat data in memory,
not both sorts), which kind of makes sense for a resource starved
environment like PocketPC.

Max Bolingbroke
 
A

Alex Feinman [MVP]

First of all, Bitmap object in CF is a screen bitmap (DDB), so naturally it
is converted to the screen format. It's not its purpose to enable graphic
manipulations. Limited as it is it was mainly designed to enable advanced
screen painting.

Having said this, there is a known issue with the CF 1.0 where the bitmaps
in memory are actually represented in a wrong color depth for most of PPC
devices. The majority of devices are using 16-bit color with 5:6:5 color
layout. The CF loads bitmaps using 5:5:5 layout. If you had a white pixel
(FF FF FF), it fill be loaded as F8 F8 F8 although the correct color for
white in 5:6:5 is F8 FC F8. Because of this, white will be *almost* white,
but noticeably greyish. Most of the rest of the colors (save those very
close to black) will be slightly skewed. It is especially noticeable when
you draw over a background created using a disk bitmap. You erase a block by
drawing a white box over the part of the image, but it appears to be whiter
than the white part of the bitmap.

This issue is fixed in CF 2.0 but there is no DIB support even there. You
will indeed need to roll out your won bitmap handling
 
M

Max Bolingbroke

Alex said:
First of all, Bitmap object in CF is a screen bitmap (DDB), so naturally
it is converted to the screen format. It's not its purpose to enable
graphic manipulations. Limited as it is it was mainly designed to enable
advanced screen painting.

Having said this, there is a known issue with the CF 1.0 where the
bitmaps in memory are actually represented in a wrong color depth for
most of PPC devices. The majority of devices are using 16-bit color with
5:6:5 color layout. The CF loads bitmaps using 5:5:5 layout. If you had
a white pixel (FF FF FF), it fill be loaded as F8 F8 F8 although the
correct color for white in 5:6:5 is F8 FC F8. Because of this, white
will be *almost* white, but noticeably greyish. Most of the rest of the
colors (save those very close to black) will be slightly skewed. It is
especially noticeable when you draw over a background created using a
disk bitmap. You erase a block by drawing a white box over the part of
the image, but it appears to be whiter than the white part of the bitmap.

This issue is fixed in CF 2.0 but there is no DIB support even there.
You will indeed need to roll out your won bitmap handling

Thanks for the reply! I see why the issue occurs now. I did notice the 5
bits of green issue thanks to Ilya's great explanation, though
thankfully it wasn't an issue in my particular program. Instead of
rolling my own bitmap code I've been able to implement a workaround that
makes my program reliant upon the number of bits of colour depth of the
screen of the device I'm currently running on. This is a bit of a hack,
but it sure beats having to deal with the BMP format manually.

Thanks again,

Max Bolingbroke
 
S

Serg Kuryata [MS]

I believe that when the bitmap is loaded into memory it is stored in the
555 format (as far as I remember, this is determined by display
characteristics). That's why 00CC00 is translated into 00C800.

Thank you,
Sergiy.

This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
| Date: Sat, 19 Mar 2005 17:37:29 +0000
| From: Max Bolingbroke <[email protected]>
| User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5)
Gecko/20041208 Thunderbird/1.0 - [MOOX M3] Mnenhy/0.6.0.104
| X-Accept-Language: en-us, en
| MIME-Version: 1.0
| Newsgroups: microsoft.public.dotnet.framework.compactframework
| Subject: Bitmap.GetPixel(x, y) dosen't return the right color
| Content-Type: text/plain; charset=ISO-8859-1; format=flowed
| Content-Transfer-Encoding: 7bit
| Lines: 89
| Message-ID: <[email protected]>
| Organization: Zen Internet
| NNTP-Posting-Host: 82.68.176.166
| X-Trace: 1111253848 cockburn.zen.co.uk 32603 82.68.176.166:4114
| X-Complaints-To: (e-mail address removed)
| Path:
TK2MSFTNGXA02.phx.gbl!TK2MSFTNGXA01.phx.gbl!TK2MSFTNGP08.phx.gbl!newsfeed00.
sul.t-online.de!t-online.de!newsfeed-0.progon.net!progon.net!dedekind.zen.co
.uk!zen.net.uk!fuller.zen.co.uk!cockburn.zen.co.uk.POSTED!not-for-mail
| Xref: TK2MSFTNGXA02.phx.gbl
microsoft.public.dotnet.framework.compactframework:73645
| X-Tomcat-NG: microsoft.public.dotnet.framework.compactframework
|
| Hi,
|
| I'm trying to get the color of a palette-based BMP image at a certain
| point, using Bitmap.GetPixel. However, the method call isnt returning
| the correct color! Every editing program on my computer agrees that the
| pixel in question is, for instance #00CC00, but GetPixel insists that
| the pixel is actually #00C800.
|
| Does anyone know why this might be the case?
|
| Thanks in advance!
|
| Max Bolingbroke
|
| The image in question is here (104kb download):
| http://www.omega-prime.co.uk/images/Map.bmp
|
| And here is a demo app that demonstrates the problem:
| using System;
| using System.Drawing;
| using System.Collections;
| using System.Windows.Forms;
| using System.Data;
|
| namespace PocketDebug
| {
| /// <summary>
| /// Summary description for Form1.
| /// </summary>
| public class Form1 : System.Windows.Forms.Form
| {
|
| private Bitmap bitmap;
|
| public Form1()
| {
| //
| // Required for Windows Form Designer support
| //
| InitializeComponent();
|
| bitmap = new Bitmap("/Program Files/PocketDebug/Map.bmp");
|
|
| }
| /// <summary>
| /// Clean up any resources being used.
| /// </summary>
| protected override void Dispose( bool disposing )
| {
| base.Dispose( disposing );
| }
| #region Windows Form Designer generated code
| /// <summary>
| /// Required method for Designer support - do not modify
| /// the contents of this method with the code editor.
| /// </summary>
| private void InitializeComponent()
| {
| //
| // Form1
| //
| this.Text = "Form1";
| this.Paint += new
| System.Windows.Forms.PaintEventHandler(this.Form1_Paint);
|
| }
| #endregion
|
| /// <summary>
| /// The main entry point for the application.
| /// </summary>
|
| static void Main()
| {
| Application.Run(new Form1());
| }
|
| private void Form1_Paint(object sender,
| System.Windows.Forms.PaintEventArgs e)
| {
| Brush brush = new SolidBrush(Color.Black);
| Font font = new Font("Tahoma", 10.0f, FontStyle.Regular);
| Color color = bitmap.GetPixel(89, 115);
| e.Graphics.DrawString(color.R.ToString() + ", " + color.G.ToString()
| + ", " + color.B.ToString(), font, brush, 0.0f, 0.0f);
| }
| }
| }
|
 

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