Coverage Report

Created: 2025-08-28 06:22

/src/ogre/OgreMain/include/OgreImage.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#ifndef _Image_H__
29
#define _Image_H__
30
31
#include "OgrePrerequisites.h"
32
#include "OgreCommon.h"
33
#include "OgrePixelFormat.h"
34
35
namespace Ogre {
36
    /** \addtogroup Core
37
    *  @{
38
    */
39
    /** \addtogroup Image
40
    *  @{
41
    */
42
43
    enum ImageFlags
44
    {
45
        IF_COMPRESSED = 0x00000001,
46
        IF_CUBEMAP    = 0x00000002,
47
        IF_3D_TEXTURE = 0x00000004
48
    };
49
    /** Class representing an image file.
50
51
        The Image class usually holds uncompressed image data and is the
52
        only object that can be loaded in a texture. Image  objects handle
53
        image data decoding themselves by the means of locating the correct
54
        Codec object for each data type.
55
        @par
56
            Typically, you would want to use an Image object to load a texture
57
            when extra processing needs to be done on an image before it is
58
            loaded or when you want to blit to an existing texture.
59
    */
60
    class _OgreExport Image : public ImageAlloc
61
    {
62
    friend class ImageCodec;
63
    public:
64
        /** Standard constructor.
65
         *
66
         * allocates a buffer of given size if buffer pointer is NULL.
67
         */
68
        Image(PixelFormat format = PF_UNKNOWN, uint32 width = 0, uint32 height = 0, uint32 depth = 1,
69
              uchar* buffer = NULL, bool autoDelete = true);
70
        /** Copy-constructor - copies all the data from the target image.
71
         */
72
        Image( const Image &img );
73
74
        /**
75
         * allocates a buffer of given size if needed
76
         *
77
         * - If the current allocation is equal to the requested size, this does nothing
78
         * - Otherwise any current allocation is freed, and memory of specified size is allocated
79
         *
80
         * @see loadDynamicImage
81
         */
82
        void create(PixelFormat format, uint32 width, uint32 height, uint32 depth = 1, uint32 numFaces = 1,
83
                    uint32 numMipMaps = 0);
84
85
        /** Standard destructor.
86
        */
87
        ~Image();
88
89
        /** Assignment operator - copies all the data from the target image.
90
        */
91
        Image & operator = ( const Image & img );
92
93
        /**
94
         * sets all pixels to the specified colour
95
         *
96
         * format conversion is performed as needed
97
         */
98
        void setTo(const ColourValue& col);
99
100
        /** Flips (mirrors) the image around the Y-axis. 
101
102
            An example of an original and flipped image:
103
            <pre>
104
            originalimg
105
            00000000000
106
            00000000000
107
            00000000000
108
            00000000000
109
            00000000000
110
            ------------> flip axis
111
            00000000000
112
            00000000000
113
            00000000000
114
            00000000000
115
            00000000000
116
            originalimg
117
            </pre>
118
        */
119
        Image & flipAroundY();
120
121
        /** Flips (mirrors) the image around the X-axis.
122
123
            An example of an original and flipped image:
124
            <pre>
125
                   flip axis
126
                       |
127
            originalimg|gmilanigiro
128
            00000000000|00000000000
129
            00000000000|00000000000
130
            00000000000|00000000000
131
            00000000000|00000000000
132
            00000000000|00000000000
133
            </pre>
134
        */                 
135
        Image & flipAroundX();
136
137
        /** Stores a pointer to raw data in memory. The pixel format has to be specified.
138
139
            This method loads an image into memory held in the object. The
140
            pixel format will be either greyscale or RGB with an optional
141
            Alpha component.
142
            The type can be determined by calling getFormat().
143
            @note
144
                Whilst typically your image is likely to be a simple 2D image,
145
                you can define complex images including cube maps, volume maps,
146
                and images including custom mip levels. The layout of the 
147
                internal memory should be:
148
                <ul><li>face 0, mip 0 (top), width x height (x depth)</li>
149
                <li>face 0, mip 1, width/2 x height/2 (x depth/2)</li>
150
                <li>face 0, mip 2, width/4 x height/4 (x depth/4)</li>
151
                <li>.. remaining mips for face 0 .. </li>
152
                <li>face 1, mip 0 (top), width x height (x depth)</li
153
                <li>.. and so on. </li>
154
                </ul>
155
                Of course, you will never have multiple faces (cube map) and
156
                depth too.
157
            @param data
158
                The data pointer
159
            @param width
160
                Width of image
161
            @param height
162
                Height of image
163
            @param depth
164
                Image Depth (in 3d images, numbers of layers, otherwise 1)
165
            @param format
166
                Pixel Format
167
            @param autoDelete
168
                If memory associated with this buffer is to be destroyed
169
                with the Image object. Note: it's important that if you set
170
                this option to true, that you allocated the memory using OGRE_ALLOC_T
171
                with a category of MEMCATEGORY_GENERAL to ensure the freeing of memory 
172
                matches up.
173
            @param numFaces
174
                The number of faces the image data has inside (6 for cubemaps, 1 otherwise)
175
            @param numMipMaps
176
                The number of mipmaps the image data has inside
177
            @note
178
                 The memory associated with this buffer is NOT destroyed with the
179
                 Image object, unless autoDelete is set to true.
180
181
                The size of the buffer must be numFaces * PixelUtil::getMemorySize(width, height, depth, format)
182
         */
183
        Image& loadDynamicImage(uchar* data, uint32 width, uint32 height, uint32 depth, PixelFormat format,
184
                                bool autoDelete = false, uint32 numFaces = 1, uint32 numMipMaps = 0);
185
186
        /// @overload
187
        Image& loadDynamicImage(uchar* data, uint32 width, uint32 height, PixelFormat format)
188
0
        {
189
0
            return loadDynamicImage(data, width, height, 1, format);
190
0
        }
191
        /** Loads raw data from a stream. See the function
192
            loadDynamicImage for a description of the parameters.
193
194
            The size of the buffer must be numFaces * PixelUtil::getMemorySize(width, height, depth, format)
195
            @note
196
                Whilst typically your image is likely to be a simple 2D image,
197
                you can define complex images including cube maps
198
                and images including custom mip levels. The layout of the 
199
                internal memory should be:
200
                <ul><li>face 0, mip 0 (top), width x height (x depth)</li>
201
                <li>face 0, mip 1, width/2 x height/2 (x depth/2)</li>
202
                <li>face 0, mip 2, width/4 x height/4 (x depth/4)</li>
203
                <li>.. remaining mips for face 0 .. </li>
204
                <li>face 1, mip 0 (top), width x height (x depth)</li
205
                <li>.. and so on. </li>
206
                </ul>
207
                Of course, you will never have multiple faces (cube map) and
208
                depth too.
209
        */
210
        Image& loadRawData(const DataStreamPtr& stream, uint32 width, uint32 height, uint32 depth,
211
                           PixelFormat format, uint32 numFaces = 1, uint32 numMipMaps = 0);
212
        /// @overload
213
        Image& loadRawData(const DataStreamPtr& stream, uint32 width, uint32 height, PixelFormat format)
214
0
        {
215
0
            return loadRawData(stream, width, height, 1, format);
216
0
        }
217
218
        /** Loads an image file.
219
220
            This method loads an image into memory. Any format for which
221
            an associated ImageCodec is registered can be loaded.
222
            This can include complex formats like DDS with embedded custom
223
            mipmaps, cube faces and volume textures.
224
            The type can be determined by calling getFormat().
225
            @param
226
                filename Name of an image file to load.
227
            @param
228
                groupName Name of the resource group to search for the image
229
            @note
230
                The memory associated with this buffer is destroyed with the
231
                Image object.
232
        */
233
        Image & load( const String& filename, const String& groupName );
234
235
        /** Loads an image file from a stream.
236
237
            This method works in the same way as the filename-based load
238
            method except it loads the image from a DataStream object.
239
            This DataStream is expected to contain the
240
            encoded data as it would be held in a file.
241
            Any format for which an associated ImageCodec is registered
242
            can be loaded.
243
            This can include complex formats like DDS with embedded custom
244
            mipmaps, cube faces and volume textures.
245
            The type can be determined by calling getFormat().
246
            @param
247
                stream The source data.
248
            @param
249
                type The type of the image. Used to decide what decompression
250
                codec to use. Can be left blank if the stream data includes
251
                a header to identify the data.
252
            @see
253
                Image::load( const String& filename )
254
        */
255
        Image & load(const DataStreamPtr& stream, String type = BLANKSTRING );
256
257
        /** Utility method to combine 2 separate images into this one, with the first
258
        image source supplying the RGB channels, and the second image supplying the 
259
        alpha channel (as luminance or separate alpha). 
260
        @param rgbFilename Filename of image supplying the RGB channels (any alpha is ignored)
261
        @param alphaFilename Filename of image supplying the alpha channel. If a luminance image the
262
            single channel is used directly, if an RGB image then the values are
263
            converted to greyscale.
264
        @param groupName The resource group from which to load the images
265
        @param format The destination format
266
        */
267
        Image & loadTwoImagesAsRGBA(const String& rgbFilename, const String& alphaFilename,
268
            const String& groupName, PixelFormat format = PF_BYTE_RGBA);
269
270
        /** Utility method to combine 2 separate images into this one, with the first
271
        image source supplying the RGB channels, and the second image supplying the 
272
        alpha channel (as luminance or separate alpha). 
273
        @param rgbStream Stream of image supplying the RGB channels (any alpha is ignored)
274
        @param alphaStream Stream of image supplying the alpha channel. If a luminance image the
275
            single channel is used directly, if an RGB image then the values are
276
            converted to greyscale.
277
        @param format The destination format
278
        @param rgbType The type of the RGB image. Used to decide what decompression
279
            codec to use. Can be left blank if the stream data includes
280
            a header to identify the data.
281
        @param alphaType The type of the alpha image. Used to decide what decompression
282
            codec to use. Can be left blank if the stream data includes
283
            a header to identify the data.
284
        */
285
        Image& loadTwoImagesAsRGBA(const DataStreamPtr& rgbStream, const DataStreamPtr& alphaStream,
286
                                   PixelFormat format = PF_BYTE_RGBA,
287
                                   const String& rgbType = BLANKSTRING,
288
                                   const String& alphaType = BLANKSTRING);
289
290
        /** Utility method to combine 2 separate images into this one, with the first
291
            image source supplying the RGB channels, and the second image supplying the 
292
            alpha channel (as luminance or separate alpha). 
293
        @param rgb Image supplying the RGB channels (any alpha is ignored)
294
        @param alpha Image supplying the alpha channel. If a luminance image the
295
            single channel is used directly, if an RGB image then the values are
296
            converted to greyscale.
297
        @param format The destination format
298
        */
299
        Image & combineTwoImagesAsRGBA(const Image& rgb, const Image& alpha, PixelFormat format = PF_BYTE_RGBA);
300
301
        
302
        /** Save the image as a file. 
303
304
            Saving and loading are implemented by back end (sometimes third 
305
            party) codecs.  Implemented saving functionality is more limited
306
            than loading in some cases. Particularly DDS file format support 
307
            is currently limited to true colour or single channel float32, 
308
            square, power of two textures with no mipmaps.  Volumetric support
309
            is currently limited to DDS files.
310
        */
311
        void save(const String& filename);
312
313
        /** Encode the image and return a stream to the data. 
314
            @param formatextension An extension to identify the image format
315
                to encode into, e.g. "jpg" or "png"
316
        */
317
        DataStreamPtr encode(const String& formatextension);
318
319
        /** Returns a pointer to the internal image buffer at the specified pixel location.
320
321
            Be careful with this method. You will almost certainly
322
            prefer to use getPixelBox, especially with complex images
323
            which include many faces or custom mipmaps.
324
        */
325
        uchar* getData(uint32 x = 0, uint32 y = 0, uint32 z = 0)
326
676
        {
327
676
            assert((!mBuffer && (x + y + z) == 0) || (x < mWidth && y < mHeight && z < mDepth));
328
676
            return mBuffer + mPixelSize * (z * mWidth * mHeight + mWidth * y + x);
329
676
        }
330
331
        /// @overload
332
        const uchar* getData(uint32 x = 0, uint32 y = 0, uint32 z = 0) const
333
0
        {
334
0
            assert(mBuffer);
335
0
            assert(x < mWidth && y < mHeight && z < mDepth);
336
0
            return mBuffer + mPixelSize * (z * mWidth * mHeight + mWidth * y + x);
337
0
        }
338
339
        /// @overload
340
        template <typename T> T* getData(uint32 x = 0, uint32 y = 0, uint32 z = 0)
341
0
        {
342
0
            return reinterpret_cast<T*>(getData(x, y, z));
343
0
        }
344
345
        /// @overload
346
        template <typename T> const T* getData(uint32 x = 0, uint32 y = 0, uint32 z = 0) const
347
        {
348
            return reinterpret_cast<const T*>(getData(x, y, z));
349
        }
350
351
        /** Returns the size of the data buffer in bytes
352
        */
353
0
        size_t getSize() const { return mBufSize; }
354
355
        /** Returns the number of mipmaps contained in the image.
356
        */
357
0
        uint32 getNumMipmaps() const { return mNumMipmaps; }
358
359
        /** Returns true if the image has the appropriate flag set.
360
        */
361
0
        bool hasFlag(const ImageFlags imgFlag) const { return (mFlags & imgFlag) != 0; }
362
363
        /** Gets the width of the image in pixels.
364
        */
365
676
        uint32 getWidth(void) const { return mWidth; }
366
367
        /** Gets the height of the image in pixels.
368
        */
369
676
        uint32 getHeight(void) const { return mHeight; }
370
371
        /** Gets the depth of the image.
372
        */
373
0
        uint32 getDepth(void) const { return mDepth; }
374
        
375
        /** Get the number of faces of the image. This is usually 6 for a cubemap, and
376
            1 for a normal image.
377
        */
378
0
        uint32 getNumFaces(void) const { return hasFlag(IF_CUBEMAP) ? 6 : 1; }
379
380
        /** Gets the physical width in bytes of each row of pixels.
381
        */
382
676
        size_t getRowSpan(void) const { return mWidth * mPixelSize; }
383
384
        /** Returns the image format.
385
        */
386
676
        PixelFormat getFormat() const { return mFormat; }
387
388
        /** Returns the number of bits per pixel.
389
        */
390
0
        uchar getBPP() const { return mPixelSize * 8;}
391
392
        /** Returns true if the image has an alpha component.
393
        */
394
        bool getHasAlpha() const;
395
        
396
        /** Does gamma adjustment.
397
            @note
398
                Basic algo taken from Titan Engine, copyright (c) 2000 Ignacio 
399
                Castano Iguado
400
        */
401
        static void applyGamma( uchar *buffer, Real gamma, size_t size, uchar bpp );
402
403
        /**
404
         * Get colour value from a certain location in the image. The z coordinate
405
         * is only valid for cubemaps and volume textures. This uses the first (largest)
406
         * mipmap.
407
         */
408
        ColourValue getColourAt(uint32 x, uint32 y, uint32 z) const;
409
        
410
        /**
411
         * Set colour value at a certain location in the image. The z coordinate
412
         * is only valid for cubemaps and volume textures. This uses the first (largest)
413
         * mipmap.
414
         */
415
        void setColourAt(ColourValue const &cv, uint32 x, uint32 y, uint32 z);
416
417
        /**
418
         * Get a PixelBox encapsulating the image data of a mipmap
419
         */
420
        PixelBox getPixelBox(uint32 face = 0, uint32 mipmap = 0) const;
421
422
        /// Delete all the memory held by this image, if owned by this image (not dynamic)
423
        void freeMemory();
424
425
        enum Filter
426
        {
427
            FILTER_NEAREST,
428
            FILTER_LINEAR,
429
            FILTER_BILINEAR = FILTER_LINEAR
430
        };
431
        /** Scale a 1D, 2D or 3D image volume. 
432
            @param  src         PixelBox containing the source pointer, dimensions and format
433
            @param  dst         PixelBox containing the destination pointer, dimensions and format
434
            @param  filter      Which filter to use
435
            This function can do pixel format conversion in the process.
436
            @note   dst and src can point to the same PixelBox object without any problem
437
        */
438
        static void scale(const PixelBox &src, const PixelBox &dst, Filter filter = FILTER_BILINEAR);
439
        
440
        /** Resize a 2D image, applying the appropriate filter. */
441
        void resize(ushort width, ushort height, Filter filter = FILTER_BILINEAR);
442
        
443
        /// Static function to calculate size in bytes from the number of mipmaps, faces and the dimensions
444
        static size_t calculateSize(uint32 mipmaps, uint32 faces, uint32 width, uint32 height, uint32 depth, PixelFormat format);
445
446
        /// Static function to get an image type string from a stream via magic numbers
447
        OGRE_DEPRECATED static String getFileExtFromMagic(DataStreamPtr stream);
448
449
    private:
450
        /// The width of the image in pixels
451
        uint32 mWidth;
452
        /// The height of the image in pixels
453
        uint32 mHeight;
454
        /// The depth of the image
455
        uint32 mDepth;
456
        /// The number of mipmaps the image contains
457
        uint32 mNumMipmaps;
458
        /// The size of the image buffer
459
        size_t mBufSize;
460
        /// Image specific flags.
461
        int mFlags;
462
463
        /// The pixel format of the image
464
        PixelFormat mFormat;
465
466
        uchar* mBuffer;
467
        /// The number of bytes per pixel
468
        uchar mPixelSize;
469
        /// A bool to determine if we delete the buffer or the calling app does
470
        bool mAutoDelete;
471
    };
472
473
    typedef std::vector<Image*> ImagePtrList;
474
    typedef std::vector<const Image*> ConstImagePtrList;
475
476
    /** @} */
477
    /** @} */
478
479
} // namespace
480
481
#endif