📄 bmp2osd.cpp
字号:
#include <windows.h>
#include <ddraw.h>
#include "DISIOCTL.h"
#include "OSDType.h"
void PrintOSDHeader( volatile LPOSDHEADER3 pOH )
{
RETAILMSG(1, (TEXT("HEADER = 0x%08X, 0x%08X, 0x%08X\n"), pOH->Header[0], pOH->Header[1], pOH->Header[2] ));
RETAILMSG(1, (TEXT("NextAddr = 0x%08X\n"), pOH->NextAddr ));
RETAILMSG(1, (TEXT("IsEOR = %d\n"), pOH->IsEOR ));
RETAILMSG(1, (TEXT("Position = (%d, %d) - (%d, %d)\n"), pOH->StartX, pOH->StartY, pOH->EndX, pOH->EndY ));
RETAILMSG(1, (TEXT("Resolution = %d\n"), pOH->Resolution ));
RETAILMSG(1, (TEXT("BPP = %d\n"), pOH->BPP ));
RETAILMSG(1, (TEXT("IsCompressed = %d\n"), pOH->IsCompressed ));
RETAILMSG(1, (TEXT("GMW = %d, %d\n"), pOH->IsGMW, pOH->GMW ));
RETAILMSG(1, (TEXT("Transparent = %d, %d\n"), pOH->IsTransparent, pOH->Transparency ));
}
//------------------------------------------------------------------------------
DWORD RGB2OSDPalette( DWORD RGBData )
{
int Y, U, V, R, G, B;
RGBQUAD rgbQuad;
R = (int)((RGBQUAD *)&RGBData)->rgbRed;
G = (int)((RGBQUAD *)&RGBData)->rgbGreen;
B = (int)((RGBQUAD *)&RGBData)->rgbBlue;
Y = ( ( 66 * R + 129 * G + 25 * B + 128) >> 8) + 16;
U = ( ( -38 * R - 74 * G + 112 * B + 128) >> 8) + 128;
V = ( ( 112 * R - 94 * G - 18 * B + 128) >> 8) + 128;
//--------------------------------------------------------------------------
// Palette format for OSD layer
//--------------------------------------------------------------------------
// [31:28] = Reserved, [27:24] = Alpha, [23:16] = Cr, [15:8] = Cb, [7:0] = Y
//--------------------------------------------------------------------------
rgbQuad.rgbBlue = (BYTE)Y;
rgbQuad.rgbGreen = (BYTE)U;
rgbQuad.rgbRed = (BYTE)V;
rgbQuad.rgbReserved = 8;
return *(DWORD *)&rgbQuad;
}
BOOL CopyBMPData2OSDData( BYTE *pOSDData, BYTE *pBMPData, int bpp, int size )
{
BYTE temp;
switch( bpp )
{
case 2 :
while( size-- )
{
temp = *pBMPData++;
temp = ((temp&0xC0)>>6) | ((temp&0x30)>>2) | ((temp&0x0C)<<2) | ((temp&0x03)<<6);
*pOSDData++ = temp;
}
break;
case 4 :
while( size-- )
{
temp = *pBMPData++;
temp = (temp>>4) | (temp<<4);
*pOSDData++ = temp;
}
break;
case 8 :
memcpy( (PVOID)pOSDData, (const PVOID)pBMPData, size );
break;
default :
return FALSE;
}
return TRUE;
}
HRESULT LoadBMPToOSD
(
LPTSTR pszFilename,
LPDIRECTDRAW4 pDD4,
LPGPEMMSP2DRIVERINFO psGPEDI,
LPOSDHEADER3 pOH,
LPDIRECTDRAWSURFACE4 *lplpDDSurface,
int *pWidth,
int *pHeight,
DWORD *pPalette
)
{
DDSURFACEDESC2 ddsd;
LPDIRECTDRAWSURFACE4 lpDDSurface = NULL;
BYTE *pDIB = NULL;
BYTE *pDIBBits = NULL;
BITMAPFILEHEADER bmfHeader;
BITMAPINFO *pbmInfo = NULL;
BITMAPINFOHEADER *pbmiHeader = NULL;
DWORD dwSizeRead;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwFileSize;
BOOL b;
DWORD dwRegionAddr, dwRegionSize;
DWORD *pRgb;
DWORD i, dwDstStride, dwSrcStride, dwDstAddr, dwSrcAddr;
HRESULT hr = S_OK;
//--------------------------------------------------------------------------
// 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 LoadBMPToOSD_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 LoadBMPToOSD_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 LoadBMPToOSD_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 LoadBMPToOSD_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 LoadBMPToOSD_Failed;
}
// Initialize the bitmap info pointer
pbmInfo = (BITMAPINFO *)pDIB;
pbmiHeader = &(pbmInfo->bmiHeader);
if( pbmiHeader->biBitCount != 2 &&
pbmiHeader->biBitCount != 4 &&
pbmiHeader->biBitCount != 8 )
{
ERRORMSG(1, (TEXT("Bpp is %d\r\n"), pbmiHeader->biBitCount ));
hr = E_FAIL;
goto LoadBMPToOSD_Failed;
}
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 LoadBMPToOSD_Failed;
}
hFile = INVALID_HANDLE_VALUE;
RETAILMSG(1, (TEXT("bfOffBits = %d\r\n"), bmfHeader.bfOffBits ));
RETAILMSG(1, (TEXT("biSize = %d\r\n"), pbmiHeader->biSize ));
RETAILMSG(1, (TEXT("biWidth = %d\r\n"), pbmiHeader->biWidth ));
RETAILMSG(1, (TEXT("biHeight = %d\r\n"), pbmiHeader->biHeight ));
RETAILMSG(1, (TEXT("biPlanes = %d\r\n"), pbmiHeader->biPlanes ));
RETAILMSG(1, (TEXT("biBitCount = %d\r\n"), pbmiHeader->biBitCount ));
RETAILMSG(1, (TEXT("biCompression = %d\r\n"), pbmiHeader->biCompression ));
RETAILMSG(1, (TEXT("biSizeImage = %d\r\n"), pbmiHeader->biSizeImage ));
RETAILMSG(1, (TEXT("biXPelsPerMeter = %d\r\n"), pbmiHeader->biXPelsPerMeter ));
RETAILMSG(1, (TEXT("biYPelsPerMeter = %d\r\n"), pbmiHeader->biYPelsPerMeter ));
RETAILMSG(1, (TEXT("biClrUsed = %d\r\n"), pbmiHeader->biClrUsed ));
RETAILMSG(1, (TEXT("biClrImportant = %d\r\n"), pbmiHeader->biClrImportant ));
//--------------------------------------------------------------------------
// Allocate video memory(surface) for OSD data
//--------------------------------------------------------------------------
// Byte size to be allocated.
dwRegionSize = sizeof(OSDHEADER3) + pbmiHeader->biSizeImage;
dwRegionSize = (dwRegionSize + 3) & 0xFFFFFFFC; // DWORD align
// Get a surface
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
// because Surface is 16 bpp(2 Bytes per pixel)
ddsd.dwWidth = dwRegionSize>>1;
ddsd.dwHeight = 1;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsd.ddpfPixelFormat.dwFourCC = 0;
ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
ddsd.ddpfPixelFormat.dwRBitMask = 0xF800;
ddsd.ddpfPixelFormat.dwGBitMask = 0x07E0;
ddsd.ddpfPixelFormat.dwBBitMask = 0x001F;
ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0;
hr = pDD4->CreateSurface(&ddsd, &lpDDSurface, NULL);
if( hr != DD_OK )
{
ERRORMSG(1, (TEXT("CreateSurface FAILED.\r\n")));
goto LoadBMPToOSD_Failed;
}
hr = lpDDSurface->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Lock Failed = 0x%08X\r\n"), hr ));
goto LoadBMPToOSD_Failed;
}
RETAILMSG(1, (TEXT("Surface Buffer = 0x%08X\r\n"), (DWORD)ddsd.lpSurface ));
dwRegionAddr = (DWORD)ddsd.lpSurface;
//--------------------------------------------------------------------------
// Set a region header
//--------------------------------------------------------------------------
pOH->NextAddr = 0xDEADBEEF;
pOH->IsEOR = 1;
pOH->IsCompressed = 0;
pOH->EndX = pOH->StartX + ((pOH->Resolution) ? (pbmiHeader->biWidth*2) : (pbmiHeader->biWidth)) - 1;
pOH->EndY = pOH->StartY + pbmiHeader->biHeight - 1;
switch( pbmiHeader->biBitCount )
{
case 2 : pOH->BPP = 0; pbmiHeader->biClrUsed = 4; break;
case 4 : pOH->BPP = 1; pbmiHeader->biClrUsed = 16; break;
case 8 : pOH->BPP = 2; pbmiHeader->biClrUsed = 256; break;
}
memcpy( (PVOID)dwRegionAddr, (const PVOID)pOH, sizeof(OSDHEADER3) );
//--------------------------------------------------------------------------
// Copy bitmap data to region data
//--------------------------------------------------------------------------
dwDstStride = (((pbmiHeader->biWidth * pbmiHeader->biBitCount)+7)/8);
dwSrcStride = (dwDstStride + 3) & 0xFFFFFFFC; // DWORD align
dwDstAddr = dwRegionAddr+sizeof(OSDHEADER3);
dwSrcAddr = (DWORD)pDIBBits + (pbmiHeader->biHeight - 1)*dwSrcStride;
for( i=0 ; i<(DWORD)pbmiHeader->biHeight ; i++ )
{
CopyBMPData2OSDData( (PBYTE)dwDstAddr, (PBYTE)dwSrcAddr, pbmiHeader->biBitCount, dwDstStride );
dwDstAddr += dwDstStride;
dwSrcAddr -= dwSrcStride;
}
//--------------------------------------------------------------------------
// Convert RGB palette to OSD palette
//--------------------------------------------------------------------------
pRgb = (DWORD *)pbmInfo->bmiColors;
for( i=0 ; i<pbmiHeader->biClrUsed ; i++ )
pPalette[i] = RGB2OSDPalette( pRgb[i] );
hr = lpDDSurface->Unlock( NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Unlock Failed = 0x%08X\r\n"), hr ));
goto LoadBMPToOSD_Failed;
}
*lplpDDSurface = lpDDSurface;
*pWidth = pbmiHeader->biWidth;
*pHeight = pbmiHeader->biHeight;
//--------------------------------------------------------------------------
// Release resources
//--------------------------------------------------------------------------
ASSERT( pDIB != NULL ); delete pDIB;
return S_OK;
LoadBMPToOSD_Failed :
*lplpDDSurface = NULL;
*pWidth = 0;
*pHeight = 0;
if( pDIB != NULL ) delete pDIB;
if( lpDDSurface != NULL ) lpDDSurface->Release();
if( hFile != INVALID_HANDLE_VALUE ) ::CloseHandle(hFile);
return hr;
}
BOOL SetOSDHeader( HDC hdc, LPDIRECTDRAWSURFACE4 lpDDSurface, LPOSDHEADER3 pOH )
{
DDSURFACEDESC2 ddsd;
HRESULT hr;
if( lpDDSurface == NULL || pOH == NULL ) return FALSE;
hr = lpDDSurface->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Lock Failed = 0x%08X\r\n"), hr ));
return FALSE;
}
memcpy( (PVOID)ddsd.lpSurface, (const PVOID)pOH, sizeof(OSDHEADER3) );
hr = lpDDSurface->Unlock( NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Unlock Failed = 0x%08X\r\n"), hr ));
return FALSE;
}
return TRUE;
}
BOOL SetOSDPalette( HDC hdc, DWORD *pPalette, int NumberOfPalette )
{
if( ExtEscape( hdc, IOCTL_DIS_SETOSDPALETTE, NumberOfPalette*sizeof(DWORD), (LPCSTR)pPalette, 0, NULL ) <= 0 )
return FALSE;
return TRUE;
}
BOOL SetOSDAddress( HDC hdc, LPDIRECTDRAWSURFACE4 lpDDSurface, LPGPEMMSP2DRIVERINFO psGPEDI )
{
DWORD temp[2];
DDSURFACEDESC2 ddsd;
HRESULT hr;
if( lpDDSurface == NULL ) return FALSE;
hr = lpDDSurface->Lock( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Lock Failed = 0x%08X\r\n"), hr ));
return FALSE;
}
// Convert virtual address to physical address
temp[0] = (DWORD)ddsd.lpSurface - psGPEDI->dwVirtualFrameBuffer + psGPEDI->dwPhysicalFrameBuffer;
temp[1] = temp[0];
hr = lpDDSurface->Unlock( NULL );
if( FAILED(hr) )
{
ERRORMSG(1, (TEXT("Surface Unlock Failed = 0x%08X\r\n"), hr ));
return FALSE;
}
if( ExtEscape( hdc, IOCTL_DIS_SETOSDADDR, sizeof(DWORD)*2, (LPCSTR)temp, 0, NULL ) <= 0 )
{
return FALSE;
}
return TRUE;
}
BOOL SetOSDEnable( HDC hdc, BOOL enb )
{
if( ExtEscape( hdc, IOCTL_DIS_SETOSDENB, 4, (LPCSTR)&enb, 0, NULL ) <= 0 )
{
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -