www.pudn.com > GameEngine_src.rar > CEasyDraw.cpp
#include "CEasyDraw.h" #include "normal.h" #include "BaseUtil.h" //#include "ijl.h" #include#include #include #include #include #include #pragma comment( lib, "ddraw.lib" ) #pragma comment( lib, "dxguid.lib" ) //#pragma comment( lib, "ijl15l.lib" ) CEasyDraw theEasyDraw; const int MAX_NUM_SURF = 1024; int CEasyDraw::g_CharWidth; int CEasyDraw::g_CharHeight; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CEasyDraw::CEasyDraw() { m_lpDD = NULL; m_lpDDSBack = NULL; m_lpDDSPrimary = NULL; m_hWnd = NULL; m_DisplayFormat = R5G6B5; m_iWidth = 800; m_iHeight = 600; m_lpGammaControl = NULL; m_pGammaData = NULL; } CEasyDraw::~CEasyDraw() { } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CEasyDraw::Init( HWND hwnd, bool isWindowed, int iW, int iH ) { Free(); HRESULT hr; //创建lpdd7对象: hr = DirectDrawCreateEx(NULL, (void **)&m_lpDD, IID_IDirectDraw7, NULL); if ( hr != DD_OK ) { Warn( "创建DirectDraw7接口失败!" ); return false; } if ( !isWindowed ) { SetWindowLong( hwnd, GWL_STYLE, WS_POPUP ); hr = m_lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); if ( hr != DD_OK ) { return false; } //设置屏幕模式: hr = m_lpDD->SetDisplayMode( iW, iH, 16, 0, 0 ); //只支持16位模式 if ( hr != DD_OK ) { return false; } //创建主页面: DDSURFACEDESC2 ddsd; ZeroMemory( &ddsd, sizeof(ddsd) ); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; hr = m_lpDD->CreateSurface(&ddsd, &m_lpDDSPrimary, NULL); if ( hr != DD_OK ) { return false; } //创建后台页面: DDSCAPS2 ddscaps; ZeroMemory( &ddscaps, sizeof( ddscaps ) ); ddscaps.dwCaps = DDSCAPS_BACKBUFFER; hr = m_lpDDSPrimary->GetAttachedSurface( &ddscaps, &m_lpDDSBack ); if ( hr != DD_OK ) { return false; } m_bWindowed = false; } else { hr = m_lpDD->SetCooperativeLevel(hwnd, DDSCL_NORMAL); if ( hr != DD_OK ) { return false; } RECT rcWork; RECT rc; DWORD dwStyle; // If we are still a WS_POPUP window we should convert to a normal app // window so we look like a windows app. dwStyle = GetWindowStyle( hwnd ); dwStyle &= ~WS_POPUP; dwStyle &= ~WS_SIZEBOX; dwStyle &= ~WS_THICKFRAME; dwStyle &= ~WS_MAXIMIZE; dwStyle &= ~WS_MAXIMIZEBOX; dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX;// | WS_SYSMENU; SetWindowLong( hwnd, GWL_STYLE, dwStyle ); // Aet window size SetRect( &rc, 0, 0, iW, iH ); AdjustWindowRectEx( &rc, GetWindowStyle(hwnd), GetMenu(hwnd) != NULL, GetWindowExStyle(hwnd) ); SetWindowPos( hwnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); SetWindowPos( hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE ); // Make sure our window does not hang outside of the work area SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 ); GetWindowRect( hwnd, &rc ); if( rc.left < rcWork.left ) rc.left = rcWork.left; if( rc.top < rcWork.top ) rc.top = rcWork.top; SetWindowPos( hwnd, NULL, rc.left, rc.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); LPDIRECTDRAWCLIPPER pcClipper; // Create the primary surface DDSURFACEDESC2 ddsd; ZeroMemory( &ddsd, sizeof( ddsd ) ); ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if( FAILED( m_lpDD->CreateSurface( &ddsd, &m_lpDDSPrimary, NULL ) ) ) return false; // Create the backbuffer surface ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; ddsd.dwWidth = iW; ddsd.dwHeight = iH; if( FAILED( hr = m_lpDD->CreateSurface( &ddsd, &m_lpDDSBack, NULL ) ) ) return false; if( FAILED( hr = m_lpDD->CreateClipper( 0, &pcClipper, NULL ) ) ) return false; if( FAILED( hr = pcClipper->SetHWnd( 0, hwnd ) ) ) { pcClipper->Release(); Warn( "设置裁剪器失败!" ); return false; } if( FAILED( hr = m_lpDDSPrimary->SetClipper( pcClipper ) ) ) { pcClipper->Release(); return false; } // Done with clipper pcClipper->Release(); m_bWindowed = true; } m_hWnd = hwnd; UpdateRect(); //创建特效页面: hr = CreateSurfaceHelp( m_lpDD, &m_lpDDSTemp, iW, iH, true, false, 0 ); if ( hr != DD_OK ) { return false; } //检测显示模式: DDPIXELFORMAT ddpf; ddpf.dwSize = sizeof( DDPIXELFORMAT ); hr = m_lpDDSPrimary->GetPixelFormat( &ddpf ); if ( hr != DD_OK ) { return false; } if ( ddpf.dwRGBBitCount != 16 ) { if ( Ask( "当前显示模式不是16位,将切换到全屏模式,是否继续" ) ) { Init( hwnd, false, iW, iH ); } else { return false; } } if ( ddpf.dwRBitMask == 0xf800 ) { m_DisplayFormat = R5G6B5; //565模式 } else if ( ddpf.dwRBitMask == 0x7c00 ) { m_DisplayFormat = R5G5B5; //555模式 } m_iWidth = iW; m_iHeight= iH; //获得GAMMA接口 hr = m_lpDDSPrimary->QueryInterface( IID_IDirectDrawGammaControl, (LPVOID *) &m_lpGammaControl ); if ( hr != DD_OK ) { return false; } m_pGammaData = new DDGAMMARAMP; if ( m_pGammaData == NULL ) return false; //获取字符的宽,高 HDC hdc; HFONT hFont; if ( m_lpDDSBack->GetDC( &hdc ) != DD_OK ) return false; hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); if ( hFont == NULL ) return false; SelectObject(hdc, hFont); TEXTMETRIC tm; GetTextMetrics(hdc, &tm); g_CharWidth = tm.tmAveCharWidth; g_CharHeight= tm.tmHeight + tm.tmExternalLeading + 2; m_lpDDSBack->ReleaseDC(hdc); bool ismmx = false; _asm { mov eax, 1; cpuid; test edx,00800000h; jz _no; mov ismmx, 1; _no: } m_IsMMX = ismmx; return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CEasyDraw::Free() { if ( m_lpDD != NULL ) { SafeRelease( m_lpGammaControl ); SafeDelete( m_pGammaData ); m_SurfaceList.Clear(); SafeRelease( m_lpDDSTemp ); SafeRelease( m_lpDDSBack ); SafeRelease( m_lpDDSPrimary ); m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ); m_lpDD->Release(); m_lpDD = NULL; m_hWnd = NULL; } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CSurface * CEasyDraw::NewSurface() { CSurface *surf = m_SurfaceList.CreateOneNode(); if ( surf != NULL ) surf->Init(); return surf; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CEasyDraw::DeleteSurface( CSurface *pSurf ) { if ( pSurf != NULL ) { m_SurfaceList.Delete( pSurf ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CEasyDraw::IsLost() { bool isLost = false; if ( m_lpDDSPrimary->IsLost() == DDERR_SURFACELOST ) { isLost = true; m_lpDDSPrimary->Restore(); DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof( DDSURFACEDESC2 ); if ( m_lpDDSPrimary->GetSurfaceDesc( &ddsd ) == DD_OK ) { m_iWidth = ddsd.dwWidth; m_iHeight = ddsd.dwHeight; } } if ( m_lpDDSBack->IsLost() == DDERR_SURFACELOST ) { isLost = true; m_lpDDSBack->Restore(); } if ( isLost ) { CList ::Iterator it; for ( it = m_SurfaceList.Begin(); it != m_SurfaceList.End(); ++it ) (*it).Restore(); } return isLost; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CEasyDraw::Present() { HRESULT hr; if( NULL == m_lpDDSPrimary && NULL == m_lpDDSBack ) return false; IsLost(); if( m_bWindowed ) hr = m_lpDDSPrimary->Blt( &m_rcWindow, m_lpDDSBack, NULL, 0, NULL ); //hr = m_lpDDSPrimary->BltFast( 0, 0, m_lpDDSBack, NULL, DDBLTFAST_WAIT ); else hr = m_lpDDSPrimary->Flip( NULL, 0 ); if ( hr != DD_OK ) return false; return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CEasyDraw::UpdateRect() { if( m_bWindowed ) { GetClientRect( m_hWnd, &m_rcWindow ); ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); } else { SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) ); } m_iHeight = m_rcWindow.bottom - m_rcWindow.top; m_iWidth = m_rcWindow.right - m_rcWindow.left; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CEasyDraw::SetDisplayRect( const RECT *pRect ) { if( m_bWindowed ) { //GetClientRect( m_hWnd, &m_rcWindow ); SetRect( &m_rcWindow, pRect->left, pRect->top, pRect->right, pRect->bottom ); ClientToScreen( m_hWnd, (POINT*)&m_rcWindow ); ClientToScreen( m_hWnd, (POINT*)&m_rcWindow+1 ); } else { SetRect( &m_rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) ); } m_iHeight = m_rcWindow.bottom - m_rcWindow.top; m_iWidth = m_rcWindow.right - m_rcWindow.left; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CEasyDraw::Clear( DWORD color ) { ClearSurfaceHelp( m_lpDDSBack, NULL, color ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CEasyDraw::LightenessControl( int iAdd ) { assert( m_lpGammaControl != NULL && m_pGammaData != NULL ); m_lpGammaControl->GetGammaRamp( 0, m_pGammaData ); //获取GAMMA int r = m_pGammaData->red[1] - m_pGammaData->red[0] + iAdd; int g = m_pGammaData->green[1] - m_pGammaData->green[0] + iAdd; int b = m_pGammaData->blue[1] - m_pGammaData->blue[0] + iAdd; if ( r < 0 ) r = 0; if ( g < 0 ) g = 0; if ( b < 0 ) b = 0; if ( r > 255 ) r = 255; if ( g > 255 ) g = 255; if ( b > 255 ) b = 255; for ( int i = 1; i < 256; ++i ) { m_pGammaData->red[i] = m_pGammaData->red[i-1] + r; m_pGammaData->green[i] = m_pGammaData->green[i-1] + g; m_pGammaData->blue[i] = m_pGammaData->blue[i-1] + b; } m_lpGammaControl->SetGammaRamp( 0, m_pGammaData ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CEasyDraw::ScreenShot( char *szDirectory ) { char sz[128]; ZeroMemory( sz, 128 ); if ( szDirectory != NULL ) { strcpy( sz, szDirectory ); } strcat( sz, "ScreenShot%d.bmp" ); FILE *fp; int i = 0; char buf[128]; wsprintf( buf, sz, i ); while ( ( fp = fopen(buf, "rb") ) != NULL && i < 255 ) { fclose(fp); wsprintf( buf, sz, i ); ++i; } return CopySurfaceToBmp16( m_lpDDSBack, buf, NULL, Is565() );; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// DWORD CEasyDraw::ChangeColorKey( DWORD colorkey ) { DWORD w = colorkey; if ( !Is565() ) { return CHANGE_565_TO_555( w ); } return w; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CSurface * CEasyDraw::CreateSurfaceEx( char *szFileName, int iWidth, int iHeight, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { CSurface *surf = NewSurface(); if ( surf != NULL ) { bool b; ColorKey = ChangeColorKey( ColorKey ); if ( szFileName != NULL ) { b = surf->CreateImageSurface( szFileName, isSysMemory, isColorKey, ColorKey ); } else { b = surf->CreateNullSurface( iWidth, iHeight, isSysMemory, isColorKey, ColorKey ); } if ( b == false ) { DeleteSurface( surf ); return NULL; } } return surf; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CSurface * CEasyDraw::CreateSurface( char *szFileName, bool isColorKey, DWORD ColorKey ) { return CreateSurfaceEx( szFileName, 0, 0, false, isColorKey, ColorKey ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CSurface * CEasyDraw::CreateSurfaceFromMemory( BYTE *pData, enum FILE_TYPE FileType, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { CSurface *surf = NewSurface(); if ( surf != NULL ) { bool b; ColorKey = ChangeColorKey( ColorKey ); switch ( FileType ) { case FT_ECP: b = ( surf->CreateEcpSurfaceFromMemory( pData, isSysMemory, 0 ) != 0 ); break; default: b = false; break; } if ( b == false ) { debug_assert( false ); DeleteSurface( surf ); return NULL; } } else assert( false ); return surf; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CSurface * CEasyDraw::CreateSurfaceFromEPG( FILE *fp, int offset, POINT *pPoint ) { CSurface *surf = NewSurface(); if ( surf != NULL ) { if ( surf->CreateEcpSurfaceHelp( fp, offset, pPoint, false ) == false ) { DeleteSurface( surf ); return NULL; } } return surf; } //-------------------------------------------------EasyDraw辅助函数------------------------------------------------------ ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CEasyDraw * InitEasyDraw( HWND hwnd, bool isWindowed, int iW, int iH ) { if ( theEasyDraw.Init( hwnd, isWindowed, iW, iH ) == false ) { return NULL; } return &theEasyDraw; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void FreeEasyDraw() { theEasyDraw.Free(); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CEasyDraw *GetEasyDrawPointer() { return &theEasyDraw; } //-------------------------------------------------EasyDraw应用函数------------------------------------------------------ ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void ClearSurfaceHelp( LPDIRECTDRAWSURFACE7 lpDDSurface, RECT *pRect, DWORD Color ) { DDBLTFX ddbltfx; ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = Color; lpDDSurface->Blt( pRect, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); } ////////////////////////////////////////////////////////////////////// //创建一个离屏页面 //参数:页面宽高,是否使用系统内存,是否有关键色 ////////////////////////////////////////////////////////////////////// HRESULT CreateSurfaceHelp( LPDIRECTDRAW7 lpdd, LPDIRECTDRAWSURFACE7 *ppSurface, int iW, int iH, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { if ( ppSurface == NULL ) return E_FAIL; LPDIRECTDRAWSURFACE7 lpDDSurface = NULL; DDSURFACEDESC2 ddsd; ZeroMemory( &ddsd, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; if ( isSysMemory ) ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; else ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; ddsd.dwWidth = iW; ddsd.dwHeight = iH; HRESULT hr; hr = lpdd->CreateSurface( &ddsd, &lpDDSurface, NULL ); if ( hr == DDERR_OUTOFVIDEOMEMORY ) //如果显存不足,将在内存中分配页面 { ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; hr = lpdd->CreateSurface( &ddsd, &lpDDSurface, NULL ); if ( hr != DD_OK ) return hr; else hr = DDERR_OUTOFVIDEOMEMORY; //如果在内存中分配成功,返回DDERR_OUTOFVIDEOMEMORY } //设置关键色 if ( isColorKey ) SetColorKeyHelp( lpDDSurface, ColorKey ); *ppSurface = lpDDSurface; return hr; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void SetColorKeyHelp( LPDIRECTDRAWSURFACE7 lpDDSurface, DWORD ColorKey) { DDCOLORKEY ddck; ddck.dwColorSpaceLowValue = ColorKey; ddck.dwColorSpaceHighValue = ColorKey; lpDDSurface->SetColorKey( DDCKEY_SRCBLT, &ddck ); } ////////////////////////////////////////////////////////////////////// //将一个位图载入到一个页面中 ////////////////////////////////////////////////////////////////////// LPDIRECTDRAWSURFACE7 LoadBmpToSurface( char *szFileName, LPDIRECTDRAWSURFACE7 lpDDSurface, int x, int y, bool isFromFile ) { if ( lpDDSurface == NULL ) return NULL; HBITMAP hBmp; //当一个资源 if ( isFromFile ) hBmp = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE ); else hBmp = (HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); if ( hBmp == NULL ) return NULL; return LoadBmpToSurfaceFromHBmp( hBmp, lpDDSurface, x, y ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// LPDIRECTDRAWSURFACE7 LoadBmpToSurfaceFromHBmp( HBITMAP hBmp, LPDIRECTDRAWSURFACE7 lpDDSurface, int x, int y ) { HDC hDCImage; HDC hDC; BITMAP bmp; DDSURFACEDESC2 ddsd; HRESULT hr; if( hBmp == NULL || lpDDSurface == NULL ) return NULL; if( FAILED( hr = lpDDSurface->Restore() ) ) return NULL; ddsd.dwSize = sizeof(ddsd); lpDDSurface->GetSurfaceDesc( &ddsd ); if( ddsd.ddpfPixelFormat.dwFlags == DDPF_FOURCC ) return NULL; hDCImage = CreateCompatibleDC( NULL ); if( NULL == hDCImage ) return NULL; SelectObject( hDCImage, hBmp ); GetObject( hBmp, sizeof(bmp), &bmp ); if( FAILED( hr = lpDDSurface->GetDC( &hDC ) ) ) return NULL; BitBlt(hDC, x, y, bmp.bmWidth, bmp.bmHeight, hDCImage, 0, 0, SRCCOPY ); if( FAILED( hr = lpDDSurface->ReleaseDC( hDC ) ) ) return NULL; DeleteDC( hDCImage ); //此处并没有DeleteObject( hBmp ) return lpDDSurface; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// HRESULT CreateSurfaceOfBmp( LPDIRECTDRAW7 lpdd, LPDIRECTDRAWSURFACE7 *ppSurface, char *szFileName, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { if ( ppSurface == NULL ) return E_FAIL; LPDIRECTDRAWSURFACE7 lpDDSurface = NULL; HBITMAP hBmp; hBmp = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE ); if ( hBmp == NULL ) return E_FAIL; BITMAP bmp; GetObject( hBmp, sizeof(bmp), &bmp ); HRESULT hr = CreateSurfaceHelp( lpdd, &lpDDSurface, bmp.bmWidth, bmp.bmHeight, isSysMemory, isColorKey, ColorKey ); if ( lpDDSurface == NULL ) return hr; if ( LoadBmpToSurfaceFromHBmp( hBmp, lpDDSurface, 0, 0 ) == NULL ) { SafeRelease( lpDDSurface ); return E_FAIL; } *ppSurface = lpDDSurface; return hr; } //------------------------------------------------ inline WORD Alpha_Pixel565(WORD sour, WORD dest ) { WORD rgbTemp; rgbTemp = ( ( sour >> 1 ) & 0x7bef ) + ( ( dest >> 1 ) & 0x7bef ) ; return rgbTemp; } //------------------------------------------------ inline WORD Alpha_Pixel555(WORD sour, WORD dest ) { WORD rgbTemp; rgbTemp = ( ( sour >> 1 ) & 0x3def ) + ( ( dest >> 1 ) & 0x3def ) ; return rgbTemp; } inline WORD Alpha_WindSoul_565( DWORD src, DWORD dest, DWORD alpha ) { src = ( src | ( src << 16 ) ) & 0x7e0f81f; dest= ( dest| ( dest<< 16 ) ) & 0x7e0f81f; DWORD result = ( ( ( src - dest ) * alpha / 32 ) + dest ) & 0x7e0f81f; return (WORD)(( result & 0xffff ) | ( result >> 16 )); } inline WORD Alpha_WindSoul_555( DWORD src, DWORD dest, DWORD alpha ) { src = ( src | ( src << 16 ) ) & 0x3E07C1F; dest= ( dest| ( dest<< 16 ) ) & 0x3E07C1F; DWORD result = ( ( ( src - dest ) * alpha / 32 ) + dest ) & 0x3E07C1F; return (WORD)(( result & 0xffff ) | ( result >> 16 )); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void AlphaSurfaceRect16( LPDIRECTDRAWSURFACE7 lpSourceSur, LPDIRECTDRAWSURFACE7 lpDestSur, RECT *rcSrc, RECT *rcDest, bool is565, bool isColorKey, WORD ColorKey, DWORD alpha ) { DDSURFACEDESC2 ddsd; WORD *lpSourceBuf; //指向源页面的指针 WORD *lpDestBuf; //目标页面指针 int iPitch; int iPitch2; DWORD iW = 0; DWORD iH = 0; DWORD i, j; ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 if ( lpSourceSur->Lock( rcSrc, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ) != DD_OK ) { lpDestSur->Unlock( NULL ); return; } lpSourceBuf = (WORD *)ddsd.lpSurface; //注意这里有个类型转换 iPitch = ddsd.lPitch >> 1; iW = ddsd.dwWidth; iH = ddsd.dwHeight; ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 if ( lpDestSur->Lock( rcDest, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) { return; } lpDestBuf = (WORD *)ddsd.lpSurface; //注意这里有个类型转换 iPitch2 = ddsd.lPitch >> 1; if ( ddsd.dwWidth < iW ) iW = ddsd.dwWidth; if ( ddsd.dwHeight < iH ) iH = ddsd.dwHeight; if ( isColorKey ) { WORD data; if ( is565 ) { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { data = lpDestBuf[ i * iPitch2 + j ]; if ( data != ColorKey ) lpDestBuf[ i * iPitch2 + j ] = Alpha_WindSoul_565( lpSourceBuf[ i * iPitch + j ], data, alpha );//Alpha_Pixel565( data, lpDestBuf[ i * iPitch2 + j ] ); } } } else { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { data = lpDestBuf[ i * iPitch2 + j ]; if ( data != ColorKey ) lpDestBuf[ i * iPitch2 + j ] = Alpha_WindSoul_555( lpSourceBuf[ i * iPitch + j ], data, alpha ); } } } } else { if ( is565 ) { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { WORD data = lpDestBuf[ i * iPitch2 + j ]; lpDestBuf[ i * iPitch2 + j ] = Alpha_WindSoul_565( lpSourceBuf[ i * iPitch + j ], data, alpha ); } } } else { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { WORD data = lpDestBuf[ i * iPitch2 + j ]; lpDestBuf[ i * iPitch2 + j ] = Alpha_WindSoul_555( lpSourceBuf[ i * iPitch + j ], data, alpha ); } } } } lpSourceSur->Unlock( NULL ); lpDestSur->Unlock( NULL ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void AlphaHalf16( LPDIRECTDRAWSURFACE7 lpSourceSur, LPDIRECTDRAWSURFACE7 lpDestSur, RECT *rcSrc, RECT *rcDest, bool is565, bool isColorKey, WORD ColorKey ) { DDSURFACEDESC2 ddsd; WORD *lpSourceBuf; //指向源页面的指针 WORD *lpDestBuf; //目标页面指针 int iPitch; int iPitch2; int iW = 0; int iH = 0; int i, j; ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 if ( lpSourceSur->Lock( rcSrc, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL ) != DD_OK ) { lpDestSur->Unlock( NULL ); return; } lpSourceBuf = (WORD *)ddsd.lpSurface; //注意这里有个类型转换 iPitch = ddsd.lPitch >> 1; iW = ddsd.dwWidth; iH = ddsd.dwHeight; ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 if ( lpDestSur->Lock( rcDest, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) { return; } lpDestBuf = (WORD *)ddsd.lpSurface; //注意这里有个类型转换 iPitch2 = ddsd.lPitch >> 1; if ( ddsd.dwWidth < iW ) iW = ddsd.dwWidth; if ( ddsd.dwHeight < iH ) iH = ddsd.dwHeight; if ( isColorKey ) { WORD data; if ( is565 ) { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { data = lpDestBuf[ i * iPitch2 + j ]; if ( data != ColorKey ) lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel565( lpSourceBuf[ i * iPitch + j ], data ); } } } else { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { data = lpDestBuf[ i * iPitch2 + j ]; if ( data != ColorKey ) lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel555( lpSourceBuf[ i * iPitch + j ], data ); } } } } else { if ( is565 ) { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { WORD data = lpDestBuf[ i * iPitch2 + j ]; lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel565( lpSourceBuf[ i * iPitch + j ], data ); } } } else { for ( i = 0; i < iH; i++ ) { for ( j = 0; j < iW; j++ ) { WORD data = lpDestBuf[ i * iPitch2 + j ]; lpDestBuf[ i * iPitch2 + j ] = Alpha_Pixel555( lpSourceBuf[ i * iPitch + j ], data ); } } } } lpSourceSur->Unlock( NULL ); lpDestSur->Unlock( NULL ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void DrawTextOnSurface( LPDIRECTDRAWSURFACE7 lpSurface, const char *szText, int TextLen, int x, int y, DWORD Color ) { HDC hDC; if ( lpSurface->GetDC( &hDC ) == DD_OK ) { //SetBkColor( hDCBack, NULL ); SetBkMode( hDC, TRANSPARENT ); //背景透明 SetTextColor( hDC, Color ); HFONT hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); SelectObject(hDC, hFont); TextOut( hDC, x, y, szText, TextLen ); lpSurface->ReleaseDC( hDC ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// LPDIRECTDRAWSURFACE7 LoadBmpFromMemory( BYTE *pData, LPDIRECTDRAW7 lpdd, LPDIRECTDRAWSURFACE7 lpDDSurface, RECT *pDestRect, bool isSysMemory ) { debug_assert( pData != NULL ); BITMAPFILEHEADER bmfh; //位图的文件头 BITMAPINFOHEADER bmih; //位图信息头 bmfh = READ_MEMORY( pData, BITMAPFILEHEADER); pData += sizeof(bmfh); //int offset = sizeof(bmfh); //memcpy( &bmfh, pData, sizeof(bmfh) ); //ReadMemory( (BYTE *)&bmih, pData, sizeof(bmih), offset ); //offset += sizeof(bmih); bmih = READ_MEMORY( pData, BITMAPINFOHEADER ); pData += sizeof(bmih); //计算补码 int byte = bmih.biBitCount / 8; int iResidue = (bmih.biWidth * byte) % 4; if ( iResidue != 0 ) iResidue = 4 - iResidue; if ( lpDDSurface == NULL ) { CreateSurfaceHelp( lpdd, &lpDDSurface, bmih.biWidth, bmih.biHeight, isSysMemory, false, 0 ); } //锁定页面: DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); WORD *buf16; int iW, iH, iPitch; if ( lpDDSurface->Lock( pDestRect, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) return NULL; buf16 = (WORD *)ddsd.lpSurface; iPitch = ddsd.lPitch >> 1; iW = ddsd.dwWidth; iH = ddsd.dwHeight; if ( iW < bmih.biWidth || iH < bmih.biHeight ) { lpDDSurface->Unlock( 0 ); return NULL; } //开始拷贝数据 bool is565 = GetEasyDrawPointer()->Is565(); //pData += bmfh.bfOffBits; //Show( bmfh.bfOffBits ); if ( bmih.biBitCount == 32 ) //32位图 { int data; int r, g, b; if ( is565 ) //565 { for ( int i = bmih.biHeight-1; i >= 0; --i ) { for ( int j = 0; j < bmih.biWidth; ++j ) { //ReadMemory( (BYTE *)&data, pData, 4, offset ); data = READ_MEMORY( pData, int ); pData += 4; r = GET_R_32( data ); g = GET_G_32( data ); b = GET_B_32( data ); buf16[ i * iPitch + j ] = RGBTO565( r, g, b ); } } } else { for ( int i = bmih.biHeight-1; i >= 0; --i ) { for ( int j = 0; j < bmih.biWidth; ++j ) { data = READ_MEMORY( pData, int ); pData += 4; r = GET_R_32( data ); g = GET_G_32( data ); b = GET_B_32( data ); buf16[ i * iPitch + j ] = RGBTO555( r, g, b ); } } } } else if ( bmih.biBitCount == 24 ) //24位图 { BYTE r, g, b; if ( is565 ) { for ( int i = bmih.biHeight - 1; i >= 0 ; --i ) { for ( int j = 0; j < bmih.biWidth; ++j ) { b = READ_MEMORY( pData, BYTE ); ++pData; g = READ_MEMORY( pData, BYTE ); ++pData; r = READ_MEMORY( pData, BYTE ); ++pData; buf16[ i * iPitch + j ] = RGBTO565( r, g, b ); } pData += iResidue; } } else { for ( int i = bmih.biHeight-1; i >= 0; --i ) { for ( int j = 0; j < bmih.biWidth; ++j ) { b = READ_MEMORY( pData, BYTE ); ++pData; g = READ_MEMORY( pData, BYTE ); ++pData; r = READ_MEMORY( pData, BYTE ); ++pData; buf16[ i * iPitch + j ] = RGBTO555( r, g, b ); } pData += iResidue; } } } else if ( bmih.biBitCount == 16 ) { bool isBmp565 = true; //判断位图是565还是555格式 if ( bmih.biCompression == BI_RGB ) isBmp565 = false; else { int mask; memcpy( &mask, pData, 4 ); pData += 12; if ( mask == 0x7c00 ) isBmp565 = false; } WORD data; if ( isBmp565 == is565 ) { for ( int i = iH - 1; i >= 0; --i ) { for ( int j = 0; j < iW; ++j ) { data = READ_MEMORY( pData, WORD ); buf16[ i * iPitch + j ] = data; pData += 2; } pData += iResidue; } } else if ( is565 && !isBmp565 ) { for ( int i = iH - 1; i >= 0; --i ) { for ( int j = 0; j < iW; ++j ) { data = READ_MEMORY( pData, WORD ); pData += 2; buf16[ i * iPitch + j ] = CHANGE_555_TO_565( data ); } pData += iResidue; } } else if ( !is565 && isBmp565 ) { for ( int i = iH - 1; i >= 0; --i ) { for ( int j = 0; j < iW; ++j ) { data = READ_MEMORY( pData, WORD ); buf16[ i * iPitch + j ] = CHANGE_565_TO_555( data ); pData += 2; } pData += iResidue; } } } else { return NULL; } lpDDSurface->Unlock( 0 ); return lpDDSurface; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// WORD RGB_To_565( int r, int g, int b ) { return WORD( ((r%32) << 11) + ((g%64) << 5 ) + (b%32) ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// WORD RGB_To_555( int r, int g, int b ) { return WORD( ((r%32) << 10) + ((g%32) << 5 ) + (b%32) ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CopySurfaceToBmp16( LPDIRECTDRAWSURFACE7 lpDDSurface, char *szFileName, RECT *pRect, bool is565 ) { debug_assert( lpDDSurface != NULL && szFileName != NULL ); DDSURFACEDESC2 ddsd; WORD *lpBuffer; //指向页面的指针 int iPitch; int iResidue = 0; //补上的可以被4整除的数,单位字节 int iW = 0; int iH = 0; BITMAPFILEHEADER bmfh; //位图的文件头 BITMAPINFOHEADER bmih; //位图信息头 DWORD dwRMask = 0xf800; //565的遮码 DWORD dwGMask = 0x07e0; DWORD dwBMask = 0x001f; if ( !is565 ) //如果显示模式不是565的话 { dwRMask = 0x7c00; dwGMask = 0x03e0; } FILE *fp = fopen( szFileName, "wb+" ); if ( fp == NULL ) return false; //锁定主页面: ddsd.dwSize = sizeof(ddsd); //这句话不要少了,否则就LOCK不了 if ( lpDDSurface->Lock( pRect, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_READONLY | DDLOCK_WAIT, NULL ) != DD_OK ) { fclose(fp); return false; } lpBuffer = (WORD *)ddsd.lpSurface; //注意这里有个类型转换 iPitch = ddsd.lPitch >> 1; if ( pRect == NULL ) { iW = ddsd.dwWidth; iH = ddsd.dwHeight; } else { iW = pRect->right - pRect->left; iH = pRect->bottom- pRect->top; } iResidue = (iW % 2) * 2; //计算出补数 //写入文件头: bmfh.bfType = 'MB'; //注意这里是MB,而不是BM bmfh.bfSize = 0x36 + 12 + ( iW + iResidue / 2 ) * iH * 2; bmfh.bfOffBits = 0x36 + 12; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; fwrite( &bmfh, sizeof(bmfh), 1, fp ); //写入信息头: bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = iW; bmih.biHeight = iH; bmih.biPlanes = 1; bmih.biBitCount = 16; bmih.biCompression = BI_BITFIELDS; //16位的565格式,若为其它格式,图像失真 bmih.biSizeImage = ( iW + iResidue / 2 ) * iH * 2; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; fwrite( &bmih, sizeof(bmih), 1, fp ); fwrite( &dwRMask, 4, 1, fp ); fwrite( &dwGMask, 4, 1, fp ); fwrite( &dwBMask, 4, 1, fp ); //写入遮码 //开始写入数据: fseek( fp, 0x36+12, SEEK_SET ); for ( int i = iH - 1; i >= 0; i-- ) //i为高 { for ( int j = 0; j < iW; j++ ) //j为宽 { WORD word = lpBuffer[ i * iPitch + j ]; fwrite( &word, 2, 1, fp ); } fseek( fp, iResidue, SEEK_CUR ); //跳过补数部份 } lpDDSurface->Unlock( NULL ); fclose(fp); return true; } /* //-------------------------------------------------------载入JPEG图片----------------------------------------------- #define RGB555(r, g, b) ((r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10)) #define RGB565(r, g, b) ((r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11)) //16Bit Color Formats #define PF_555 1 #define PF_565 2 //Color modes const int C16BIT = 16; const int C24BIT = 24; #define C32BIT 32 ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// HRESULT LoadJpegHelp( LPDIRECTDRAW7 lpdd, LPDIRECTDRAWSURFACE7 *ppSurface, \ char *szFileName, LPDIRECTDRAWSURFACE7 surf, \ bool isSysMemory, \ bool isColorKey, \ DWORD ColorKey, \ bool is565 ) { if ( ppSurface == NULL ) return E_FAIL; //Error handle IJLERR jerr; int nPixelFormat = PF_555; //Create the JPEG object JPEG_CORE_PROPERTIES jcprops; //Get green bitmask and set pixel format if( is565 ) nPixelFormat = PF_565; else nPixelFormat = PF_555; //Initialize the JPEG object jerr = ijlInit(&jcprops); if (jerr != IJL_OK) return E_FAIL; //Set the IJL data source as a filename jcprops.JPGFile = szFileName; //Read JPEG parameters from the file jerr = ijlRead(&jcprops, IJL_JFILE_READPARAMS); //Make sure Parameter read was successful if (jerr != IJL_OK) return E_FAIL; //Set up the DIB specification for the JPEG decoder jcprops.DIBWidth = jcprops.JPGWidth; jcprops.DIBHeight = jcprops.JPGHeight; //Implies a bottom-up DIB. jcprops.DIBChannels = 3; jcprops.DIBColor = IJL_BGR; jcprops.DIBPadBytes = 0; //IJL_DIB_PAD_BYTES(jcprops.JPGWidth,3); //jcprops.DIBHeight = -jcprops.JPGHeight; //Set the JPG color space ... this will always be somewhat of an //educated guess at best because JPEG is "color blind" (i.e., //nothing in the bit stream tells you what color space the data was //encoded from. However, in this example we assume that we are //reading JFIF files which means that 3 channel images are in the //YCbCr color space and 1 channel images are in the Y color space. switch(jcprops.JPGChannels) { case 1: jcprops.JPGColor = IJL_G; break; case 3: jcprops.JPGColor = IJL_YCBCR; break; default: //This catches everything else, but no color twist will be //performed by the IJL. jcprops.DIBColor = (IJL_COLOR)IJL_OTHER; jcprops.JPGColor = (IJL_COLOR)IJL_OTHER; break; } //Prepare a 24Bit buffer to receive image data BYTE *buffer24; //Determine the required size long szbuff24 = jcprops.DIBWidth * 3 * jcprops.DIBHeight; //Resize the buffer buffer24 = new BYTE [szbuff24]; if (buffer24 == NULL) return E_FAIL; //Read JPEG image data into our 24bit buffer jcprops.DIBBytes = reinterpret_cast (buffer24); jerr = ijlRead(&jcprops, IJL_JFILE_READWHOLEIMAGE); //Make sure the read was successful if (jerr != IJL_OK) return E_FAIL; HBITMAP hbm = NULL; //Convert to current CLRMODE //Create a 16bit buffer WORD *buffer16; long szbuff16; //determine the size of our buffer szbuff16 = jcprops.DIBWidth * 2 * jcprops.DIBHeight; //resize the buffer and make sure resize works buffer16 = new WORD [szbuff16]; if (buffer16 == NULL) return E_FAIL; //Start at the beginning of the buffer //Step through the 24bit buffer //Retrieve 3 channels at a time and convert their values to 16bit //Check the pixel format and write the color data //to the 16bit buffer. After the write, advance the //16bit buffer by one. long j = 0; if ( nPixelFormat == PF_555 ) { for (long i = 0; i < szbuff24; i += 3) { buffer16[j++] = RGB555(buffer24[i], buffer24[i + 1], buffer24[i + 2]); } } else { for (long i = 0; i < szbuff24; i += 3) { buffer16[j++] = RGB565(buffer24[i], buffer24[i + 1], buffer24[i + 2]); } } //Create the bitmap using the new 16bit buffer hbm = CreateBitmap (jcprops.JPGWidth, jcprops.JPGHeight, 1, C16BIT, buffer16); if(hbm == NULL) return NULL; //remove the new buffer delete [] buffer16; //remove the old buffer delete [] buffer24; ijlFree(&jcprops); //If DirectDraw Surface is NULL, create it HRESULT hr; if ( *ppSurface == NULL ) { hr = CreateSurfaceHelp( lpdd, ppSurface, jcprops.JPGWidth, jcprops.JPGHeight, isSysMemory, isColorKey, ColorKey ); if ( *ppSurface == NULL ) return hr; } //Copy bitmap data to DirectDraw Surface if ( LoadBmpToSurfaceFromHBmp( hbm, *ppSurface, 0, 0 ) == NULL ) { SafeRelease( *ppSurface ); return E_FAIL; } // clean up and destroy the JPEG Decompressor DeleteObject(hbm); return hr; }*/