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

Revision 692, 37.9 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

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