SD + Bitmap

Dependencies:   TS_DISCO_F746NG LCD_DISCO_F746NG BSP_DISCO_F746NG

Revision:
0:14e97aa401f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bitmap.h	Tue May 21 10:24:03 2019 +0000
@@ -0,0 +1,774 @@
+/*
+ * Windows Bitmap File Loader
+ * Version 1.2.5 (20120929)
+ *
+ * Supported Formats: 1, 4, 8, 16, 24, 32 Bit Images
+ * Alpha Bitmaps are also supported.
+ * Supported compression types: RLE 8, BITFIELDS
+ *
+ * Created by: Benjamin Kalytta, 2006 - 2012
+ * Thanks for bug fixes goes to: Chris Campbell
+ *
+ * Licence: Free to use, URL to my source and my name is required in your source code.
+ *
+ * Source can be found at http://www.kalytta.com/bitmap.h
+ *
+ * Warning: This code should not be used in unmodified form in a production environment.
+ * It should only serve as a basis for your own development.
+ * There is only a minimal error handling in this code. (Notice added 20111211)
+ */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#ifndef __LITTLE_ENDIAN__
+    #ifndef __BIG_ENDIAN__
+        #define __LITTLE_ENDIAN__
+    #endif
+#endif
+
+#ifdef __LITTLE_ENDIAN__
+    #define BITMAP_SIGNATURE 0x4d42
+#else
+    #define BITMAP_SIGNATURE 0x424d
+#endif
+
+#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
+    typedef unsigned __int32 uint32_t;
+    typedef unsigned __int16 uint16_t;
+    typedef unsigned __int8 uint8_t;
+    typedef __int32 int32_t;
+#elif defined(__GNUC__) || defined(__CYGWIN__) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__PGI) || defined(__LCC__)
+    #include <stdint.h>
+#else
+    typedef unsigned int uint32_t;
+    typedef unsigned short int uint16_t;
+    typedef unsigned char uint8_t;
+    typedef int int32_t;
+#endif
+
+#pragma pack(push, 1)
+
+typedef struct _BITMAP_FILEHEADER {
+    uint16_t Signature;
+    uint32_t Size;
+    uint32_t Reserved;
+    uint32_t BitsOffset;
+} BITMAP_FILEHEADER;
+
+#define BITMAP_FILEHEADER_SIZE 14
+
+typedef struct _BITMAP_HEADER {
+    uint32_t HeaderSize;
+    int32_t Width;
+    int32_t Height;
+    uint16_t Planes;
+    uint16_t BitCount;
+    uint32_t Compression;
+    uint32_t SizeImage;
+    int32_t PelsPerMeterX;
+    int32_t PelsPerMeterY;
+    uint32_t ClrUsed;
+    uint32_t ClrImportant;
+    uint32_t RedMask;
+    uint32_t GreenMask;
+    uint32_t BlueMask;
+    uint32_t AlphaMask;
+    uint32_t CsType;
+    uint32_t Endpoints[9]; // see http://msdn2.microsoft.com/en-us/library/ms536569.aspx
+    uint32_t GammaRed;
+    uint32_t GammaGreen;
+    uint32_t GammaBlue;
+} BITMAP_HEADER;
+
+typedef struct _RGBA {
+    uint8_t Red;
+    uint8_t Green;
+    uint8_t Blue;
+    uint8_t Alpha;
+} RGBA;
+
+typedef struct _BGRA {
+    uint8_t Blue;
+    uint8_t Green;
+    uint8_t Red;
+    uint8_t Alpha;
+} BGRA;
+
+#pragma pack(pop)
+
+class CBitmap {
+private:
+    BITMAP_FILEHEADER m_BitmapFileHeader;
+    BITMAP_HEADER m_BitmapHeader;
+    BGRA *m_BitmapData;
+    unsigned int m_BitmapSize;
+    
+    // Masks and bit counts shouldn't exceed 32 Bits
+public:
+    class CColor {
+public:
+        static inline unsigned int BitCountByMask(unsigned int Mask) {
+            unsigned int BitCount = 0;
+            while (Mask) {
+                Mask &= Mask - 1;
+                BitCount++;
+            }
+            return BitCount;
+        }
+
+        static inline unsigned int BitPositionByMask(unsigned int Mask) {
+            return BitCountByMask((Mask & (~Mask + 1)) - 1);
+        }
+
+        static inline unsigned int ComponentByMask(unsigned int Color, unsigned int Mask) {
+            unsigned int Component = Color & Mask;
+            return Component >> BitPositionByMask(Mask);
+        }
+
+        static inline unsigned int BitCountToMask(unsigned int BitCount) {
+            return (BitCount == 32) ? 0xFFFFFFFF : (1 << BitCount) - 1;
+        }
+
+        static unsigned int Convert(unsigned int Color, unsigned int FromBitCount, unsigned int ToBitCount) {
+            if (ToBitCount < FromBitCount) {
+                Color >>= (FromBitCount - ToBitCount);
+            } else {
+                Color <<= (ToBitCount - FromBitCount);
+                if (Color > 0) {
+                    Color |= BitCountToMask(ToBitCount - FromBitCount);
+                }
+            }
+            return Color;
+        }
+    };
+
+public:
+    
+    CBitmap() : m_BitmapData(0), m_BitmapSize(0)  {
+        Dispose();
+    }
+    
+    CBitmap(const char* Filename) : m_BitmapData(0), m_BitmapSize(0) {
+        Load(Filename);
+    }
+    
+    ~CBitmap() {
+        Dispose();
+    }
+    
+    void Dispose() {
+        if (m_BitmapData) {
+            delete[] m_BitmapData;
+            m_BitmapData = 0;
+        }
+        memset(&m_BitmapFileHeader, 0, sizeof(m_BitmapFileHeader));
+        memset(&m_BitmapHeader, 0, sizeof(m_BitmapHeader));
+    }
+    
+    /* Load specified Bitmap and stores it as RGBA in an internal buffer */
+    
+    bool Load(const char *Filename) {
+        std::ifstream file(Filename, std::ios::binary | std::ios::in);
+        
+        if (file.bad()) {
+            return false;
+        }
+
+        if (file.is_open() == false) {
+            return false;
+        }
+        
+        Dispose();
+        
+        file.read((char*) &m_BitmapFileHeader, BITMAP_FILEHEADER_SIZE);
+        if (m_BitmapFileHeader.Signature != BITMAP_SIGNATURE) {
+            return false;
+        }
+
+        file.read((char*) &m_BitmapHeader, sizeof(BITMAP_HEADER));
+        
+        /* Load Color Table */
+        
+        file.seekg(BITMAP_FILEHEADER_SIZE + m_BitmapHeader.HeaderSize, std::ios::beg);
+        
+        unsigned int ColorTableSize = 0;
+
+        if (m_BitmapHeader.BitCount == 1) {
+            ColorTableSize = 2;
+        } else if (m_BitmapHeader.BitCount == 4) {
+            ColorTableSize = 16;
+        } else if (m_BitmapHeader.BitCount == 8) {
+            ColorTableSize = 256;
+        }
+        
+        // Always allocate full sized color table
+
+        BGRA* ColorTable = new BGRA[ColorTableSize]; // std::bad_alloc exception should be thrown if memory is not available
+        
+        file.read((char*) ColorTable, sizeof(BGRA) * m_BitmapHeader.ClrUsed);
+
+        /* ... Color Table for 16 bits images are not supported yet */  
+        
+        m_BitmapSize = GetWidth() * GetHeight();
+        m_BitmapData = new BGRA[m_BitmapSize];
+        
+        unsigned int LineWidth = ((GetWidth() * GetBitCount() / 8) + 3) & ~3;
+        uint8_t *Line = new uint8_t[LineWidth];
+        
+        file.seekg(m_BitmapFileHeader.BitsOffset, std::ios::beg);
+
+        int Index = 0;
+        bool Result = true;
+
+        if (m_BitmapHeader.Compression == 0) {
+            for (unsigned int i = 0; i < GetHeight(); i++) {
+                file.read((char*) Line, LineWidth);
+
+                uint8_t *LinePtr = Line;
+                
+                for (unsigned int j = 0; j < GetWidth(); j++) {
+                    if (m_BitmapHeader.BitCount == 1) {
+                        uint32_t Color = *((uint8_t*) LinePtr);
+                        for (int k = 0; k < 8; k++) {
+                            m_BitmapData[Index].Red = ColorTable[Color & 0x80 ? 1 : 0].Red;
+                            m_BitmapData[Index].Green = ColorTable[Color & 0x80 ? 1 : 0].Green;
+                            m_BitmapData[Index].Blue = ColorTable[Color & 0x80 ? 1 : 0].Blue;
+                            m_BitmapData[Index].Alpha = ColorTable[Color & 0x80 ? 1 : 0].Alpha;
+                            Index++;
+                            Color <<= 1;
+                        }
+                        LinePtr++;
+                        j += 7;
+                    } else if (m_BitmapHeader.BitCount == 4) {
+                        uint32_t Color = *((uint8_t*) LinePtr);
+                        m_BitmapData[Index].Red = ColorTable[(Color >> 4) & 0x0f].Red;
+                        m_BitmapData[Index].Green = ColorTable[(Color >> 4) & 0x0f].Green;
+                        m_BitmapData[Index].Blue = ColorTable[(Color >> 4) & 0x0f].Blue;
+                        m_BitmapData[Index].Alpha = ColorTable[(Color >> 4) & 0x0f].Alpha;
+                        Index++;
+                        m_BitmapData[Index].Red = ColorTable[Color & 0x0f].Red;
+                        m_BitmapData[Index].Green = ColorTable[Color & 0x0f].Green;
+                        m_BitmapData[Index].Blue = ColorTable[Color & 0x0f].Blue;
+                        m_BitmapData[Index].Alpha = ColorTable[Color & 0x0f].Alpha;
+                        Index++;
+                        LinePtr++;
+                        j++;
+                    } else if (m_BitmapHeader.BitCount == 8) {
+                        uint32_t Color = *((uint8_t*) LinePtr);
+                        m_BitmapData[Index].Red = ColorTable[Color].Red;
+                        m_BitmapData[Index].Green = ColorTable[Color].Green;
+                        m_BitmapData[Index].Blue = ColorTable[Color].Blue;
+                        m_BitmapData[Index].Alpha = ColorTable[Color].Alpha;
+                        Index++;
+                        LinePtr++;
+                    } else if (m_BitmapHeader.BitCount == 16) {
+                        uint32_t Color = *((uint16_t*) LinePtr);
+                        m_BitmapData[Index].Red = ((Color >> 10) & 0x1f) << 3;
+                        m_BitmapData[Index].Green = ((Color >> 5) & 0x1f) << 3;
+                        m_BitmapData[Index].Blue = (Color & 0x1f) << 3;
+                        m_BitmapData[Index].Alpha = 255;
+                        Index++;
+                        LinePtr += 2;
+                    } else if (m_BitmapHeader.BitCount == 24) {
+                        uint32_t Color = *((uint32_t*) LinePtr);
+                        m_BitmapData[Index].Blue = Color & 0xff;
+                        m_BitmapData[Index].Green = (Color >> 8) & 0xff;
+                        m_BitmapData[Index].Red = (Color >> 16) & 0xff;
+                        m_BitmapData[Index].Alpha = 255;
+                        Index++;
+                        LinePtr += 3;
+                    } else if (m_BitmapHeader.BitCount == 32) {
+                        uint32_t Color = *((uint32_t*) LinePtr);
+                        m_BitmapData[Index].Blue = Color & 0xff;
+                        m_BitmapData[Index].Green = (Color >> 8) & 0xff;
+                        m_BitmapData[Index].Red = (Color >> 16) & 0xff;
+                        m_BitmapData[Index].Alpha = Color >> 24;
+                        Index++;
+                        LinePtr += 4;
+                    }
+                }
+            }
+        } else if (m_BitmapHeader.Compression == 1) { // RLE 8
+            uint8_t Count = 0;
+            uint8_t ColorIndex = 0;
+            int x = 0, y = 0;
+
+            while (file.eof() == false) {
+                file.read((char*) &Count, sizeof(uint8_t));
+                file.read((char*) &ColorIndex, sizeof(uint8_t));
+
+                if (Count > 0) {
+                    Index = x + y * GetWidth();
+                    for (int k = 0; k < Count; k++) {
+                        m_BitmapData[Index + k].Red = ColorTable[ColorIndex].Red;
+                        m_BitmapData[Index + k].Green = ColorTable[ColorIndex].Green;
+                        m_BitmapData[Index + k].Blue = ColorTable[ColorIndex].Blue;
+                        m_BitmapData[Index + k].Alpha = ColorTable[ColorIndex].Alpha;
+                    }
+                    x += Count;
+                } else if (Count == 0) {
+                    int Flag = ColorIndex;
+                    if (Flag == 0) {
+                        x = 0;
+                        y++;
+                    } else if (Flag == 1) {
+                        break;
+                    } else if (Flag == 2) {
+                        char rx = 0;
+                        char ry = 0;
+                        file.read((char*) &rx, sizeof(char));
+                        file.read((char*) &ry, sizeof(char));
+                        x += rx;
+                        y += ry;
+                    } else {
+                        Count = Flag;
+                        Index = x + y * GetWidth();
+                        for (int k = 0; k < Count; k++) {
+                            file.read((char*) &ColorIndex, sizeof(uint8_t));
+                            m_BitmapData[Index + k].Red = ColorTable[ColorIndex].Red;
+                            m_BitmapData[Index + k].Green = ColorTable[ColorIndex].Green;
+                            m_BitmapData[Index + k].Blue = ColorTable[ColorIndex].Blue;
+                            m_BitmapData[Index + k].Alpha = ColorTable[ColorIndex].Alpha;
+                        }
+                        x += Count;
+                        // Attention: Current Microsoft STL implementation seems to be buggy, tellg() always returns 0.
+                        if (file.tellg() & 1) {
+                            file.seekg(1, std::ios::cur);
+                        }
+                    }
+                }
+            }
+        } else if (m_BitmapHeader.Compression == 2) { // RLE 4
+            /* RLE 4 is not supported */
+            Result = false;
+        } else if (m_BitmapHeader.Compression == 3) { // BITFIELDS
+            
+            /* We assumes that mask of each color component can be in any order */
+
+            uint32_t BitCountRed = CColor::BitCountByMask(m_BitmapHeader.RedMask);
+            uint32_t BitCountGreen = CColor::BitCountByMask(m_BitmapHeader.GreenMask);
+            uint32_t BitCountBlue = CColor::BitCountByMask(m_BitmapHeader.BlueMask);
+            uint32_t BitCountAlpha = CColor::BitCountByMask(m_BitmapHeader.AlphaMask);
+
+            for (unsigned int i = 0; i < GetHeight(); i++) {
+                file.read((char*) Line, LineWidth);
+                
+                uint8_t *LinePtr = Line;
+                
+                for (unsigned int j = 0; j < GetWidth(); j++) {
+                    
+                    uint32_t Color = 0;
+
+                    if (m_BitmapHeader.BitCount == 16) {
+                        Color = *((uint16_t*) LinePtr);
+                        LinePtr += 2;
+                    } else if (m_BitmapHeader.BitCount == 32) {
+                        Color = *((uint32_t*) LinePtr);
+                        LinePtr += 4;
+                    } else {
+                        // Other formats are not valid
+                    }
+                    m_BitmapData[Index].Red = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.RedMask), BitCountRed, 8);
+                    m_BitmapData[Index].Green = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.GreenMask), BitCountGreen, 8);
+                    m_BitmapData[Index].Blue = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.BlueMask), BitCountBlue, 8);
+                    m_BitmapData[Index].Alpha = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.AlphaMask), BitCountAlpha, 8);
+
+                    Index++;
+                }
+            }
+        }
+        
+        delete [] ColorTable;
+        delete [] Line;
+
+        file.close();
+        return Result;
+    }
+    
+    bool Save(const char* Filename, unsigned int BitCount = 32) {
+        bool Result = true;
+
+        std::ofstream file(Filename, std::ios::out | std::ios::binary);
+
+        if (file.is_open() == false) {
+            return false;
+        }
+        
+        BITMAP_FILEHEADER bfh;
+        BITMAP_HEADER bh;
+        memset(&bfh, 0, sizeof(bfh));
+        memset(&bh, 0, sizeof(bh));
+
+        bfh.Signature = BITMAP_SIGNATURE;
+        bfh.BitsOffset = BITMAP_FILEHEADER_SIZE + sizeof(BITMAP_HEADER);
+        bfh.Size = (GetWidth() * GetHeight() * BitCount) / 8 + bfh.BitsOffset;
+    
+        bh.HeaderSize = sizeof(BITMAP_HEADER);
+        bh.BitCount = BitCount;
+        
+        if (BitCount == 32) {
+            bh.Compression = 3; // BITFIELD
+            bh.AlphaMask = 0xff000000;
+            bh.BlueMask = 0x00ff0000;
+            bh.GreenMask = 0x0000ff00;
+            bh.RedMask = 0x000000ff;
+        } else if (BitCount == 16) {
+            bh.Compression = 3; // BITFIELD
+            bh.AlphaMask = 0x00000000;
+            bh.BlueMask = 0x0000001f;
+            bh.GreenMask = 0x000007E0;
+            bh.RedMask = 0x0000F800;
+        } else {
+            bh.Compression = 0; // RGB
+        }
+        
+        unsigned int LineWidth = (GetWidth() + 3) & ~3;
+
+        bh.Planes = 1;
+        bh.Height = GetHeight();
+        bh.Width = GetWidth();
+        bh.SizeImage = (LineWidth * BitCount * GetHeight()) / 8;
+        bh.PelsPerMeterX = 3780;
+        bh.PelsPerMeterY = 3780;
+        
+        if (BitCount == 32) {
+            file.write((char*) &bfh, sizeof(BITMAP_FILEHEADER));
+            file.write((char*) &bh, sizeof(BITMAP_HEADER));
+            file.write((char*) m_BitmapData, bh.SizeImage);
+        } else if (BitCount < 16) {
+            uint8_t* Bitmap = new uint8_t[bh.SizeImage];
+            
+            BGRA *Palette = 0;
+            unsigned int PaletteSize = 0;
+
+            if (GetBitsWithPalette(Bitmap, bh.SizeImage, BitCount, Palette, PaletteSize)) {
+                bfh.BitsOffset += PaletteSize * sizeof(BGRA);
+
+                file.write((char*) &bfh, BITMAP_FILEHEADER_SIZE);
+                file.write((char*) &bh, sizeof(BITMAP_HEADER));
+                file.write((char*) Palette, PaletteSize * sizeof(BGRA));
+                file.write((char*) Bitmap, bh.SizeImage);
+            }
+            delete [] Bitmap;
+            delete [] Palette;
+        } else {
+            uint32_t RedMask = 0;
+            uint32_t GreenMask = 0;
+            uint32_t BlueMask = 0;
+            uint32_t AlphaMask = 0;
+
+            if (BitCount == 16) {
+                RedMask = 0x0000F800;
+                GreenMask = 0x000007E0;
+                BlueMask = 0x0000001F;
+                AlphaMask = 0x00000000;
+            } else if (BitCount == 24) {
+                RedMask = 0x00FF0000;
+                GreenMask = 0x0000FF00;
+                BlueMask = 0x000000FF;
+            } else {
+                // Other color formats are not valid
+                Result = false;
+            }
+
+            if (Result) {
+                if (GetBits(NULL, bh.SizeImage, RedMask, GreenMask, BlueMask, AlphaMask)) {
+                    uint8_t* Bitmap = new uint8_t[bh.SizeImage];
+                    if (GetBits(Bitmap, bh.SizeImage, RedMask, GreenMask, BlueMask, AlphaMask)) {
+                        file.write((char*) &bfh, sizeof(BITMAP_FILEHEADER));
+                        file.write((char*) &bh, sizeof(BITMAP_HEADER));
+                        file.write((char*) Bitmap, bh.SizeImage);
+                    }
+                    delete [] Bitmap;
+                }
+            }
+        }
+
+        file.close();
+        return Result;
+    }
+
+    unsigned int GetWidth() {
+        /* Add plausibility test */
+        // if (abs(m_BitmapHeader.Width) > 8192) {
+        //  m_BitmapHeader.Width = 8192;
+        // }
+        return m_BitmapHeader.Width < 0 ? -m_BitmapHeader.Width : m_BitmapHeader.Width;
+    }
+    
+    unsigned int GetHeight() {
+        /* Add plausibility test */
+        // if (abs(m_BitmapHeader.Height) > 8192) {
+        //  m_BitmapHeader.Height = 8192;
+        // }
+        return m_BitmapHeader.Height < 0 ? -m_BitmapHeader.Height : m_BitmapHeader.Height;
+    }
+    
+    unsigned int GetBitCount() {
+        /* Add plausibility test */
+        // if (m_BitmapHeader.BitCount > 32) {
+        //  m_BitmapHeader.BitCount = 32;
+        // }
+        return m_BitmapHeader.BitCount;
+    }
+    
+    /* Copies internal RGBA buffer to user specified buffer */
+    
+    bool GetBits(void* Buffer, unsigned int &Size) {
+        bool Result = false;
+        if (Size == 0 || Buffer == 0) {
+            Size = m_BitmapSize * sizeof(RGBA);
+            Result = m_BitmapSize != 0;
+        } else {
+            memcpy(Buffer, m_BitmapData, Size);
+            Result = true;
+        }
+        return Result;
+    }
+
+    /* Returns internal RGBA buffer */
+    
+    void* GetBits() {
+        return m_BitmapData;
+    }
+    
+    /* Copies internal RGBA buffer to user specified buffer and converts it into destination
+     * bit format specified by component masks.
+     *
+     * Typical Bitmap color formats (BGR/BGRA):
+     *
+     * Masks for 16 bit (5-5-5): ALPHA = 0x00000000, RED = 0x00007C00, GREEN = 0x000003E0, BLUE = 0x0000001F
+     * Masks for 16 bit (5-6-5): ALPHA = 0x00000000, RED = 0x0000F800, GREEN = 0x000007E0, BLUE = 0x0000001F
+     * Masks for 24 bit: ALPHA = 0x00000000, RED = 0x00FF0000, GREEN = 0x0000FF00, BLUE = 0x000000FF
+     * Masks for 32 bit: ALPHA = 0xFF000000, RED = 0x00FF0000, GREEN = 0x0000FF00, BLUE = 0x000000FF
+     *
+     * Other color formats (RGB/RGBA):
+     *
+     * Masks for 32 bit (RGBA): ALPHA = 0xFF000000, RED = 0x000000FF, GREEN = 0x0000FF00, BLUE = 0x00FF0000
+     *
+     * Bit count will be rounded to next 8 bit boundary. If IncludePadding is true, it will be ensured
+     * that line width is a multiple of 4. padding bytes are included if necessary.
+     *
+     * NOTE: systems with big endian byte order may require masks in inversion order.
+     */
+
+    bool GetBits(void* Buffer, unsigned int &Size, unsigned int RedMask, unsigned int GreenMask, unsigned int BlueMask, unsigned int AlphaMask, bool IncludePadding = true) {
+        bool Result = false;
+
+        uint32_t BitCountRed = CColor::BitCountByMask(RedMask);
+        uint32_t BitCountGreen = CColor::BitCountByMask(GreenMask);
+        uint32_t BitCountBlue = CColor::BitCountByMask(BlueMask);
+        uint32_t BitCountAlpha = CColor::BitCountByMask(AlphaMask);
+        
+        unsigned int BitCount = (BitCountRed + BitCountGreen + BitCountBlue + BitCountAlpha + 7) & ~7;
+
+        if (BitCount > 32) {
+            return false;
+        }
+        
+        unsigned int w = GetWidth();
+        //unsigned int LineWidth = (w + 3) & ~3;
+        unsigned int dataBytesPerLine = (w * BitCount + 7) / 8;
+        unsigned int LineWidth = (dataBytesPerLine + 3) & ~3;
+
+        if (Size == 0 || Buffer == 0) {
+            //Size = (LineWidth * GetHeight() * BitCount) / 8 + sizeof(unsigned int);
+            Size = (GetWidth() * GetHeight() * BitCount) / 8 + sizeof(unsigned int);
+            return true;
+        }
+
+        uint8_t* BufferPtr = (uint8_t*) Buffer;
+        
+        Result = true;
+
+        uint32_t BitPosRed = CColor::BitPositionByMask(RedMask);
+        uint32_t BitPosGreen = CColor::BitPositionByMask(GreenMask);
+        uint32_t BitPosBlue = CColor::BitPositionByMask(BlueMask);
+        uint32_t BitPosAlpha = CColor::BitPositionByMask(AlphaMask);
+        
+        unsigned int j = 0;
+
+        for (unsigned int i = 0; i < m_BitmapSize; i++) {
+            *(uint32_t*) BufferPtr =
+            (CColor::Convert(m_BitmapData[i].Blue, 8, BitCountBlue) << BitPosBlue) |
+            (CColor::Convert(m_BitmapData[i].Green, 8, BitCountGreen) << BitPosGreen) | 
+            (CColor::Convert(m_BitmapData[i].Red, 8, BitCountRed) << BitPosRed) | 
+            (CColor::Convert(m_BitmapData[i].Alpha, 8, BitCountAlpha) << BitPosAlpha);
+            
+            if (IncludePadding) {
+                j++;
+                if (j >= w) {
+                    for (unsigned int k = 0; k < LineWidth - dataBytesPerLine; k++) {
+                        BufferPtr += (BitCount >> 3);
+                    }
+                    j = 0;
+                }
+            }
+
+            BufferPtr += (BitCount >> 3);
+        }
+        
+        Size -= sizeof(unsigned int);
+
+        return Result;
+    }
+    
+    /* See GetBits(). 
+     * It creates a corresponding color table (palette) which have to be destroyed by the user after usage.
+     *
+     * Supported Bit depths are: 4, 8
+     *
+     * Todo: Optimize, use optimized palette, do ditehring (see my dithering class), support padding for 4 bit bitmaps
+     */
+
+    bool GetBitsWithPalette(void* Buffer, unsigned int &Size, unsigned int BitCount, BGRA* &Palette, unsigned int &PaletteSize, bool OptimalPalette = false, bool IncludePadding = true) {
+        bool Result = false;
+
+        if (BitCount > 16) {
+            return false;
+        }
+        
+        unsigned int w = GetWidth();
+        unsigned int dataBytesPerLine = (w * BitCount + 7) / 8;
+        unsigned int LineWidth = (dataBytesPerLine + 3) & ~3;
+
+        if (Size == 0 || Buffer == 0) {
+            Size = (LineWidth * GetHeight() * BitCount) / 8;
+            return true;
+        }
+        
+
+        if (OptimalPalette) {
+            PaletteSize = 0;
+            // Not implemented
+        } else {
+            if (BitCount == 1) {
+                PaletteSize = 2;
+                // Not implemented: Who need that?
+            } else if (BitCount == 4) { // 2:2:1
+                PaletteSize = 16;
+                Palette = new BGRA[PaletteSize];
+                for (int r = 0; r < 4; r++) {
+                    for (int g = 0; g < 2; g++) {
+                        for (int b = 0; b < 2; b++) {
+                            Palette[r | g << 2 | b << 3].Red = r ? (r << 6) | 0x3f : 0;
+                            Palette[r | g << 2 | b << 3].Green = g ? (g << 7) | 0x7f : 0;
+                            Palette[r | g << 2 | b << 3].Blue = b ? (b << 7) | 0x7f : 0;
+                            Palette[r | g << 2 | b << 3].Alpha = 0xff;
+                        }
+                    }
+                }
+            } else if (BitCount == 8) { // 3:3:2
+                PaletteSize = 256;
+                Palette = new BGRA[PaletteSize];
+                for (int r = 0; r < 8; r++) {
+                    for (int g = 0; g < 8; g++) {
+                        for (int b = 0; b < 4; b++) {
+                            Palette[r | g << 3 | b << 6].Red = r ? (r << 5) | 0x1f : 0;
+                            Palette[r | g << 3 | b << 6].Green = g ? (g << 5) | 0x1f : 0;
+                            Palette[r | g << 3 | b << 6].Blue = b ? (b << 6) | 0x3f : 0;
+                            Palette[r | g << 3 | b << 6].Alpha = 0xff;
+                        }
+                    }
+                }
+            } else if (BitCount == 16) { // 5:5:5
+                // Not implemented
+            }
+        }
+
+        unsigned int j = 0;
+        uint8_t* BufferPtr = (uint8_t*) Buffer;
+        
+        for (unsigned int i = 0; i < m_BitmapSize; i++) {
+            if (BitCount == 1) {
+                // Not implemented: Who needs that?
+            } else if (BitCount == 4) {
+                *BufferPtr = ((m_BitmapData[i].Red >> 6) | (m_BitmapData[i].Green >> 7) << 2 | (m_BitmapData[i].Blue >> 7) << 3) << 4;
+                i++;
+                *BufferPtr |= (m_BitmapData[i].Red >> 6) | (m_BitmapData[i].Green >> 7) << 2 | (m_BitmapData[i].Blue >> 7) << 3;
+            } else if (BitCount == 8) {
+                *BufferPtr = (m_BitmapData[i].Red >> 5) | (m_BitmapData[i].Green >> 5) << 3 | (m_BitmapData[i].Blue >> 5) << 6;
+            } else if (BitCount == 16) {
+                // Not implemented
+            }
+
+            if (IncludePadding) {
+                j++;
+                if (j >= w) {
+                    for (unsigned int k = 0; k < (LineWidth - dataBytesPerLine); k++) {
+                        BufferPtr += BitCount / 8;
+                    }
+                    j = 0;
+                }
+            }
+
+            BufferPtr++;
+        }
+        
+        Result = true;
+
+        return Result;
+    }
+
+    /* Set Bitmap Bits. Will be converted to RGBA internally */
+
+    bool SetBits(void* Buffer, unsigned int Width, unsigned int Height, unsigned int RedMask, unsigned int GreenMask, unsigned int BlueMask, unsigned int AlphaMask = 0) {
+        if (Buffer == 0) {
+            return false;
+        }
+
+        uint8_t *BufferPtr = (uint8_t*) Buffer;
+        
+        Dispose();
+
+        m_BitmapHeader.Width = Width;
+        m_BitmapHeader.Height = Height;
+        m_BitmapHeader.BitCount = 32;
+        m_BitmapHeader.Compression = 3; 
+
+        m_BitmapSize = GetWidth() * GetHeight();
+        m_BitmapData = new BGRA[m_BitmapSize];
+        
+        /* Find bit count by masks (rounded to next 8 bit boundary) */
+        
+        unsigned int BitCount = (CColor::BitCountByMask(RedMask | GreenMask | BlueMask | AlphaMask) + 7) & ~7;
+        
+        uint32_t BitCountRed = CColor::BitCountByMask(RedMask);
+        uint32_t BitCountGreen = CColor::BitCountByMask(GreenMask);
+        uint32_t BitCountBlue = CColor::BitCountByMask(BlueMask);
+        uint32_t BitCountAlpha = CColor::BitCountByMask(AlphaMask);
+
+        for (unsigned int i = 0; i < m_BitmapSize; i++) {
+            unsigned int Color = 0;
+            if (BitCount <= 8) {
+                Color = *((uint8_t*) BufferPtr);
+                BufferPtr += 1;
+            } else if (BitCount <= 16) {
+                Color = *((uint16_t*) BufferPtr);
+                BufferPtr += 2;
+            } else if (BitCount <= 24) {
+                Color = *((uint32_t*) BufferPtr);
+                BufferPtr += 3;
+            } else if (BitCount <= 32) {
+                Color = *((uint32_t*) BufferPtr);
+                BufferPtr += 4;
+            } else {
+                /* unsupported */
+                BufferPtr += 1;
+            }
+            m_BitmapData[i].Alpha = CColor::Convert(CColor::ComponentByMask(Color, AlphaMask), BitCountAlpha, 8);
+            m_BitmapData[i].Red = CColor::Convert(CColor::ComponentByMask(Color, RedMask), BitCountRed, 8);
+            m_BitmapData[i].Green = CColor::Convert(CColor::ComponentByMask(Color, GreenMask), BitCountGreen, 8);
+            m_BitmapData[i].Blue = CColor::Convert(CColor::ComponentByMask(Color, BlueMask), BitCountBlue, 8);
+        }
+
+        return true;
+    }
+};
+
+#endif