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