save 24 bit mode screen to file in 8 bit mode

Posted on 1997-11-12
Last Modified: 2010-04-04
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?

Question by:cadenza

Author Comment

ID: 1350083
Edited text of question

Expert Comment

ID: 1350084

Why not try the following:
procedure SaveDesktop;
    Bmp: TBitmap;
    DC: HDC;
    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);

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


Author Comment

ID: 1350085
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.

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

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.


Expert Comment

ID: 1350086
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.

Accepted Solution

ergates earned 150 total points
ID: 1350087
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.

Author Comment

ID: 1350088
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.


Expert Comment

ID: 1350089
Unfortunately not, Windoze is not at all clever!

Author Comment

ID: 1350090
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,


Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
delphi exception 7 68
Tviruailstringtree sort multi columns on header click 1 74
firemonkey keyboard covers the controls 1 37
DBCtrlGrid, Delphi, Scroll 7 24
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below.…

790 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question