• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 279
  • Last Modified:

save 24 bit mode screen to file in 8 bit mode

My basic question is:

-the video card is in 16 or 24 bit mode,
-less than 256 colours are dispayed (some windows colours, some my own),

How can I save (part of) the screen to file in 8 bit mode?

The following approach gives the wrong colours (some kind of standard palette with a number of shades of a number of colours):

ScreenDC     := GetDc(0);
MemDc        := CreateCompatibleDc(ScreenDC);
MemBitmap    := CreateCompatibleBitmap(ScreenDC, SrcRect.width, SrcRect.height);
OldMemBitmap := SelectObject(MemDc, MemBitmap);

BitBlt(MemDC, ..., SrcDC, ...);  //SrcDC is the dc of the form

Then I fill a DIB info header with the format I want the bitmap: 1 plane, 8 bits per pixel

and then I call GetDIBits twice: the first time to get the colours into the header, and then to get the bits:

GetDIBits(MemDC, MemBitmap, 0, SrcRect.Height, nil,
      PBitmapInfo(pDibHeader)^, DIB_RGB_COLORS);

GetDIBits(MemDC, MemBitmap, 0, SrcRect.Height, pBits,
      PBitmapInfo(pDibHeader)^, DIB_RGB_COLORS);

After the first GetDIBits, the header does not contain my colours, but some sort of standard colour table, containing a couple of shades of every base colour. Saving the bitmap to file and viewing it with MS Paint indeed shows the wrong colours.
This approach works fine in 8 bit screen mode, but I need to handle screens in higher modes as well.

So my question is: what do I have to do to get the correct colours?

Wim
0
cadenza
Asked:
cadenza
1 Solution
 
cadenzaAuthor Commented:
Edited text of question
0
 
JimBob091197Commented:
Hi

Why not try the following:
procedure SaveDesktop;
var
    Bmp: TBitmap;
    DC: HDC;
begin
    Bmp := TBitmap.Create;
    DC := GetDC(0);
    Bmp.Width := Screen.Width;
    Bmp.Height := Screen.Height;
    BitBlt(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height, DC, 0, 0, SRCCOPY);
    ReleaseDC(0, DC);
    Bmp.SaveToFile('C:\Temp\Desktop.bmp');
    Bmp.Free;
end;

If that doesn't work, try the following before Bmp.SaveToFile:
Bmp.PixelFormat := pf8bit;
(I think that PixelFormat will only work on Delphi 3...)

Regards,
JB
0
 
cadenzaAuthor Commented:
Hi Jim Bob,

thanks for your suggestion.

1- if you let Delphi create a bitmap, it makes it compatible with the screen. So if your video card is in 24 bit mode, it makes a 24 bit bitmap. Saving this to file gives a 24 bit mode file.

2- pf8bit is Delphi 3. I use Delphi 2. (if this works in D3, which I think it does not, I would be very curious to learn how they do it).

I think my question boils down to: how can I make Windoze derive a proper RGB table (<= 256 entries) from the screen/a bitmap.

Wim
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

 
greendotCommented:
Windows does not store "palettes" in any mode higher than 8-bit.  All pixels are stored in (R,G,B).  This is just a guess but you're probably going to have to create your own palette structure and translate the internal (R,G,B) pixels into palette mapped pixels.
0
 
ergatesCommented:
I wrote some code to do this, to save GIF files from a 24bit bitmap. Essentially its what grrendot said.

The only way I have found to convert True Color bitmap to a palette based bitmap is to create a palette by going through every pixel and adding each new color to the palette, and setting the value in the destination bitmap to the palette index of the color.

Yep, its slow, one way to optimise is to remember last palette index when looking up a pixel, as adjacent pixels are often the same. Also if you have more colors in the source bitmap than entries in the palette, you will have to throw the lesser used ones away, and map them to similar colors, or dither.

Not easy.
0
 
cadenzaAuthor Commented:
Hi Greendot & Ergates,

thanks for your comment/answer. I think I'll have to do what you say, but I thought of taking a shortcut about which I would like your (or anyone else's) opinion.

My advantage is: I know the colours that are present in the source: there are a couple of bitmaps of which I set the colours myself + some gray around it from the window's background + black and white. So do you think it would work if I loaded these colours into the RGB quad entries of the DIB header explicitly before calling GetDIBits to get the 8-bit pixels. In other words: is Windoze so clever to map the 24 bit pixels to the right indices of the colours in the header? If that would be the case, my problem seems to be solved, I guess.

Wim
0
 
ergatesCommented:
Unfortunately not, Windoze is not at all clever!
0
 
cadenzaAuthor Commented:
That is a pitty, although it answers my question. I'll follow your approach and see if I can live with the speed. Maybe I can take advantage of the fact that I already know the colours used.. Or I simply force my users to switch to 8 bit colour :) .

thanks again for your answer,

Wim
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now