From eb510f2cbbd86585a672730fc33084ed9aa56748 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 15 Feb 2017 08:12:59 +0000 Subject: [PATCH] EgtGraphics : - miglioramenti a GetImage con risoluzioni elevate. --- Scene.h | 6 ++-- SceneImage.cpp | 89 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 65 insertions(+), 30 deletions(-) diff --git a/Scene.h b/Scene.h index dea1be9..a0a16fe 100644 --- a/Scene.h +++ b/Scene.h @@ -179,7 +179,7 @@ class Scene : public IEGrScene bool GetTextureDimensions( const std::string& sName, double& dDimX, double& dDimY) const override ; bool ChangeTextureDimensions( const std::string& sName, double dDimX, double dDimY) override ; // Image - bool GetImage( int nShowMode, bool bShowGrid, bool bShowFrame, Color colBackTop, Color colBackBottom, + bool GetImage( int nShowMode, Color colBackTop, Color colBackBottom, int nDestWidth, int nDestHeight, const std::string& sFile) override ; public : @@ -304,8 +304,8 @@ class Scene : public IEGrScene BBox3d m_b3ExtWorld ; // estensione della geometria nel riferimento globale (mondo) BBox3d m_b3ExtView ; // estensione nel riferimento di vista bool m_bExtViewOk ; // flag per stato aggiornamento di EView - double m_dHalfWidth ; // semialtezza della vista - double m_dHalfHeight ; // semilarghezza della vista + double m_dHalfWidth ; // semilarghezza della vista + double m_dHalfHeight ; // semialtezza della vista double m_dZNear ; // distanza del piano di clipping vicino double m_dZFar ; // distanza del piano di clipping lontano // Grid diff --git a/SceneImage.cpp b/SceneImage.cpp index 351ed62..4f4ed5f 100644 --- a/SceneImage.cpp +++ b/SceneImage.cpp @@ -21,7 +21,7 @@ using namespace std ; //---------------------------------------------------------------------------- bool -Scene::GetImage( int nShowMode, bool bShowGrid, bool bShowFrame, Color colBackTop, Color colBackBottom, +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 @@ -41,32 +41,73 @@ Scene::GetImage( int nShowMode, bool bShowGrid, bool bShowFrame, Color colBackTo double dCoeffW = double( nDestWidth) / nWidth ; double dCoeffH = double( nDestHeight) / nHeight ; - // Alloco il buffer di lettura dei pixel della vista OpenGL ( fattore 4 perché RGBA) + // 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 ; - // Imposto attributi di visualizzazione + // Salvo stato di visualizzazione int nCurrShowMode = m_nShowMode ; - m_nShowMode = nShowMode ; bool bCurrShowGrid = m_bShowGrid ; - m_bShowGrid = bShowGrid ; bool bCurrShowFrame = m_bShowFrame ; - m_bShowFrame = 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 ; - // Imposto zoom + // Salvo stato di zoom + Point3d ptCurrCenter = m_ptCenter ; double dCurrHalfWidth = m_dHalfWidth ; double dCurrHalfHeight = m_dHalfHeight ; - double dCoeff = max( dCoeffW, dCoeffH) / min( dCoeffW, dCoeffH) ; - m_dHalfWidth *= dCoeff ; - m_dHalfHeight *= dCoeff ; + // Imposto zoom globale + double dZoom = max( dCoeffW / nN, dCoeffH / nM) / min( dCoeffW / nN, dCoeffH / nM) ; + m_dHalfWidth *= dZoom ; + m_dHalfHeight *= dZoom ; - // Eseguo disegno sul back buffer - if ( ! MyDraw( false)) - return false ; + // 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)) + 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 ; @@ -75,16 +116,10 @@ Scene::GetImage( int nShowMode, bool bShowGrid, bool bShowFrame, Color colBackTo m_colBackBottom = colCurrBackBottom ; m_colBackTop = colCurrBackTop ; // Ripristino zoom + m_ptCenter = ptCurrCenter ; m_dHalfWidth = dCurrHalfWidth ; m_dHalfHeight = dCurrHalfHeight ; - // 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* pDib = FreeImage_ConvertFromRawBits( pBuffer, nWidth, nHeight, 4 * nWidth, 32, - 0x0000FF00, 0xFF000000, 0x00FF0000, false) ; // converto l'immagine a 24 bit per pixel FIBITMAP* pTmpDib = pDib ; pDib = FreeImage_ConvertTo24Bits( pTmpDib) ; @@ -93,19 +128,19 @@ Scene::GetImage( int nShowMode, bool bShowGrid, bool bShowFrame, Color colBackTo // Eseguo scalatura della bitmap int nLeft ; int nTop ; int nRight ; int nBottom ; - if ( dCoeffW >= dCoeffH) { + if ( dCoeffW / nN >= dCoeffH / nM) { nLeft = 0 ; - nRight = nWidth - 1 ; - int nDeltaH = nHeight - int( nDestHeight / dCoeffW) ; + nRight = nN * nWidth - 1 ; + int nDeltaH = nM * nHeight - nN * int( nDestHeight / dCoeffW) ; nTop = nDeltaH / 2 ; - nBottom = nHeight - nTop ; + nBottom = nM * nHeight - nTop - 1 ; } else { nTop = 0 ; - nBottom = nHeight ; - int nDeltaW = nWidth - int( nDestWidth / dCoeffH) ; + nBottom = nM * nHeight - 1 ; + int nDeltaW = nN * nWidth - nM * int( nDestWidth / dCoeffH) ; nLeft = nDeltaW / 2 ; - nRight = nWidth - nLeft ; + nRight = nN * nWidth - nLeft - 1 ; } FIBITMAP* pTmp2Dib = pDib ; pDib = FreeImage_RescaleRect( pTmp2Dib, nDestWidth, nDestHeight, nLeft, nTop, nRight, nBottom, FILTER_BSPLINE) ;