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

Revision 690, 35.2 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 "OgrePixelFormat.h"
27#include "OgreBitwise.h"
28#include "OgreColourValue.h"
29#include "OgreException.h"
30
31
32namespace {
33#include "OgrePixelConversions.h"
34};
35
36namespace Ogre {
37
38    //-----------------------------------------------------------------------
39    /**
40    * A record that describes a pixel format in detail.
41    */
42    struct PixelFormatDescription {
43        /* Name of the format, as in the enum */
44        char *name;
45        /* Number of bytes one element (colour value) takes. */
46        size_t elemBytes;
47        /* Pixel format flags, see enum PixelFormatFlags for the bit field
48        * definitions
49        */
50        unsigned int flags;
51        /* Number of bits in one element. */
52        // int elemBits; == elemBytes * 8
53        /* Number of bits for red(or luminance), green, blue, alpha
54        */
55        int rbits,gbits,bbits,abits; /*, ibits, dbits, ... */
56
57        /* Masks and shifts as used by packers/unpackers */
58        uint32 rmask, gmask, bmask, amask;
59        int rshift, gshift, bshift, ashift;
60    };
61    //-----------------------------------------------------------------------
62    /** Pixel format database */
63    PixelFormatDescription _pixelFormats[PF_COUNT] = {
64        //-----------------------------------------------------------------------
65        {"PF_UNKNOWN",
66            /* Bytes per element */
67            0, 
68            /* Flags */
69            0, 
70            /* rbits, gbits, bbits, abits */
71            0, 0, 0, 0,
72            /* Masks and shifts */
73            0, 0, 0, 0, 0, 0, 0, 0
74        },
75        //-----------------------------------------------------------------------
76        {"PF_L8",
77        /* Bytes per element */
78        1, 
79        /* Flags */
80        PFF_LUMINANCE | PFF_NATIVEENDIAN,
81        /* rbits, gbits, bbits, abits */
82        8, 0, 0, 0,
83        /* Masks and shifts */
84        0xFF, 0, 0, 0, 0, 0, 0, 0
85        },
86        //-----------------------------------------------------------------------
87        {"PF_L16",
88        /* Bytes per element */
89        2, 
90        /* Flags */
91        PFF_LUMINANCE | PFF_NATIVEENDIAN, 
92        /* rbits, gbits, bbits, abits */
93        16, 0, 0, 0,
94        /* Masks and shifts */
95        0xFFFF, 0, 0, 0, 0, 0, 0, 0
96        },
97        //-----------------------------------------------------------------------
98        {"PF_A8",
99        /* Bytes per element */
100        1, 
101        /* Flags */
102        PFF_HASALPHA | PFF_NATIVEENDIAN,
103        /* rbits, gbits, bbits, abits */
104        0, 0, 0, 8,
105        /* Masks and shifts */
106        0, 0, 0, 0xFF, 0, 0, 0, 0
107        },
108        //-----------------------------------------------------------------------
109        {"PF_A4L4",
110        /* Bytes per element */
111        1, 
112        /* Flags */
113        PFF_HASALPHA | PFF_LUMINANCE | PFF_NATIVEENDIAN,
114        /* rbits, gbits, bbits, abits */
115        4, 0, 0, 4,
116        /* Masks and shifts */
117        0x0F, 0, 0, 0xF0, 0, 0, 0, 4
118        },
119        //-----------------------------------------------------------------------
120        {"PF_BYTE_LA",
121        /* Bytes per element */
122        2, 
123        /* Flags */
124        PFF_HASALPHA | PFF_LUMINANCE, 
125        /* rbits, gbits, bbits, abits */
126        8, 0, 0, 8,
127        /* Masks and shifts */
128        0,0,0,0,0,0,0,0
129        },
130        //-----------------------------------------------------------------------
131        {"PF_R5G6B5",
132        /* Bytes per element */
133        2, 
134        /* Flags */
135        PFF_NATIVEENDIAN, 
136        /* rbits, gbits, bbits, abits */
137        5, 6, 5, 0,
138        /* Masks and shifts */
139        0xF800, 0x07E0, 0x001F, 0,
140        11, 5, 0, 0
141        },
142        //-----------------------------------------------------------------------
143                {"PF_B5G6R5",
144        /* Bytes per element */
145        2, 
146        /* Flags */
147        PFF_NATIVEENDIAN, 
148        /* rbits, gbits, bbits, abits */
149        5, 6, 5, 0,
150        /* Masks and shifts */
151        0x001F, 0x07E0, 0xF800, 0,
152        0, 5, 11, 0
153        },
154        //-----------------------------------------------------------------------
155        {"PF_A4R4G4B4",
156        /* Bytes per element */
157        2, 
158        /* Flags */
159        PFF_HASALPHA | PFF_NATIVEENDIAN, 
160        /* rbits, gbits, bbits, abits */
161        4, 4, 4, 4,
162        /* Masks and shifts */
163        0x0F00, 0x00F0, 0x000F, 0xF000,
164        8, 4, 0, 12
165        },
166        //-----------------------------------------------------------------------
167        {"PF_A1R5G5B5",
168        /* Bytes per element */
169        2, 
170        /* Flags */
171        PFF_HASALPHA | PFF_NATIVEENDIAN, 
172        /* rbits, gbits, bbits, abits */
173        5, 5, 5, 1,
174        /* Masks and shifts */
175        0x7C00, 0x03E0, 0x001F, 0x8000,
176        10, 5, 0, 15,
177        },
178        //-----------------------------------------------------------------------
179        {"PF_R8G8B8",
180        /* Bytes per element */
181        3,  // 24 bit integer -- special
182        /* Flags */
183        PFF_NATIVEENDIAN, 
184        /* rbits, gbits, bbits, abits */
185        8, 8, 8, 0,
186        /* Masks and shifts */
187        0xFF0000, 0x00FF00, 0x0000FF, 0,
188        16, 8, 0, 0
189        },
190        //-----------------------------------------------------------------------
191        {"PF_B8G8R8",
192        /* Bytes per element */
193        3,  // 24 bit integer -- special
194        /* Flags */
195        PFF_NATIVEENDIAN, 
196        /* rbits, gbits, bbits, abits */
197        8, 8, 8, 0,
198        /* Masks and shifts */
199        0x0000FF, 0x00FF00, 0xFF0000, 0,
200        0, 8, 16, 0
201        },
202        //-----------------------------------------------------------------------
203        {"PF_A8R8G8B8",
204        /* Bytes per element */
205        4, 
206        /* Flags */
207        PFF_HASALPHA | PFF_NATIVEENDIAN, 
208        /* rbits, gbits, bbits, abits */
209        8, 8, 8, 8,
210        /* Masks and shifts */
211        0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
212        16, 8, 0, 24
213        },
214        //-----------------------------------------------------------------------
215        {"PF_A8B8G8R8",
216        /* Bytes per element */
217        4, 
218        /* Flags */
219        PFF_HASALPHA | PFF_NATIVEENDIAN, 
220        /* rbits, gbits, bbits, abits */
221        8, 8, 8, 8,
222        /* Masks and shifts */
223        0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000,
224        0, 8, 16, 24,
225        },
226        //-----------------------------------------------------------------------
227        {"PF_B8G8R8A8",
228        /* Bytes per element */
229        4, 
230        /* Flags */
231        PFF_HASALPHA | PFF_NATIVEENDIAN, 
232        /* rbits, gbits, bbits, abits */
233        8, 8, 8, 8,
234        /* Masks and shifts */
235        0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF,
236        8, 16, 24, 0
237        },
238        //-----------------------------------------------------------------------
239        {"PF_A2R10G10B10",
240        /* Bytes per element */
241        4, 
242        /* Flags */
243        PFF_HASALPHA | PFF_NATIVEENDIAN, 
244        /* rbits, gbits, bbits, abits */
245        10, 10, 10, 2,
246        /* Masks and shifts */
247        0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000,
248        20, 10, 0, 30
249        },
250        //-----------------------------------------------------------------------
251        {"PF_A2B10G10R10",
252        /* Bytes per element */
253        4, 
254        /* Flags */
255        PFF_HASALPHA | PFF_NATIVEENDIAN, 
256        /* rbits, gbits, bbits, abits */
257        10, 10, 10, 2,
258        /* Masks and shifts */
259        0x000003FF, 0x000FFC00, 0x3FF00000, 0xC0000000,
260        0, 10, 20, 30
261        },
262        //-----------------------------------------------------------------------
263        {"PF_DXT1",
264        /* Bytes per element */
265        0, 
266        /* Flags */
267        PFF_COMPRESSED | PFF_HASALPHA, 
268        /* rbits, gbits, bbits, abits */
269        0, 0, 0, 0,
270        /* Masks and shifts */
271        0, 0, 0, 0, 0, 0, 0, 0
272        },
273        //-----------------------------------------------------------------------
274        {"PF_DXT2",
275        /* Bytes per element */
276        0, 
277        /* Flags */
278        PFF_COMPRESSED | PFF_HASALPHA, 
279        /* rbits, gbits, bbits, abits */
280        0, 0, 0, 0,
281        /* Masks and shifts */
282        0, 0, 0, 0, 0, 0, 0, 0
283        },
284        //-----------------------------------------------------------------------
285        {"PF_DXT3",
286        /* Bytes per element */
287        0, 
288        /* Flags */
289        PFF_COMPRESSED | PFF_HASALPHA, 
290        /* rbits, gbits, bbits, abits */
291        0, 0, 0, 0,
292        /* Masks and shifts */
293        0, 0, 0, 0, 0, 0, 0, 0
294        },
295        //-----------------------------------------------------------------------
296        {"PF_DXT4",
297        /* Bytes per element */
298        0, 
299        /* Flags */
300        PFF_COMPRESSED | PFF_HASALPHA, 
301        /* rbits, gbits, bbits, abits */
302        0, 0, 0, 0,
303        /* Masks and shifts */
304        0, 0, 0, 0, 0, 0, 0, 0
305        },
306        //-----------------------------------------------------------------------
307        {"PF_DXT5",
308        /* Bytes per element */
309        0, 
310        /* Flags */
311        PFF_COMPRESSED | PFF_HASALPHA, 
312        /* rbits, gbits, bbits, abits */
313        0, 0, 0, 0,
314        /* Masks and shifts */
315        0, 0, 0, 0, 0, 0, 0, 0
316        },
317        //-----------------------------------------------------------------------
318        {"PF_FLOAT16_RGB",
319        /* Bytes per element */
320        6, 
321        /* Flags */
322        PFF_FLOAT, 
323        /* rbits, gbits, bbits, abits */
324        16, 16, 16, 0,
325        /* Masks and shifts */
326        0, 0, 0, 0, 0, 0, 0, 0
327        },
328        //-----------------------------------------------------------------------
329        {"PF_FLOAT16_RGBA",
330        /* Bytes per element */
331        8, 
332        /* Flags */
333        PFF_FLOAT, 
334        /* rbits, gbits, bbits, abits */
335        16, 16, 16, 16,
336        /* Masks and shifts */
337        0, 0, 0, 0, 0, 0, 0, 0
338        },
339        //-----------------------------------------------------------------------
340        {"PF_FLOAT32_RGB",
341        /* Bytes per element */
342        12, 
343        /* Flags */
344        PFF_FLOAT, 
345        /* rbits, gbits, bbits, abits */
346        32, 32, 32, 0,
347        /* Masks and shifts */
348        0, 0, 0, 0, 0, 0, 0, 0
349        },
350        //-----------------------------------------------------------------------
351        {"PF_FLOAT32_RGBA",
352        /* Bytes per element */
353        16, 
354        /* Flags */
355        PFF_FLOAT, 
356        /* rbits, gbits, bbits, abits */
357        32, 32, 32, 32,
358        /* Masks and shifts */
359        0, 0, 0, 0, 0, 0, 0, 0
360        },
361        //-----------------------------------------------------------------------
362        {"PF_X8R8G8B8",
363        /* Bytes per element */
364        4, 
365        /* Flags */
366        PFF_NATIVEENDIAN, 
367        /* rbits, gbits, bbits, abits */
368        8, 8, 8, 0,
369        /* Masks and shifts */
370        0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000,
371        16, 8, 0, 24
372        },
373        //-----------------------------------------------------------------------
374        {"PF_X8B8G8R8",
375        /* Bytes per element */
376        4, 
377        /* Flags */
378        PFF_NATIVEENDIAN, 
379        /* rbits, gbits, bbits, abits */
380        8, 8, 8, 0,
381        /* Masks and shifts */
382        0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000,
383        0, 8, 16, 24
384        },
385        //-----------------------------------------------------------------------
386        {"PF_R8G8B8A8",
387        /* Bytes per element */
388        4, 
389        /* Flags */
390        PFF_HASALPHA | PFF_NATIVEENDIAN, 
391        /* rbits, gbits, bbits, abits */
392        8, 8, 8, 8,
393        /* Masks and shifts */
394        0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF,
395        24, 16, 8, 0
396        },
397        //-----------------------------------------------------------------------
398                {"PF_DEPTH",
399        /* Bytes per element */
400        4, 
401        /* Flags */
402        PFF_DEPTH, 
403        /* rbits, gbits, bbits, abits */
404        0, 0, 0, 0,
405        /* Masks and shifts */
406                0, 0, 0, 0, 0, 0, 0, 0
407        },
408        //-----------------------------------------------------------------------
409                {"PF_SHORT_RGBA",
410                /* Bytes per element */
411        8, 
412        /* Flags */
413        PFF_HASALPHA, 
414        /* rbits, gbits, bbits, abits */
415        16, 16, 16, 16,
416        /* Masks and shifts */
417                0, 0, 0, 0, 0, 0, 0, 0
418        },
419        //-----------------------------------------------------------------------
420        {"PF_R3G3B2",
421        /* Bytes per element */
422        1, 
423        /* Flags */
424        PFF_NATIVEENDIAN, 
425        /* rbits, gbits, bbits, abits */
426        3, 3, 2, 0,
427        /* Masks and shifts */
428        0xE0, 0x1C, 0x03, 0,
429        5, 2, 0, 0
430        },
431        //-----------------------------------------------------------------------
432        {"PF_FLOAT16_R",
433        /* Bytes per element */
434        2, 
435        /* Flags */
436        PFF_FLOAT, 
437        /* rbits, gbits, bbits, abits */
438        16, 0, 0, 0,
439        /* Masks and shifts */
440        0, 0, 0, 0, 0, 0, 0, 0
441        },
442        //-----------------------------------------------------------------------
443        {"PF_FLOAT32_R",
444        /* Bytes per element */
445        4, 
446        /* Flags */
447        PFF_FLOAT, 
448        /* rbits, gbits, bbits, abits */
449        32, 0, 0, 0,
450        /* Masks and shifts */
451        0, 0, 0, 0, 0, 0, 0, 0
452        },
453    };
454    //-----------------------------------------------------------------------
455        size_t PixelBox::getConsecutiveSize() const
456        {
457                return PixelUtil::getMemorySize(getWidth(), getHeight(), getDepth(), format);
458        }
459        PixelBox PixelBox::getSubVolume(const Box &def) const
460        {
461                if(PixelUtil::isCompressed(format))
462                {
463                        if(def.left == left && def.top == top && def.front == front &&
464                           def.right == right && def.bottom == bottom && def.back == back)
465                        {
466                                // Entire buffer is being queried
467                                return *this;
468                        }
469                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Cannot return subvolume of compressed PixelBuffer", "PixelBox::getSubVolume");
470                }
471                if(!contains(def))
472                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Bounds out of range", "PixelBox::getSubVolume");
473
474                const size_t elemSize = PixelUtil::getNumElemBytes(format);
475                // Calculate new data origin
476                PixelBox rval(def, format, ((uint8*)data)
477                        + ((def.left-left)*elemSize)
478                        + ((def.top-top)*rowPitch*elemSize)
479                        + ((def.front-front)*slicePitch*elemSize)
480                );             
481
482                rval.rowPitch = rowPitch;
483                rval.slicePitch = slicePitch;
484                rval.format = format;
485
486                return rval;
487        }
488    //-----------------------------------------------------------------------
489    /**
490    * Directly get the description record for provided pixel format. For debug builds,
491    * this checks the bounds of fmt with an assertion.
492    */   
493    static inline const PixelFormatDescription &getDescriptionFor(const PixelFormat fmt)
494    {
495        const int ord = (int)fmt;
496        assert(ord>=0 && ord<PF_COUNT);
497
498        return _pixelFormats[ord];
499    }
500    //-----------------------------------------------------------------------
501    size_t PixelUtil::getNumElemBytes( PixelFormat format )
502    {
503        return getDescriptionFor(format).elemBytes;
504    }
505        //-----------------------------------------------------------------------
506        size_t PixelUtil::getMemorySize(size_t width, size_t height, size_t depth, PixelFormat format)
507        {
508                if(isCompressed(format))
509                {
510                        switch(format)
511                        {
512                                // DXT formats work by dividing the image into 4x4 blocks, then encoding each
513                                // 4x4 block with a certain number of bytes. DXT can only be used on 2D images.
514                                case PF_DXT1:
515                                        assert(depth == 1);
516                                        return ((width+3)/4)*((height+3)/4)*8;
517                                case PF_DXT2:
518                                case PF_DXT3:
519                                case PF_DXT4:
520                                case PF_DXT5:
521                                        assert(depth == 1);
522                                        return ((width+3)/4)*((height+3)/4)*16;
523                                default:
524                                OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid compressed pixel format",
525                                        "PixelUtil::getMemorySize");
526                        }
527                }
528                else
529                {
530                        return width*height*depth*getNumElemBytes(format);
531                }
532        }
533    //-----------------------------------------------------------------------
534    size_t PixelUtil::getNumElemBits( PixelFormat format )
535    {
536        return getDescriptionFor(format).elemBytes * 8;
537    }
538    //-----------------------------------------------------------------------
539    unsigned int PixelUtil::getFlags( PixelFormat format )
540    {
541        return getDescriptionFor(format).flags;
542    }
543    //-----------------------------------------------------------------------
544    bool PixelUtil::hasAlpha(PixelFormat format)
545    {
546        return (PixelUtil::getFlags(format) & PFF_HASALPHA) > 0;
547    }
548    //-----------------------------------------------------------------------
549    bool PixelUtil::isFloatingPoint(PixelFormat format)
550    {
551        return (PixelUtil::getFlags(format) & PFF_FLOAT) > 0;
552    }
553    //-----------------------------------------------------------------------
554    bool PixelUtil::isCompressed(PixelFormat format)
555    {
556        return (PixelUtil::getFlags(format) & PFF_COMPRESSED) > 0;
557    }
558    //-----------------------------------------------------------------------
559    bool PixelUtil::isDepth(PixelFormat format)
560    {
561        return (PixelUtil::getFlags(format) & PFF_DEPTH) > 0;
562    }
563    //-----------------------------------------------------------------------
564    bool PixelUtil::isNativeEndian(PixelFormat format)
565    {
566        return (PixelUtil::getFlags(format) & PFF_NATIVEENDIAN) > 0;
567    }
568    //-----------------------------------------------------------------------
569    bool PixelUtil::isLuminance(PixelFormat format)
570    {
571        return (PixelUtil::getFlags(format) & PFF_LUMINANCE) > 0;
572    }
573    //-----------------------------------------------------------------------
574        bool PixelUtil::isValidExtent(size_t width, size_t height, size_t depth, PixelFormat format)
575        {
576                if(isCompressed(format))
577                {
578                        switch(format)
579                        {
580                                case PF_DXT1:
581                                case PF_DXT2:
582                                case PF_DXT3:
583                                case PF_DXT4:
584                                case PF_DXT5:
585                                        return ((width&3)==0 && (height&3)==0 && depth==1);
586                                default:
587                                        return true;
588                        }
589                }
590                else
591                {
592                        return true;
593                }
594        }
595        //-----------------------------------------------------------------------
596    void PixelUtil::getBitDepths(PixelFormat format, int rgba[4])
597    {
598        const PixelFormatDescription &des = getDescriptionFor(format);
599        rgba[0] = des.rbits;
600        rgba[1] = des.gbits;
601        rgba[2] = des.bbits;
602        rgba[3] = des.abits;
603    }
604        //-----------------------------------------------------------------------
605        void PixelUtil::getBitMasks(PixelFormat format, uint32 rgba[4])
606    {
607        const PixelFormatDescription &des = getDescriptionFor(format);
608        rgba[0] = des.rmask;
609        rgba[1] = des.gmask;
610        rgba[2] = des.bmask;
611        rgba[3] = des.amask;
612    }
613    //-----------------------------------------------------------------------
614    String PixelUtil::getFormatName(PixelFormat srcformat)
615    {
616        return getDescriptionFor(srcformat).name;
617    }
618    //-----------------------------------------------------------------------
619    bool PixelUtil::isAccessible(PixelFormat srcformat) {
620        unsigned int flags = getFlags(srcformat);
621        return !((flags & PFF_COMPRESSED) || (flags & PFF_DEPTH));
622    }
623    //-----------------------------------------------------------------------
624    /*************************************************************************
625    * Pixel packing/unpacking utilities
626    */
627    void PixelUtil::packColour(const ColourValue &colour, const PixelFormat pf,  const void* dest)
628    {
629        packColour(colour.r, colour.g, colour.b, colour.a, pf, dest);
630    }
631    //-----------------------------------------------------------------------
632    void PixelUtil::packColour(const uint8 r, const uint8 g, const uint8 b, const uint8 a, const PixelFormat pf,  const void* dest)
633    {
634        const PixelFormatDescription &des = getDescriptionFor(pf);
635        if(des.flags & PFF_NATIVEENDIAN) {
636            // Shortcut for integer formats packing
637            unsigned int value = ((Bitwise::fixedToFixed(r, 8, des.rbits)<<des.rshift) & des.rmask) |
638                ((Bitwise::fixedToFixed(g, 8, des.gbits)<<des.gshift) & des.gmask) |
639                ((Bitwise::fixedToFixed(b, 8, des.bbits)<<des.bshift) & des.bmask) |
640                ((Bitwise::fixedToFixed(a, 8, des.abits)<<des.ashift) & des.amask);
641            // And write to memory
642            Bitwise::intWrite(dest, des.elemBytes, value);
643        } else {
644            // Convert to float
645            packColour((float)r/255.0f,(float)g/255.0f,(float)b/255.0f,(float)a/255.0f, pf, dest);
646        }
647    }
648    //-----------------------------------------------------------------------
649    void PixelUtil::packColour(const float r, const float g, const float b, const float a, const PixelFormat pf,  const void* dest)
650    {
651        // Catch-it-all here
652        const PixelFormatDescription &des = getDescriptionFor(pf);
653        if(des.flags & PFF_NATIVEENDIAN) {
654            // Do the packing
655            //std::cerr << dest << " " << r << " " << g <<  " " << b << " " << a << std::endl;
656            const unsigned int value = ((Bitwise::floatToFixed(r, des.rbits)<<des.rshift) & des.rmask) |
657                ((Bitwise::floatToFixed(g, des.gbits)<<des.gshift) & des.gmask) |
658                ((Bitwise::floatToFixed(b, des.bbits)<<des.bshift) & des.bmask) |
659                ((Bitwise::floatToFixed(a, des.abits)<<des.ashift) & des.amask);
660            // And write to memory
661            Bitwise::intWrite(dest, des.elemBytes, value);                               
662        } else {
663            switch(pf)
664            {
665            case PF_FLOAT32_R:
666                ((float*)dest)[0] = r;
667                break;
668            case PF_FLOAT32_RGB:
669                ((float*)dest)[0] = r;
670                ((float*)dest)[1] = g;
671                ((float*)dest)[2] = b;
672                break;
673            case PF_FLOAT32_RGBA:
674                ((float*)dest)[0] = r;
675                ((float*)dest)[1] = g;
676                ((float*)dest)[2] = b;
677                ((float*)dest)[3] = a;
678                break;
679            case PF_FLOAT16_R:
680                ((uint16*)dest)[0] = Bitwise::floatToHalf(r);
681                break;
682            case PF_FLOAT16_RGB:
683                ((uint16*)dest)[0] = Bitwise::floatToHalf(r);
684                ((uint16*)dest)[1] = Bitwise::floatToHalf(g);
685                ((uint16*)dest)[2] = Bitwise::floatToHalf(b);
686                break;
687            case PF_FLOAT16_RGBA:
688                ((uint16*)dest)[0] = Bitwise::floatToHalf(r);
689                ((uint16*)dest)[1] = Bitwise::floatToHalf(g);
690                ((uint16*)dest)[2] = Bitwise::floatToHalf(b);
691                ((uint16*)dest)[3] = Bitwise::floatToHalf(a);
692                break;
693                        case PF_SHORT_RGBA:
694                                ((uint16*)dest)[0] = Bitwise::floatToFixed(r, 16);
695                ((uint16*)dest)[1] = Bitwise::floatToFixed(g, 16);
696                ((uint16*)dest)[2] = Bitwise::floatToFixed(b, 16);
697                ((uint16*)dest)[3] = Bitwise::floatToFixed(a, 16);
698                                break;
699                        case PF_BYTE_LA:
700                                ((uint8*)dest)[0] = Bitwise::floatToFixed(r, 8);
701                ((uint8*)dest)[1] = Bitwise::floatToFixed(a, 8);
702                                break;
703            default:
704                // Not yet supported
705                OGRE_EXCEPT(
706                    Exception::UNIMPLEMENTED_FEATURE,
707                    "pack to "+getFormatName(pf)+" not implemented",
708                    "PixelUtil::packColour");
709                break;
710            }
711        }
712    }
713    //-----------------------------------------------------------------------
714    void PixelUtil::unpackColour(ColourValue *colour, PixelFormat pf,  const void* src)
715    {
716        unpackColour(&colour->r, &colour->g, &colour->b, &colour->a, pf, src);
717    }
718    //-----------------------------------------------------------------------
719    void PixelUtil::unpackColour(uint8 *r, uint8 *g, uint8 *b, uint8 *a, PixelFormat pf,  const void* src)
720    {
721        const PixelFormatDescription &des = getDescriptionFor(pf);
722        if(des.flags & PFF_NATIVEENDIAN) {
723            // Shortcut for integer formats unpacking
724            const unsigned int value = Bitwise::intRead(src, des.elemBytes);
725            if(des.flags & PFF_LUMINANCE)
726            {
727                // Luminance format -- only rbits used
728                *r = *g = *b = Bitwise::fixedToFixed(
729                    (value & des.rmask)>>des.rshift, des.rbits, 8);
730            }
731            else
732            {
733                *r = Bitwise::fixedToFixed((value & des.rmask)>>des.rshift, des.rbits, 8);
734                *g = Bitwise::fixedToFixed((value & des.gmask)>>des.gshift, des.gbits, 8);
735                *b = Bitwise::fixedToFixed((value & des.bmask)>>des.bshift, des.bbits, 8);
736            }
737            if(des.flags & PFF_HASALPHA)
738            {
739                *a = Bitwise::fixedToFixed((value & des.amask)>>des.ashift, des.abits, 8);
740            }
741            else
742            {
743                *a = 255; // No alpha, default a component to full
744            }
745        } else {
746            // Do the operation with the more generic floating point
747            float rr, gg, bb, aa;
748            unpackColour(&rr,&gg,&bb,&aa, pf, src);
749            *r = Bitwise::floatToFixed(rr, 8);
750            *g = Bitwise::floatToFixed(gg, 8);           
751            *b = Bitwise::floatToFixed(bb, 8);
752            *a = Bitwise::floatToFixed(aa, 8);                   
753        }
754    }
755    //-----------------------------------------------------------------------
756    void PixelUtil::unpackColour(float *r, float *g, float *b, float *a,
757        PixelFormat pf,  const void* src)
758    {
759        const PixelFormatDescription &des = getDescriptionFor(pf);
760        if(des.flags & PFF_NATIVEENDIAN) {
761            // Shortcut for integer formats unpacking
762            const unsigned int value = Bitwise::intRead(src, des.elemBytes);
763            if(des.flags & PFF_LUMINANCE)
764            {
765                // Luminance format -- only rbits used
766                *r = *g = *b = Bitwise::fixedToFloat(
767                    (value & des.rmask)>>des.rshift, des.rbits);
768            }
769            else
770            {
771                *r = Bitwise::fixedToFloat((value & des.rmask)>>des.rshift, des.rbits);
772                *g = Bitwise::fixedToFloat((value & des.gmask)>>des.gshift, des.gbits);
773                *b = Bitwise::fixedToFloat((value & des.bmask)>>des.bshift, des.bbits);
774            }
775            if(des.flags & PFF_HASALPHA)
776            {
777                *a = Bitwise::fixedToFloat((value & des.amask)>>des.ashift, des.abits);
778            }
779            else
780            {
781                *a = 1.0f; // No alpha, default a component to full
782            }
783        } else {
784            switch(pf)
785            {
786            case PF_FLOAT32_R:
787                *r = *g = *b = ((float*)src)[0];
788                *a = 1.0f;
789                break;
790            case PF_FLOAT32_RGB:
791                *r = ((float*)src)[0];
792                *g = ((float*)src)[1];
793                *b = ((float*)src)[2];
794                *a = 1.0f;
795                break;
796            case PF_FLOAT32_RGBA:
797                *r = ((float*)src)[0];
798                *g = ((float*)src)[1];
799                *b = ((float*)src)[2];
800                *a = ((float*)src)[3];
801                break;
802            case PF_FLOAT16_R:
803                *r = *g = *b = Bitwise::halfToFloat(((uint16*)src)[0]);
804                *a = 1.0f;
805                break;
806            case PF_FLOAT16_RGB:
807                *r = Bitwise::halfToFloat(((uint16*)src)[0]);
808                *g = Bitwise::halfToFloat(((uint16*)src)[1]);
809                *b = Bitwise::halfToFloat(((uint16*)src)[2]);
810                *a = 1.0f;
811                break;
812            case PF_FLOAT16_RGBA:
813                *r = Bitwise::halfToFloat(((uint16*)src)[0]);
814                *g = Bitwise::halfToFloat(((uint16*)src)[1]);
815                *b = Bitwise::halfToFloat(((uint16*)src)[2]);
816                *a = Bitwise::halfToFloat(((uint16*)src)[3]);
817                break;
818                        case PF_SHORT_RGBA:
819                                *r = Bitwise::fixedToFloat(((uint16*)src)[0], 16);
820                *g = Bitwise::fixedToFloat(((uint16*)src)[1], 16);
821                                *b = Bitwise::fixedToFloat(((uint16*)src)[2], 16);
822                                *a = Bitwise::fixedToFloat(((uint16*)src)[3], 16);
823                                break;
824                        case PF_BYTE_LA:
825                                *r = *g = *b = Bitwise::fixedToFloat(((uint8*)src)[0], 8);
826                                *a = Bitwise::fixedToFloat(((uint8*)src)[1], 8);
827                                break;
828            default:
829                // Not yet supported
830                OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE,
831                    "unpack from "+getFormatName(pf)+" not implemented",
832                    "PixelUtil::unpackColour");
833                break;
834            }
835        }   
836    }
837    //-----------------------------------------------------------------------
838    /* Convert pixels from one format to another */
839    void PixelUtil::bulkPixelConversion(void *srcp, PixelFormat srcFormat,
840        void *destp, PixelFormat dstFormat, unsigned int count)
841    {
842        PixelBox src(count, 1, 1, srcFormat, srcp),
843                                 dst(count, 1, 1, dstFormat, destp);
844
845        bulkPixelConversion(src, dst);
846    }
847    //-----------------------------------------------------------------------
848    void PixelUtil::bulkPixelConversion(const PixelBox &src, const PixelBox &dst)
849    {
850        assert(src.getWidth() == dst.getWidth() &&
851                           src.getHeight() == dst.getHeight() &&
852                           src.getDepth() == dst.getDepth());
853
854                // Check for compressed formats, we don't support decompression, compression or recoding
855                if(PixelUtil::isCompressed(src.format) || PixelUtil::isCompressed(dst.format))
856                {
857                        if(src.format == dst.format)
858                        {
859                                memcpy(dst.data, src.data, src.getConsecutiveSize());
860                                return;
861                        }
862                        else
863                        {
864                                OGRE_EXCEPT(Exception::UNIMPLEMENTED_FEATURE,
865                                        "This method can not be used to compress or decompress images",
866                                        "PixelUtil::bulkPixelConversion");
867                        }
868                }
869
870        // The easy case
871        if(src.format == dst.format) {
872            // Everything consecutive?
873            if(src.isConsecutive() && dst.isConsecutive())
874            {
875                                memcpy(dst.data, src.data, src.getConsecutiveSize());
876                return;
877            }
878
879            uint8 *srcptr = static_cast<uint8*>(src.data);
880            uint8 *dstptr = static_cast<uint8*>(dst.data);
881            const size_t srcPixelSize = PixelUtil::getNumElemBytes(src.format);
882            const size_t dstPixelSize = PixelUtil::getNumElemBytes(dst.format);
883
884            // Calculate pitches+skips in bytes
885            const size_t srcRowPitchBytes = src.rowPitch*srcPixelSize;
886            //const size_t srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
887            const size_t srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
888
889            const size_t dstRowPitchBytes = dst.rowPitch*dstPixelSize;
890            //const size_t dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
891            const size_t dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
892
893            // Otherwise, copy per row
894            const size_t rowSize = src.getWidth()*srcPixelSize;
895            for(size_t z=src.front; z<src.back; z++)
896            {
897                for(size_t y=src.top; y<src.bottom; y++)
898                {
899                                        memcpy(dstptr, srcptr, rowSize);
900                    srcptr += srcRowPitchBytes;
901                    dstptr += dstRowPitchBytes;
902                }
903                srcptr += srcSliceSkipBytes;
904                dstptr += dstSliceSkipBytes;
905            }
906            return;
907        }
908                // Converting to PF_X8R8G8B8 is exactly the same as converting to
909                // PF_A8R8G8B8. (same with PF_X8B8G8R8 and PF_A8B8G8R8)
910                if(dst.format == PF_X8R8G8B8 || dst.format == PF_X8B8G8R8)
911                {
912                        // Do the same conversion, with PF_A8R8G8B8, which has a lot of
913                        // optimized conversions
914                        PixelBox tempdst = dst;
915                        tempdst.format = dst.format==PF_X8R8G8B8?PF_A8R8G8B8:PF_A8B8G8R8;
916                        bulkPixelConversion(src, tempdst);
917                        return;
918                }
919                // Converting from PF_X8R8G8B8 is exactly the same as converting from
920                // PF_A8R8G8B8, given that the destination format does not have alpha.
921                if((src.format == PF_X8R8G8B8||src.format == PF_X8B8G8R8) && !hasAlpha(dst.format))
922                {
923                        // Do the same conversion, with PF_A8R8G8B8, which has a lot of
924                        // optimized conversions
925                        PixelBox tempsrc = src;
926                        tempsrc.format = src.format==PF_X8R8G8B8?PF_A8R8G8B8:PF_A8B8G8R8;
927                        bulkPixelConversion(tempsrc, dst);
928                        return;
929                }
930
931// NB VC6 can't handle the templates required for optimised conversion, tough
932#if OGRE_COMPILER != OGRE_COMPILER_MSVC || OGRE_COMP_VER >= 1300
933        // Is there a specialized, inlined, conversion?
934        if(doOptimizedConversion(src, dst))
935        {
936            // If so, good
937            return;
938        }
939#endif
940
941        uint8 *srcptr = static_cast<uint8*>(src.data);
942        uint8 *dstptr = static_cast<uint8*>(dst.data);
943        const size_t srcPixelSize = PixelUtil::getNumElemBytes(src.format);
944        const size_t dstPixelSize = PixelUtil::getNumElemBytes(dst.format);
945
946        // Calculate pitches+skips in bytes
947        const size_t srcRowSkipBytes = src.getRowSkip()*srcPixelSize;
948        const size_t srcSliceSkipBytes = src.getSliceSkip()*srcPixelSize;
949        const size_t dstRowSkipBytes = dst.getRowSkip()*dstPixelSize;
950        const size_t dstSliceSkipBytes = dst.getSliceSkip()*dstPixelSize;
951
952        // The brute force fallback
953        float r,g,b,a;
954        for(size_t z=src.front; z<src.back; z++)
955        {
956            for(size_t y=src.top; y<src.bottom; y++)
957            {
958                for(size_t x=src.left; x<src.right; x++)
959                {
960                    unpackColour(&r, &g, &b, &a, src.format, srcptr);
961                    packColour(r, g, b, a, dst.format, dstptr);
962                    srcptr += srcPixelSize;
963                    dstptr += dstPixelSize;
964                }
965                srcptr += srcRowSkipBytes;
966                dstptr += dstRowSkipBytes;
967            }
968            srcptr += srcSliceSkipBytes;
969            dstptr += dstSliceSkipBytes;
970        }
971    }
972
973}
Note: See TracBrowser for help on using the repository browser.