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