Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreImage.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 #include "OgreImage.h"
00027 
00028 #include "OgreArchiveManager.h"
00029 #include "OgreException.h"
00030 #include "OgreImageCodec.h"
00031 #include "OgreSDDataChunk.h"
00032 
00033 namespace Ogre {
00034 
00035     //-----------------------------------------------------------------------------
00036     Image::Image()
00037         : m_uDepth(0),
00038           m_uSize(0),
00039           m_uNumMipmaps(0),
00040           m_uFlags(0),
00041           m_pBuffer( NULL ),
00042           m_bAutoDelete( true )
00043     {
00044     }
00045 
00046     //-----------------------------------------------------------------------------
00047     Image::Image( const Image &img )
00048     {
00049         // call assignment operator
00050         *this = img;
00051     }
00052 
00053     //-----------------------------------------------------------------------------
00054     Image::~Image()
00055     {
00056         //Only delete if this was not a dynamic image (meaning app holds & destroys buffer)
00057         if( m_pBuffer && m_bAutoDelete )
00058         {
00059             delete[] m_pBuffer;
00060             m_pBuffer = NULL;
00061         }
00062     }
00063 
00064     //-----------------------------------------------------------------------------
00065     Image & Image::operator = ( const Image &img )
00066     {
00067         m_uWidth = img.m_uWidth;
00068         m_uHeight = img.m_uHeight;
00069         m_uDepth = img.m_uDepth;
00070         m_eFormat = img.m_eFormat;
00071         m_uSize = img.m_uSize;
00072         m_uFlags = img.m_uFlags;
00073         m_ucPixelSize = img.m_ucPixelSize;
00074         m_uNumMipmaps = img.m_uNumMipmaps;
00075         m_bAutoDelete = img.m_bAutoDelete;
00076 
00077         //Only create/copy when previous data was not dynamic data
00078         if( m_bAutoDelete )
00079         {
00080             m_pBuffer = new uchar[ m_uSize ];
00081             memcpy( m_pBuffer, img.m_pBuffer, m_uSize );
00082         }
00083         else
00084         {
00085             m_pBuffer = img.m_pBuffer;
00086         }
00087 
00088         return *this;
00089     }
00090 
00091     //-----------------------------------------------------------------------------
00092     Image & Image::flipAroundY()
00093     {
00094         OgreGuard( "Image::flipAroundY" );
00095 
00096         if( !m_pBuffer )
00097         {
00098             Except( 
00099                 Exception::ERR_INTERNAL_ERROR,
00100                 "Can not flip an unitialized texture",
00101                 "Image::flipAroundY" );
00102         }
00103         
00104         uchar   *pTempBuffer1 = NULL;
00105         ushort  *pTempBuffer2 = NULL;
00106         uchar   *pTempBuffer3 = NULL;
00107         uint    *pTempBuffer4 = NULL;
00108 
00109         uchar   *src1 = m_pBuffer, *dst1 = NULL;
00110         ushort  *src2 = (ushort *)m_pBuffer, *dst2 = NULL;
00111         uchar   *src3 = m_pBuffer, *dst3 = NULL;
00112         uint    *src4 = (uint *)m_pBuffer, *dst4 = NULL;
00113 
00114         ushort y;
00115         switch (m_ucPixelSize)
00116         {
00117         case 1:
00118             pTempBuffer1 = new uchar[m_uWidth * m_uHeight];
00119             for (y = 0; y < m_uHeight; y++)
00120             {
00121                 dst1 = (pTempBuffer1 + ((y * m_uWidth) + m_uWidth - 1));
00122                 for (ushort x = 0; x < m_uWidth; x++)
00123                     memcpy(dst1--, src1++, sizeof(uchar));
00124             }
00125 
00126             memcpy(m_pBuffer, pTempBuffer1, m_uWidth * m_uHeight * sizeof(uchar));
00127             delete [] pTempBuffer1;
00128             break;
00129 
00130         case 2:
00131             pTempBuffer2 = new ushort[m_uWidth * m_uHeight];
00132             for (y = 0; y < m_uHeight; y++)
00133             {
00134                 dst2 = (pTempBuffer2 + ((y * m_uWidth) + m_uWidth - 1));
00135                 for (ushort x = 0; x < m_uWidth; x++)
00136                     memcpy(dst2--, src2++, sizeof(ushort));
00137             }
00138 
00139             memcpy(m_pBuffer, pTempBuffer2, m_uWidth * m_uHeight * sizeof(ushort));
00140             delete [] pTempBuffer2;
00141             break;
00142 
00143         case 3:
00144             pTempBuffer3 = new uchar[m_uWidth * m_uHeight * 3];
00145             for (y = 0; y < m_uHeight; y++)
00146             {
00147                 uint offset = ((y * m_uWidth) + (m_uWidth - 1)) * 3;
00148                 dst3 = pTempBuffer3;
00149                 dst3 += offset;
00150                 for (ushort x = 0; x < m_uWidth; x++)
00151                 {
00152                     memcpy(dst3, src3, sizeof(uchar) * 3);
00153                     dst3 -= 3; src3 += 3;
00154                 }
00155             }
00156 
00157             memcpy(m_pBuffer, pTempBuffer3, m_uWidth * m_uHeight * sizeof(uchar) * 3);
00158             delete [] pTempBuffer3;
00159             break;
00160 
00161         case 4:
00162             pTempBuffer4 = new uint[m_uWidth * m_uHeight];
00163             for (y = 0; y < m_uHeight; y++)
00164             {
00165                 dst4 = (pTempBuffer4 + ((y * m_uWidth) + m_uWidth - 1));
00166                 for (ushort x = 0; x < m_uWidth; x++)
00167                     memcpy(dst4--, src4++, sizeof(uint));
00168             }
00169 
00170             memcpy(m_pBuffer, pTempBuffer4, m_uWidth * m_uHeight * sizeof(uint));
00171             delete [] pTempBuffer4;
00172             break;
00173 
00174         default:
00175             Except( 
00176                 Exception::ERR_INTERNAL_ERROR,
00177                 "Unknown pixel depth",
00178                 "Image::flipAroundY" );
00179             break;
00180         }
00181 
00182         OgreUnguardRet( *this );
00183     }
00184 
00185     //-----------------------------------------------------------------------------
00186     Image & Image::flipAroundX()
00187     {
00188         OgreGuard( "Image::flipAroundX" );
00189 
00190         if( !m_pBuffer )
00191         {
00192             Except( 
00193                 Exception::ERR_INTERNAL_ERROR,
00194                 "Can not flip an unitialized texture",
00195                 "Image::flipAroundX" );
00196         }
00197         
00198         size_t rowSpan = m_uWidth * m_ucPixelSize;
00199         
00200         uchar *pTempBuffer = new uchar[ rowSpan * m_uHeight ];
00201         uchar *ptr1 = m_pBuffer, *ptr2 = pTempBuffer + ( ( m_uHeight - 1 ) * rowSpan );
00202 
00203         for( ushort i = 0; i < m_uHeight; i++ )
00204         {
00205             memcpy( ptr2, ptr1, rowSpan );
00206             ptr1 += rowSpan; ptr2 -= rowSpan;
00207         }
00208 
00209         memcpy( m_pBuffer, pTempBuffer, rowSpan * m_uHeight);
00210 
00211         delete [] pTempBuffer;
00212 
00213         OgreUnguardRet( *this );
00214     }
00215 
00216     //-----------------------------------------------------------------------------
00217     Image& Image::loadDynamicImage( uchar* pData, ushort uWidth, ushort uHeight, 
00218                              PixelFormat eFormat )
00219     {
00220         OgreGuard( "Image::loadDynamicImage" );
00221 
00222         m_uWidth = uWidth;
00223         m_uHeight = uHeight;
00224         m_eFormat = eFormat;
00225         m_ucPixelSize = PF2PS( m_eFormat );
00226         m_uSize = m_uWidth * m_uHeight * m_ucPixelSize;
00227 
00228         m_pBuffer = pData;
00229         
00230         m_bAutoDelete = false;
00231         
00232         OgreUnguardRet( *this );
00233     }
00234 
00235     //-----------------------------------------------------------------------------
00236     Image & Image::loadRawData(
00237         const DataChunk &pData,
00238         ushort uWidth, ushort uHeight,
00239         PixelFormat eFormat )
00240     {
00241         OgreGuard( "Image::loadRawData" );
00242 
00243         m_uWidth = uWidth;
00244         m_uHeight = uHeight;
00245         m_eFormat = eFormat;
00246         m_ucPixelSize = PF2PS( m_eFormat );
00247         m_uSize = m_uWidth * m_uHeight * m_ucPixelSize;
00248 
00249         m_pBuffer = new uchar[ uWidth * uHeight * m_ucPixelSize ];
00250         memcpy( m_pBuffer, pData.getPtr(), uWidth * uHeight * m_ucPixelSize );
00251 
00252         OgreUnguardRet( *this );
00253     }
00254 
00255     //-----------------------------------------------------------------------------
00256     Image & Image::load( const String& strFileName )
00257     {
00258         OgreGuard( "Image::load" );
00259 
00260         if( m_pBuffer )
00261         {
00262             delete[] m_pBuffer;
00263             m_pBuffer = NULL;
00264         }
00265 
00266         String strExt;
00267 
00268         size_t pos = strFileName.find_last_of(".");
00269         if( pos == String::npos )
00270             Except(
00271             Exception::ERR_INVALIDPARAMS, 
00272             "Unable to load image file '" + strFileName + "' - invalid extension.",
00273             "Image::load" );
00274 
00275         while( pos != strFileName.length() - 1 )
00276             strExt += strFileName[++pos];
00277 
00278         Codec * pCodec = Codec::getCodec(strExt);
00279         if( !pCodec )
00280             Except(
00281             Exception::ERR_INVALIDPARAMS, 
00282             "Unable to load image file '" + strFileName + "' - invalid extension.",
00283             "Image::load" );
00284 
00285         SDDataChunk encoded;
00286         DataChunk decoded;
00287 
00288         if( !ArchiveManager::getSingleton()._findResourceData( 
00289             strFileName, 
00290             encoded ) )
00291         {
00292             Except(
00293             Exception::ERR_INVALIDPARAMS, 
00294             "Unable to find image file '" + strFileName + "'.",
00295             "Image::load" );
00296         }
00297 
00298         ImageCodec::ImageData * pData = static_cast< ImageCodec::ImageData * > (
00299             pCodec->decode( encoded, &decoded ) );
00300 
00301         // Get the format and compute the pixel size
00302         m_uWidth = pData->width;
00303         m_uHeight = pData->height;
00304         m_uDepth = pData->depth;
00305         m_uSize = pData->size;
00306         m_eFormat = pData->format;
00307         m_uNumMipmaps = pData->num_mipmaps;
00308         m_ucPixelSize = PF2PS( m_eFormat );
00309         m_uFlags = pData->flags;
00310 
00311         delete pData;
00312 
00313         m_pBuffer = decoded.getPtr();
00314         
00315         OgreUnguardRet( *this );
00316     }
00317 
00318     //-----------------------------------------------------------------------------
00319     Image & Image::load( const DataChunk& chunk, const String& type )
00320     {
00321         OgreGuard( "Image::load" );
00322 
00323         String strType = type;
00324 
00325         Codec * pCodec = Codec::getCodec(strType);
00326         if( !pCodec )
00327             Except(
00328             Exception::ERR_INVALIDPARAMS, 
00329             "Unable to load image - invalid extension.",
00330             "Image::load" );
00331 
00332         DataChunk decoded;
00333 
00334         ImageCodec::ImageData * pData = static_cast< ImageCodec::ImageData * >(
00335             pCodec->decode( chunk, &decoded ) );
00336 
00337         m_uWidth = pData->width;
00338         m_uHeight = pData->height;
00339         m_uDepth = pData->depth;
00340         m_uSize = pData->size;
00341         m_uNumMipmaps = pData->num_mipmaps;
00342         m_uFlags = pData->flags;
00343         
00344         // Get the format and compute the pixel size
00345         m_eFormat = pData->format;
00346         m_ucPixelSize = PF2PS( m_eFormat );
00347 
00348         delete pData;
00349 
00350         m_pBuffer = decoded.getPtr();
00351 
00352         OgreUnguardRet( *this );
00353     }
00354 
00355     //-----------------------------------------------------------------------------
00356     uchar* Image::getData()
00357     {
00358         return m_pBuffer;
00359     }
00360 
00361     //-----------------------------------------------------------------------------
00362     const uchar* Image::getData() const
00363     {
00364         assert( m_pBuffer );
00365         return m_pBuffer;
00366     }
00367 
00368     //-----------------------------------------------------------------------------
00369     size_t Image::getSize() const
00370     {
00371        return m_uSize;
00372     }
00373 
00374     //-----------------------------------------------------------------------------
00375     unsigned short Image::getNumMipmaps() const
00376     {
00377        return m_uNumMipmaps;
00378     }
00379 
00380     //-----------------------------------------------------------------------------
00381     bool Image::hasFlag(const ImageFlags imgFlag)
00382     {
00383         if(m_uFlags & imgFlag)
00384         {
00385             return true;
00386         }
00387         else
00388         {
00389             return false;
00390         }
00391     }
00392 
00393     //-----------------------------------------------------------------------------
00394     ushort Image::getDepth() const
00395     {
00396         return m_uDepth;
00397     }
00398     //-----------------------------------------------------------------------------
00399     ushort Image::getWidth() const
00400     {
00401         return m_uWidth;
00402     }
00403 
00404     //-----------------------------------------------------------------------------
00405     ushort Image::getHeight() const
00406     {
00407         return m_uHeight;
00408     }
00409 
00410     //-----------------------------------------------------------------------------
00411     ushort Image::getRowSpan() const
00412     {
00413         return m_uWidth * m_ucPixelSize;
00414     }
00415 
00416     //-----------------------------------------------------------------------------
00417     PixelFormat Image::getFormat() const
00418     {
00419         return m_eFormat;
00420     }
00421 
00422     //-----------------------------------------------------------------------------
00423     uchar Image::getBPP() const
00424     {
00425         return m_ucPixelSize * 8;
00426     }
00427 
00428     //-----------------------------------------------------------------------------
00429     bool Image::getHasAlpha(void) const
00430     {
00431         return Image::formatHasAlpha(m_eFormat);
00432     }
00433     //-----------------------------------------------------------------------------
00434     bool Image::formatHasAlpha(PixelFormat format)
00435     {
00436         switch( format )
00437         {
00438         case PF_A8:
00439         case PF_A4L4:
00440         case PF_L4A4:
00441         case PF_A4R4G4B4:
00442         case PF_B4G4R4A4:
00443         case PF_A8R8G8B8:
00444         case PF_B8G8R8A8:
00445         case PF_A2R10G10B10:
00446         case PF_B10G10R10A2:
00447             return true;
00448 
00449         case PF_UNKNOWN:
00450         case PF_L8:
00451         case PF_R5G6B5:
00452         case PF_B5G6R5:
00453         case PF_R8G8B8:
00454         case PF_B8G8R8:
00455         default:
00456             return false;
00457         }
00458     }
00459 
00460     void Image::applyGamma( unsigned char *buffer, Real gamma, size_t size, uchar bpp )
00461     {
00462         if( gamma == 1.0f )
00463             return;
00464 
00465         //NB only 24/32-bit supported
00466         if( bpp != 24 && bpp != 32 ) return;
00467 
00468         uint stride = bpp >> 3;
00469 
00470         for( size_t i = 0, j = size / stride; i < j; i++, buffer += stride )
00471         {
00472             float r, g, b;
00473 
00474             r = (float)buffer[0];
00475             g = (float)buffer[1];
00476             b = (float)buffer[2];
00477 
00478             r = r * gamma;
00479             g = g * gamma;
00480             b = b * gamma;
00481 
00482             float scale = 1.0f, tmp;
00483 
00484             if( r > 255.0f && (tmp=(255.0f/r)) < scale )
00485                 scale = tmp;
00486             if( g > 255.0f && (tmp=(255.0f/g)) < scale )
00487                 scale = tmp;
00488             if( b > 255.0f && (tmp=(255.0f/b)) < scale )
00489                 scale = tmp;
00490 
00491             r *= scale; g *= scale; b *= scale;
00492 
00493             buffer[0] = (uchar)r;
00494             buffer[1] = (uchar)g;
00495             buffer[2] = (uchar)b;
00496         }
00497     }
00498 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:17 2004