[BCB6] Edycja palety kolorów BMPy

0

Witam,

Niech mi jakaś mądra głowa powie, jak to jest z tymi bitmapami z paletą kolorów. Prawie żywcem z helpa kod:

typedef struct{
  TLogPalette lpal;
  TPaletteEntry dummy[256];
}LogPal;

// IBmp4 - to TImage *
void __fastcall TForm1::Button16Click(TObject *Sender)
{
    IBmp4->Picture->Bitmap->LoadFromFile("test256.bmp");

    LogPal Pltt;
    Pltt.lpal.palVersion = 0x300;
    Pltt.lpal.palNumEntries = 256;

    for(int i = 0; i < 256; i++){
        Pltt.dummy[i].peRed = i;
        Pltt.dummy[i].peGreen = i;// * 3;
        Pltt.dummy[i].peBlue = i;// * 2;
        Pltt.dummy[i].peFlags = 0;//PC_NOCOLLAPSE;

    }

    IBmp4->Picture->Bitmap->Palette = CreatePalette((const tagLOGPALETTE *)&Pltt.lpal);
    IBmp4->Invalidate();

}

Mam testową bitmapę zrobioną w Paint'cie. Zapisana jako 256 kolorów. Przedstawia paski w różnych kolorach. Po ustawieniu kolorów w pętli - każdy różny, niektóre paski mają ten sam kolor. Jeśli użyję zakomentarzowanych *2 i *3 to każdy pasek jest różny. Czy te kolory są mapowane??
Kombinowałem z peFlags i żadnych rezultatów.

Najbardziej zależałoby mi na zrobieniu bitmapy 4-kolorowej (2bpp).

0

błąd tkwi w tym :

Pltt.dummy[i].peGreen = i* 3;
Pltt.dummy[i].peBlue = i * 2;

peRed , peGreen i peBlue to zmienne typu unsigned char czyli mają zakres 0-255,

jeśli teraz mnożysz np. 200 *2 wychodzi Ci wartość 400 i zostają od niej obcięte bity "nadmiarowe " w wyniku takiej operacji zamiast 400 dostajesz 144 .
więc pasek o składowej 200 będzie miał "fałszywą" wartość.
musisz sprawdzać czy nie nastąpiło przepełnienie.

Małe wyjaśnienie :

unsigned char to zmienna zajmująca 1 bajt .

liczba 400 bitowo na jednym bajcie się nie mieści

110010000 - czyli 400 obcięte do 8 bitów czyli
10010000 co odpowiada liczbie 144 .
oczywiście analogicznie dzieje się z innymi wartościami które po wymnożeniu przekraczają 255.

0

:] Tyle to wiem. Po prostu się licznik przekręca. I właśnie przy użyciu przekręcania jest ok. A jak zakomentarzowane, to nie ok.
Popróbuję na żywca robić bitmapę: BITMAPINFOHEADER.. CreateDIBitmap.. itp. zamiast korzystać z TBitmap.

0

Zrobiłem tak:

typedef struct{
  BITMAPINFOHEADER bmiHeader;
  RGBQUAD pal[256];    // 256 ZAWSZE ??
} BITMAPA;

void __fastcall TForm1::Button16Click(TObject *Sender)
{
    HBITMAP hbmp = 0;

    BITMAPA binf;
    binf.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    binf.bmiHeader.biWidth = 100;
    binf.bmiHeader.biHeight = 50;
    binf.bmiHeader.biPlanes = 1;
    binf.bmiHeader.biBitCount = 8;
    binf.bmiHeader.biCompression = BI_RGB;
    binf.bmiHeader.biSizeImage = 0;
    binf.bmiHeader.biXPelsPerMeter = 96;
    binf.bmiHeader.biYPelsPerMeter = 96;
    binf.bmiHeader.biClrUsed = 4;
    binf.bmiHeader.biClrImportant = 4;

    HDC hdc = GetDC(0);
    HDC dc = CreateCompatibleDC(hdc);
    hbmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)&binf, 0, 0, 0, DIB_RGB_COLORS);
    if(hbmp){

        char bufor[5000]; memset(bufor, 0, 5000);

        int ires = GetDIBits(hdc, hbmp, 0, 50, bufor, (BITMAPINFO *)&binf, DIB_RGB_COLORS);
        if(ires){

            ShowMessage(IntToStr(binf.bmiHeader.biClrUsed));     // Dlaczego 0 ??
            for(int i = 0; i < 50; i++){
                for(int j = 0; j < 100; j++){
                    bufor[i * 100 + j] = (i+j)/25%4;
                }
            }
          
            binf.pal[0].rgbBlue = 255;
            binf.pal[0].rgbGreen = 0;
            binf.pal[0].rgbRed = 0;

            binf.pal[1].rgbBlue = 0;
            binf.pal[1].rgbGreen = 255;
            binf.pal[1].rgbRed = 0;

            binf.pal[2].rgbBlue = 0;
            binf.pal[2].rgbGreen = 0;
            binf.pal[2].rgbRed = 255;

            binf.pal[3].rgbBlue = 255;
            binf.pal[3].rgbGreen = 255;
            binf.pal[3].rgbRed = 255;

            ires = SetDIBits(hdc, hbmp, 0, 50, bufor, (BITMAPINFO *)&binf, DIB_RGB_COLORS);
            if(ires){

                SelectObject(dc, hbmp);
                BitBlt(hdc, 0, 0, 100, 50, dc, 0, 0, SRCCOPY);
                DeleteObject(hbmp);
            }else{
                ShowMessage("Blad 2");
            }
        }else{
            ShowMessage("Blad 1");
        }
    }
    DeleteDC(dc);
    ReleaseDC(0, hdc);
}

No i działa.

Ale:
a) czy ZAWSZE musi być 256 RGBQUADow? Dalem 4 i sie sypal program,
b) dlaczego wartosc biClrUsed wynosi 0?</b>

1 użytkowników online, w tym zalogowanych: 0, gości: 1