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

Revision 657, 10.3 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
26#include "OgreStableHeaders.h"
27
28#include "OgreRoot.h"
29#include "OgreRenderSystem.h"
30#include "OgreILImageCodec.h"
31#include "OgreImage.h"
32#include "OgreException.h"
33#include "OgreILUtil.h"
34
35#include "OgreLogManager.h"
36#include "OgreStringConverter.h"
37
38#include <IL/il.h>
39#include <IL/ilu.h>
40
41namespace Ogre {
42
43    bool ILImageCodec::_is_initialised = false;   
44    //---------------------------------------------------------------------
45
46    ILImageCodec::ILImageCodec(const String &type, unsigned int ilType):
47        mType(type),
48        mIlType(ilType)
49    {
50        initialiseIL();
51    }
52
53    //---------------------------------------------------------------------
54    DataStreamPtr ILImageCodec::code(MemoryDataStreamPtr& input, Codec::CodecDataPtr& pData) const
55    {       
56        OgreGuard( "ILCodec::code" );
57
58        OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE, "code to memory not implemented",
59            "ILCodec::code");
60
61        OgreUnguard();
62
63    }
64    //---------------------------------------------------------------------
65    void ILImageCodec::codeToFile(MemoryDataStreamPtr& input,
66        const String& outFileName, Codec::CodecDataPtr& pData) const
67    {
68        OgreGuard( "ILImageCodec::codeToFile" );
69
70        ILuint ImageName;
71
72        ilGenImages( 1, &ImageName );
73        ilBindImage( ImageName );
74
75                ImageData* pImgData = static_cast< ImageData * >( pData.getPointer() );
76                PixelBox src(pImgData->width, pImgData->height, pImgData->depth, pImgData->format, input->getPtr());
77
78                // Convert image from OGRE to current IL image
79                ILUtil::fromOgre(src);
80
81        iluFlipImage();
82
83        // Implicitly pick DevIL codec
84        ilSaveImage(const_cast< char * >( outFileName.c_str() ) );
85       
86        // Check if everything was ok
87        ILenum PossibleError = ilGetError() ;
88        if( PossibleError != IL_NO_ERROR ) {
89           ilDeleteImages(1, &ImageName);
90           OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
91                "IL Error, could not save file: " + outFileName,
92                iluErrorString(PossibleError) ) ;
93        }
94
95        ilDeleteImages(1, &ImageName);
96
97        OgreUnguard();
98    }
99    //---------------------------------------------------------------------
100    Codec::DecodeResult ILImageCodec::decode(DataStreamPtr& input) const
101    {
102        OgreGuard( "ILImageCodec::decode" );
103
104        // DevIL variables
105        ILuint ImageName;
106
107        ILint ImageFormat, BytesPerPixel, ImageType;
108        ImageData* imgData = new ImageData();
109        MemoryDataStreamPtr output;
110
111        // Load the image
112        ilGenImages( 1, &ImageName );
113        ilBindImage( ImageName );
114
115        // Put it right side up
116        ilEnable(IL_ORIGIN_SET);
117        ilSetInteger(IL_ORIGIN_MODE, IL_ORIGIN_UPPER_LEFT);
118
119        // Keep DXTC(compressed) data if present
120        ilSetInteger(IL_KEEP_DXTC_DATA, IL_TRUE);
121
122        // Load image from stream, cache into memory
123        MemoryDataStream memInput(input);
124        ilLoadL(
125            mIlType,
126            memInput.getPtr(),
127            static_cast< ILuint >(memInput.size()));
128
129        // Check if everything was ok
130        ILenum PossibleError = ilGetError() ;
131        if( PossibleError != IL_NO_ERROR ) {
132            OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
133                "IL Error",
134                iluErrorString(PossibleError) ) ;
135        }
136
137        ImageFormat = ilGetInteger( IL_IMAGE_FORMAT );
138        ImageType = ilGetInteger( IL_IMAGE_TYPE );
139
140        // Convert image if ImageType is incompatible with us (double or long)
141        if(ImageType != IL_BYTE && ImageType != IL_UNSIGNED_BYTE &&
142                        ImageType != IL_FLOAT &&
143                        ImageType != IL_UNSIGNED_SHORT && ImageType != IL_SHORT) {
144            ilConvertImage(ImageFormat, IL_FLOAT);
145                        ImageType = IL_FLOAT;
146        }
147                // Converted paletted images
148                if(ImageFormat == IL_COLOUR_INDEX)
149                {
150                        ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
151                        ImageFormat = IL_BGRA;
152                        ImageType = IL_UNSIGNED_BYTE;
153                }
154
155        // Now sets some variables
156        BytesPerPixel = ilGetInteger( IL_IMAGE_BYTES_PER_PIXEL );
157
158        imgData->format = ILUtil::ilFormat2OgreFormat( ImageFormat, ImageType );
159        imgData->width = ilGetInteger( IL_IMAGE_WIDTH );
160        imgData->height = ilGetInteger( IL_IMAGE_HEIGHT );
161        imgData->depth = ilGetInteger( IL_IMAGE_DEPTH );
162        imgData->num_mipmaps = ilGetInteger ( IL_NUM_MIPMAPS );
163        imgData->flags = 0;
164               
165                if(imgData->format == PF_UNKNOWN)
166                {
167                        std::stringstream err;
168                        err << "Unsupported devil format ImageFormat=" << std::hex << ImageFormat <<
169                                " ImageType="<< ImageType << std::dec;
170                        ilDeleteImages( 1, &ImageName );
171                       
172                        OGRE_EXCEPT( Exception::UNIMPLEMENTED_FEATURE,
173                err.str(),
174                "ILImageCodec::decode" ) ;
175                }
176
177        // Check for cubemap
178        //ILuint cubeflags = ilGetInteger ( IL_IMAGE_CUBEFLAGS );
179                size_t numFaces = ilGetInteger ( IL_NUM_IMAGES ) + 1;
180        if(numFaces == 6)
181                        imgData->flags |= IF_CUBEMAP;
182        else
183            numFaces = 1; // Support only 1 or 6 face images for now
184 
185        // Keep DXT data (if present at all and the GPU supports it)
186        ILuint dxtFormat = ilGetInteger( IL_DXTC_DATA_FORMAT );
187        if(dxtFormat != IL_DXT_NO_COMP && Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_COMPRESSION_DXT ))
188        {
189                        imgData->format = ILUtil::ilFormat2OgreFormat( dxtFormat, ImageType );
190            imgData->flags |= IF_COMPRESSED;
191           
192            // Validate that this devil version saves DXT mipmaps
193            if(imgData->num_mipmaps>0)
194            {
195                ilBindImage(ImageName);
196                ilActiveMipmap(1);
197                if((size_t)ilGetInteger( IL_DXTC_DATA_FORMAT ) != dxtFormat)
198                {
199                    imgData->num_mipmaps=0;
200                    LogManager::getSingleton().logMessage(
201                    "Warning: Custom mipmaps for compressed image "+input->getName()+" were ignored because they are not loaded by this DevIL version");
202                }
203            }
204        }
205       
206        // Calculate total size from number of mipmaps, faces and size
207        imgData->size = Image::calculateSize(imgData->num_mipmaps, numFaces,
208            imgData->width, imgData->height, imgData->depth, imgData->format);
209
210        // Bind output buffer
211        output.bind(new MemoryDataStream(imgData->size));
212        size_t offset = 0;
213       
214        // Dimensions of current mipmap
215        size_t width = imgData->width;
216        size_t height = imgData->height;
217        size_t depth = imgData->depth;
218       
219        // Transfer data
220        for(size_t mip=0; mip<=imgData->num_mipmaps; ++mip)
221        {   
222            for(size_t i = 0; i < numFaces; ++i)
223            {
224                ilBindImage(ImageName);
225                if(numFaces > 1)
226                    ilActiveImage(i);
227                if(imgData->num_mipmaps > 0)
228                    ilActiveMipmap(mip);
229                /// Size of this face
230                size_t imageSize = PixelUtil::getMemorySize(
231                        width, height, depth, imgData->format);
232                if(imgData->flags & IF_COMPRESSED)
233                {
234
235                    // Compare DXT size returned by DevIL with our idea of the compressed size
236                    if(imageSize == ilGetDXTCData(NULL, 0, dxtFormat))
237                    {
238                        // Retrieve data from DevIL
239                        ilGetDXTCData((unsigned char*)output->getPtr()+offset, imageSize, dxtFormat);
240                    } else
241                    {
242                        LogManager::getSingleton().logMessage(
243                            "Warning: compressed image "+input->getName()+" size mismatch, devilsize="+StringConverter::toString(ilGetDXTCData(NULL, 0, dxtFormat))+" oursize="+
244                            StringConverter::toString(imageSize));
245                    }
246                }
247                else
248                {
249                    /// Retrieve data from DevIL
250                    PixelBox dst(width, height, depth, imgData->format, (unsigned char*)output->getPtr()+offset);
251                    ILUtil::toOgre(dst);
252                }
253                offset += imageSize;
254            }
255            /// Next mip
256            if(width!=1) width /= 2;
257            if(height!=1) height /= 2;
258            if(depth!=1) depth /= 2;
259        }
260
261        // Restore IL state
262        ilDisable(IL_ORIGIN_SET);
263        ilDisable(IL_FORMAT_SET);
264
265        ilDeleteImages( 1, &ImageName );
266
267        DecodeResult ret;
268        ret.first = output;
269        ret.second = CodecDataPtr(imgData);
270
271
272        OgreUnguardRet( ret );
273    }
274    //---------------------------------------------------------------------
275    void ILImageCodec::initialiseIL(void)
276    {
277        if( !_is_initialised )
278        {
279            ilInit();
280            ilEnable( IL_FILE_OVERWRITE );
281            _is_initialised = true;
282        }
283    }
284    //---------------------------------------------------------------------   
285    String ILImageCodec::getType() const
286    {
287        return mType;
288    }
289}
Note: See TracBrowser for help on using the repository browser.