D3 Palettes - how do I get them to work?

I keep struggling with this one thing over and over.

I am making a small 256-colour game, and I want to use a custom palette, but I don't understand how I am to get my Delphi 3.0 form to apply it. All my bitmaps use exactly the same palette, and when I load them in an image box, they are drawn correctly. But when I copy them from a hidden TImage to a visible empty TImage or TPaintBox, the colours turn out in the standard Windows 16 colours.

I have tried typing the following in the paint event of my form, but to no avail:

      SelectPalette(Handle, HiddenSource.Picture.Bitmap.Palette, False);
      RealizePalette(Handle);

How do I get my own custom palette to be used all over the form?

Thanks in advance for any answer.
JosefGAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

bcrotazCommented:
I know the feeling.  I've spent 2 years on this one.
0
JosefGAuthor Commented:
Adjusted points to 150
0
bcrotazCommented:
With the frequency this one is asked and not answered well, 1500 points might be better!!!
0
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

JosefGAuthor Commented:
Adjusted points to 215
0
bcrotazCommented:
he he he!
0
icampbe1Commented:
When you say 'copied' to the visible Timage, what do you mean?  I believe that if you use the assign method then it should work.  If this is OK then I'll turn this into an answer, OK?

Ian C.

0
JosefGAuthor Commented:
When I say 'copy', I mean that I use the CopyRect function to copy a portion of the hidden TImage to the visible TImage or TPaintBox. The strange thing is that it worked all right in Delphi 2, as far as I can remember...
0
bcrotazCommented:
He is right.
If you use the Assign method, you copy the bitmap and palette.
However, with what you (and I) are going, with a CopyRect, the palette does not get copied.  You can copy the palette:
Image1.Picture.Bitmap.Palette:=SourceBmp.Palette;
BUT This references the palette.  So if you destroy SourceBmp, the palette in Image1 goes too.
0
JosefGAuthor Commented:
I noticed an error I made while entering the question. Instead of

SelectPalette(Handle, HiddenSource.Picture.Bitmap.Palette, False);
RealizePalette(Handle);

the example should read

SelectPalette(Canvas.Handle, HiddenSource.Picture.Bitmap.Palette, False);
RealizePalette(Canvas.Handle);

Still, the problem remains the same...
0
mirek071497Commented:
Ohh. Why You can't use BitBlt and bitmaps ?

Here is example for You.

First Create Form, Place on them PaintBox and Button.
Then to OnClick (TButton) add following code.

procedure TForm1.Button1Click(Sender: TObject);
var
  Bmp     : HBitmap;
  NewDC   : HDC;
  MyPal   : HPalette;
  MyLPal  : PLogPalette;
begin
  { create palette (this is mono palette)}
  GetMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  MyLPal^.PalVersion := $0300;
  MyLPal^.palNumEntries:=256;
  for i:=0 to 255 do
  begin
    MyLPal^.palPalEntry[i].peRed   := i;
    MyLPal^.palPalEntry[i].peGreen := i;
    MyLPal^.palPalEntry[i].peBlue  := i;
    MyLPal^.palPalEntry[i].peFlags := 0;
  end;
  MyPal := CreatePalette(MyLPal^);
  FreeMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  { create DC for hidden writing }
  NewDC := CreateCompatibleDC( PaintBox2.Canvas.Handle );
  { select new palette }
  DeleteObject(SelectPalette( NewDC,MyPal,false));
  RealizePalette( NewDC );
  { create bitmap (work without too!) }
  Bmp := CreateCompatibleBitmap( PaintBox2.Canvas.Handle, XSize, YSize );

  { draw on Hidden DC for example from memory image of pixels }
{ This is My Example You must add here You'r Own
  SetDIBits( NewDC, Bmp, 0, YSize, @ByteBits, ByteInfo^, DIB_RGB_Colors );
  SelectObject( NewDC, Bmp ); }

  { copy from Hidden DC to PaintBox
  BitBlt( PaintBox2.Canvas.Handle, 0, 0, XSize, YSize, NewDC, 0, 0, SrcCopy );
  DeleteObject( Bmp );
  DeleteDC( NewDC );
end;


If You have any comments please submit comment or mail to me
mirek@izabell.itcomp.tpnet.pl

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
JosefGAuthor Commented:
By looking at your example, I assume you are creating a bitmap in memory, the same way you would in a C++ program. As Delphi is a "visual" development tool, I thought I could just place the source bitmap in a TImage component on my form, with the visible property set to False. I then wanted to copy a portion of this bitmap to a visible TPaintBox on my form.

You will see what I mean if you create a new project with a TImage, a TPaintBox and a TButton. Set the Visible property of the TImage to False (or true, the effect is in fact the same), and set its Picture to a 256 colour bitmap.

Then type the following in the eventhandler of your command button:
  BitBlt( PaintBox1.Canvas.Handle, 0, 0, 100, 100, Image1.Canvas.Handle, 0, 0, SrcCopy );

You should see the image appears, but only in 16 colours (not my 256).

Although your example code is rather detailed, I'm not sure I understood all the turns and twists in it, and what part corrects the palette problem.

As far as i understand, the problem lies in applying the palette in my 256-colour bitmap to the form. The form does not seem to want to apply any palette I give it, no matter how I do it, and what palette I use...
0
mirek071497Commented:
1.I made project with TPicture and paint box, then I load in design time bitmap. When i execute BitBlt Bitmap was correctly copied.

2.Tell me more what you try doing. If You for example need changed You'r palette then You must rather use Memory bitmap not the bitmap in TPicture. TPicture is component for handlign any kind of graphics and there are more functions.

3.You must assign correct palette to source bitmap not to form.

4.If You need working on palette You must use WinApi.

5.If You describe short problem I write code and submit it here.
0
mirek071497Commented:
I try comment my code

begin
  { here I create pallete description}
  GetMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  MyLPal^.PalVersion := $0300; { this is always $0300}
  MyLPal^.palNumEntries:=256;  { how many items in palette define}
  for i:=0 to 255 do
  begin { here I set RGB values for every new pallete entry }
    MyLPal^.palPalEntry[i].peRed := i;
    MyLPal^.palPalEntry[i].peGreen := i;
    MyLPal^.palPalEntry[i].peBlue := i;
    MyLPal^.palPalEntry[i].peFlags := 0; { if you don't need palette animation set to 0 }
  end;
  MyPal := CreatePalette(MyLPal^); { here i create GDI object (HPalette) }
  { description is no loger needed because palette was created }
  FreeMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  { create DC for hidden writing }
  NewDC := CreateCompatibleDC( PaintBox2.Canvas.Handle );
  { select new palette for NewDC and Delete previous }
  DeleteObject(SelectPalette( NewDC,MyPal,false));
  { after select You must realize palette because You don't know What colors Windows can display now }
  RealizePalette( NewDC );

  { here you cand draw on Hidden DC }

  { copy from Hidden DC to PaintBox }
  BitBlt( PaintBox2.Canvas.Handle, 0, 0, XSize, YSize, NewDC, 0, 0, SrcCopy );
  DeleteDC( NewDC ); { HDC must be deleted }
end;

0
mirek071497Commented:
Sorry, I must travell tomorrow and I return on Thursday.
Mail to me directly so I can answerr you'r questions or correct you'r code.
0
mirek071497Commented:
hello. I just arrived. Do you need any help ?
0
JosefGAuthor Commented:
I'll get back to the subject in some days. Unfortunately I'm too busy right now to try out your suggestion. See you! (read you).
0
mirek071497Commented:
Hi Josef!
Do you busy now ?
0
JosefGAuthor Commented:
Really, I'm not sure whether you have understood my problem. I'll try to clarify it: Why does a 256-colour bitmap only display in 16 colours when copied from one TImage to another?

I tried your code by typing:

      { here I create pallete description}
  GetMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  MyLPal^.PalVersion := $0300; { this is always $0300}
  MyLPal^.palNumEntries:=256; { how many items in palette define}
  for i:=0 to 255 do
  begin { here I set RGB values for every new pallete entry }
    MyLPal^.palPalEntry[i].peRed := i;
    MyLPal^.palPalEntry[i].peGreen := i;
    MyLPal^.palPalEntry[i].peBlue := i;
    MyLPal^.palPalEntry[i].peFlags := 0; { if you don't need palette animation set to 0 }
  end;
  MyPal := CreatePalette(MyLPal^); { here i create GDI object (HPalette) }
  { description is no loger needed because palette was created }
  FreeMem(MyLPal, (SizeOf(TLogPalette) + SizeOf(TPaletteEntry)*256));
  { create DC for hidden writing }
  NewDC := CreateCompatibleDC( PaintBox2.Canvas.Handle );
  { select new palette for NewDC and Delete previous }
  DeleteObject(SelectPalette( NewDC,MyPal,false));
  { after select You must realize palette because You don't know What colors Windows can display now }
  RealizePalette( NewDC );

  { here you cand draw on Hidden DC }
  SelectObject(NewDC,Image1.Picture.Bitmap.Handle);

  { copy from Hidden DC to PaintBox }
  BitBlt( PaintBox2.Canvas.Handle, 0, 0, 100, 100, NewDC, 0, 0, SrcCopy );
  DeleteDC( NewDC ); { HDC must be deleted }

The result still appeared in 16 colours...

I'm not sure how I'm supposed to treat the newly created palette object, so maybe I'm doing something wrong here...
0
mirek071497Commented:
Hi JosefG.
I think so you must have any other mistake because w made simple form with 2 TImage and 1 TButton. Then load 256color image from Windows directory and write proc for ButtonClick

procedure TForm1.Button1Click(Sender: TObject);
begin
  BitBlt( Image2.Canvas.Handle, 0, 0, Image2.Width, Image2.Height, Image1.Canvas.Handle, 0, 0, SrcCopy );
end;

I try with Image1 visible and invisible - All Work's Fine !!!

But when i edit this image with ImageEditor then palette was demaged, but by ImageEditor not by my program.

I can send to You my simple project with 256color bitmap as example or you must send to me you'r example wich not working ! I can't find any other solution.


0
bcrotazCommented:
I've seen this same problem in Delphi 1, but that was a long time ago...
0
mirek071497Commented:
Hi all experts !

Josef send me example which work's on My delphi2 but don't work on his Delphi3. Mayby any of us meet with this problem.
I havn't now delphi3 so i can't test this.
0
JosefGAuthor Commented:
Mirek's solution is to realise the palette right before using the copyrect method (in the same procedure).
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.