Solved

save 24 bit mode screen to file in 8 bit mode

Posted on 1997-11-12
8
273 Views
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?

Wim
0
Comment
Question by:cadenza
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
8 Comments
 

Author Comment

by:cadenza
ID: 1350083
Edited text of question
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1350084
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
 

Author Comment

by:cadenza
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.

Wim
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 2

Expert Comment

by:greendot
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.
0
 
LVL 1

Accepted Solution

by:
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.
0
 

Author Comment

by:cadenza
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.

Wim
0
 
LVL 1

Expert Comment

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

Author Comment

by:cadenza
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,

Wim
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

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.

Question has a verified solution.

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

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
This is a high-level webinar that covers the history of enterprise open source database use. It addresses both the advantages companies see in using open source database technologies, as well as the fears and reservations they might have. In this…
NetCrunch network monitor is a highly extensive platform for network monitoring and alert generation. In this video you'll see a live demo of NetCrunch with most notable features explained in a walk-through manner. You'll also get to know the philos…

691 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