source: OGRE/trunk/ogrenew/OgreMain/src/OgreImage.cpp @ 657

Revision 657, 22.8 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

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