//---------------------------------------------------------------------------- // EgalTech 2017-2017 //---------------------------------------------------------------------------- // File : SceneImage.cpp Data : 11.02.17 Versione : 1.8b2 // Contenuto : Implementazione della gestione immagini della classe scena. // // // // Modifiche : 11.02.17 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "Scene.h" #include "\EgtDev\Include\EgtStringConverter.h" #include "\EgtDev\Extern\FreeImage\Include\FreeImage.h" using namespace std ; //---------------------------------------------------------------------------- bool Scene::GetImage( int nShowMode, Color colBackTop, Color colBackBottom, int nDestWidth, int nDestHeight, const string& sFile) { // Cerco e verifico il formato del file da scrivere a partire dall'estensione FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilenameU( stringtoW( sFile)) ; if ( fif == FIF_UNKNOWN || ! FreeImage_FIFSupportsWriting( fif)) return false ; // Dimensioni della vista int nWidth = m_nViewportW ; int nHeight = m_nViewportH ; if ( nWidth == 0 || nHeight == 0) return false ; // Coefficienti di scalatura if ( nDestWidth == 0 || nDestHeight == 0) return false ; double dCoeffW = double( nDestWidth) / nWidth ; double dCoeffH = double( nDestHeight) / nHeight ; // Costanti per mask colori (BGRA) const unsigned int BLUE_MASK = 0xFF000000 ; const unsigned int GREEN_MASK = 0x00FF0000 ; const unsigned int RED_MASK = 0x0000FF00 ; // Alloco immagine complessiva int nN = max( int( dCoeffW + 0.5), 1) ; int nM = max( int( dCoeffH + 0.5), 1) ; FIBITMAP* pDib = FreeImage_Allocate( nN * nWidth, nM * nHeight, 32, RED_MASK, GREEN_MASK, BLUE_MASK) ; if ( pDib == nullptr) return false ; // Alloco il buffer di lettura dei pixel della vista OpenGL ( fattore 4 perché BGRA) BYTE* pBuffer = new BYTE[ 4 * nWidth * nHeight] ; if ( pBuffer == nullptr) return false ; // Salvo stato di visualizzazione int nCurrShowMode = m_nShowMode ; bool bCurrShowGrid = m_bShowGrid ; bool bCurrShowFrame = m_bShowFrame ; bool bCurrShowGlobFrame = m_bShowGlobFrame ; Color colCurrBackTop = m_colBackTop ; Color colCurrBackBottom = m_colBackBottom ; // Imposto attributi di visualizzazione m_nShowMode = nShowMode ; m_bShowGrid = false ; m_bShowFrame = false ; m_bShowGlobFrame = false ; m_colBackTop = colBackTop ; m_colBackBottom = colBackBottom ; // Salvo stato di zoom Point3d ptCurrCenter = m_ptCenter ; double dCurrHalfWidth = m_dHalfWidth ; double dCurrHalfHeight = m_dHalfHeight ; // Imposto zoom globale double dZoom = max( dCoeffW / nN, dCoeffH / nM) / min( dCoeffW / nN, dCoeffH / nM) ; m_dHalfWidth *= dZoom ; m_dHalfHeight *= dZoom ; // Eseguo N x M disegni double dCoeff = max( 1.0 / nN, 1.0 / nM) ; double dWs = m_dHalfWidth * dCoeff ; double dHs = m_dHalfHeight * dCoeff ; Vector3d vtX = m_vtUp ^ m_vtDirCamera ; Vector3d vtY = m_vtUp ; Point3d ptOrig = m_ptCenter - vtX * dWs * nN - vtY * dHs * nM ; for ( int i = 0 ; i < nN ; ++ i) { for ( int j = 0 ; j < nM ; ++ j) { // Aggiusto scalature m_ptCenter = ptOrig + vtX * (( 2 * i + 1) * dWs) + vtY * (( 2 * j + 1) * dHs) ; m_dHalfWidth = dWs ; m_dHalfHeight = dHs ; // Eseguo disegno sul back buffer if ( ! MyDraw( false)) { delete [] pBuffer ; return false ; } // Leggo l'immagine nel buffer glReadBuffer( GL_BACK) ; glReadPixels( 0, 0, nWidth, nHeight, GL_BGRA, GL_UNSIGNED_BYTE, pBuffer) ; // Converto al formato di FreeImage FIBITMAP* pTmpDib = FreeImage_ConvertFromRawBits( pBuffer, nWidth, nHeight, 4 * nWidth, 32, RED_MASK, GREEN_MASK, BLUE_MASK, false) ; // Inserisco nell'immagine complessiva FreeImage_Paste( pDib, pTmpDib, i * nWidth, ( nM - 1 - j) * nHeight, 255) ; FreeImage_Unload( pTmpDib) ; } } // Ripristino attributi di visualizzazione originali m_nShowMode = nCurrShowMode ; m_bShowGrid = bCurrShowGrid ; m_bShowFrame = bCurrShowFrame ; m_bShowGlobFrame = bCurrShowGlobFrame ; m_colBackBottom = colCurrBackBottom ; m_colBackTop = colCurrBackTop ; // Ripristino zoom m_ptCenter = ptCurrCenter ; m_dHalfWidth = dCurrHalfWidth ; m_dHalfHeight = dCurrHalfHeight ; // converto l'immagine a 24 bit per pixel FIBITMAP* pTmpDib = pDib ; pDib = FreeImage_ConvertTo24Bits( pTmpDib) ; FreeImage_Unload( pTmpDib) ; // Se necessario, eseguo scalatura della bitmap if ( nDestWidth != nN * nWidth || nDestHeight != nM * nHeight) { int nLeft ; int nTop ; int nRight ; int nBottom ; if ( dCoeffW / nN >= dCoeffH / nM) { nLeft = 0 ; nRight = nN * nWidth - 1 ; int nDeltaH = nM * nHeight - nN * int( nDestHeight / dCoeffW) ; nTop = nDeltaH / 2 ; nBottom = nM * nHeight - nTop - 1 ; } else { nTop = 0 ; nBottom = nM * nHeight - 1 ; int nDeltaW = nN * nWidth - nM * int( nDestWidth / dCoeffH) ; nLeft = nDeltaW / 2 ; nRight = nN * nWidth - nLeft - 1 ; } FIBITMAP* pTmp2Dib = pDib ; pDib = FreeImage_RescaleRect( pTmp2Dib, nDestWidth, nDestHeight, nLeft, nTop, nRight, nBottom, FILTER_CATMULLROM) ; FreeImage_Unload( pTmp2Dib) ; } // Salvataggio int nFlag = 0 ; bool bOk = ( FreeImage_SaveU( fif, pDib, stringtoW( sFile), nFlag) != FALSE) ; // Libero le risorse FreeImage_Unload( pDib) ; delete [] pBuffer ; return bOk ; }