⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmp2osd.cpp

📁 在嵌入式 WINCE 中实现 OSD 功能
💻 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 + -