📄 bmp2ovr.cpp
字号:
#include <windows.h>
#include <ddraw.h>
DWORD GetBMPPixel( int x, int y, BYTE *pDIBBits, BITMAPINFO *pbmInfo )
{
BITMAPINFOHEADER *pbmiHeader = &(pbmInfo->bmiHeader);
RGBQUAD *pRgb = (RGBQUAD *)pbmInfo->bmiColors;
RGBQUAD rgbQuad;
DWORD dwStride;
// RETAILMSG(1, (TEXT("%d, %d, 0x%08X\r\n"), x, y, (DWORD)pDIBBits ));
dwStride = ((((pbmiHeader->biWidth * pbmiHeader->biBitCount)+7)/8) + 3) & 0xFFFFFFFC; // DWORD align
pDIBBits += dwStride * (pbmiHeader->biHeight - (y+1));
switch( pbmiHeader->biBitCount )
{
case 1 :
pDIBBits += (x>>3);
return *(DWORD *)(pRgb + ((*pDIBBits>>(7 - x%8)) & 0x01));
case 2 :
pDIBBits += (x>>2);
return *(DWORD *)(pRgb + ((*pDIBBits>>((3 - x%4)<<1)) & 0x03));
case 4 :
pDIBBits += (x>>1);
return *(DWORD *)(pRgb + ((*pDIBBits>>((1 - x%2)<<2)) & 0x0F));
case 8 :
pDIBBits += x;
return *(DWORD *)(pRgb + *pDIBBits);
case 16 :
pDIBBits += (x<<1);
rgbQuad.rgbBlue = (BYTE)((*(WORD *)pDIBBits & 0x001F)<<3);
rgbQuad.rgbGreen = (BYTE)((*(WORD *)pDIBBits & 0x03E0)>>2);
rgbQuad.rgbRed = (BYTE)((*(WORD *)pDIBBits & 0x7C00)>>7);
rgbQuad.rgbReserved = 0;
return *(DWORD *)&rgbQuad;
case 24 :
pDIBBits += x*3;
// RETAILMSG(1, (TEXT("-> 0x%08X\r\n"), (DWORD)pDIBBits ));
rgbQuad.rgbBlue = *pDIBBits++;
rgbQuad.rgbGreen = *pDIBBits++;
rgbQuad.rgbRed = *pDIBBits++;
rgbQuad.rgbReserved = 0;
return *(DWORD *)&rgbQuad;
case 32 :
pDIBBits += (x<<2);
rgbQuad.rgbBlue = *pDIBBits++;
rgbQuad.rgbGreen = *pDIBBits++;
rgbQuad.rgbRed = *pDIBBits++;
rgbQuad.rgbReserved = 0;
return *(DWORD *)&rgbQuad;
default :
ERRORMSG(1, (TEXT("GetBMPPixel : Unknown bpp = %d\r\n"), pbmiHeader->biBitCount ));
return 0;
}
}
HRESULT LoadBMPToOverlay
(
LPTSTR pszFilename,
LPDIRECTDRAW4 pDD4,
LPDIRECTDRAWSURFACE4 *lplpDDSurface,
int *pWidth,
int *pHeight
)
{
DDSURFACEDESC2 ddsd;
LPDIRECTDRAWSURFACE4 lpDDSurface = NULL;
BYTE *pDIB = NULL;
BYTE *pDIBBits = NULL;
BITMAPFILEHEADER bmfHeader;
BITMAPINFO *pbmInfo = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwSizeRead;
DWORD dwFileSize;
DWORD RGBData;
int R, G, B, Y0, Y1, U, V;
BYTE *pSurf;
int i, j;
BOOL b;
HRESULT hr = S_OK;
*lplpDDSurface = NULL;
//--------------------------------------------------------------------------
// Load a bitmap file
//--------------------------------------------------------------------------
// Open file
hFile = ::CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
ERRORMSG(1, (TEXT("CreateFile Failed\r\n")));
hr = E_FAIL;
goto LoadBMPToOverlay_Failed;
}
// Read file header
b = ::ReadFile(hFile, (LPVOID)&bmfHeader, sizeof(bmfHeader),
&dwSizeRead, NULL);
if (b == FALSE)
{
ERRORMSG(1, (TEXT("ReadFile : BITMAPFILEHEADER Failed\r\n")));
hr = E_FAIL;
goto LoadBMPToOverlay_Failed;
}
// File type should be 'BM'
if (bmfHeader.bfType != ((WORD)('M'<<8) | 'B'))
{
ERRORMSG(1, (TEXT("Type is not BM\r\n")));
hr = E_FAIL;
goto LoadBMPToOverlay_Failed;
}
// Get file size
dwFileSize = ::GetFileSize(hFile, NULL);
// Allocate memory for DIB
pDIB = new BYTE[dwFileSize];
if( pDIB == NULL )
{
ERRORMSG(1, (TEXT("OUTOFMEMORY : %d\r\n"), dwFileSize ));
hr = E_OUTOFMEMORY;
goto LoadBMPToOverlay_Failed;
}
// Read the other data
b = ::ReadFile(hFile, pDIB, dwFileSize - sizeof(bmfHeader),
&dwSizeRead, NULL);
if (dwSizeRead != dwFileSize - sizeof(bmfHeader))
{
ERRORMSG(1, (TEXT("ReadFile : BITMAPINFO & Data Failed\r\n")));
hr = E_FAIL;
goto LoadBMPToOverlay_Failed;
}
// Initialize the bitmap info pointer
pbmInfo = (BITMAPINFO *)pDIB;
pDIBBits = (LPBYTE)((DWORD)pDIB + bmfHeader.bfOffBits - sizeof(BITMAPFILEHEADER));
// Close file
b = ::CloseHandle(hFile);
if (b == FALSE)
{
ERRORMSG(1, (TEXT("Error to close the file handle!\r\n")));
hr = E_FAIL;
goto LoadBMPToOverlay_Failed;
}
hFile = INVALID_HANDLE_VALUE;
if( pbmInfo->bmiHeader.biWidth & 1 )
{
ERRORMSG(1, (TEXT("Image must have even width = %d\r\n"), pbmInfo->bmiHeader.biWidth ));
hr = E_FAIL;
goto LoadBMPToOverlay_Failed;
}
RETAILMSG(1, (TEXT("bfOffBits = %d\r\n"), bmfHeader.bfOffBits ));
RETAILMSG(1, (TEXT("biSize = %d\r\n"), pbmInfo->bmiHeader.biSize ));
RETAILMSG(1, (TEXT("biWidth = %d\r\n"), pbmInfo->bmiHeader.biWidth ));
RETAILMSG(1, (TEXT("biHeight = %d\r\n"), pbmInfo->bmiHeader.biHeight ));
RETAILMSG(1, (TEXT("biPlanes = %d\r\n"), pbmInfo->bmiHeader.biPlanes ));
RETAILMSG(1, (TEXT("biBitCount = %d\r\n"), pbmInfo->bmiHeader.biBitCount ));
RETAILMSG(1, (TEXT("biCompression = %d\r\n"), pbmInfo->bmiHeader.biCompression ));
RETAILMSG(1, (TEXT("biSizeImage = %d\r\n"), pbmInfo->bmiHeader.biSizeImage ));
RETAILMSG(1, (TEXT("biXPelsPerMeter = %d\r\n"), pbmInfo->bmiHeader.biXPelsPerMeter ));
RETAILMSG(1, (TEXT("biYPelsPerMeter = %d\r\n"), pbmInfo->bmiHeader.biYPelsPerMeter ));
RETAILMSG(1, (TEXT("biClrUsed = %d\r\n"), pbmInfo->bmiHeader.biClrUsed ));
RETAILMSG(1, (TEXT("biClrImportant = %d\r\n"), pbmInfo->bmiHeader.biClrImportant ));
//--------------------------------------------------------------------------
// Allocate Surface
//--------------------------------------------------------------------------
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth = pbmInfo->bmiHeader.biWidth;
ddsd.dwHeight = pbmInfo->bmiHeader.biHeight;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','Y','2');
hr = pDD4->CreateSurface(&ddsd, &lpDDSurface, NULL);
if( hr != DD_OK )
{
ERRORMSG(1, (TEXT("CreateSurface FAILED.\r\n")));
goto LoadBMPToOverlay_Failed;
}
hr = lpDDSurface->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Lock Failed = 0x%08X\r\n"), hr ));
goto LoadBMPToOverlay_Failed;
}
RETAILMSG(1, (TEXT("Surface Buffer = 0x%08X\r\n"), (DWORD)ddsd.lpSurface ));
pSurf = (BYTE *)ddsd.lpSurface;
//--------------------------------------------------------------------------
// Copy bitmap data to overlay surface
//--------------------------------------------------------------------------
for( j=0 ; j<pbmInfo->bmiHeader.biHeight ; j++ )
{
for( i=0 ; i<pbmInfo->bmiHeader.biWidth ; i+=2 )
{
RGBData = GetBMPPixel( i, j, pDIBBits, pbmInfo );
R = (int)(((RGBQUAD *)&RGBData)->rgbRed);
G = (int)(((RGBQUAD *)&RGBData)->rgbGreen);
B = (int)(((RGBQUAD *)&RGBData)->rgbBlue);
Y0 = (( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = (( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
RGBData = GetBMPPixel( i+1, j, pDIBBits, pbmInfo );
R = (int)(((RGBQUAD *)&RGBData)->rgbRed);
G = (int)(((RGBQUAD *)&RGBData)->rgbGreen);
B = (int)(((RGBQUAD *)&RGBData)->rgbBlue);
Y1 = (( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
V = (( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
*(pSurf++) = (BYTE)Y0;
*(pSurf++) = (BYTE)U;
*(pSurf++) = (BYTE)Y1;
*(pSurf++) = (BYTE)V;
}
}
hr = lpDDSurface->Unlock( NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Unlock Failed = 0x%08X\r\n"), hr ));
goto LoadBMPToOverlay_Failed;
}
*lplpDDSurface = lpDDSurface;
*pWidth = pbmInfo->bmiHeader.biWidth;
*pHeight = pbmInfo->bmiHeader.biHeight;
ASSERT( pDIB != NULL ); delete pDIB;
return S_OK;
LoadBMPToOverlay_Failed :
if( hFile != INVALID_HANDLE_VALUE ) ::CloseHandle(hFile);
if( pDIB != NULL ) delete pDIB;
if( lpDDSurface != NULL ) lpDDSurface->Release();
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -