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 // Dependency on IL/ILU for resize
    00033 #include <IL/il.h>
    00034 #include <IL/ilu.h>
    00035 namespace Ogre {
    00036     ImageCodec::~ImageCodec() {
    00037     }
    00038
    00039     //-----------------------------------------------------------------------------
    00040     Image::Image()
    00041         : m_uDepth(0),
    00042           m_uSize(0),
    00043           m_uNumMipmaps(0),
    00044           m_uFlags(0),
    00045           m_pBuffer( NULL ),
    00046           m_bAutoDelete( true )
    00047     {
    00048     }
    00049
    00050     //-----------------------------------------------------------------------------
    00051     Image::Image( const Image &img )
    00052     {
    00053         // call assignment operator
    00054         *this = img;
    00055     }
    00056
    00057     //-----------------------------------------------------------------------------
    00058     Image::~Image()
    00059     {
    00060         //Only delete if this was not a dynamic image (meaning app holds & destroys buffer)
    00061         if( m_pBuffer && m_bAutoDelete )
    00062         {
    00063             delete[] m_pBuffer;
    00064             m_pBuffer = NULL;
    00065         }
    00066     }
    00067
    00068     //-----------------------------------------------------------------------------
    00069     Image & Image::operator = ( const Image &img )
    00070     {
    00071         m_uWidth = img.m_uWidth;
    00072         m_uHeight = img.m_uHeight;
    00073         m_uDepth = img.m_uDepth;
    00074         m_eFormat = img.m_eFormat;
    00075         m_uSize = img.m_uSize;
    00076         m_uFlags = img.m_uFlags;
    00077         m_ucPixelSize = img.m_ucPixelSize;
    00078         m_uNumMipmaps = img.m_uNumMipmaps;
    00079         m_bAutoDelete = img.m_bAutoDelete;
    00080
    00081         //Only create/copy when previous data was not dynamic data
    00082         if( m_bAutoDelete )
    00083         {
    00084             m_pBuffer = new uchar[ m_uSize ];
    00085             memcpy( m_pBuffer, img.m_pBuffer, m_uSize );
    00086         }
    00087         else
    00088         {
    00089             m_pBuffer = img.m_pBuffer;
    00090         }
    00091
    00092         return *this;
    00093     }
    00094
    00095     //-----------------------------------------------------------------------------
    00096     Image & Image::flipAroundY()
    00097     {
    00098         OgreGuard( "Image::flipAroundY" );
    00099
    00100         if( !m_pBuffer )
    00101         {
    00102             Except(
    00103                 Exception::ERR_INTERNAL_ERROR,
    00104                 "Can not flip an unitialized texture",
    00105                 "Image::flipAroundY" );
    00106         }
    00107
    00108         uchar   *pTempBuffer1 = NULL;
    00109         ushort  *pTempBuffer2 = NULL;
    00110         uchar   *pTempBuffer3 = NULL;
    00111         uint    *pTempBuffer4 = NULL;
    00112
    00113         uchar   *src1 = m_pBuffer, *dst1 = NULL;
    00114         ushort  *src2 = (ushort *)m_pBuffer, *dst2 = NULL;
    00115         uchar   *src3 = m_pBuffer, *dst3 = NULL;
    00116         uint    *src4 = (uint *)m_pBuffer, *dst4 = NULL;
    00117
    00118         ushort y;
    00119         switch (m_ucPixelSize)
    00120         {
    00121         case 1:
    00122             pTempBuffer1 = new uchar[m_uWidth * m_uHeight];
    00123             for (y = 0; y < m_uHeight; y++)
    00124             {
    00125                 dst1 = (pTempBuffer1 + ((y * m_uWidth) + m_uWidth - 1));
    00126                 for (ushort x = 0; x < m_uWidth; x++)
    00127                     memcpy(dst1--, src1++, sizeof(uchar));
    00128             }
    00129
    00130             memcpy(m_pBuffer, pTempBuffer1, m_uWidth * m_uHeight * sizeof(uchar));
    00131             delete [] pTempBuffer1;
    00132             break;
    00133
    00134         case 2:
    00135             pTempBuffer2 = new ushort[m_uWidth * m_uHeight];
    00136             for (y = 0; y < m_uHeight; y++)
    00137             {
    00138                 dst2 = (pTempBuffer2 + ((y * m_uWidth) + m_uWidth - 1));
    00139                 for (ushort x = 0; x < m_uWidth; x++)
    00140                     memcpy(dst2--, src2++, sizeof(ushort));
    00141             }
    00142
    00143             memcpy(m_pBuffer, pTempBuffer2, m_uWidth * m_uHeight * sizeof(ushort));
    00144             delete [] pTempBuffer2;
    00145             break;
    00146
    00147         case 3:
    00148             pTempBuffer3 = new uchar[m_uWidth * m_uHeight * 3];
    00149             for (y = 0; y < m_uHeight; y++)
    00150             {
    00151                 uint offset = ((y * m_uWidth) + (m_uWidth - 1)) * 3;
    00152                 dst3 = pTempBuffer3;
    00153                 dst3 += offset;
    00154                 for (ushort x = 0; x < m_uWidth; x++)
    00155                 {
    00156                     memcpy(dst3, src3, sizeof(uchar) * 3);
    00157                     dst3 -= 3; src3 += 3;
    00158                 }
    00159             }
    00160
    00161             memcpy(m_pBuffer, pTempBuffer3, m_uWidth * m_uHeight * sizeof(uchar) * 3);
    00162             delete [] pTempBuffer3;
    00163             break;
    00164
    00165         case 4:
    00166             pTempBuffer4 = new uint[m_uWidth * m_uHeight];
    00167             for (y = 0; y < m_uHeight; y++)
    00168             {
    00169                 dst4 = (pTempBuffer4 + ((y * m_uWidth) + m_uWidth - 1));
    00170                 for (ushort x = 0; x < m_uWidth; x++)
    00171                     memcpy(dst4--, src4++, sizeof(uint));
    00172             }
    00173
    00174             memcpy(m_pBuffer, pTempBuffer4, m_uWidth * m_uHeight * sizeof(uint));
    00175             delete [] pTempBuffer4;
    00176             break;
    00177
    00178         default:
    00179             Except(
    00180                 Exception::ERR_INTERNAL_ERROR,
    00181                 "Unknown pixel depth",
    00182                 "Image::flipAroundY" );
    00183             break;
    00184         }
    00185
    00186         OgreUnguardRet( *this );
    00187     }
    00188
    00189     //-----------------------------------------------------------------------------
    00190     Image & Image::flipAroundX()
    00191     {
    00192         OgreGuard( "Image::flipAroundX" );
    00193
    00194         if( !m_pBuffer )
    00195         {
    00196             Except(
    00197                 Exception::ERR_INTERNAL_ERROR,
    00198                 "Can not flip an unitialized texture",
    00199                 "Image::flipAroundX" );
    00200         }
    00201
    00202         size_t rowSpan = m_uWidth * m_ucPixelSize;
    00203
    00204         uchar *pTempBuffer = new uchar[ rowSpan * m_uHeight ];
    00205         uchar *ptr1 = m_pBuffer, *ptr2 = pTempBuffer + ( ( m_uHeight - 1 ) * rowSpan );
    00206
    00207         for( ushort i = 0; i < m_uHeight; i++ )
    00208         {
    00209             memcpy( ptr2, ptr1, rowSpan );
    00210             ptr1 += rowSpan; ptr2 -= rowSpan;
    00211         }
    00212
    00213         memcpy( m_pBuffer, pTempBuffer, rowSpan * m_uHeight);
    00214
    00215         delete [] pTempBuffer;
    00216
    00217         OgreUnguardRet( *this );
    00218     }
    00219
    00220     //-----------------------------------------------------------------------------
    00221     Image& Image::loadDynamicImage( uchar* pData, ushort uWidth, ushort uHeight,
    00222                              PixelFormat eFormat )
    00223     {
    00224         OgreGuard( "Image::loadDynamicImage" );
    00225
    00226         m_uWidth = uWidth;
    00227         m_uHeight = uHeight;
    00228         m_eFormat = eFormat;
    00229         m_ucPixelSize = PF2PS( m_eFormat );
    00230         m_uSize = m_uWidth * m_uHeight * m_ucPixelSize;
    00231
    00232         m_pBuffer = pData;
    00233
    00234         m_bAutoDelete = false;
    00235
    00236         OgreUnguardRet( *this );
    00237     }
    00238
    00239     //-----------------------------------------------------------------------------
    00240     Image & Image::loadRawData(
    00241         const DataChunk &pData,
    00242         ushort uWidth, ushort uHeight,
    00243         PixelFormat eFormat )
    00244     {
    00245         OgreGuard( "Image::loadRawData" );
    00246
    00247         m_uWidth = uWidth;
    00248         m_uHeight = uHeight;
    00249         m_eFormat = eFormat;
    00250         m_ucPixelSize = PF2PS( m_eFormat );
    00251         m_uSize = m_uWidth * m_uHeight * m_ucPixelSize;
    00252
    00253         m_pBuffer = new uchar[ uWidth * uHeight * m_ucPixelSize ];
    00254         memcpy( m_pBuffer, pData.getPtr(), uWidth * uHeight * m_ucPixelSize );
    00255
    00256         OgreUnguardRet( *this );
    00257     }
    00258
    00259     //-----------------------------------------------------------------------------
    00260     Image & Image::load( const String& strFileName )
    00261     {
    00262         OgreGuard( "Image::load" );
    00263
    00264         if( m_pBuffer )
    00265         {
    00266             delete[] m_pBuffer;
    00267             m_pBuffer = NULL;
    00268         }
    00269
    00270         String strExt;
    00271
    00272         size_t pos = strFileName.find_last_of(".");
    00273         if( pos == String::npos )
    00274             Except(
    00275             Exception::ERR_INVALIDPARAMS,
    00276             "Unable to load image file '" + strFileName + "' - invalid extension.",
    00277             "Image::load" );
    00278
    00279         while( pos != strFileName.length() - 1 )
    00280             strExt += strFileName[++pos];
    00281
    00282         Codec * pCodec = Codec::getCodec(strExt);
    00283         if( !pCodec )
    00284             Except(
    00285             Exception::ERR_INVALIDPARAMS,
    00286             "Unable to load image file '" + strFileName + "' - invalid extension.",
    00287             "Image::load" );
    00288
    00289         SDDataChunk encoded;
    00290         DataChunk decoded;
    00291
    00292         if( !ArchiveManager::getSingleton()._findResourceData(
    00293             strFileName,
    00294             encoded ) )
    00295         {
    00296             Except(
    00297             Exception::ERR_INVALIDPARAMS,
    00298             "Unable to find image file '" + strFileName + "'.",
    00299             "Image::load" );
    00300         }
    00301
    00302         ImageCodec::ImageData * pData = static_cast< ImageCodec::ImageData * > (
    00303             pCodec->decode( encoded, &decoded ) );
    00304
    00305         // Get the format and compute the pixel size
    00306         m_uWidth = pData->width;
    00307         m_uHeight = pData->height;
    00308         m_uDepth = pData->depth;
    00309         m_uSize = pData->size;
    00310         m_eFormat = pData->format;
    00311         m_uNumMipmaps = pData->num_mipmaps;
    00312         m_ucPixelSize = PF2PS( m_eFormat );
    00313         m_uFlags = pData->flags;
    00314
    00315         delete pData;
    00316
    00317         m_pBuffer = decoded.getPtr();
    00318
    00319         OgreUnguardRet( *this );
    00320     }
    00321     //-----------------------------------------------------------------------------
    00322     void Image::save(const String& filename)
    00323     {
    00324         if( !m_pBuffer )
    00325         {
    00326             Except(Exception::ERR_INVALIDPARAMS, "No image data loaded",
    00327                 "Image::save");
    00328         }
    00329
    00330         String strExt;
    00331         size_t pos = filename.find_last_of(".");
    00332         if( pos == String::npos )
    00333             Except(
    00334             Exception::ERR_INVALIDPARAMS,
    00335             "Unable to save image file '" + filename + "' - invalid extension.",
    00336             "Image::save" );
    00337
    00338         while( pos != filename.length() - 1 )
    00339             strExt += filename[++pos];
    00340
    00341         Codec * pCodec = Codec::getCodec(strExt);
    00342         if( !pCodec )
    00343             Except(
    00344             Exception::ERR_INVALIDPARAMS,
    00345             "Unable to save image file '" + filename + "' - invalid extension.",
    00346             "Image::save" );
    00347
    00348         ImageCodec::ImageData imgData;
    00349         imgData.format = m_eFormat;
    00350         imgData.height = m_uHeight;
    00351         imgData.width = m_uWidth;
    00352         DataChunk wrapper(m_pBuffer, m_uSize);
    00353
    00354         pCodec->codeToFile(wrapper, filename, &imgData);
    00355     }
    00356     //-----------------------------------------------------------------------------
    00357     Image & Image::load( const DataChunk& chunk, const String& type )
    00358     {
    00359         OgreGuard( "Image::load" );
    00360
    00361         String strType = type;
    00362
    00363         Codec * pCodec = Codec::getCodec(strType);
    00364         if( !pCodec )
    00365             Except(
    00366             Exception::ERR_INVALIDPARAMS,
    00367             "Unable to load image - invalid extension.",
    00368             "Image::load" );
    00369
    00370         DataChunk decoded;
    00371
    00372         ImageCodec::ImageData * pData = static_cast< ImageCodec::ImageData * >(
    00373             pCodec->decode( chunk, &decoded ) );
    00374
    00375         m_uWidth = pData->width;
    00376         m_uHeight = pData->height;
    00377         m_uDepth = pData->depth;
    00378         m_uSize = pData->size;
    00379         m_uNumMipmaps = pData->num_mipmaps;
    00380         m_uFlags = pData->flags;
    00381
    00382         // Get the format and compute the pixel size
    00383         m_eFormat = pData->format;
    00384         m_ucPixelSize = PF2PS( m_eFormat );
    00385
    00386         delete pData;
    00387
    00388         m_pBuffer = decoded.getPtr();
    00389
    00390         OgreUnguardRet( *this );
    00391     }
    00392
    00393     //-----------------------------------------------------------------------------
    00394     uchar* Image::getData()
    00395     {
    00396         return m_pBuffer;
    00397     }
    00398
    00399     //-----------------------------------------------------------------------------
    00400     const uchar* Image::getData() const
    00401     {
    00402         assert( m_pBuffer );
    00403         return m_pBuffer;
    00404     }
    00405
    00406     //-----------------------------------------------------------------------------
    00407     size_t Image::getSize() const
    00408     {
    00409        return m_uSize;
    00410     }
    00411
    00412     //-----------------------------------------------------------------------------
    00413     unsigned short Image::getNumMipmaps() const
    00414     {
    00415        return m_uNumMipmaps;
    00416     }
    00417
    00418     //-----------------------------------------------------------------------------
    00419     bool Image::hasFlag(const ImageFlags imgFlag) const
    00420     {
    00421         if(m_uFlags & imgFlag)
    00422         {
    00423             return true;
    00424         }
    00425         else
    00426         {
    00427             return false;
    00428         }
    00429     }
    00430
    00431     //-----------------------------------------------------------------------------
    00432     ushort Image::getDepth() const
    00433     {
    00434         return m_uDepth;
    00435     }
    00436     //-----------------------------------------------------------------------------
    00437     ushort Image::getWidth() const
    00438     {
    00439         return m_uWidth;
    00440     }
    00441
    00442     //-----------------------------------------------------------------------------
    00443     ushort Image::getHeight() const
    00444     {
    00445         return m_uHeight;
    00446     }
    00447
    00448     //-----------------------------------------------------------------------------
    00449     ushort Image::getRowSpan() const
    00450     {
    00451         return m_uWidth * m_ucPixelSize;
    00452     }
    00453
    00454     //-----------------------------------------------------------------------------
    00455     PixelFormat Image::getFormat() const
    00456     {
    00457         return m_eFormat;
    00458     }
    00459
    00460     //-----------------------------------------------------------------------------
    00461     uchar Image::getBPP() const
    00462     {
    00463         return m_ucPixelSize * 8;
    00464     }
    00465
    00466     //-----------------------------------------------------------------------------
    00467     bool Image::getHasAlpha(void) const
    00468     {
    00469         return Image::formatHasAlpha(m_eFormat);
    00470     }
    00471     //-----------------------------------------------------------------------------
    00472     bool Image::formatHasAlpha(PixelFormat format)
    00473     {
    00474         switch( format )
    00475         {
    00476         case PF_A8:
    00477         case PF_A4L4:
    00478         case PF_L4A4:
    00479         case PF_A4R4G4B4:
    00480         case PF_B4G4R4A4:
    00481         case PF_A8R8G8B8:
    00482         case PF_B8G8R8A8:
    00483         case PF_A2R10G10B10:
    00484         case PF_B10G10R10A2:
    00485             return true;
    00486
    00487         case PF_UNKNOWN:
    00488         case PF_L8:
    00489         case PF_R5G6B5:
    00490         case PF_B5G6R5:
    00491         case PF_R8G8B8:
    00492         case PF_B8G8R8:
    00493         default:
    00494             return false;
    00495         }
    00496     }
    00497     //-----------------------------------------------------------------------------
    00498     void Image::applyGamma( unsigned char *buffer, Real gamma, size_t size, uchar bpp )
    00499     {
    00500         if( gamma == 1.0f )
    00501             return;
    00502
    00503         //NB only 24/32-bit supported
    00504         if( bpp != 24 && bpp != 32 ) return;
    00505
    00506         uint stride = bpp >> 3;
    00507
    00508         for( size_t i = 0, j = size / stride; i < j; i++, buffer += stride )
    00509         {
    00510             float r, g, b;
    00511
    00512             r = (float)buffer[0];
    00513             g = (float)buffer[1];
    00514             b = (float)buffer[2];
    00515
    00516             r = r * gamma;
    00517             g = g * gamma;
    00518             b = b * gamma;
    00519
    00520             float scale = 1.0f, tmp;
    00521
    00522             if( r > 255.0f && (tmp=(255.0f/r)) < scale )
    00523                 scale = tmp;
    00524             if( g > 255.0f && (tmp=(255.0f/g)) < scale )
    00525                 scale = tmp;
    00526             if( b > 255.0f && (tmp=(255.0f/b)) < scale )
    00527                 scale = tmp;
    00528
    00529             r *= scale; g *= scale; b *= scale;
    00530
    00531             buffer[0] = (uchar)r;
    00532             buffer[1] = (uchar)g;
    00533             buffer[2] = (uchar)b;
    00534         }
    00535     }
    00536     //-----------------------------------------------------------------------------
    00537     // Local declaration of DevIL functions to prevent DevIL dependencies on header users
    00538     ILenum getILFilter(Image::Filter filter)
    00539     {
    00540         switch (filter)
    00541         {
    00542             case Image::FILTER_NEAREST:
    00543                 return ILU_NEAREST;
    00544             case Image::FILTER_LINEAR:
    00545                 return ILU_LINEAR;
    00546             case Image::FILTER_BILINEAR:
    00547                 return ILU_BILINEAR;
    00548             case Image::FILTER_BOX:
    00549                 return ILU_SCALE_BOX;
    00550             case Image::FILTER_TRIANGLE:
    00551                 return ILU_SCALE_TRIANGLE;
    00552             case Image::FILTER_BICUBIC:
    00553                 return ILU_SCALE_BSPLINE;
    00554         };
    00555         // keep compiler happy
    00556         return ILU_NEAREST;
    00557     }
    00558     //-----------------------------------------------------------------------------
    00559     void Image::resize(ushort width, ushort height, Filter filter)
    00560     {
    00561         ILuint ImageName;
    00562
    00563         ilGenImages( 1, &ImageName );
    00564         ilBindImage( ImageName );
    00565
    00566         std::pair< int, int > fmt_bpp = OgreFormat2ilFormat( m_eFormat );
    00567         ilTexImage(
    00568             m_uWidth, m_uHeight, 1, fmt_bpp.second, fmt_bpp.first, IL_UNSIGNED_BYTE,
    00569             static_cast< void * >( m_pBuffer ) );
    00570
    00571         // set filter
    00572         iluImageParameter(ILU_FILTER, getILFilter(filter));
    00573
    00574         iluScale(width, height, 1);
    00575
    00576         // delete existing buffer and recreate with new settings
    00577         delete [] m_pBuffer;
    00578         m_uWidth = width;
    00579         m_uHeight = height;
    00580         size_t dataSize = width * height * m_ucPixelSize;
    00581         m_pBuffer = new uchar[dataSize];
    00582         memcpy(m_pBuffer, ilGetData(), dataSize);
    00583
    00584         ilDeleteImages(1, &ImageName);
    00585
    00586         // return to default filter
    00587         iluImageParameter(ILU_FILTER, ILU_NEAREST);
    00588     }
    00589
    00590 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:30 2004