#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() ) ); // !!! this causes all of the artwork to change slightly // since the rounding mode is different /* return MakePixel( MakeInt(color.GetRed() * RedSize() ), MakeInt(color.GetGreen() * GreenSize()), MakeInt(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); // // gdi doesn't support alpha // if (mask.Test(BitMask(DDPF_ALPHA | DDPF_ALPHAPIXELS))) { return false; } if (m_ddpf.dwRGBBitCount == 8) { // // 8 bpp must be palettized // return mask.Test(BitMask(DDPF_PALETTEINDEXED8)); } else if (m_ddpf.dwRGBBitCount > 8) { // // 16 bpp must be RGB // return mask.Test(BitMask(DDPF_RGB)); } // // less than 8 bpp not supported // 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; } ////////////////////////////////////////////////////////////////////////////// // // constructor // ////////////////////////////////////////////////////////////////////////////// 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) { // // Default DIB format. Color masks are implicit for each bit depth. // case BI_RGB: switch (ddpf.dwRGBBitCount) { case 4: case 8: { ddpf.dwFlags |= ((ddpf.dwRGBBitCount == 4) ? DDPF_PALETTEINDEXED4 : DDPF_PALETTEINDEXED8); // // Create a palette for the surface // RGBQUAD prgb[256]; int ncolors = GetDIBColorTable(hdc, 0, 256, prgb); ZAssert(ncolors == (1 << ddpf.dwRGBBitCount)); PALETTEENTRY ppe[256]; // // convert BGR to RGB // 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; } // // create a DirectDraw palette for the texture. // DDCall(pdd->CreatePalette( (ddpf.dwRGBBitCount == 4) ? DDPCAPS_4BIT : DDPCAPS_8BIT, ppe, pppalette, NULL )); return true; } case 16: // 16bpp default is 555 BGR-ordering ddpf.dwRBitMask = MakeMask(5, 10); ddpf.dwGBitMask = MakeMask(5, 5); ddpf.dwBBitMask = MakeMask(5, 0); return true; case 24: case 32: // 24 and 32bpp default is 888 BGR-ordering ddpf.dwRBitMask = MakeMask(8, 16); ddpf.dwGBitMask = MakeMask(8, 8); ddpf.dwBBitMask = MakeMask(8, 0); return true; } break; case BI_BITFIELDS: // // Call a second time to get the color masks. // It's a GetDIBits Win32 "feature". // 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; }