source: OGRE/trunk/ogrenew/OgreMain/src/OgreILUtil.cpp @ 690

Revision 690, 11.7 KB checked in by mattausch, 18 years ago (diff)

added ogre 1.07 main

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 "OgreILUtil.h"
27#include "OgrePixelFormat.h"
28#include "OgreBitwise.h"
29#include "OgreColourValue.h"
30#include "OgreException.h"
31
32#include <IL/il.h>
33#include <IL/ilu.h>
34   
35namespace Ogre {
36       
37        /*************************************************************************
38    * IL specific functions
39    */
40    PixelFormat ILUtil::ilFormat2OgreFormat( int ImageFormat, int ImageType )
41        {
42        PixelFormat fmt = PF_UNKNOWN;
43        switch( ImageFormat )
44        {
45                /* Compressed formats -- ignore type */
46                case IL_DXT1:   fmt = PF_DXT1; break;
47                case IL_DXT2:   fmt = PF_DXT2; break;
48                case IL_DXT3:   fmt = PF_DXT3; break;
49                case IL_DXT4:   fmt = PF_DXT4; break;
50                case IL_DXT5:   fmt = PF_DXT5; break;
51                /* Normal formats */
52        case IL_RGB:
53                        switch(ImageType)
54            {
55                        case IL_FLOAT:  fmt = PF_FLOAT32_RGB; break;
56                        case IL_UNSIGNED_SHORT:
57                        case IL_SHORT:  fmt = PF_SHORT_RGBA; break;
58                        default:        fmt = PF_BYTE_RGB; break;
59                        }
60            break;
61        case IL_BGR:
62                        switch(ImageType)
63            {
64                        case IL_FLOAT:  fmt = PF_FLOAT32_RGB; break;
65                        case IL_UNSIGNED_SHORT:
66                        case IL_SHORT:  fmt = PF_SHORT_RGBA; break;
67                        default:        fmt = PF_BYTE_BGR; break;
68                        }
69            break;           
70        case IL_RGBA:
71                        switch(ImageType)
72            {
73                        case IL_FLOAT:  fmt = PF_FLOAT32_RGBA; break;
74                        case IL_UNSIGNED_SHORT:
75                        case IL_SHORT:  fmt = PF_SHORT_RGBA; break;
76                        default:        fmt = PF_BYTE_RGBA; break;
77                        }
78            break;
79        case IL_BGRA:
80                        switch(ImageType)
81            {
82                        case IL_FLOAT:  fmt = PF_FLOAT32_RGBA; break;
83                        case IL_UNSIGNED_SHORT:
84                        case IL_SHORT:  fmt = PF_SHORT_RGBA; break;
85                        default:        fmt = PF_BYTE_BGRA; break;
86                        }
87            break;
88        case IL_LUMINANCE:
89            switch(ImageType)
90            {
91            case IL_BYTE:
92            case IL_UNSIGNED_BYTE:
93                fmt = PF_L8;
94                break;
95            default:
96                fmt = PF_L16;
97            }
98            break;           
99        case IL_LUMINANCE_ALPHA:
100                        fmt = PF_BYTE_LA;
101            break;
102        } 
103        return fmt;
104    }
105
106    //-----------------------------------------------------------------------
107
108    ILUtil::ILFormat ILUtil::OgreFormat2ilFormat( PixelFormat format )
109    {
110                switch(format) {
111            case PF_BYTE_L: return ILFormat(1, IL_LUMINANCE, IL_UNSIGNED_BYTE);
112                        case PF_BYTE_A: return ILFormat(1, IL_LUMINANCE, IL_UNSIGNED_BYTE);
113                        case PF_SHORT_L: return ILFormat(1, IL_LUMINANCE, IL_UNSIGNED_SHORT);
114                        case PF_BYTE_LA: return ILFormat(2, IL_LUMINANCE_ALPHA, IL_UNSIGNED_BYTE);
115                        case PF_BYTE_RGB: return ILFormat(3, IL_RGB, IL_UNSIGNED_BYTE);
116                        case PF_BYTE_RGBA: return ILFormat(4, IL_RGBA, IL_UNSIGNED_BYTE);
117            case PF_BYTE_BGR: return ILFormat(3, IL_BGR, IL_UNSIGNED_BYTE);
118            case PF_BYTE_BGRA: return ILFormat(4, IL_BGRA, IL_UNSIGNED_BYTE);
119                        case PF_SHORT_RGBA: return ILFormat(4, IL_RGBA, IL_UNSIGNED_SHORT);
120                        case PF_FLOAT32_RGB: return ILFormat(3, IL_RGB, IL_FLOAT);
121                        case PF_FLOAT32_RGBA: return ILFormat(4, IL_RGBA, IL_FLOAT);
122                        case PF_DXT1: return ILFormat(0, IL_DXT1);
123                        case PF_DXT2: return ILFormat(0, IL_DXT2);
124                        case PF_DXT3: return ILFormat(0, IL_DXT3);
125                        case PF_DXT4: return ILFormat(0, IL_DXT4);
126                        case PF_DXT5: return ILFormat(0, IL_DXT5);
127                        default: return ILFormat();
128                }
129        }
130
131    //-----------------------------------------------------------------------
132        /// Helper functions for DevIL to Ogre conversion
133        inline void packI(uint8 r, uint8 g, uint8 b, uint8 a, PixelFormat pf,  void* dest)
134        {
135                PixelUtil::packColour(r, g, b, a, pf, dest);
136        }
137        inline void packI(uint16 r, uint16 g, uint16 b, uint16 a, PixelFormat pf,  void* dest)
138        {
139                PixelUtil::packColour((float)r/65535.0f, (float)g/65535.0f,
140                        (float)b/65535.0f, (float)a/65535.0f, pf, dest);
141        }
142        inline void packI(float r, float g, float b, float a, PixelFormat pf,  void* dest)
143        {
144                PixelUtil::packColour(r, g, b, a, pf, dest);
145        }
146    template <typename T> void ilToOgreInternal(uint8 *tar, PixelFormat ogrefmt,
147        T r, T g, T b, T a)
148    {
149        const int ilfmt = ilGetInteger( IL_IMAGE_FORMAT );
150        T *src = (T*)ilGetData();
151        T *srcend = (T*)((uint8*)ilGetData() + ilGetInteger( IL_IMAGE_SIZE_OF_DATA ));
152        const size_t elemSize = PixelUtil::getNumElemBytes(ogrefmt);
153        while(src < srcend) {
154            switch(ilfmt) {
155                        case IL_RGB:
156                                r = src[0];     g = src[1];     b = src[2];
157                                src += 3;
158                                break;
159                        case IL_BGR:
160                                b = src[0];     g = src[1];     r = src[2];
161                                src += 3;
162                                break;
163                        case IL_LUMINANCE:
164                                r = src[0];     g = src[0];     b = src[0];
165                                src += 1;
166                                break;
167                        case IL_LUMINANCE_ALPHA:
168                                r = src[0];     g = src[0];     b = src[0];     a = src[1];
169                                src += 2;
170                                break;
171                        case IL_RGBA:
172                                r = src[0];     g = src[1];     b = src[2];     a = src[3];
173                                src += 4;
174                                break;
175                        case IL_BGRA:
176                                b = src[0];     g = src[1];     r = src[2];     a = src[3];
177                                src += 4;
178                                break;
179                        default:
180                                return;
181            }
182            packI(r, g, b, a, ogrefmt, tar);
183            tar += elemSize;
184        }
185
186    }   
187    //-----------------------------------------------------------------------
188        /// Utility function to convert IL data types to UNSIGNED_
189        ILenum ILabs(ILenum in) {
190                switch(in) {
191                case IL_INT: return IL_UNSIGNED_INT;
192                case IL_BYTE: return IL_UNSIGNED_BYTE;
193                case IL_SHORT: return IL_UNSIGNED_SHORT;
194                default: return in;
195                }
196        }
197    //-----------------------------------------------------------------------
198    void ILUtil::toOgre(const PixelBox &dst)
199    {
200                if(!dst.isConsecutive())
201                        OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
202                "Destination must currently be consecutive",
203                "ILUtil::ilToOgre" ) ;
204                if(dst.getWidth() != static_cast<size_t>(ilGetInteger( IL_IMAGE_WIDTH )) ||
205                dst.getHeight() != static_cast<size_t>(ilGetInteger( IL_IMAGE_HEIGHT )) ||
206                dst.getDepth() != static_cast<size_t>(ilGetInteger( IL_IMAGE_DEPTH )))
207                        OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
208                "Destination dimensions must equal IL dimension",
209                "ILUtil::ilToOgre" ) ;
210       
211        int ilfmt = ilGetInteger( IL_IMAGE_FORMAT );
212        int iltp = ilGetInteger( IL_IMAGE_TYPE );
213
214                // Check if in-memory format just matches
215                // If yes, we can just copy it and save conversion
216                ILFormat ifmt = OgreFormat2ilFormat( dst.format );
217                if(ifmt.format == ilfmt && ILabs(ifmt.type) == ILabs(iltp)) {
218            memcpy(dst.data, ilGetData(), ilGetInteger( IL_IMAGE_SIZE_OF_DATA ));
219            return;
220        }
221                // Try if buffer is in a known OGRE format so we can use OGRE its
222                // conversion routines
223                PixelFormat bufFmt = ilFormat2OgreFormat((int)ilfmt, (int)iltp);
224               
225                ifmt = OgreFormat2ilFormat( bufFmt );
226                if(ifmt.format == ilfmt && ILabs(ifmt.type) == ILabs(iltp))
227                {
228                        // IL format matches another OGRE format
229                        PixelBox src(dst.getWidth(), dst.getHeight(), dst.getDepth(), bufFmt, ilGetData());
230                        PixelUtil::bulkPixelConversion(src, dst);
231                        return;
232                }
233               
234        // Thee extremely slow method
235        if(iltp == IL_UNSIGNED_BYTE || iltp == IL_BYTE)
236        {
237            ilToOgreInternal(static_cast<uint8*>(dst.data), dst.format, (uint8)0x00,(uint8)0x00,(uint8)0x00,(uint8)0xFF);
238        }
239        else if(iltp == IL_FLOAT)
240        {
241            ilToOgreInternal(static_cast<uint8*>(dst.data), dst.format, 0.0f,0.0f,0.0f,1.0f);         
242        }
243                else if(iltp == IL_SHORT || iltp == IL_UNSIGNED_SHORT)
244        {
245                        ilToOgreInternal(static_cast<uint8*>(dst.data), dst.format,
246                                (uint16)0x0000,(uint16)0x0000,(uint16)0x0000,(uint16)0xFFFF);
247        }
248        else
249        {
250            OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
251                "Cannot convert this DevIL type",
252                "ILUtil::ilToOgre" ) ;
253        }
254    }
255    //-----------------------------------------------------------------------
256    void ILUtil::fromOgre(const PixelBox &src)
257    {
258                // ilTexImage http://openil.sourceforge.net/docs/il/f00059.htm
259                ILFormat ifmt = OgreFormat2ilFormat( src.format );
260                if(src.isConsecutive() && ifmt.isValid())
261                {
262                        // The easy case, the buffer is laid out in memory just like
263                        // we want it to be and is in a format DevIL can understand directly
264                        // We could even save the copy if DevIL would let us
265                        ilTexImage(static_cast<ILuint>(src.getWidth()),
266                                static_cast<ILuint>(src.getHeight()),
267                                static_cast<ILuint>(src.getDepth()), ifmt.numberOfChannels,
268                                ifmt.format, ifmt.type, src.data);
269                }
270                else if(ifmt.isValid())
271                {
272                        // The format can be understood directly by DevIL. The only
273                        // problem is that ilTexImage expects our image data consecutively
274                        // so we cannot use that directly.
275                       
276                        // Let DevIL allocate the memory for us, and copy the data consecutively
277                        // to its memory
278                        ilTexImage(static_cast<ILuint>(src.getWidth()),
279                                static_cast<ILuint>(src.getHeight()),
280                                static_cast<ILuint>(src.getDepth()), ifmt.numberOfChannels,
281                                ifmt.format, ifmt.type, 0);
282                        PixelBox dst(src.getWidth(), src.getHeight(), src.getDepth(), src.format, ilGetData());
283                        PixelUtil::bulkPixelConversion(src, dst);
284                }
285                else
286                {
287                        // Here it gets ugly. We're stuck with a pixel format that DevIL
288                        // can't do anything with. We will do a bulk pixel conversion and
289                        // then feed it to DevIL anyway. The problem is finding the best
290                        // format to convert to.
291                       
292                        // most general format supported by OGRE and DevIL
293                        PixelFormat fmt = PixelUtil::hasAlpha(src.format)?PF_FLOAT32_RGBA:PF_FLOAT32_RGB;
294
295                        // Make up a pixel format
296                        // We don't have to consider luminance formats as they have
297                        // straight conversions to DevIL, just weird permutations of RGBA an LA
298                        int depths[4];
299                        PixelUtil::getBitDepths(src.format, depths);
300                       
301                        // Native endian format with all bit depths<8 can safely and quickly be
302                        // converted to 24/32 bit
303                        if(PixelUtil::isNativeEndian(src.format) &&
304                                depths[0]<=8 && depths[1]<=8 && depths[2]<=8 && depths[3]<=8) {
305                                if(PixelUtil::hasAlpha(src.format)) {
306                                        fmt = PF_A8R8G8B8;
307                                } else {
308                                        fmt = PF_R8G8B8;
309                                }
310                        }
311                       
312                        // Let DevIL allocate the memory for us, then do the conversion ourselves
313                        ifmt = OgreFormat2ilFormat( fmt );
314                        ilTexImage(static_cast<ILuint>(src.getWidth()),
315                                static_cast<ILuint>(src.getHeight()),
316                                static_cast<ILuint>(src.getDepth()), ifmt.numberOfChannels,
317                                ifmt.format, ifmt.type, 0);
318                        PixelBox dst(src.getWidth(), src.getHeight(), src.getDepth(), fmt, ilGetData());
319                        PixelUtil::bulkPixelConversion(src, dst);
320                }
321    }
322
323}
Note: See TracBrowser for help on using the repository browser.