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

📄 core_graphics.cpp

📁 旋转图像Demo和其源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
					fputc( p[1], fp);	// g
					fputc( p[2], fp);	// r
					if( j==m_iWidth-1 && i==0 )
						break;
					p += 4;
				}
				if( i==0 )
					p -= (ddsd.lPitch<<1)-(iPitch<<2) - 4;
				else
					p -= (ddsd.lPitch<<1)-(iPitch<<2);
			}
		}
		else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
		{
			int iPitch = ((2-ddsd.dwWidth&1)&1);
			p += (m_iHeight - 1) * ddsd.lPitch;
			for(int i=0; i<m_iHeight; i++)
			{
				for(int j=0; j<m_iWidth; j++)
				{
					fputc( g_pDirectDraw->GetB(p[0]),       fp);    // b
					fputc( g_pDirectDraw->GetG(p[0],p[1]),  fp);	// g
					fputc( g_pDirectDraw->GetR(p[1]),       fp);    // r
					if( j==m_iWidth-1 && i==0 )
						break;
					p += 2;
				}
				if( i==0 )
					p -= (ddsd.lPitch<<1)-(iPitch<<1) - 2;
				else
					p -= (ddsd.lPitch<<1)-(iPitch<<1);	// 指针转到上一行的开始
			}
		}

		fclose(fp);
	}
	m_lpDDS->Unlock( NULL );
	return TRUE;
}

void cGraphics::Release()
{
	//SAFE_RELEASE( m_lpDDS );
	if( m_lpDDS )
	{
		m_lpDDS->Release();
		m_lpDDS = NULL;
	}
}

void cGraphics::Lock(void** pSurface, int* lPitch )
{
	DDSURFACEDESC2 ddsd;
	memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
	ddsd.dwSize = sizeof(DDSURFACEDESC2);
	m_lpDDS->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
	*pSurface = ddsd.lpSurface;
	*lPitch   = ddsd.lPitch;
}

void cGraphics::Unlock()
{
	m_lpDDS->Unlock( NULL );
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
cDirectDraw::cDirectDraw()
{
	g_pDirectDraw = this;
	m_lpDD      = NULL;
	m_hWnd      = NULL;
	m_iHeight   = 600;
	m_iWidth    = 800;
	m_lpDDS_Prim = NULL;
	m_lpDDS_Back = NULL;
}

cDirectDraw::~cDirectDraw()
{
	Release();
}


BOOL cDirectDraw::Create( HWND hWnd, HINSTANCE hInst, BOOL bFullScreen, int iWidth, int iHeight )
{
	m_lpDD    = NULL;
	m_hWnd    = hWnd;
	m_iWidth  = iWidth;
	m_iHeight = iHeight;

	m_bExclusive = bFullScreen;
	HRESULT hr;
	//Create DirectDraw
	hr = DirectDrawCreateEx( NULL, (void**)&m_lpDD, IID_IDirectDraw7, NULL );
	if( hr == DDERR_INVALIDDIRECTDRAWGUID )
	{
		MessageBox( GetActiveWindow(), _T("需要DirectX7.0版本,请升级你DirectX到7.0版!"), _T("ERROR Info"), MB_OK );
		exit(0);
		return FALSE;
	}
	if( hr != DD_OK )
		return FALSE;
	//Set Cooperative Level
	if( m_bExclusive )
		hr = m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_FULLSCREEN|DDSCL_EXCLUSIVE);
	else
		hr = m_lpDD->SetCooperativeLevel( NULL, DDSCL_NORMAL );//m_hWnd is better than NULL
	//Set Display Mode
	if( m_bExclusive )
		SetDisplayMode( m_iWidth, m_iHeight );
	//Create Prim Surface
	DDSURFACEDESC2 ddsd;
	memset(&ddsd,0,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS;
	//看网上的一篇文章,说这需要改成ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
	//原因:2D情况下,表面的渲染是由CPU而不是显卡来完成的!当然没有直接操纵系统内存快。
	//ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_SYSTEMMEMORY; //faster in Exclusive Mode
	if( m_bExclusive )
	{
		ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP|DDSCAPS_COMPLEX;
		ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
		ddsd.dwBackBufferCount=1;
	}
	hr = m_lpDD->CreateSurface( &ddsd, (LPDIRECTDRAWSURFACE7*)(&m_lpDDS_Prim), NULL );
	if( hr != DD_OK )
		return FALSE;
	if( !m_bExclusive )
	{
		LPDIRECTDRAWCLIPPER pcClipper;
		hr = m_lpDD->CreateClipper( 0, &pcClipper, NULL );
		if(hr != DD_OK)
			return FALSE;
		hr = pcClipper->SetHWnd( 0, m_hWnd );
		if(hr != DD_OK)
			return FALSE;
		//hr = m_lpDDS->SetClipper(pcClipper);
		hr = m_lpDDS_Prim->SetClipper( pcClipper );
		if(hr != DD_OK)
			return FALSE;
		pcClipper->Release();
	}
	//Create Back Surface
	if( m_bExclusive )
	{
		DDSCAPS2 dds;
		memset(&dds,0,sizeof(dds));
		dds.dwCaps = DDSCAPS_BACKBUFFER;
		hr = m_lpDDS_Prim->GetAttachedSurface( &dds, (LPDIRECTDRAWSURFACE7*)(&m_lpDDS_Back) );
		if( hr != DD_OK)
			return FALSE;
	}
	else
	{
		memset(&ddsd,0,sizeof(ddsd));
		ddsd.dwSize           = sizeof(ddsd);
		ddsd.dwFlags          = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT;
		ddsd.ddsCaps.dwCaps   = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
		ddsd.dwHeight         = m_iHeight;
		ddsd.dwWidth          = m_iWidth;
		hr = m_lpDD->CreateSurface( &ddsd, (LPDIRECTDRAWSURFACE7*)&m_lpDDS_Back, NULL );
		if( hr != DD_OK )
			return FALSE;
	}
	//Create Input Device
	//如果执行到这,而此时程序窗口不是active状态时,创建失败
	m_bInputSucc = TRUE;
	if( !m_input.Init( m_hWnd, hInst ) )//m_hWnd -> GetActiveWindow()
	{
		//DebugMB( _T( "Input Device Init Failed !" ) );
		m_bInputSucc = FALSE;
	}
	if( !m_keyboardDev.Create( &m_input, KEYBOARD, TRUE ) )
	{
		//DebugMB( _T( "Keyboard Device Init Failed !" ) );
		m_bInputSucc = FALSE;
	}
	if( !m_mouseDev.Create( &m_input, MOUSE, TRUE ) )
	{
		//DebugMB( _T( "Mouse Device Init Failed !" ) );
		m_bInputSucc = FALSE;
	}
	//Create Music here:
	//......
	//m_sound.Init( GethWnd() );
	//m_musicChannel.Create( &m_sound );
	return TRUE;
}


BOOL cDirectDraw::LoadToBackSurface( cGraphics* offScreenGraphics, int left, int top, LPRECT srcRect/* =NULL  */)
{
	if( offScreenGraphics == NULL || offScreenGraphics->GetSurface() == NULL )
		return FALSE;
	LPRECT pRect = srcRect;
	if( pRect == NULL )
	{
		pRect = new RECT;
		DDSURFACEDESC2 ddsd;
		memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
		ddsd.dwSize = sizeof(DDSURFACEDESC2);
		offScreenGraphics->GetSurface()->GetSurfaceDesc( &ddsd );
		pRect->left = 0;
		pRect->top  = 0;
		pRect->right = ddsd.dwWidth;
		pRect->bottom = ddsd.dwHeight;
	}
	//在此进行矩形的合理性判断
	if( left >= m_iWidth || top >= m_iHeight )
		return FALSE;
	if( left < 0 )
	{
		pRect->left -= left;
		left = 0;
	}
	if( top < 0 )
	{
		pRect->top  -= top;
		top = 0;
	}
	if( left + pRect->right-pRect->left - m_iWidth >= 0 )
		pRect->right = m_iWidth - left;
	if( top + pRect->bottom - pRect->top - m_iHeight >= 0 )
		pRect->bottom = m_iHeight-top;
	if( pRect->right - pRect->left <= 0 )
		return FALSE;
	if( pRect->bottom - pRect->top <= 0 )
		return FALSE;
	//在这里进行改进,判断是否ColorKey.
	HRESULT hr;
	if( offScreenGraphics->m_bColorKey )
	{
		hr = m_lpDDS_Back->BltFast( left, top, offScreenGraphics->GetSurface(), pRect, DDBLTFAST_WAIT|DDBLTFAST_SRCCOLORKEY );
	}
	else
	{
		hr = m_lpDDS_Back->BltFast( left, top, offScreenGraphics->GetSurface(), pRect, DDBLTFAST_WAIT );
	}
	switch( hr )
	{
	case DDERR_SURFACELOST:
		return FALSE;
		break;

	case DDERR_SURFACEBUSY:
		return FALSE;
		break;

	case DDERR_INVALIDOBJECT:
		return FALSE;
		break;

	case DDERR_INVALIDRECT:
		return FALSE;
		break;

	case DDERR_EXCEPTION:
		return FALSE;
		break;

	case DDERR_UNSUPPORTED:
		return FALSE;
		break;
	case DDERR_GENERIC:
		return FALSE;
		break;
	case DDERR_NOBLTHW:
		return FALSE;
		break;

	default:break;
	}
	//BOOL bSucc = LoadToBackSurface( offScreenGraphics->GetSurface(), left, top, pRect );
	if( srcRect == NULL )
		SAFE_DELETE( pRect );
	if( DD_OK == hr )
		return TRUE;
	return FALSE;
}

BOOL cDirectDraw::LoadToBackSurface( cGraphics* offScreenGraphics, int left, int top, int height, int width )
{
	RECT rcSrc;
	rcSrc.left = left;
	rcSrc.top  = top;
	rcSrc.right = rcSrc.left + width;
	rcSrc.bottom = rcSrc.top + height;
	return LoadToBackSurface( offScreenGraphics, left, top, &rcSrc );
}

BOOL cDirectDraw::DrawAlpha( cGraphics* offScreenGraphics, int left, int top, LPRECT srcRect )
{
	//在此进行矩形的合理性判断
	if( left >= m_iWidth || top >= m_iHeight )
		return FALSE;
	if( left < 0 )
	{
		srcRect->left  -= left;
		srcRect->right -= left;
		left = 0;
	}
	if( top < 0 )
	{
		srcRect->top    -= top;
		srcRect->bottom -= top;
		top = 0;
	}
	if( srcRect->right - srcRect->left - m_iWidth >= 0 )
	{
		srcRect->right -= srcRect->right - srcRect->left - m_iWidth;
	}
	if( srcRect->bottom - srcRect->top - m_iHeight > 0 )
	{
		srcRect->bottom -= srcRect->bottom - srcRect->top - m_iHeight;
	}
	if( srcRect->right - srcRect->left <= 0 )
		return FALSE;
	if( srcRect->bottom - srcRect->top <= 0 )
		return FALSE;

	COLORREF gdiColorKey = RGB2GDIColor( offScreenGraphics->m_clrKey );
	BYTE rKey = GetRValue(gdiColorKey);
	BYTE gKey = GetGValue(gdiColorKey);
	BYTE bKey = GetBValue(gdiColorKey);

	DDSURFACEDESC2 ddsd;
	memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
	ddsd.dwSize = sizeof(DDSURFACEDESC2);
	m_lpDDS_Back->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
	BYTE* pBack = (BYTE*)ddsd.lpSurface;
	BYTE* p     = (BYTE*)ddsd.lpSurface;

	DDSURFACEDESC2 ddsd2;
	memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
	ddsd2.dwSize = sizeof(DDSURFACEDESC2);
	offScreenGraphics->GetSurface()->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
	BYTE* pOff = (BYTE*)ddsd2.lpSurface;
	BYTE* p2   = (BYTE*)ddsd2.lpSurface;

	int pos1 = 0;
	int pos2 = 0;
	int t1=0,t2=0;
	//move to the currect line
	t1 = srcRect->top*ddsd2.lPitch;
	t2 = top*ddsd.lPitch;

	//32位色
	if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
	{
		//有透明色
		if( offScreenGraphics->m_bColorKey )
		{

			for( int y=srcRect->top; y<srcRect->bottom; y++ )
			{
				pos1 = t1 + (srcRect->left<<2);
				pos2 = t2 +(left<<2);
				for( int x=srcRect->left; x<srcRect->right; x++ )
				{
					if( pOff[pos1] != bKey && pOff[pos1+1] != gKey && pOff[pos1+2] != rKey )//color key
					{
						pBack[pos2]   = ( pBack[pos2]   + pOff[pos1] )>>1;
						pBack[pos2+1] = ( pBack[pos2+1] + pOff[pos1+1] )>>1;
						pBack[pos2+2] = ( pBack[pos2+2] + pOff[pos1+2] )>>1;
					}
					pos1 += 4;//next pixel
					pos2 += 4;
				}
				t1 += ddsd2.lPitch;//next line
				t2 += ddsd.lPitch;
			}
		}
		//无透明色
		else
		{
			for( int y=srcRect->top; y<srcRect->bottom; y++ )
			{
				pos1 = t1 + (srcRect->left<<2);
				pos2 = t2 +(left<<2);
				for( int x=srcRect->left; x<srcRect->right; x++ )
				{
					pBack[pos2]   = ( pBack[pos2]   + pOff[pos1] )>>1;
					pBack[pos2+1] = ( pBack[pos2+1] + pOff[pos1+1] )>>1;
					pBack[pos2+2] = ( pBack[pos2+2] + pOff[pos1+2] )>>1;
					pos1 += 4;//next pixel
					pos2 += 4;
				}
				t1 += ddsd2.lPitch;//next line
				t2 += ddsd.lPitch;
			}
		}
	}

	//16位色
	else if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
	{
	}

	offScreenGraphics->GetSurface()->Unlock( NULL );
	m_lpDDS_Back->Unlock( NULL );
	return TRUE;
}

BOOL cDirectDraw::DrawAlpha(cGraphics* offScreenGraphics, int left, int top )
{
	LPRECT pRect = new RECT;
	DDSURFACEDESC2 ddsd;
	memset( &ddsd, 0, sizeof(DDSURFACEDESC2) );
	ddsd.dwSize = sizeof(DDSURFACEDESC2);
	offScreenGraphics->GetSurface()->GetSurfaceDesc( &ddsd );
	pRect->left = 0;
	pRect->top  = 0;
	pRect->right = ddsd.dwWidth;
	pRect->bottom = ddsd.dwHeight;
	DrawAlpha( offScreenGraphics, left, top, pRect );
	SAFE_DELETE( pRect );
	return TRUE;
}


cGraphics* cDirectDraw::RotateImage( cGraphics** ppGrDest, cGraphics* pGrSrc, float arcAngle, COLORREF clrKey, BOOL bIsColorKey, int mode/* = 1*/ )
{
	assert( pGrSrc != NULL );
	/*Lock Source Surface*/
	DDSURFACEDESC2 ddsdSrc;
	memset( &ddsdSrc, 0, sizeof(DDSURFACEDESC2) );
	ddsdSrc.dwSize = sizeof(DDSURFACEDESC2);
	pGrSrc->GetSurface()->Lock( NULL, &ddsdSrc, DDLOCK_WAIT, NULL );

	float cosA = cos( arcAngle );
	float sinA = sin( arcAngle );
	int   H    = ddsdSrc.dwHeight;
	int   W    = ddsdSrc.dwWidth;
	/*
	以源图的中心为圆心旋转
	srcX  = yDest*sin + xDest*cos;
	srcY  = yDest*cos - xDest*sin;
	destX = xSrc*cos  - ySrc*sin;
	destY = xSrc*sin  + ySrc*cos;
	源图上对角线上的点旋转后的新坐标的X差和Y差即是新图的高和宽
	有2对可能的值
	*/
	int   h1   = abs( (int)( H*cosA - W*sinA ) );
	int   w1   = abs( (int)( H*sinA - W*cosA ) );
	int   h2   = abs( (int)( H*cosA + W*sinA ) );
	int   w2   = abs( (int)( H*sinA + W*cosA ) );
	/*计算新图的高和宽*/
	int   h,w;
	if( h1 > h2 )
	{
		h = h1;
		w = w1;
	}
	else
	{
		h = h2;
		w = w2;
	}
	/*旋转圆心*/
	int x1 = W>>1;//源图
	int y1 = H>>1;
	int x2 = w>>1;//新图
	int y2 = h>>1;

	/*Rotate*/
	cGraphics* pGrDest = NULL;
	if( ppGrDest == NULL )
	{
		pGrDest = new cGraphics( w, h );
	}
	else
	{
		pGrDest = *ppGrDest;
		//Reset Image Size
		DDSURFACEDESC2 ddsdDest;
		memset( &ddsdDest, 0, sizeof(DDSURFACEDESC2) );
		ddsdDest.dwSize = sizeof(DDSURFACEDESC2);
		pGrDest->GetSurface()->GetSurfaceDesc( &ddsdDest );
		ddsdDest.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT;
		ddsdDest.dwHeight = h;
		ddsdDest.dwWidth  = w;
		HRESULT hr = pGrDest->GetSurface()->SetSurfaceDesc( &ddsdDest, 0 );
		/* return DDERR_INVALIDPARAMS
		so let ppGrDest be NULL when use this function */
		/* 这里执行失败,暂时还没有解决这个Bug */
		int errCode = 0;
		switch( hr )
		{
		case DDERR_INVALIDPARAMS:
			errCode = 1;
			break;
		case DDERR_INVALIDOBJECT:
			errCode = 2;
			break;
		case DDERR_SURFACELOST:
			errCode = 3;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -