Recent

Author Topic: Get palette  (Read 1852 times)

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Get palette
« on: March 01, 2021, 07:42:21 pm »
Hi guys,
I have a code (source: https://stackoverflow.com/questions/1240673/how-can-i-access-the-palette-of-a-tpicture-graphic).
But, it does nothing when trying to get a palette from a bmp or jpg picture (I mean I got 'No palette entries!').
The code:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button2Click(Sender: TObject);
  2. var
  3.   i: integer;
  4.   fStringList: TStringList;
  5.   fColor: TColor;
  6.   fColorString: string;
  7.   fPal: PLogPalette;
  8.   fBitmapPalEntries: Cardinal;
  9.   fBitmap: TBitmap;
  10. begin
  11.   if OpenPictureDialog1.Execute then
  12.   begin
  13.     Screen.Cursor := crHourGlass;
  14.     try
  15.       fPal := nil;
  16.       try
  17.         fStringList := TStringList.Create;
  18.         Image1.Picture.LoadFromFile( OpenPictureDialog1.Filename );
  19.         fBitmap := TBitmap.Create;
  20.         fBitmap.PixelFormat := pf8bit;
  21.         //fBitmap.Assign(Image1.Picture.Graphic);
  22.         fBitmap.Canvas.Draw( 0, 0, Image1.Picture.Graphic );
  23.         if fBitmap.Palette <> 0 then
  24.         begin
  25.           GetMem( fPal, Sizeof( TLogPalette ) + Sizeof( TPaletteEntry ) * 255 );
  26.           fPal.palversion := $300;
  27.           fPal.palnumentries := 256;
  28.           fBitmapPalEntries := GetPaletteEntries( Image1.Picture.Graphic.Palette, 0, 256, fPal.palPalEntry[ 0 ] );
  29.           for i := 0 to fBitmapPalEntries - 1 do
  30.           begin
  31.             fColor := fPal.PalPalEntry[ i ].PeBlue shl 16
  32.               + fPal.PalPalEntry[ i ].PeGreen shl 8
  33.               + fPal.PalPalEntry[ i ].PeRed;
  34.             fColorString := ColorToString( fColor );
  35.             fStringList.Add( fColorString );
  36.           end;
  37.         end;
  38.       finally; FreeMem( fPal ); end;
  39.       if fStringList.Count = 0 then
  40.         ShowMessage('No palette entries!')
  41.       else      
  42.       fStringList.Free;
  43.     finally; Screen.Cursor := crDefault; end;
  44.   end;
  45. end;          

What is the problem?

jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Get palette
« Reply #1 on: March 01, 2021, 07:46:19 pm »
U have no image.
Set the size of the destination bitmap before drawing on it.
The only true wisdom is knowing you know nothing

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Get palette
« Reply #2 on: March 01, 2021, 08:23:30 pm »
U have no image.
Set the size of the destination bitmap before drawing on it.

Added this:
Code: Pascal  [Select][+][-]
  1. fBitmap.Width:=Image1.Picture.Width;
  2. fBitmap.Height:=Image1.Picture.Height;

but nothing changed.
Did I misunderstand you?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Get palette
« Reply #3 on: March 01, 2021, 09:42:43 pm »
Note that this only goes for palletted modes and -bitmaps, which have become rare nowadays.

Most are now simply RGB or RGBA

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Get palette
« Reply #4 on: March 01, 2021, 10:10:51 pm »
Note that this only goes for palletted modes and -bitmaps, which have become rare nowadays.

Most are now simply RGB or RGBA
So, does it mean that the code is good, but the images are "not ready" for getting palette?
If yes, is there any simple solution to get palette from any bmp/jpg/png picture?

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Get palette
« Reply #5 on: March 02, 2021, 12:13:41 am »
Hi!

Just be happy that the palette is nearly dead.

It was an awfull construction from the last millenium introduced for the Windows BMP.

It was "constructed" because in the Windows 3.x times the RAM was expensive and Windows was not able to operate on bigger amounts of RAM.

Nobody needs 256-Color-Images today.

Be happy that this emergeny solution slowly vanishes.

Winni


jamie

  • Hero Member
  • *****
  • Posts: 6090
Re: Get palette
« Reply #6 on: March 02, 2021, 01:17:52 am »
that must of been a Delphi example?

Yes, it works with Delphi because the TBitmap there is native all the way where is Lazarus does not do such a native job as you might think.

If you are in windows use the native API's or of all you want is to read the header of the files then just again use the standard headers for bitmaps to get that information.

 I think TBitMap in laz does support it to some point, I maybe just reading the image and converting it to a 24bi


-------PS---

 I do think if you directly loaded the image VIA the Tbitmap then you will get your palette.
fBitmap.LoadeFromFIle…..
« Last Edit: March 02, 2021, 01:20:11 am by jamie »
The only true wisdom is knowing you know nothing

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Get palette
« Reply #7 on: March 02, 2021, 01:30:31 am »
If yes, is there any simple solution to get palette from any bmp/jpg/png picture?

Not from any, only from those that, on loading, resolve to a [pf4bit,pf8bit] image; any other won't have a palette to get. And I'm not even sure a jpeg can be a 4 or 8 bpp image.

For any other you'll have to build the palette yourself from the colors in the image (e.g. by dithering) and transform the bitmap.

It was "constructed" because in the Windows 3.x times the RAM was expensive and Windows was not able to operate on bigger amounts of RAM.

Not quite. It was used because that's what the underlying hardware (EGA/VGA 16/256 colors) used; and the hardware itself used it because it's the easiest solution to allow those no. of colors with the less fuss (and yes, the less memory).

Also, it's not a "Windows only" thing; high-end *nix workstations, the AmigaOS, and most other systems of that era used them too (each one in its own incompatible way, of course >:D). And conversely, you could have a Windows 3 install working on 32K/64K/16M colors: you just needed a driver (most times from the manufacturer of the card) and a capable card+monitor combo.
« Last Edit: March 02, 2021, 01:32:06 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Get palette
« Reply #8 on: March 02, 2021, 09:05:35 am »
@winni:
I don't want palette for displaying a picture, but I need the best fit colors from a picture.

Guys, what about gif? It would give the 256 colors palette that I need for.
Is there a simple way in Lazarus to convert bmp/jpg/png to gif?

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Get palette
« Reply #9 on: March 02, 2021, 10:20:17 am »
Hi!


There is not only one palette for an image.
Windows  3.x had a system palette which was used by default.

Some image processing software offered

a) reduction down to the  nearest 256 colors  - or
b) optimization for a dithered image which made a smother impression


The palette made the BMPs complicated and as you see it ends in more complications.

Leave the deads behind they want follow you (Bob Dylan)

Winni

justnewbie

  • Sr. Member
  • ****
  • Posts: 292
Re: Get palette
« Reply #10 on: March 02, 2021, 11:20:34 am »
Maybe I used "palette" as a wrong term.
I need (max) 256 colors that "best fit" with an image.
So, what about gif?
Meanwhile I found this Delphi code, but gives an error (see attached):
Code: Pascal  [Select][+][-]
  1. procedure ConvertBMP2GIF;
  2. var
  3.   bmp: TBitmap;
  4.   gif: TGIFImage;
  5. begin
  6.   gif := TGifImage.Create;
  7.   try
  8.     bmp := TBitmap.Create;
  9.     try
  10.       bmp.LoadFromFile('MyBitmap.BMP');
  11.       gif.Assign(bmp);
  12.     finally
  13.       bmp.Free;
  14.     end;
  15.     gif.SaveToFile('MyBitmap.GIF');
  16.   finally
  17.     gif.Free;
  18.   end;
  19. end;
Is it possible to make it work?

 

TinyPortal © 2005-2018