bool DibCopyRectROP( LPBYTE lpDstDib, int dstx, int dsty, LPBYTE lpSrcDib, LPRECT prSrc1, DWORD dwROP ) { if ( !lpDstDib || !lpSrcDib || DIB_BPP( lpDstDib ) != DIB_BPP( lpSrcDib ) ) return false; RECT rDst, rDst1, rDst2, rSrc2, rSrc; SetRect( &rSrc2, 0, 0, DIB_CX( lpSrcDib ), DIB_CY( lpSrcDib ) ); IntersectRect( &rSrc, prSrc1, &rSrc2 ); SetRect( &rDst1, 0, 0, rSrc.right - rSrc.left, rSrc.bottom - rSrc.top ); OffsetRect( &rDst1, dstx, dsty ); SetRect( &rDst2, 0, 0, DIB_CX( lpDstDib ), DIB_CY( lpDstDib ) ); IntersectRect( &rDst, &rDst1, &rDst2 ); LPBYTE lpSrc, lpDst; int y, i, nWidth = (rDst.right - rDst.left) * DIB_BPP( lpSrcDib ) / 8; for ( y = rDst.top; y < rDst.bottom; y++ ) { lpSrc = DIB_DATAXY_INV( lpSrcDib, rSrc.left, rSrc.top + y - rDst.top ); lpDst = DIB_DATAXY_INV( lpDstDib, rDst.left, y ); switch ( dwROP ) { case SRCAND: for ( i = 0; i < nWidth; i++ ) { *lpDst = *lpDst & *lpSrc; lpDst++; lpSrc++; } break; case SRCPAINT: for ( i = 0; i < nWidth; i++ ) { *lpDst = *lpDst | *lpSrc; lpDst++; lpSrc++; } break; case SRCCOPY: memcpy( lpDst, lpSrc, nWidth ); break; default: break; } } return true; }
/// BMP파일을 열어서 높이맵을 생성한다. HRESULT ZTerrain::_BuildHeightMap( LPSTR lpFilename ) { LPBYTE pDIB = DibLoadHandle( lpFilename ); if( !pDIB ) return E_FAIL; m_cxDIB = DIB_CX( pDIB ); m_czDIB = DIB_CY( pDIB ); // 여기서 m_cxDIB나 m_czDIB가 (2^n+1)이 아닌경우 E_FAIL을 반환하도록 수정할 것 m_pvHeightMap = new TERRAINVERTEX[m_cxDIB * m_czDIB]; TERRAINVERTEX v; for( int z = 0 ; z < m_czDIB ; z++ ) { for( int x = 0 ; x < m_cxDIB ; x++ ) { v.p.x = (float)( ( x - m_cxDIB / 2 ) * m_vfScale.x ); v.p.z = -(float)( ( z - m_czDIB / 2 ) * m_vfScale.z ); v.p.y = (float)( *( DIB_DATAXY_INV( pDIB, x, z ) ) ) * m_vfScale.y; D3DXVec3Normalize( &v.n, &v.p ); v.t.x = (float)x / (float)( m_cxDIB - 1 ); v.t.y = (float)z / (float)( m_czDIB - 1 ); m_pvHeightMap[x + z * m_czDIB] = v; } } DibDeleteHandle( pDIB ); return S_OK; }
LPBYTE DibGRAY2RGBHandle(LPBYTE lpGrayDib){ LPBYTE lpRgbDib, lpSrc, lpDst; int cx, cy; if(!lpGrayDib || DIB_BPP(lpGrayDib) != 8) return NULL; cx = DIB_CX(lpGrayDib); cy = DIB_CY(lpGrayDib); if(!(lpRgbDib = DibCreateEmptyHandle(24, cx, cy))) return NULL; for(int y = 0; y < cy; y++){ lpSrc = DIB_DATA8XY(lpGrayDib, 0, y); lpDst = DIB_DATA24XY(lpRgbDib, 0, y); for(int x = 0; x < cx; x++){ *lpDst++ = *lpSrc; *lpDst++ = *lpSrc; *lpDst++ = *lpSrc; lpSrc++; } } return lpRgbDib; }
LPBYTE DibRGB2GRAYHandle( LPBYTE lpRgbDib ) { LPBYTE lpGrayDib, lpSrc, lpDst; int x, y, cx, cy; if ( !lpRgbDib || DIB_BPP( lpRgbDib ) != 24 ) return NULL; cx = DIB_CX( lpRgbDib ); cy = DIB_CY( lpRgbDib ); if ( !(lpGrayDib = DibCreateEmptyHandle( 8, cx, cy )) ) return NULL; for ( y = 0; y < cy; y++ ) { lpSrc = DIB_DATA24XY( lpRgbDib, 0, y ); lpDst = DIB_DATA8XY( lpGrayDib, 0, y ); for ( x = 0; x < cx; x++ ) { *lpDst++ = (*lpSrc + *(lpSrc+1) + *(lpSrc+2))/3; lpSrc += 3; } } return lpGrayDib; }
LPBYTE DibReverseHandle( LPBYTE lpDib ) { if ( !lpDib ) return NULL; LPBYTE lpNewDib, lpNewData, lpData; int x, y; lpNewDib = (LPBYTE) GlobalLock( DibCreateEmptyHandle( DIB_BPP( lpDib ), DIB_CX( lpDib ), DIB_CY( lpDib ) ) ); if ( lpNewDib ) { for ( y = 0; y < DIB_CY( lpDib ); y++ ) { lpData = DIB_DATAXY( lpDib, 0, y ); lpNewData = DIB_DATAXY( lpNewDib, DIB_CX( lpNewDib ) - 1, y ); if ( DIB_BPP( lpDib ) == 8 ) { for ( x = 0; x < DIB_CX( lpDib ); x++ ) *lpNewData-- = *lpData++; } else if ( DIB_BPP( lpDib ) == 24 ) { for ( x = 0; x < DIB_CX( lpDib ); x++ ) { *lpNewData = *lpData++; *(lpNewData + 1) = *lpData++; *(lpNewData + 2) = *lpData++; lpNewData -= 3; } } } } return lpNewDib; }
LPBYTE DibReduce( LPBYTE lpSrcDib, int newCx, int newCy ) { LPBYTE lpDstDib, lpSrc, lpDst, lpTemp; float fXratio, fYratio; int x, y, cx, cy, nBps; if ( !lpSrcDib || newCx <= 0 || newCy <= 0 ) return NULL; cx = DIB_CX( lpSrcDib ); cy = DIB_CY( lpSrcDib ); nBps = DIB_BPP( lpSrcDib ); if ( nBps != 24 && nBps != 8 ) return NULL; fXratio = (float)cx / newCx; fYratio = (float)cy / newCy; if ( (lpDstDib = DibCreateEmpty( nBps, newCx, newCy )) == NULL ) return NULL; if ( nBps == 8 ) { for ( y = 0; y < newCy; y++ ) { lpSrc = DIB_ALPHAXY( lpSrcDib, 0, ((int)(y * fYratio)) ); lpDst = DIB_ALPHAXY( lpDstDib, 0, y ); for ( x = 0; x < newCx; x++ ) *lpDst++ = *(lpSrc + (int)(x * fXratio)); } } else if ( nBps == 24 ) { for ( y = 0; y < newCy; y++ ) { lpSrc = DIB_IMAGEXY( lpSrcDib, 0, ((int)(y * fYratio)) ); lpDst = DIB_IMAGEXY( lpDstDib, 0, y ); for ( x = 0; x < newCx; x++ ) { lpTemp = lpSrc + (int)(x * fXratio) * 3; *lpDst++ = *lpTemp++; *lpDst++ = *lpTemp++; *lpDst++ = *lpTemp++; } } } return lpDstDib; }
bool DibCopyRect(LPBYTE lpDstDib, int dstx, int dsty, LPBYTE lpSrcDib, LPRECT prSrc1){ if(!lpDstDib || !lpSrcDib || DIB_BPP(lpDstDib) != DIB_BPP(lpSrcDib)) return false; RECT rDst, rDst1, rDst2, rSrc2, rSrc; SetRect(&rSrc2, 0, 0, DIB_CX(lpSrcDib), DIB_CY(lpSrcDib)); IntersectRect(&rSrc, prSrc1, &rSrc2); SetRect(&rDst1, 0, 0, rSrc.right - rSrc.left, rSrc.bottom - rSrc.top); OffsetRect(&rDst1, dstx, dsty); SetRect(&rDst2, 0, 0, DIB_CX(lpDstDib), DIB_CY(lpDstDib)); IntersectRect(&rDst, &rDst1, &rDst2); LPBYTE lpSrc, lpDst; int y, nWidth = (rDst.right - rDst.left) * DIB_BPP(lpSrcDib) / 8; for(y = rDst.top; y < rDst.bottom; y++){ lpSrc = DIB_DATAXY_INV(lpSrcDib, rSrc.left, rSrc.top + y - rDst.top); lpDst = DIB_DATAXY_INV(lpDstDib, rDst.left, y); memcpy(lpDst, lpSrc, nWidth); } return true; }
LPBYTE DibFlipHandle( LPBYTE lpDib ) { if ( !lpDib ) return NULL; LPBYTE lpNewDib; int y; lpNewDib = (LPBYTE) GlobalLock( DibCreateEmptyHandle( DIB_BPP( lpDib ), DIB_CX( lpDib ), DIB_CY( lpDib ) ) ); if ( lpNewDib ) { for ( y = 0; y < DIB_CY( lpDib ); y++ ) { memcpy( DIB_DATAXY( lpNewDib, 0, y ), DIB_DATAXY_INV( lpDib, 0, y ), DIB_LINESIZE( lpDib ) ); } } return lpNewDib; }
/// BMP파일을 열어서 높이맵을 생성한다. HRESULT ZTerrain::_BuildHeightMap( const char* lpFilename ) { #ifdef _UNICODE char temp[256]={0,}; WideCharToMultiByte(CP_ACP, 0, lpFilename, -1, temp, 256, NULL, NULL); LPBYTE pDIB = DibLoadHandle( temp ); #else LPBYTE pDIB = DibLoadHandle( lpFilename ); #endif if( !pDIB ) return E_FAIL; char filename[256]; _splitpath_s(lpFilename,NULL,0,NULL,0,filename,256,NULL,0); m_strNodeName = filename; m_cxDIB = DIB_CX( pDIB ); m_czDIB = DIB_CY( pDIB ); // 여기서 m_cxDIB나 m_czDIB가 (2^n+1)이 아닌경우 E_FAIL을 반환하도록 수정할 것 m_pvHeightMap = new TERRAINVERTEX[m_cxDIB * m_czDIB]; TERRAINVERTEX v; for( int z = 0 ; z < m_czDIB ; z++ ) { for( int x = 0 ; x < m_cxDIB ; x++ ) { v.p.x = (float)( ( x - m_cxDIB / 2 ) * m_vfScale.x ); v.p.z = -(float)( ( z - m_czDIB / 2 ) * m_vfScale.z ); v.p.y = (float)( *( DIB_DATAXY_INV( pDIB, x, z ) ) ) * m_vfScale.y; D3DXVec3Normalize( &v.n, &v.p ); v.u = (float)x / (float)( m_cxDIB - 1 ); v.v = (float)z / (float)( m_czDIB - 1 ); m_pvHeightMap[x + z * m_czDIB] = v; } } DibDeleteHandle( pDIB ); return S_OK; }
HRGN DibCreateRegion(LPBYTE lpDib, BYTE byColor){ LPBYTE lpData; int cx, cy; DWORD dwMaxRect; RECT r; RGNDATA *pRd; HGLOBAL hMem; HRGN hRgn; if(!lpDib || DIB_BPP(lpDib) != 8){ return NULL; } cx = DIB_CX(lpDib); cy = DIB_CY(lpDib); dwMaxRect = 3000; hMem = GlobalAlloc(GMEM_FIXED, sizeof(RGNDATAHEADER) + sizeof(RECT) * dwMaxRect); pRd = (RGNDATA*)GlobalLock(hMem); pRd->rdh.dwSize = sizeof(RGNDATAHEADER); pRd->rdh.iType = RDH_RECTANGLES; pRd->rdh.nCount = 0; pRd->rdh.nRgnSize = 0; SetRect(&(pRd->rdh.rcBound), cx, cy, 0, 0); for(int y = 0; y < cy; y++){ lpData = DIB_DATA8XY_INV(lpDib, 0, y); for(int x = 0; x < cx; x++){ if(*lpData == byColor){ // get run length rect r.left = x; r.top = r.bottom = y; while (*lpData == byColor && x < cx){ x++; lpData++; } r.right = x; // update bound rect if(r.left < pRd->rdh.rcBound.left) pRd->rdh.rcBound.left = r.left; if(r.top < pRd->rdh.rcBound.top) pRd->rdh.rcBound.top = r.top; if(r.right > pRd->rdh.rcBound.right) pRd->rdh.rcBound.right = r.right; if(r.bottom > pRd->rdh.rcBound.bottom) pRd->rdh.rcBound.bottom = r.bottom; memcpy(&pRd->Buffer[pRd->rdh.nCount++], &r, sizeof(RECT)); if(pRd->rdh.nCount >= dwMaxRect) goto exitLoop; } lpData++; } } exitLoop: pRd->rdh.nRgnSize = sizeof(RECT) * pRd->rdh.nCount; hRgn = ExtCreateRegion(NULL, sizeof(RGNDATAHEADER) + sizeof(RECT) * pRd->rdh.nCount, pRd); GlobalUnlock(hMem); GlobalFree(hMem); return hRgn; }
LPBYTE DibRotateHandle(LPBYTE lpDib, float fDegree){ if(!lpDib) return NULL; LPBYTE lpNewDib = NULL, lpNewData, lpData; int cx, cy; cx = DIB_CX(lpDib); cy = DIB_CY(lpDib); if(fDegree == 90.0f){ if(!(lpNewDib = (LPBYTE)GlobalLock(DibCreateEmptyHandle(DIB_BPP(lpDib), cy, cx)))) return NULL; for(int y = 0; y < cy; y++){ lpData = DIB_DATAXY(lpDib, 0, y); lpNewData = DIB_DATAXY(lpNewDib, y, cx - 1); if(DIB_BPP(lpDib) == 8){ for(int x = 0; x < cx; x++, lpNewData -= ALIGN_4B(cy)) *lpNewData = *lpData++; } else if (DIB_BPP(lpDib) == 24){ for(int x = 0; x < cx; x++, lpNewData -= ALIGN_4B(cy * 3)){ *lpNewData = *lpData++; *(lpNewData + 1) = *lpData++; *(lpNewData + 2) = *lpData++; } } } } else if(fDegree == 180.0f){ if(!(lpNewDib = (LPBYTE)GlobalLock(DibCreateEmptyHandle(DIB_BPP(lpDib), cx, cy)))) return NULL; for(int y = 0; y < cy; y++){ lpData = DIB_DATAXY(lpDib, 0, y); lpNewData = DIB_DATAXY(lpNewDib, cx - 1, cy - 1 - y); if(DIB_BPP(lpDib) == 8){ for(int x = 0; x < cx; x++, lpNewData--) *lpNewData = *lpData++; } else if(DIB_BPP(lpDib) == 24) { for(int x = 0; x < cx; x++, lpNewData -= 3){ *lpNewData = *lpData++; *(lpNewData + 1) = *lpData++; *(lpNewData + 2) = *lpData++; } } } } else if(fDegree == 270.0f){ if(!(lpNewDib = (LPBYTE)GlobalLock(DibCreateEmptyHandle(DIB_BPP(lpDib), cy, cx)))) return NULL; for(int y = 0; y < cy; y++){ lpData = DIB_DATAXY(lpDib, 0, y); lpNewData = DIB_DATAXY(lpNewDib, cy - 1 - y, 0); if(DIB_BPP(lpDib) == 8){ for(int x = 0; x < cx; x++, lpNewData += ALIGN_4B(cy)) *lpNewData = *lpData++; } else if(DIB_BPP(lpDib) == 24){ for(int x = 0; x < cx; x++, lpNewData += ALIGN_4B(cy * 3)){ *lpNewData = *lpData++; *(lpNewData + 1) = *lpData++; *(lpNewData + 2) = *lpData++; } } } } else { // free angle /* CLeadBitmap lBitmap; lBitmap.ConvertFromDIB((LPBITMAPINFO)lpDib, lpDIb); lBitmap.Rotate(nNewWidth, nNewHeight); lpNewDib = (LPBYTE)GlobalLock(lBItmap.ConverToDIB()); */ } return lpNewDib; }