Jump to content
dummzeuch

palette for 8 bit greyscale bitmap

Recommended Posts

The following code is supposed to create a TBitmap in 8 bit greyscale:

function MakeGrayPalette(_NumColors: TNumColors = 256): HPALETTE;
var
  i: Integer;
  lp: TMaxLogPalette;
  Grey: Byte;
begin
  lp.palVersion := $300;
  lp.palNumEntries := _NumColors;
  for i := 0 to _NumColors - 1 do begin
    Grey := i * 255 div _NumColors;
    lp.palPalEntry[i].peRed := Grey;
    lp.palPalEntry[i].peGreen := Grey;
    lp.palPalEntry[i].peBlue := Grey;
    lp.palPalEntry[i].peFlags := PC_RESERVED;
  end;
  Result := CreatePalette(pLogPalette(@lp)^);
end;

// to be used like this:

bmp := TBitmap.Create;
bmp.PixelFormat := pf8bit;
butBmp.Palette := MakeGrayPalette();

I think I got it from here (stackoverflow) but there are several Google hits for the same code, e.g. here (book "Delphi in a Nutshell") or here (DelphiPower), but I guess the book is the original source.

 

Since it looked fine I never questioned it until I used it today to load a bitmap from a file, modify a part of it and save it again. When I checked the result, I found that in addition to the expected changes there were subtle differences in gray shades varying by a few values.

 

Looking at the code again now, I think there is a bug in the line assigning Grey:

 

    Grey := i * 255 div _NumColors;

Shouldn't that be ...

    Grey := i * 256 div _NumColors;

... instead? If I change it like that the bitmaps only contain the expected differences. Or am I missing something here?

Edited by dummzeuch

Share this post


Link to post

What you're dealing with is an unavavoidable rounding problem and a misunderstanding of what's going on mathematically.

The two versions are equally bad. They just distribute the rounding error differently.

 

You want the first palette entry to have a grey-level value of 0 and the last one to have a value of 255 - not 256.

 

  Level = 255 * (Index / (Levels-1))

 

or

 

  Grey := i * 255 div (_NumColors-1)

  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×