Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreImage.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 20.7 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreStableHeaders.h"
30#include "OgreImage.h"
31#include "OgreArchiveManager.h"
32#include "OgreException.h"
33#include "OgreImageCodec.h"
34#include "OgreColourValue.h"
35
36#include "OgreImageResampler.h"
37
38namespace Ogre {
39        ImageCodec::~ImageCodec() {
40        }
41
42        //-----------------------------------------------------------------------------
43        Image::Image()
44                : m_uWidth(0),
45                m_uHeight(0),
46                m_uDepth(0),
47                m_uSize(0),
48                m_uNumMipmaps(0),
49                m_uFlags(0),
50                m_pBuffer( NULL ),
51                m_bAutoDelete( true )
52        {
53        }
54
55        //-----------------------------------------------------------------------------
56        Image::Image( const Image &img )
57                : m_pBuffer( NULL ),
58                m_bAutoDelete( true )
59        {
60                // call assignment operator
61                *this = img;
62        }
63
64        //-----------------------------------------------------------------------------
65        Image::~Image()
66        {
67                //Only delete if this was not a dynamic image (meaning app holds & destroys buffer)
68                if( m_pBuffer && m_bAutoDelete )
69                {
70                        delete[] m_pBuffer;
71                        m_pBuffer = NULL;
72                }
73        }
74
75        //-----------------------------------------------------------------------------
76        Image & Image::operator = ( const Image &img )
77        {
78                if( m_pBuffer && m_bAutoDelete )
79                {
80                        delete[] m_pBuffer;
81                        m_pBuffer = NULL;
82                }
83                m_uWidth = img.m_uWidth;
84                m_uHeight = img.m_uHeight;
85                m_uDepth = img.m_uDepth;
86                m_eFormat = img.m_eFormat;
87                m_uSize = img.m_uSize;
88                m_uFlags = img.m_uFlags;
89                m_ucPixelSize = img.m_ucPixelSize;
90                m_uNumMipmaps = img.m_uNumMipmaps;
91                m_bAutoDelete = img.m_bAutoDelete;
92                //Only create/copy when previous data was not dynamic data
93                if( m_bAutoDelete )
94                {
95                        m_pBuffer = new uchar[ m_uSize ];
96                        memcpy( m_pBuffer, img.m_pBuffer, m_uSize );
97                }
98                else
99                {
100                        m_pBuffer = img.m_pBuffer;
101                }
102
103                return *this;
104        }
105
106        //-----------------------------------------------------------------------------
107        Image & Image::flipAroundY()
108        {
109                if( !m_pBuffer )
110                {
111                        OGRE_EXCEPT( 
112                                Exception::ERR_INTERNAL_ERROR,
113                                "Can not flip an unitialized texture",
114                                "Image::flipAroundY" );
115                }
116       
117         m_uNumMipmaps = 0; // Image operations lose precomputed mipmaps
118
119                uchar   *pTempBuffer1 = NULL;
120                ushort  *pTempBuffer2 = NULL;
121                uchar   *pTempBuffer3 = NULL;
122                uint    *pTempBuffer4 = NULL;
123
124                uchar   *src1 = m_pBuffer, *dst1 = NULL;
125                ushort  *src2 = (ushort *)m_pBuffer, *dst2 = NULL;
126                uchar   *src3 = m_pBuffer, *dst3 = NULL;
127                uint    *src4 = (uint *)m_pBuffer, *dst4 = NULL;
128
129                ushort y;
130                switch (m_ucPixelSize)
131                {
132                case 1:
133                        pTempBuffer1 = new uchar[m_uWidth * m_uHeight];
134                        for (y = 0; y < m_uHeight; y++)
135                        {
136                                dst1 = (pTempBuffer1 + ((y * m_uWidth) + m_uWidth - 1));
137                                for (ushort x = 0; x < m_uWidth; x++)
138                                        memcpy(dst1--, src1++, sizeof(uchar));
139                        }
140
141                        memcpy(m_pBuffer, pTempBuffer1, m_uWidth * m_uHeight * sizeof(uchar));
142                        delete [] pTempBuffer1;
143                        break;
144
145                case 2:
146                        pTempBuffer2 = new ushort[m_uWidth * m_uHeight];
147                        for (y = 0; y < m_uHeight; y++)
148                        {
149                                dst2 = (pTempBuffer2 + ((y * m_uWidth) + m_uWidth - 1));
150                                for (ushort x = 0; x < m_uWidth; x++)
151                                        memcpy(dst2--, src2++, sizeof(ushort));
152                        }
153
154                        memcpy(m_pBuffer, pTempBuffer2, m_uWidth * m_uHeight * sizeof(ushort));
155                        delete [] pTempBuffer2;
156                        break;
157
158                case 3:
159                        pTempBuffer3 = new uchar[m_uWidth * m_uHeight * 3];
160                        for (y = 0; y < m_uHeight; y++)
161                        {
162                                size_t offset = ((y * m_uWidth) + (m_uWidth - 1)) * 3;
163                                dst3 = pTempBuffer3;
164                                dst3 += offset;
165                                for (size_t x = 0; x < m_uWidth; x++)
166                                {
167                                        memcpy(dst3, src3, sizeof(uchar) * 3);
168                                        dst3 -= 3; src3 += 3;
169                                }
170                        }
171
172                        memcpy(m_pBuffer, pTempBuffer3, m_uWidth * m_uHeight * sizeof(uchar) * 3);
173                        delete [] pTempBuffer3;
174                        break;
175
176                case 4:
177                        pTempBuffer4 = new uint[m_uWidth * m_uHeight];
178                        for (y = 0; y < m_uHeight; y++)
179                        {
180                                dst4 = (pTempBuffer4 + ((y * m_uWidth) + m_uWidth - 1));
181                                for (ushort x = 0; x < m_uWidth; x++)
182                                        memcpy(dst4--, src4++, sizeof(uint));
183                        }
184
185                        memcpy(m_pBuffer, pTempBuffer4, m_uWidth * m_uHeight * sizeof(uint));
186                        delete [] pTempBuffer4;
187                        break;
188
189                default:
190                        OGRE_EXCEPT( 
191                                Exception::ERR_INTERNAL_ERROR,
192                                "Unknown pixel depth",
193                                "Image::flipAroundY" );
194                        break;
195                }
196
197                return *this;
198
199        }
200
201        //-----------------------------------------------------------------------------
202        Image & Image::flipAroundX()
203        {
204                if( !m_pBuffer )
205                {
206                        OGRE_EXCEPT( 
207                                Exception::ERR_INTERNAL_ERROR,
208                                "Can not flip an unitialized texture",
209                                "Image::flipAroundX" );
210                }
211       
212        m_uNumMipmaps = 0; // Image operations lose precomputed mipmaps
213
214                size_t rowSpan = m_uWidth * m_ucPixelSize;
215
216                uchar *pTempBuffer = new uchar[ rowSpan * m_uHeight ];
217                uchar *ptr1 = m_pBuffer, *ptr2 = pTempBuffer + ( ( m_uHeight - 1 ) * rowSpan );
218
219                for( ushort i = 0; i < m_uHeight; i++ )
220                {
221                        memcpy( ptr2, ptr1, rowSpan );
222                        ptr1 += rowSpan; ptr2 -= rowSpan;
223                }
224
225                memcpy( m_pBuffer, pTempBuffer, rowSpan * m_uHeight);
226
227                delete [] pTempBuffer;
228
229                return *this;
230        }
231
232        //-----------------------------------------------------------------------------
233        Image& Image::loadDynamicImage( uchar* pData, size_t uWidth, size_t uHeight, 
234                size_t depth,
235                PixelFormat eFormat, bool autoDelete, 
236                size_t numFaces, size_t numMipMaps)
237        {
238
239                if( m_pBuffer && m_bAutoDelete )
240                {
241                        delete[] m_pBuffer;
242                        m_pBuffer = NULL;
243                }
244                // Set image metadata
245                m_uWidth = uWidth;
246                m_uHeight = uHeight;
247                m_uDepth = depth;
248                m_eFormat = eFormat;
249                m_ucPixelSize = static_cast<uchar>(PixelUtil::getNumElemBytes( m_eFormat ));
250                m_uNumMipmaps = numMipMaps;
251                m_uFlags = 0;
252                // Set flags
253                if (PixelUtil::isCompressed(eFormat))
254                        m_uFlags |= IF_COMPRESSED;
255                if (m_uDepth != 1)
256                        m_uFlags |= IF_3D_TEXTURE;
257                if(numFaces == 6)
258                        m_uFlags |= IF_CUBEMAP;
259                if(numFaces != 6 && numFaces != 1)
260                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
261                        "Number of faces currently must be 6 or 1.", 
262                        "Image::loadDynamicImage");
263
264                m_uSize = calculateSize(numMipMaps, numFaces, uWidth, uHeight, depth, eFormat);
265                m_pBuffer = pData;
266                m_bAutoDelete = autoDelete;
267
268                return *this;
269
270        }
271
272        //-----------------------------------------------------------------------------
273        Image & Image::loadRawData(
274                DataStreamPtr& stream, 
275                size_t uWidth, size_t uHeight, size_t uDepth,
276                PixelFormat eFormat,
277                size_t numFaces, size_t numMipMaps)
278        {
279
280                size_t size = calculateSize(numMipMaps, numFaces, uWidth, uHeight, uDepth, eFormat);
281                if (size != stream->size())
282                {
283                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
284                                "Stream size does not match calculated image size", 
285                                "Image::loadRawData");
286                }
287
288                uchar *buffer = new uchar[ size ];
289                stream->read(buffer, size);
290
291                return loadDynamicImage(buffer,
292                        uWidth, uHeight, uDepth,
293                        eFormat, true, numFaces, numMipMaps);
294
295        }
296
297        //-----------------------------------------------------------------------------
298        Image & Image::load(const String& strFileName, const String& group)
299        {
300
301                if( m_pBuffer && m_bAutoDelete )
302                {
303                        delete[] m_pBuffer;
304                        m_pBuffer = NULL;
305                }
306
307                String strExt;
308
309                size_t pos = strFileName.find_last_of(".");
310                if( pos == String::npos )
311                        OGRE_EXCEPT(
312                        Exception::ERR_INVALIDPARAMS, 
313                        "Unable to load image file '" + strFileName + "' - invalid extension.",
314                        "Image::load" );
315
316                while( pos != strFileName.length() - 1 )
317                        strExt += strFileName[++pos];
318
319                Codec * pCodec = Codec::getCodec(strExt);
320                if( !pCodec )
321                        OGRE_EXCEPT(
322                        Exception::ERR_INVALIDPARAMS, 
323                        "Unable to load image file '" + strFileName + "' - invalid extension.",
324                        "Image::load" );
325
326                DataStreamPtr encoded = 
327                        ResourceGroupManager::getSingleton().openResource(strFileName, group);
328
329                Codec::DecodeResult res = pCodec->decode(encoded);
330
331                ImageCodec::ImageData* pData = 
332                        static_cast<ImageCodec::ImageData*>(res.second.getPointer());
333
334                // Get the format and compute the pixel size
335                m_uWidth = pData->width;
336                m_uHeight = pData->height;
337                m_uDepth = pData->depth;
338                m_uSize = pData->size;
339                m_eFormat = pData->format;
340                m_uNumMipmaps = pData->num_mipmaps;
341                m_ucPixelSize = static_cast<uchar>(PixelUtil::getNumElemBytes( m_eFormat ));
342                m_uFlags = pData->flags;
343
344                // re-use the decoded buffer
345                m_pBuffer = res.first->getPtr();
346                // ensure we don't delete when stream is closed
347                res.first->setFreeOnClose(false);
348
349                return *this;
350
351        }
352        //-----------------------------------------------------------------------------
353        void Image::save(const String& filename)
354        {
355                if( !m_pBuffer )
356                {
357                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "No image data loaded", 
358                                "Image::save");
359                }
360
361                String strExt;
362                size_t pos = filename.find_last_of(".");
363                if( pos == String::npos )
364                        OGRE_EXCEPT(
365                        Exception::ERR_INVALIDPARAMS, 
366                        "Unable to save image file '" + filename + "' - invalid extension.",
367                        "Image::save" );
368
369                while( pos != filename.length() - 1 )
370                        strExt += filename[++pos];
371
372                Codec * pCodec = Codec::getCodec(strExt);
373                if( !pCodec )
374                        OGRE_EXCEPT(
375                        Exception::ERR_INVALIDPARAMS, 
376                        "Unable to save image file '" + filename + "' - invalid extension.",
377                        "Image::save" );
378
379                ImageCodec::ImageData* imgData = new ImageCodec::ImageData();
380                imgData->format = m_eFormat;
381                imgData->height = m_uHeight;
382                imgData->width = m_uWidth;
383                imgData->depth = m_uDepth;
384                // Wrap in CodecDataPtr, this will delete
385                Codec::CodecDataPtr codeDataPtr(imgData);
386                // Wrap memory, be sure not to delete when stream destroyed
387                MemoryDataStreamPtr wrapper(new MemoryDataStream(m_pBuffer, m_uSize, false));
388
389                pCodec->codeToFile(wrapper, filename, codeDataPtr);
390        }
391        //-----------------------------------------------------------------------------
392        Image & Image::load(DataStreamPtr& stream, const String& type )
393        {
394                if( m_pBuffer && m_bAutoDelete )
395                {
396                        delete[] m_pBuffer;
397                        m_pBuffer = NULL;
398                }
399
400                String strType = type;
401
402                Codec * pCodec = Codec::getCodec(strType);
403                if( !pCodec )
404                        OGRE_EXCEPT(
405                        Exception::ERR_INVALIDPARAMS, 
406                        "Unable to load image - invalid extension.",
407                        "Image::load" );
408
409                Codec::DecodeResult res = pCodec->decode(stream);
410
411                ImageCodec::ImageData* pData = 
412                        static_cast<ImageCodec::ImageData*>(res.second.getPointer());
413
414                m_uWidth = pData->width;
415                m_uHeight = pData->height;
416                m_uDepth = pData->depth;
417                m_uSize = pData->size;
418                m_uNumMipmaps = pData->num_mipmaps;
419                m_uFlags = pData->flags;
420
421                // Get the format and compute the pixel size
422                m_eFormat = pData->format;
423                m_ucPixelSize = static_cast<uchar>(PixelUtil::getNumElemBytes( m_eFormat ));
424                // Just use internal buffer of returned memory stream
425                m_pBuffer = res.first->getPtr();
426                // Make sure stream does not delete
427                res.first->setFreeOnClose(false);
428
429                return *this;
430        }
431
432        //-----------------------------------------------------------------------------
433        uchar* Image::getData()
434        {
435                return m_pBuffer;
436        }
437
438        //-----------------------------------------------------------------------------
439        const uchar* Image::getData() const
440        {
441                assert( m_pBuffer );
442                return m_pBuffer;
443        }
444
445        //-----------------------------------------------------------------------------
446        size_t Image::getSize() const
447        {
448                return m_uSize;
449        }
450
451        //-----------------------------------------------------------------------------
452        size_t Image::getNumMipmaps() const
453        {
454                return m_uNumMipmaps;
455        }
456
457        //-----------------------------------------------------------------------------
458        bool Image::hasFlag(const ImageFlags imgFlag) const
459        {
460                if(m_uFlags & imgFlag)
461                {
462                        return true;
463                }
464                else
465                {
466                        return false;
467                }
468        }
469
470        //-----------------------------------------------------------------------------
471        size_t Image::getDepth() const
472        {
473                return m_uDepth;
474        }
475        //-----------------------------------------------------------------------------
476        size_t Image::getWidth() const
477        {
478                return m_uWidth;
479        }
480
481        //-----------------------------------------------------------------------------
482        size_t Image::getHeight() const
483        {
484                return m_uHeight;
485        }
486        //-----------------------------------------------------------------------------
487        size_t Image::getNumFaces(void) const
488        {
489                if(hasFlag(IF_CUBEMAP))
490                        return 6;
491                return 1;
492        }
493        //-----------------------------------------------------------------------------
494        size_t Image::getRowSpan() const
495        {
496                return m_uWidth * m_ucPixelSize;
497        }
498
499        //-----------------------------------------------------------------------------
500        PixelFormat Image::getFormat() const
501        {
502                return m_eFormat;
503        }
504
505        //-----------------------------------------------------------------------------
506        uchar Image::getBPP() const
507        {
508                return m_ucPixelSize * 8;
509        }
510
511        //-----------------------------------------------------------------------------
512        bool Image::getHasAlpha(void) const
513        {
514                return PixelUtil::getFlags(m_eFormat) & PFF_HASALPHA;
515        }
516        //-----------------------------------------------------------------------------
517        void Image::applyGamma( unsigned char *buffer, Real gamma, size_t size, uchar bpp )
518        {
519                if( gamma == 1.0f )
520                        return;
521
522                //NB only 24/32-bit supported
523                if( bpp != 24 && bpp != 32 ) return;
524
525                uint stride = bpp >> 3;
526
527                for( size_t i = 0, j = size / stride; i < j; i++, buffer += stride )
528                {
529                        float r, g, b;
530
531                        r = (float)buffer[0];
532                        g = (float)buffer[1];
533                        b = (float)buffer[2];
534
535                        r = r * gamma;
536                        g = g * gamma;
537                        b = b * gamma;
538
539                        float scale = 1.0f, tmp;
540
541                        if( r > 255.0f && (tmp=(255.0f/r)) < scale )
542                                scale = tmp;
543                        if( g > 255.0f && (tmp=(255.0f/g)) < scale )
544                                scale = tmp;
545                        if( b > 255.0f && (tmp=(255.0f/b)) < scale )
546                                scale = tmp;
547
548                        r *= scale; g *= scale; b *= scale;
549
550                        buffer[0] = (uchar)r;
551                        buffer[1] = (uchar)g;
552                        buffer[2] = (uchar)b;
553                }
554        }
555        //-----------------------------------------------------------------------------
556        void Image::resize(ushort width, ushort height, Filter filter)
557        {
558                // resizing dynamic images is not supported
559                assert(m_bAutoDelete);
560                assert(m_uDepth == 1);
561
562                // reassign buffer to temp image, make sure auto-delete is true
563                Image temp;
564                temp.loadDynamicImage(m_pBuffer, m_uWidth, m_uHeight, 1, m_eFormat, true);
565                // do not delete[] m_pBuffer!  temp will destroy it
566
567                // set new dimensions, allocate new buffer
568                m_uWidth = width;
569                m_uHeight = height;
570                m_uSize = PixelUtil::getMemorySize(m_uWidth, m_uHeight, 1, m_eFormat);
571                m_pBuffer = new uchar[m_uSize];
572        m_uNumMipmaps = 0; // Loses precomputed mipmaps
573
574                // scale the image from temp into our resized buffer
575                Image::scale(temp.getPixelBox(), getPixelBox(), filter);
576        }
577        //-----------------------------------------------------------------------
578        void Image::scale(const PixelBox &src, const PixelBox &scaled, Filter filter) 
579        {
580                assert(PixelUtil::isAccessible(src.format));
581                assert(PixelUtil::isAccessible(scaled.format));
582                MemoryDataStreamPtr buf; // For auto-delete
583                PixelBox temp;
584                switch (filter) 
585                {
586                default:
587                case FILTER_NEAREST:
588                        if(src.format == scaled.format) 
589                        {
590                                // No intermediate buffer needed
591                                temp = scaled;
592                        }
593                        else
594                        {
595                                // Allocate temporary buffer of destination size in source format
596                                temp = PixelBox(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.format);
597                                buf.bind(new MemoryDataStream(temp.getConsecutiveSize()));
598                                temp.data = buf->getPtr();
599                        }
600                        // super-optimized: no conversion
601                        switch (PixelUtil::getNumElemBytes(src.format)) 
602                        {
603                        case 1: NearestResampler<1>::scale(src, temp); break;
604                        case 2: NearestResampler<2>::scale(src, temp); break;
605                        case 3: NearestResampler<3>::scale(src, temp); break;
606                        case 4: NearestResampler<4>::scale(src, temp); break;
607                        case 6: NearestResampler<6>::scale(src, temp); break;
608                        case 8: NearestResampler<8>::scale(src, temp); break;
609                        case 12: NearestResampler<12>::scale(src, temp); break;
610                        case 16: NearestResampler<16>::scale(src, temp); break;
611                        default:
612                                // never reached
613                                assert(false);
614                        }
615                        if(temp.data != scaled.data)
616                        {
617                                // Blit temp buffer
618                                PixelUtil::bulkPixelConversion(temp, scaled);
619                        }
620                        break;
621
622                case FILTER_LINEAR:
623                case FILTER_BILINEAR:
624                        switch (src.format) 
625                        {
626                        case PF_L8: case PF_A8: case PF_BYTE_LA:
627                        case PF_R8G8B8: case PF_B8G8R8:
628                        case PF_R8G8B8A8: case PF_B8G8R8A8:
629                        case PF_A8B8G8R8: case PF_A8R8G8B8:
630                        case PF_X8B8G8R8: case PF_X8R8G8B8:
631                                if(src.format == scaled.format) 
632                                {
633                                        // No intermediate buffer needed
634                                        temp = scaled;
635                                }
636                                else
637                                {
638                                        // Allocate temp buffer of destination size in source format
639                                        temp = PixelBox(scaled.getWidth(), scaled.getHeight(), scaled.getDepth(), src.format);
640                                        buf.bind(new MemoryDataStream(temp.getConsecutiveSize()));
641                                        temp.data = buf->getPtr();
642                                }
643                                // super-optimized: byte-oriented math, no conversion
644                                switch (PixelUtil::getNumElemBytes(src.format)) 
645                                {
646                                case 1: LinearResampler_Byte<1>::scale(src, temp); break;
647                                case 2: LinearResampler_Byte<2>::scale(src, temp); break;
648                                case 3: LinearResampler_Byte<3>::scale(src, temp); break;
649                                case 4: LinearResampler_Byte<4>::scale(src, temp); break;
650                                default:
651                                        // never reached
652                                        assert(false);
653                                }
654                                if(temp.data != scaled.data)
655                                {
656                                        // Blit temp buffer
657                                        PixelUtil::bulkPixelConversion(temp, scaled);
658                                }
659                                break;
660                        case PF_FLOAT32_RGB:
661                        case PF_FLOAT32_RGBA:
662                                if (scaled.format == PF_FLOAT32_RGB || scaled.format == PF_FLOAT32_RGBA)
663                                {
664                                        // float32 to float32, avoid unpack/repack overhead
665                                        LinearResampler_Float32::scale(src, scaled);
666                                        break;
667                                }
668                                // else, fall through
669                        default:
670                                // non-optimized: floating-point math, performs conversion but always works
671                                LinearResampler::scale(src, scaled);
672                        }
673                        break;
674                }
675        }
676
677        //-----------------------------------------------------------------------------   
678
679        ColourValue Image::getColourAt(int x, int y, int z) 
680        {
681                ColourValue rval;
682                PixelUtil::unpackColour(&rval, m_eFormat, &m_pBuffer[m_ucPixelSize * (z * m_uWidth * m_uHeight + m_uWidth * y + x)]);
683                return rval;
684        }
685
686        //-----------------------------------------------------------------------------   
687
688        PixelBox Image::getPixelBox(size_t face, size_t mipmap) const
689        {
690                // Image data is arranged as:
691                // face 0, top level (mip 0)
692                // face 0, mip 1
693                // face 0, mip 2
694                // face 1, top level (mip 0)
695                // face 1, mip 1
696                // face 1, mip 2
697                // etc
698                if(mipmap > getNumMipmaps())
699                        OGRE_EXCEPT( Exception::ERR_NOT_IMPLEMENTED,
700                        "Mipmap index out of range",
701                        "Image::getPixelBox" ) ;
702                if(face >= getNumFaces())
703                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Face index out of range",
704                        "Image::getPixelBox");
705        // Calculate mipmap offset and size
706        uint8 *offset = const_cast<uint8*>(getData());
707                // Base offset is number of full faces
708        size_t width = getWidth(), height=getHeight(), depth=getDepth();
709                size_t numMips = getNumMipmaps();
710
711                // Figure out the offsets
712                size_t fullFaceSize = 0;
713                size_t finalFaceSize = 0;
714                size_t finalWidth, finalHeight, finalDepth;
715                for(size_t mip=0; mip <= numMips; ++mip)
716        {
717                        if (mip == mipmap)
718                        {
719                                finalFaceSize = fullFaceSize;
720                                finalWidth = width;
721                                finalHeight = height;
722                                finalDepth = depth;
723                        }
724            fullFaceSize += PixelUtil::getMemorySize(width, height, depth, getFormat());
725
726            /// Half size in each dimension
727            if(width!=1) width /= 2;
728            if(height!=1) height /= 2;
729            if(depth!=1) depth /= 2;
730        }
731                // Advance pointer by number of full faces, plus mip offset into
732                offset += face * fullFaceSize;
733                offset += finalFaceSize;
734                // Return subface as pixelbox
735                PixelBox src(finalWidth, finalHeight, finalDepth, getFormat(), offset);
736                return src;
737        }
738    //-----------------------------------------------------------------------------   
739    size_t Image::calculateSize(size_t mipmaps, size_t faces, size_t width, size_t height, size_t depth, 
740        PixelFormat format)
741    {
742        size_t size = 0;
743        for(size_t mip=0; mip<=mipmaps; ++mip)
744        {
745            size += PixelUtil::getMemorySize(width, height, depth, format)*faces; 
746            if(width!=1) width /= 2;
747            if(height!=1) height /= 2;
748            if(depth!=1) depth /= 2;
749        }
750        return size;
751    }
752   
753}
Note: See TracBrowser for help on using the repository browser.