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_uSize(0),
00038           m_uDepth(0),
00039           m_uNumMipmaps(0),
00040           m_uFlags(0),
00041           m_pBuffer( NULL )
00042     {
00043     }
00044 
00045     //-----------------------------------------------------------------------------
00046     Image::Image( const Image &img )
00047     {
00048         // call assignment operator
00049         *this = img;
00050     }
00051 
00052     //-----------------------------------------------------------------------------
00053     Image::~Image()
00054     {
00055         if( m_pBuffer )
00056         {
00057             delete[] m_pBuffer;
00058             m_pBuffer = NULL;
00059         }
00060     }
00061 
00062     //-----------------------------------------------------------------------------
00063     Image & Image::operator = ( const Image &img )
00064     {
00065         m_uWidth = img.m_uWidth;
00066         m_uHeight = img.m_uHeight;
00067         m_uDepth = img.m_uDepth;
00068         m_eFormat = img.m_eFormat;
00069         m_uSize = img.m_uSize;
00070         m_uFlags = img.m_uFlags;
00071         m_ucPixelSize = img.m_ucPixelSize;
00072         m_uNumMipmaps = img.m_uNumMipmaps;
00073 
00074         m_pBuffer = new uchar[ m_uSize ];
00075         memcpy( m_pBuffer, img.m_pBuffer, m_uSize );
00076 
00077         return *this;
00078     }
00079 
00080     //-----------------------------------------------------------------------------
00081     Image & Image::flipAroundY()
00082     {
00083         OgreGuard( "Image::flipAroundY" );
00084 
00085         if( !m_pBuffer )
00086         {
00087             Except( 
00088                 Exception::ERR_INTERNAL_ERROR,
00089                 "Can not flip an unitialized texture",
00090                 "Image::flipAroundY" );
00091         }
00092         
00093         uchar   *pTempBuffer1 = NULL;
00094         ushort  *pTempBuffer2 = NULL;
00095         uchar   *pTempBuffer3 = NULL;
00096         uint    *pTempBuffer4 = NULL;
00097 
00098         uchar   *src1 = m_pBuffer, *dst1 = NULL;
00099         ushort  *src2 = (ushort *)m_pBuffer, *dst2 = NULL;
00100         uchar   *src3 = m_pBuffer, *dst3 = NULL;
00101         uint    *src4 = (uint *)m_pBuffer, *dst4 = NULL;
00102 
00103         ushort y;
00104         switch (m_ucPixelSize)
00105         {
00106         case 1:
00107             pTempBuffer1 = new uchar[m_uWidth * m_uHeight];
00108             for (y = 0; y < m_uHeight; y++)
00109             {
00110                 dst1 = (pTempBuffer1 + ((y * m_uWidth) + m_uWidth - 1));
00111                 for (ushort x = 0; x < m_uWidth; x++)
00112                     memcpy(dst1--, src1++, sizeof(uchar));
00113             }
00114 
00115             memcpy(m_pBuffer, pTempBuffer1, m_uWidth * m_uHeight * sizeof(uchar));
00116             delete [] pTempBuffer1;
00117             break;
00118 
00119         case 2:
00120             pTempBuffer2 = new ushort[m_uWidth * m_uHeight];
00121             for (y = 0; y < m_uHeight; y++)
00122             {
00123                 dst2 = (pTempBuffer2 + ((y * m_uWidth) + m_uWidth - 1));
00124                 for (ushort x = 0; x < m_uWidth; x++)
00125                     memcpy(dst2--, src2++, sizeof(ushort));
00126             }
00127 
00128             memcpy(m_pBuffer, pTempBuffer2, m_uWidth * m_uHeight * sizeof(ushort));
00129             delete [] pTempBuffer2;
00130             break;
00131 
00132         case 3:
00133             pTempBuffer3 = new uchar[m_uWidth * m_uHeight * 3];
00134             for (y = 0; y < m_uHeight; y++)
00135             {
00136                 uint offset = ((y * m_uWidth) + (m_uWidth - 1)) * 3;
00137                 dst3 = pTempBuffer3;
00138                 dst3 += offset;
00139                 for (ushort x = 0; x < m_uWidth; x++)
00140                 {
00141                     memcpy(dst3, src3, sizeof(uchar) * 3);
00142                     dst3 -= 3; src3 += 3;
00143                 }
00144             }
00145 
00146             memcpy(m_pBuffer, pTempBuffer3, m_uWidth * m_uHeight * sizeof(uchar) * 3);
00147             delete [] pTempBuffer3;
00148             break;
00149 
00150         case 4:
00151             pTempBuffer4 = new uint[m_uWidth * m_uHeight];
00152             for (y = 0; y < m_uHeight; y++)
00153             {
00154                 dst4 = (pTempBuffer4 + ((y * m_uWidth) + m_uWidth - 1));
00155                 for (ushort x = 0; x < m_uWidth; x++)
00156                     memcpy(dst4--, src4++, sizeof(uint));
00157             }
00158 
00159             memcpy(m_pBuffer, pTempBuffer4, m_uWidth * m_uHeight * sizeof(uint));
00160             delete [] pTempBuffer4;
00161             break;
00162 
00163         default:
00164             Except( 
00165                 Exception::ERR_INTERNAL_ERROR,
00166                 "Unknown pixel depth",
00167                 "Image::flipAroundY" );
00168             break;
00169         }
00170 
00171         OgreUnguardRet( *this );
00172     }
00173 
00174     //-----------------------------------------------------------------------------
00175     Image & Image::flipAroundX()
00176     {
00177         OgreGuard( "Image::flipAroundX" );
00178 
00179         if( !m_pBuffer )
00180         {
00181             Except( 
00182                 Exception::ERR_INTERNAL_ERROR,
00183                 "Can not flip an unitialized texture",
00184                 "Image::flipAroundX" );
00185         }
00186         
00187         size_t rowSpan = m_uWidth * m_ucPixelSize;
00188         
00189         uchar *pTempBuffer = new uchar[ rowSpan * m_uHeight ];
00190         uchar *ptr1 = m_pBuffer, *ptr2 = pTempBuffer + ( ( m_uHeight - 1 ) * rowSpan );
00191 
00192         for( ushort i = 0; i < m_uHeight; i++ )
00193         {
00194             memcpy( ptr2, ptr1, rowSpan );
00195             ptr1 += rowSpan; ptr2 -= rowSpan;
00196         }
00197 
00198         memcpy( m_pBuffer, pTempBuffer, rowSpan * m_uHeight);
00199 
00200         delete [] pTempBuffer;
00201 
00202         OgreUnguardRet( *this );
00203     }
00204 
00205     //-----------------------------------------------------------------------------
00206     Image & Image::loadRawData(
00207         const DataChunk &pData,
00208         ushort uWidth, ushort uHeight,
00209         PixelFormat eFormat )
00210     {
00211         OgreGuard( "Image::loadRawData" );
00212 
00213         m_uWidth = uWidth;
00214         m_uHeight = uHeight;
00215         m_eFormat = eFormat;
00216         m_ucPixelSize = PF2PS( m_eFormat );
00217         m_uSize = m_uWidth * m_uHeight * m_ucPixelSize;
00218 
00219         m_pBuffer = new uchar[ uWidth * uHeight * m_ucPixelSize ];
00220         memcpy( m_pBuffer, pData.getPtr(), uWidth * uHeight * m_ucPixelSize );
00221 
00222         OgreUnguardRet( *this );
00223     }
00224 
00225     //-----------------------------------------------------------------------------
00226     Image & Image::load( const String& strFileName )
00227     {
00228         OgreGuard( "Image::load" );
00229 
00230         if( m_pBuffer )
00231         {
00232             delete[] m_pBuffer;
00233             m_pBuffer = NULL;
00234         }
00235 
00236         String strExt;
00237 
00238         size_t pos = strFileName.find_last_of(".");
00239         if( pos == String::npos )
00240             Except(
00241             Exception::ERR_INVALIDPARAMS, 
00242             "Unable to load image file '" + strFileName + "' - invalid extension.",
00243             "Image::load" );
00244 
00245         while( pos != strFileName.length() - 1 )
00246             strExt += strFileName[++pos];
00247 
00248         Codec * pCodec = Codec::getCodec(strExt);
00249         if( !pCodec )
00250             Except(
00251             Exception::ERR_INVALIDPARAMS, 
00252             "Unable to load image file '" + strFileName + "' - invalid extension.",
00253             "Image::load" );
00254 
00255         SDDataChunk encoded;
00256         DataChunk decoded;
00257 
00258         if( !ArchiveManager::getSingleton()._findResourceData( 
00259             strFileName, 
00260             encoded ) )
00261         {
00262             Except(
00263             Exception::ERR_INVALIDPARAMS, 
00264             "Unable to find image file '" + strFileName + "'.",
00265             "Image::load" );
00266         }
00267 
00268         ImageCodec::ImageData * pData = static_cast< ImageCodec::ImageData * > (
00269             pCodec->decode( encoded, &decoded ) );
00270 
00271         // Get the format and compute the pixel size
00272         m_uWidth = pData->width;
00273         m_uHeight = pData->height;
00274         m_uDepth = pData->depth;
00275         m_uSize = pData->size;
00276         m_eFormat = pData->format;
00277         m_uNumMipmaps = pData->num_mipmaps;
00278         m_ucPixelSize = PF2PS( m_eFormat );
00279         m_uFlags = pData->flags;
00280 
00281         delete pData;
00282 
00283         m_pBuffer = decoded.getPtr();
00284         
00285         OgreUnguardRet( *this );
00286     }
00287 
00288     //-----------------------------------------------------------------------------
00289     Image & Image::load( const DataChunk& chunk, const String& type )
00290     {
00291         OgreGuard( "Image::load" );
00292 
00293         String strType = type;
00294 
00295         Codec * pCodec = Codec::getCodec(strType);
00296         if( !pCodec )
00297             Except(
00298             Exception::ERR_INVALIDPARAMS, 
00299             "Unable to load image - invalid extension.",
00300             "Image::load" );
00301 
00302         DataChunk decoded;
00303 
00304         ImageCodec::ImageData * pData = static_cast< ImageCodec::ImageData * >(
00305             pCodec->decode( chunk, &decoded ) );
00306 
00307         m_uWidth = pData->width;
00308         m_uHeight = pData->height;
00309         m_uDepth = pData->depth;
00310         m_uSize = pData->size;
00311         m_uNumMipmaps = pData->num_mipmaps;
00312         m_uFlags = pData->flags;
00313         
00314         // Get the format and compute the pixel size
00315         m_eFormat = pData->format;
00316         m_ucPixelSize = PF2PS( m_eFormat );
00317 
00318         delete pData;
00319 
00320         m_pBuffer = decoded.getPtr();
00321 
00322         OgreUnguardRet( *this );
00323     }
00324 
00325     //-----------------------------------------------------------------------------
00326     uchar* Image::getData()
00327     {
00328         return m_pBuffer;
00329     }
00330 
00331     //-----------------------------------------------------------------------------
00332     const uchar* Image::getData() const
00333     {
00334         assert( m_pBuffer );
00335         return m_pBuffer;
00336     }
00337 
00338     //-----------------------------------------------------------------------------
00339     size_t Image::getSize() const
00340     {
00341        return m_uSize;
00342     }
00343 
00344     //-----------------------------------------------------------------------------
00345     unsigned short Image::getNumMipmaps() const
00346     {
00347        return m_uNumMipmaps;
00348     }
00349 
00350     //-----------------------------------------------------------------------------
00351     bool Image::hasFlag(const ImageFlags imgFlag)
00352     {
00353         if(m_uFlags & imgFlag)
00354         {
00355             return true;
00356         }
00357         else
00358         {
00359             return false;
00360         }
00361     }
00362 
00363     //-----------------------------------------------------------------------------
00364     ushort Image::getDepth() const
00365     {
00366         return m_uDepth;
00367     }
00368     //-----------------------------------------------------------------------------
00369     ushort Image::getWidth() const
00370     {
00371         return m_uWidth;
00372     }
00373 
00374     //-----------------------------------------------------------------------------
00375     ushort Image::getHeight() const
00376     {
00377         return m_uHeight;
00378     }
00379 
00380     //-----------------------------------------------------------------------------
00381     ushort Image::getRowSpan() const
00382     {
00383         return m_uWidth * m_ucPixelSize;
00384     }
00385 
00386     //-----------------------------------------------------------------------------
00387     PixelFormat Image::getFormat() const
00388     {
00389         return m_eFormat;
00390     }
00391 
00392     //-----------------------------------------------------------------------------
00393     uchar Image::getBPP() const
00394     {
00395         return m_ucPixelSize * 8;
00396     }
00397 
00398     //-----------------------------------------------------------------------------
00399     bool Image::getHasAlpha(void) const
00400     {
00401         return Image::formatHasAlpha(m_eFormat);
00402     }
00403     //-----------------------------------------------------------------------------
00404     bool Image::formatHasAlpha(PixelFormat format)
00405     {
00406         switch( format )
00407         {
00408         case PF_A8:
00409         case PF_A4L4:
00410         case PF_L4A4:
00411         case PF_A4R4G4B4:
00412         case PF_B4G4R4A4:
00413         case PF_A8R8G8B8:
00414         case PF_B8G8R8A8:
00415         case PF_A2R10G10B10:
00416         case PF_B10G10R10A2:
00417             return true;
00418 
00419         case PF_UNKNOWN:
00420         case PF_L8:
00421         case PF_R5G6B5:
00422         case PF_B5G6R5:
00423         case PF_R8G8B8:
00424         case PF_B8G8R8:
00425         default:
00426             return false;
00427         }
00428     }
00429 
00430     void Image::applyGamma( unsigned char *buffer, Real gamma, size_t size, uchar bpp )
00431     {
00432         if( gamma == 1.0f )
00433             return;
00434 
00435         //NB only 24/32-bit supported
00436         if( bpp != 24 && bpp != 32 ) return;
00437 
00438         uint stride = bpp >> 3;
00439 
00440         for( size_t i = 0, j = size / stride; i < j; i++, buffer += stride )
00441         {
00442             float r, g, b;
00443 
00444             r = (float)buffer[0];
00445             g = (float)buffer[1];
00446             b = (float)buffer[2];
00447 
00448             r = r * gamma;
00449             g = g * gamma;
00450             b = b * gamma;
00451 
00452             float scale = 1.0f, tmp;
00453 
00454             if( r > 255.0f && (tmp=(255.0f/r)) < scale )
00455                 scale = tmp;
00456             if( g > 255.0f && (tmp=(255.0f/g)) < scale )
00457                 scale = tmp;
00458             if( b > 255.0f && (tmp=(255.0f/b)) < scale )
00459                 scale = tmp;
00460 
00461             r *= scale; g *= scale; b *= scale;
00462 
00463             buffer[0] = (uchar)r;
00464             buffer[1] = (uchar)g;
00465             buffer[2] = (uchar)b;
00466         }
00467     }
00468 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:14 2004