#include "pch.h"
PixelFormat::PixelFormat(
int bits,
DWORD redMask,
DWORD greenMask,
DWORD blueMask,
DWORD alphaMask
) {
m_ddpf.dwSize = sizeof(DDPIXELFORMAT);
m_ddpf.dwFlags = DDPF_RGB;
m_ddpf.dwFourCC = 0;
m_ddpf.dwRGBBitCount = bits;
m_ddpf.dwRBitMask = redMask;
m_ddpf.dwGBitMask = greenMask;
m_ddpf.dwBBitMask = blueMask;
m_ddpf.dwRGBAlphaBitMask = alphaMask;
}
DWORD PixelFormat::RedSize() const { return RedMask() >> RedShift(); }
DWORD PixelFormat::GreenSize() const { return GreenMask() >> GreenShift(); }
DWORD PixelFormat::BlueSize() const { return BlueMask() >> BlueShift(); }
DWORD PixelFormat::AlphaSize() const { return AlphaMask() >> AlphaShift(); }
DWORD PixelFormat::RedShift() const { return GetShift(RedMask()); }
DWORD PixelFormat::GreenShift() const { return GetShift(GreenMask()); }
DWORD PixelFormat::BlueShift() const { return GetShift(BlueMask()); }
DWORD PixelFormat::AlphaShift() const { return GetShift(AlphaMask()); }
Pixel PixelFormat::MakePixel(DWORD red, DWORD green, DWORD blue) const
{
return Pixel::Create(
((red << RedShift() ) & RedMask() )
| ((green << GreenShift()) & GreenMask())
| ((blue << BlueShift() ) & BlueMask() ));
}
Pixel PixelFormat::MakePixel(const Color& color) const
{
return
MakePixel(
int(color.GetRed() * RedSize() ),
int(color.GetGreen() * GreenSize()),
int(color.GetBlue() * BlueSize() )
);
}
Color PixelFormat::MakeColor(Pixel pixel) const
{
return
Color(
(float)((pixel.Value() & RedMask()) >> RedShift()) / RedSize(),
(float)((pixel.Value() & GreenMask()) >> GreenShift()) / GreenSize(),
(float)((pixel.Value() & BlueMask()) >> BlueShift()) / BlueSize()
);
}
void PixelFormat::SetPixel(BYTE* pb, Pixel pixel) const
{
switch (PixelBytes()) {
case 1: *pb = (BYTE)(pixel.Value()); break;
case 2: *(WORD*)pb = (WORD)(pixel.Value()); break;
case 3:
pb[0] = (BYTE)(((pixel.Value()) >> 0) & 0xff);
pb[1] = (BYTE)(((pixel.Value()) >> 8) & 0xff);
pb[2] = (BYTE)(((pixel.Value()) >> 16) & 0xff);
break;
case 4: *(DWORD*)pb = (pixel.Value()); break;
}
}
Pixel PixelFormat::GetPixel(const BYTE* pb) const
{
switch (PixelBytes()) {
case 1: return Pixel::Create(*pb);
case 2: return Pixel::Create(*(WORD*)pb);
case 3:
return
Pixel::Create(
(DWORD(pb[0]) << 0)
| (DWORD(pb[1]) << 8)
| (DWORD(pb[2]) << 16)
);
case 4: return Pixel::Create(*(DWORD*)pb);
}
return Pixel::Create(0);
}
void PixelFormat::SetColor(BYTE* pb, const Color& color) const
{
SetPixel(pb, MakePixel(color));
}
Color PixelFormat::GetColor(const BYTE* pb) const
{
return MakeColor(GetPixel(pb));
}
bool PixelFormat::ValidGDIFormat() const
{
BitMask mask(m_ddpf.dwFlags);
if (mask.Test(BitMask(DDPF_ALPHA | DDPF_ALPHAPIXELS))) {
return false;
}
if (m_ddpf.dwRGBBitCount == 8) {
return mask.Test(BitMask(DDPF_PALETTEINDEXED8));
} else if (m_ddpf.dwRGBBitCount > 8) {
return mask.Test(BitMask(DDPF_RGB));
}
return false;
}
bool PixelFormat::Equivalent(const DDPIXELFORMAT& ddpf)
{
return
m_ddpf.dwFlags == ddpf.dwFlags
&& m_ddpf.dwRGBBitCount == ddpf.dwRGBBitCount
&& m_ddpf.dwRBitMask == ddpf.dwRBitMask
&& m_ddpf.dwGBitMask == ddpf.dwGBitMask
&& m_ddpf.dwGBitMask == ddpf.dwGBitMask
&& m_ddpf.dwRGBAlphaBitMask == ddpf.dwRGBAlphaBitMask;
}
bool FillDDPF(
DDPixelFormat& ddpf,
IDirectDrawX* pdd,
HDC hdc,
HBITMAP hbitmap,
IDirectDrawPalette** pppalette
) {
BYTE ajBitmapInfo[sizeof(BITMAPINFO) + 3 * sizeof(DWORD)];
BITMAPINFO* pbmi = (BITMAPINFO*)ajBitmapInfo;
BOOL bRet = FALSE;
memset(pbmi, 0, sizeof(ajBitmapInfo));
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
ZVerify(::GetDIBits(hdc, hbitmap, 0, 0, NULL, pbmi, DIB_RGB_COLORS));
ddpf.dwFlags = DDPF_RGB;
ddpf.dwRGBBitCount = pbmi->bmiHeader.biBitCount;
ddpf.dwRGBAlphaBitMask = 0;
switch(pbmi->bmiHeader.biCompression) {
case BI_RGB:
switch (ddpf.dwRGBBitCount) {
case 4:
case 8:
{
ddpf.dwFlags |= ((ddpf.dwRGBBitCount == 4) ? DDPF_PALETTEINDEXED4 : DDPF_PALETTEINDEXED8);
RGBQUAD prgb[256];
int ncolors = GetDIBColorTable(hdc, 0, 256, prgb);
ZAssert(ncolors == (1 << ddpf.dwRGBBitCount));
PALETTEENTRY ppe[256];
for (int index = 0; index < ncolors; index++) {
ppe[index].peRed = prgb[index].rgbRed;
ppe[index].peGreen = prgb[index].rgbGreen;
ppe[index].peBlue = prgb[index].rgbBlue;
}
DDCall(pdd->CreatePalette(
(ddpf.dwRGBBitCount == 4) ? DDPCAPS_4BIT : DDPCAPS_8BIT,
ppe,
pppalette,
NULL
));
return true;
}
case 16:
ddpf.dwRBitMask = MakeMask(5, 10);
ddpf.dwGBitMask = MakeMask(5, 5);
ddpf.dwBBitMask = MakeMask(5, 0);
return true;
case 24:
case 32:
ddpf.dwRBitMask = MakeMask(8, 16);
ddpf.dwGBitMask = MakeMask(8, 8);
ddpf.dwBBitMask = MakeMask(8, 0);
return true;
}
break;
case BI_BITFIELDS:
ZVerify(::GetDIBits(hdc, hbitmap, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS));
ddpf.dwRBitMask = *(DWORD *)&pbmi->bmiColors[0];
ddpf.dwGBitMask = *(DWORD *)&pbmi->bmiColors[1];
ddpf.dwBBitMask = *(DWORD *)&pbmi->bmiColors[2];
return true;
}
return false;
}