Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

=update

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