Message-ID: <3AC2CFCF.D76D30D@cornell.edu> Date: Thu, 29 Mar 2001 01:01:51 -0500 From: "Damon Chandler (TeamB)" X-Mailer: Mozilla 4.7 [en] (WinNT; I) X-Accept-Language: en,x-ns1eT9svYg$NhQ,x-ns2r3309OnmPe2 MIME-Version: 1.0 Newsgroups: borland.public.cppbuilder.graphics Subject: Re: Changing Palette entry in pf8bit bmp. Ignore previous post References: <3ac1e975$1_1@dnews> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit NNTP-Posting-Host: 24.24.28.190 X-Trace: 28 Mar 2001 22:01:00 -0800, 24.24.28.190 Lines: 117 Path: dnews!24.24.28.190 Xref: dnews borland.public.cppbuilder.graphics:16762 Hi Stuart, > I'm trying to read and display a 256 colour BMP, using > LoadFromFile and ...Draw(0,0,bitmap) etc. I then need to use a > scrollbar to change the R,G or B component of an individual > colour code with the result being immediately seen. I've got it > nearly working except when the new colour matches another colour > already in the BMP palette: the colour code permanently swaps > over to the matching colours colour code. Did you remember to update the bitmap's color table? Unless you update the bitmap's color table, the wrong color will display because the GDI will try to translate the specified pixel value (i.e., color table index) to the closest matching palette entry. Here's how it works: When you create a TBitmap with a pf8bit PixelFormat, the TBitmap class uses what's called a DIB section bitmap--specifically a DIB section that uses eight bits per pixel (8-bpp). This is different from an 8-bpp DDB (device-dependent bitmap) because the pixels of an 8-bpp DDB refer to palette indices. In contrast, the pixels of an 8-bpp DIB section bitmap refer to _color_table_ indices. This color table actually plays an important role in the DIB section's device-independence (the "DI" in "DIB" stands for device-independent) because if the DIB section's pixels did refer to palette indices, the DIB section would depend on that palette, which itself is inherently linked to a specific device. Because an 8-bpp DIB section's pixels refer color table indices, when you draw this DIB section on a palettized display, the GDI must map color table indices to palette indices, which it does by using the distance formula. If the color table contains the same entries as the palette, then (1) there's no additional mapping involved, and (2) the bitmap will draw faster. Now, if you change only a palette entry, but you don't change the corresponding color table entry, you haven't actually changed the color that the bitmap's corresponding pixels refers to. For example, if the first entry of both the palette and the color table refer to lime green, and you change only the palette entry to, say, blue, then the pixels of the bitmap that refer to lime green won't be drawn in blue; instead, they'll be drawn in the color of the palette that matches closest (in distance) to lime green. Does this make sense? So, in short, after you change your Bitmap's palette, you also need to change it's color table (via the SetDIBColorTable() function). Here's an example... void __fastcall TForm1::ScrollBar1Scroll(TObject *Sender, TScrollCode ScrollCode, int &ScrollPos) { // // NOTE: Bitmap_ is your TBitmap object // // grab a handle to the bitmap's logical palette const HPALETTE hPal = Bitmap_->Palette; // define the number of entries to change const unsigned char num_to_change = 1; // define the entry to change const int target_index = 28; // for example // initialize a PALETTEENTRY structure PALETTEENTRY palE = {0}; // e.g., grayscale palE.peRed = ScrollPos; palE.peGreen = ScrollPos; palE.peBlue = ScrollPos; // change the specified palette entry const UINT num_pal_changed = SetPaletteEntries( hPal, target_index, num_to_change, &palE ); assert(num_pal_changed == num_to_change); // initialize a corresponding RGBQUAD structure RGBQUAD rgbQ = {0}; rgbQ.rgbRed = palE.peRed; rgbQ.rgbGreen = palE.peGreen; rgbQ.rgbBlue = palE.peBlue; // update the bitmap's color table const UINT num_ct_changed = SetDIBColorTable( Bitmap_->Canvas->Handle, target_index, num_to_change, &rgbQ ); assert(num_ct_changed == num_to_change); // redraw the image // e.g., PaintBox1->Refresh(); } > Also, some of the bitmaps are pf8bit which nearly works as above > but other bitmaps although 256 colours (according to Paint Shop > Pro) are set as pfDevice. I can't do anyhing useful with these. > Changing them to pf8bit screws up the palette (possibly mapping > the colour codes straight to the system palette). I suspect that these bitmaps are RLE compressed. The VCL loads RLE compressed bitmaps as DDBs. You can use the TCanvas::Draw() member function to convert these types to pf8bit. Here's an example of that... #include void To8bit(Graphics::TBitmap& Bitmap) { std::auto_ptr TempBitmap(new Graphics::TBitmap()); TempBitmap->PixelFormat = pf8bit; TempBitmap->Width = Bitmap.Width; TempBitmap->Height = Bitmap.Height; TempBitmap->Palette = Bitmap.Palette; TempBitmap->Canvas->Draw(0, 0, &Bitmap); Bitmap.Assign(TempBitmap.get()); } Best of luck, -- Damon Chandler (TeamB) - BCBCAQ - Graphics API Black Book