SD + Bitmap

Dependencies:   TS_DISCO_F746NG LCD_DISCO_F746NG BSP_DISCO_F746NG

Committer:
iut_cachan01
Date:
Tue May 21 10:24:03 2019 +0000
Revision:
0:14e97aa401f3
SD + Bitmap

Who changed what in which revision?

UserRevisionLine numberNew contents of line
iut_cachan01 0:14e97aa401f3 1 /*
iut_cachan01 0:14e97aa401f3 2 * Windows Bitmap File Loader
iut_cachan01 0:14e97aa401f3 3 * Version 1.2.5 (20120929)
iut_cachan01 0:14e97aa401f3 4 *
iut_cachan01 0:14e97aa401f3 5 * Supported Formats: 1, 4, 8, 16, 24, 32 Bit Images
iut_cachan01 0:14e97aa401f3 6 * Alpha Bitmaps are also supported.
iut_cachan01 0:14e97aa401f3 7 * Supported compression types: RLE 8, BITFIELDS
iut_cachan01 0:14e97aa401f3 8 *
iut_cachan01 0:14e97aa401f3 9 * Created by: Benjamin Kalytta, 2006 - 2012
iut_cachan01 0:14e97aa401f3 10 * Thanks for bug fixes goes to: Chris Campbell
iut_cachan01 0:14e97aa401f3 11 *
iut_cachan01 0:14e97aa401f3 12 * Licence: Free to use, URL to my source and my name is required in your source code.
iut_cachan01 0:14e97aa401f3 13 *
iut_cachan01 0:14e97aa401f3 14 * Source can be found at http://www.kalytta.com/bitmap.h
iut_cachan01 0:14e97aa401f3 15 *
iut_cachan01 0:14e97aa401f3 16 * Warning: This code should not be used in unmodified form in a production environment.
iut_cachan01 0:14e97aa401f3 17 * It should only serve as a basis for your own development.
iut_cachan01 0:14e97aa401f3 18 * There is only a minimal error handling in this code. (Notice added 20111211)
iut_cachan01 0:14e97aa401f3 19 */
iut_cachan01 0:14e97aa401f3 20
iut_cachan01 0:14e97aa401f3 21 #ifndef BITMAP_H
iut_cachan01 0:14e97aa401f3 22 #define BITMAP_H
iut_cachan01 0:14e97aa401f3 23
iut_cachan01 0:14e97aa401f3 24 #include <iostream>
iut_cachan01 0:14e97aa401f3 25 #include <fstream>
iut_cachan01 0:14e97aa401f3 26 #include <string>
iut_cachan01 0:14e97aa401f3 27
iut_cachan01 0:14e97aa401f3 28 #ifndef __LITTLE_ENDIAN__
iut_cachan01 0:14e97aa401f3 29 #ifndef __BIG_ENDIAN__
iut_cachan01 0:14e97aa401f3 30 #define __LITTLE_ENDIAN__
iut_cachan01 0:14e97aa401f3 31 #endif
iut_cachan01 0:14e97aa401f3 32 #endif
iut_cachan01 0:14e97aa401f3 33
iut_cachan01 0:14e97aa401f3 34 #ifdef __LITTLE_ENDIAN__
iut_cachan01 0:14e97aa401f3 35 #define BITMAP_SIGNATURE 0x4d42
iut_cachan01 0:14e97aa401f3 36 #else
iut_cachan01 0:14e97aa401f3 37 #define BITMAP_SIGNATURE 0x424d
iut_cachan01 0:14e97aa401f3 38 #endif
iut_cachan01 0:14e97aa401f3 39
iut_cachan01 0:14e97aa401f3 40 #if defined(_MSC_VER) || defined(__INTEL_COMPILER)
iut_cachan01 0:14e97aa401f3 41 typedef unsigned __int32 uint32_t;
iut_cachan01 0:14e97aa401f3 42 typedef unsigned __int16 uint16_t;
iut_cachan01 0:14e97aa401f3 43 typedef unsigned __int8 uint8_t;
iut_cachan01 0:14e97aa401f3 44 typedef __int32 int32_t;
iut_cachan01 0:14e97aa401f3 45 #elif defined(__GNUC__) || defined(__CYGWIN__) || defined(__MWERKS__) || defined(__WATCOMC__) || defined(__PGI) || defined(__LCC__)
iut_cachan01 0:14e97aa401f3 46 #include <stdint.h>
iut_cachan01 0:14e97aa401f3 47 #else
iut_cachan01 0:14e97aa401f3 48 typedef unsigned int uint32_t;
iut_cachan01 0:14e97aa401f3 49 typedef unsigned short int uint16_t;
iut_cachan01 0:14e97aa401f3 50 typedef unsigned char uint8_t;
iut_cachan01 0:14e97aa401f3 51 typedef int int32_t;
iut_cachan01 0:14e97aa401f3 52 #endif
iut_cachan01 0:14e97aa401f3 53
iut_cachan01 0:14e97aa401f3 54 #pragma pack(push, 1)
iut_cachan01 0:14e97aa401f3 55
iut_cachan01 0:14e97aa401f3 56 typedef struct _BITMAP_FILEHEADER {
iut_cachan01 0:14e97aa401f3 57 uint16_t Signature;
iut_cachan01 0:14e97aa401f3 58 uint32_t Size;
iut_cachan01 0:14e97aa401f3 59 uint32_t Reserved;
iut_cachan01 0:14e97aa401f3 60 uint32_t BitsOffset;
iut_cachan01 0:14e97aa401f3 61 } BITMAP_FILEHEADER;
iut_cachan01 0:14e97aa401f3 62
iut_cachan01 0:14e97aa401f3 63 #define BITMAP_FILEHEADER_SIZE 14
iut_cachan01 0:14e97aa401f3 64
iut_cachan01 0:14e97aa401f3 65 typedef struct _BITMAP_HEADER {
iut_cachan01 0:14e97aa401f3 66 uint32_t HeaderSize;
iut_cachan01 0:14e97aa401f3 67 int32_t Width;
iut_cachan01 0:14e97aa401f3 68 int32_t Height;
iut_cachan01 0:14e97aa401f3 69 uint16_t Planes;
iut_cachan01 0:14e97aa401f3 70 uint16_t BitCount;
iut_cachan01 0:14e97aa401f3 71 uint32_t Compression;
iut_cachan01 0:14e97aa401f3 72 uint32_t SizeImage;
iut_cachan01 0:14e97aa401f3 73 int32_t PelsPerMeterX;
iut_cachan01 0:14e97aa401f3 74 int32_t PelsPerMeterY;
iut_cachan01 0:14e97aa401f3 75 uint32_t ClrUsed;
iut_cachan01 0:14e97aa401f3 76 uint32_t ClrImportant;
iut_cachan01 0:14e97aa401f3 77 uint32_t RedMask;
iut_cachan01 0:14e97aa401f3 78 uint32_t GreenMask;
iut_cachan01 0:14e97aa401f3 79 uint32_t BlueMask;
iut_cachan01 0:14e97aa401f3 80 uint32_t AlphaMask;
iut_cachan01 0:14e97aa401f3 81 uint32_t CsType;
iut_cachan01 0:14e97aa401f3 82 uint32_t Endpoints[9]; // see http://msdn2.microsoft.com/en-us/library/ms536569.aspx
iut_cachan01 0:14e97aa401f3 83 uint32_t GammaRed;
iut_cachan01 0:14e97aa401f3 84 uint32_t GammaGreen;
iut_cachan01 0:14e97aa401f3 85 uint32_t GammaBlue;
iut_cachan01 0:14e97aa401f3 86 } BITMAP_HEADER;
iut_cachan01 0:14e97aa401f3 87
iut_cachan01 0:14e97aa401f3 88 typedef struct _RGBA {
iut_cachan01 0:14e97aa401f3 89 uint8_t Red;
iut_cachan01 0:14e97aa401f3 90 uint8_t Green;
iut_cachan01 0:14e97aa401f3 91 uint8_t Blue;
iut_cachan01 0:14e97aa401f3 92 uint8_t Alpha;
iut_cachan01 0:14e97aa401f3 93 } RGBA;
iut_cachan01 0:14e97aa401f3 94
iut_cachan01 0:14e97aa401f3 95 typedef struct _BGRA {
iut_cachan01 0:14e97aa401f3 96 uint8_t Blue;
iut_cachan01 0:14e97aa401f3 97 uint8_t Green;
iut_cachan01 0:14e97aa401f3 98 uint8_t Red;
iut_cachan01 0:14e97aa401f3 99 uint8_t Alpha;
iut_cachan01 0:14e97aa401f3 100 } BGRA;
iut_cachan01 0:14e97aa401f3 101
iut_cachan01 0:14e97aa401f3 102 #pragma pack(pop)
iut_cachan01 0:14e97aa401f3 103
iut_cachan01 0:14e97aa401f3 104 class CBitmap {
iut_cachan01 0:14e97aa401f3 105 private:
iut_cachan01 0:14e97aa401f3 106 BITMAP_FILEHEADER m_BitmapFileHeader;
iut_cachan01 0:14e97aa401f3 107 BITMAP_HEADER m_BitmapHeader;
iut_cachan01 0:14e97aa401f3 108 BGRA *m_BitmapData;
iut_cachan01 0:14e97aa401f3 109 unsigned int m_BitmapSize;
iut_cachan01 0:14e97aa401f3 110
iut_cachan01 0:14e97aa401f3 111 // Masks and bit counts shouldn't exceed 32 Bits
iut_cachan01 0:14e97aa401f3 112 public:
iut_cachan01 0:14e97aa401f3 113 class CColor {
iut_cachan01 0:14e97aa401f3 114 public:
iut_cachan01 0:14e97aa401f3 115 static inline unsigned int BitCountByMask(unsigned int Mask) {
iut_cachan01 0:14e97aa401f3 116 unsigned int BitCount = 0;
iut_cachan01 0:14e97aa401f3 117 while (Mask) {
iut_cachan01 0:14e97aa401f3 118 Mask &= Mask - 1;
iut_cachan01 0:14e97aa401f3 119 BitCount++;
iut_cachan01 0:14e97aa401f3 120 }
iut_cachan01 0:14e97aa401f3 121 return BitCount;
iut_cachan01 0:14e97aa401f3 122 }
iut_cachan01 0:14e97aa401f3 123
iut_cachan01 0:14e97aa401f3 124 static inline unsigned int BitPositionByMask(unsigned int Mask) {
iut_cachan01 0:14e97aa401f3 125 return BitCountByMask((Mask & (~Mask + 1)) - 1);
iut_cachan01 0:14e97aa401f3 126 }
iut_cachan01 0:14e97aa401f3 127
iut_cachan01 0:14e97aa401f3 128 static inline unsigned int ComponentByMask(unsigned int Color, unsigned int Mask) {
iut_cachan01 0:14e97aa401f3 129 unsigned int Component = Color & Mask;
iut_cachan01 0:14e97aa401f3 130 return Component >> BitPositionByMask(Mask);
iut_cachan01 0:14e97aa401f3 131 }
iut_cachan01 0:14e97aa401f3 132
iut_cachan01 0:14e97aa401f3 133 static inline unsigned int BitCountToMask(unsigned int BitCount) {
iut_cachan01 0:14e97aa401f3 134 return (BitCount == 32) ? 0xFFFFFFFF : (1 << BitCount) - 1;
iut_cachan01 0:14e97aa401f3 135 }
iut_cachan01 0:14e97aa401f3 136
iut_cachan01 0:14e97aa401f3 137 static unsigned int Convert(unsigned int Color, unsigned int FromBitCount, unsigned int ToBitCount) {
iut_cachan01 0:14e97aa401f3 138 if (ToBitCount < FromBitCount) {
iut_cachan01 0:14e97aa401f3 139 Color >>= (FromBitCount - ToBitCount);
iut_cachan01 0:14e97aa401f3 140 } else {
iut_cachan01 0:14e97aa401f3 141 Color <<= (ToBitCount - FromBitCount);
iut_cachan01 0:14e97aa401f3 142 if (Color > 0) {
iut_cachan01 0:14e97aa401f3 143 Color |= BitCountToMask(ToBitCount - FromBitCount);
iut_cachan01 0:14e97aa401f3 144 }
iut_cachan01 0:14e97aa401f3 145 }
iut_cachan01 0:14e97aa401f3 146 return Color;
iut_cachan01 0:14e97aa401f3 147 }
iut_cachan01 0:14e97aa401f3 148 };
iut_cachan01 0:14e97aa401f3 149
iut_cachan01 0:14e97aa401f3 150 public:
iut_cachan01 0:14e97aa401f3 151
iut_cachan01 0:14e97aa401f3 152 CBitmap() : m_BitmapData(0), m_BitmapSize(0) {
iut_cachan01 0:14e97aa401f3 153 Dispose();
iut_cachan01 0:14e97aa401f3 154 }
iut_cachan01 0:14e97aa401f3 155
iut_cachan01 0:14e97aa401f3 156 CBitmap(const char* Filename) : m_BitmapData(0), m_BitmapSize(0) {
iut_cachan01 0:14e97aa401f3 157 Load(Filename);
iut_cachan01 0:14e97aa401f3 158 }
iut_cachan01 0:14e97aa401f3 159
iut_cachan01 0:14e97aa401f3 160 ~CBitmap() {
iut_cachan01 0:14e97aa401f3 161 Dispose();
iut_cachan01 0:14e97aa401f3 162 }
iut_cachan01 0:14e97aa401f3 163
iut_cachan01 0:14e97aa401f3 164 void Dispose() {
iut_cachan01 0:14e97aa401f3 165 if (m_BitmapData) {
iut_cachan01 0:14e97aa401f3 166 delete[] m_BitmapData;
iut_cachan01 0:14e97aa401f3 167 m_BitmapData = 0;
iut_cachan01 0:14e97aa401f3 168 }
iut_cachan01 0:14e97aa401f3 169 memset(&m_BitmapFileHeader, 0, sizeof(m_BitmapFileHeader));
iut_cachan01 0:14e97aa401f3 170 memset(&m_BitmapHeader, 0, sizeof(m_BitmapHeader));
iut_cachan01 0:14e97aa401f3 171 }
iut_cachan01 0:14e97aa401f3 172
iut_cachan01 0:14e97aa401f3 173 /* Load specified Bitmap and stores it as RGBA in an internal buffer */
iut_cachan01 0:14e97aa401f3 174
iut_cachan01 0:14e97aa401f3 175 bool Load(const char *Filename) {
iut_cachan01 0:14e97aa401f3 176 std::ifstream file(Filename, std::ios::binary | std::ios::in);
iut_cachan01 0:14e97aa401f3 177
iut_cachan01 0:14e97aa401f3 178 if (file.bad()) {
iut_cachan01 0:14e97aa401f3 179 return false;
iut_cachan01 0:14e97aa401f3 180 }
iut_cachan01 0:14e97aa401f3 181
iut_cachan01 0:14e97aa401f3 182 if (file.is_open() == false) {
iut_cachan01 0:14e97aa401f3 183 return false;
iut_cachan01 0:14e97aa401f3 184 }
iut_cachan01 0:14e97aa401f3 185
iut_cachan01 0:14e97aa401f3 186 Dispose();
iut_cachan01 0:14e97aa401f3 187
iut_cachan01 0:14e97aa401f3 188 file.read((char*) &m_BitmapFileHeader, BITMAP_FILEHEADER_SIZE);
iut_cachan01 0:14e97aa401f3 189 if (m_BitmapFileHeader.Signature != BITMAP_SIGNATURE) {
iut_cachan01 0:14e97aa401f3 190 return false;
iut_cachan01 0:14e97aa401f3 191 }
iut_cachan01 0:14e97aa401f3 192
iut_cachan01 0:14e97aa401f3 193 file.read((char*) &m_BitmapHeader, sizeof(BITMAP_HEADER));
iut_cachan01 0:14e97aa401f3 194
iut_cachan01 0:14e97aa401f3 195 /* Load Color Table */
iut_cachan01 0:14e97aa401f3 196
iut_cachan01 0:14e97aa401f3 197 file.seekg(BITMAP_FILEHEADER_SIZE + m_BitmapHeader.HeaderSize, std::ios::beg);
iut_cachan01 0:14e97aa401f3 198
iut_cachan01 0:14e97aa401f3 199 unsigned int ColorTableSize = 0;
iut_cachan01 0:14e97aa401f3 200
iut_cachan01 0:14e97aa401f3 201 if (m_BitmapHeader.BitCount == 1) {
iut_cachan01 0:14e97aa401f3 202 ColorTableSize = 2;
iut_cachan01 0:14e97aa401f3 203 } else if (m_BitmapHeader.BitCount == 4) {
iut_cachan01 0:14e97aa401f3 204 ColorTableSize = 16;
iut_cachan01 0:14e97aa401f3 205 } else if (m_BitmapHeader.BitCount == 8) {
iut_cachan01 0:14e97aa401f3 206 ColorTableSize = 256;
iut_cachan01 0:14e97aa401f3 207 }
iut_cachan01 0:14e97aa401f3 208
iut_cachan01 0:14e97aa401f3 209 // Always allocate full sized color table
iut_cachan01 0:14e97aa401f3 210
iut_cachan01 0:14e97aa401f3 211 BGRA* ColorTable = new BGRA[ColorTableSize]; // std::bad_alloc exception should be thrown if memory is not available
iut_cachan01 0:14e97aa401f3 212
iut_cachan01 0:14e97aa401f3 213 file.read((char*) ColorTable, sizeof(BGRA) * m_BitmapHeader.ClrUsed);
iut_cachan01 0:14e97aa401f3 214
iut_cachan01 0:14e97aa401f3 215 /* ... Color Table for 16 bits images are not supported yet */
iut_cachan01 0:14e97aa401f3 216
iut_cachan01 0:14e97aa401f3 217 m_BitmapSize = GetWidth() * GetHeight();
iut_cachan01 0:14e97aa401f3 218 m_BitmapData = new BGRA[m_BitmapSize];
iut_cachan01 0:14e97aa401f3 219
iut_cachan01 0:14e97aa401f3 220 unsigned int LineWidth = ((GetWidth() * GetBitCount() / 8) + 3) & ~3;
iut_cachan01 0:14e97aa401f3 221 uint8_t *Line = new uint8_t[LineWidth];
iut_cachan01 0:14e97aa401f3 222
iut_cachan01 0:14e97aa401f3 223 file.seekg(m_BitmapFileHeader.BitsOffset, std::ios::beg);
iut_cachan01 0:14e97aa401f3 224
iut_cachan01 0:14e97aa401f3 225 int Index = 0;
iut_cachan01 0:14e97aa401f3 226 bool Result = true;
iut_cachan01 0:14e97aa401f3 227
iut_cachan01 0:14e97aa401f3 228 if (m_BitmapHeader.Compression == 0) {
iut_cachan01 0:14e97aa401f3 229 for (unsigned int i = 0; i < GetHeight(); i++) {
iut_cachan01 0:14e97aa401f3 230 file.read((char*) Line, LineWidth);
iut_cachan01 0:14e97aa401f3 231
iut_cachan01 0:14e97aa401f3 232 uint8_t *LinePtr = Line;
iut_cachan01 0:14e97aa401f3 233
iut_cachan01 0:14e97aa401f3 234 for (unsigned int j = 0; j < GetWidth(); j++) {
iut_cachan01 0:14e97aa401f3 235 if (m_BitmapHeader.BitCount == 1) {
iut_cachan01 0:14e97aa401f3 236 uint32_t Color = *((uint8_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 237 for (int k = 0; k < 8; k++) {
iut_cachan01 0:14e97aa401f3 238 m_BitmapData[Index].Red = ColorTable[Color & 0x80 ? 1 : 0].Red;
iut_cachan01 0:14e97aa401f3 239 m_BitmapData[Index].Green = ColorTable[Color & 0x80 ? 1 : 0].Green;
iut_cachan01 0:14e97aa401f3 240 m_BitmapData[Index].Blue = ColorTable[Color & 0x80 ? 1 : 0].Blue;
iut_cachan01 0:14e97aa401f3 241 m_BitmapData[Index].Alpha = ColorTable[Color & 0x80 ? 1 : 0].Alpha;
iut_cachan01 0:14e97aa401f3 242 Index++;
iut_cachan01 0:14e97aa401f3 243 Color <<= 1;
iut_cachan01 0:14e97aa401f3 244 }
iut_cachan01 0:14e97aa401f3 245 LinePtr++;
iut_cachan01 0:14e97aa401f3 246 j += 7;
iut_cachan01 0:14e97aa401f3 247 } else if (m_BitmapHeader.BitCount == 4) {
iut_cachan01 0:14e97aa401f3 248 uint32_t Color = *((uint8_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 249 m_BitmapData[Index].Red = ColorTable[(Color >> 4) & 0x0f].Red;
iut_cachan01 0:14e97aa401f3 250 m_BitmapData[Index].Green = ColorTable[(Color >> 4) & 0x0f].Green;
iut_cachan01 0:14e97aa401f3 251 m_BitmapData[Index].Blue = ColorTable[(Color >> 4) & 0x0f].Blue;
iut_cachan01 0:14e97aa401f3 252 m_BitmapData[Index].Alpha = ColorTable[(Color >> 4) & 0x0f].Alpha;
iut_cachan01 0:14e97aa401f3 253 Index++;
iut_cachan01 0:14e97aa401f3 254 m_BitmapData[Index].Red = ColorTable[Color & 0x0f].Red;
iut_cachan01 0:14e97aa401f3 255 m_BitmapData[Index].Green = ColorTable[Color & 0x0f].Green;
iut_cachan01 0:14e97aa401f3 256 m_BitmapData[Index].Blue = ColorTable[Color & 0x0f].Blue;
iut_cachan01 0:14e97aa401f3 257 m_BitmapData[Index].Alpha = ColorTable[Color & 0x0f].Alpha;
iut_cachan01 0:14e97aa401f3 258 Index++;
iut_cachan01 0:14e97aa401f3 259 LinePtr++;
iut_cachan01 0:14e97aa401f3 260 j++;
iut_cachan01 0:14e97aa401f3 261 } else if (m_BitmapHeader.BitCount == 8) {
iut_cachan01 0:14e97aa401f3 262 uint32_t Color = *((uint8_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 263 m_BitmapData[Index].Red = ColorTable[Color].Red;
iut_cachan01 0:14e97aa401f3 264 m_BitmapData[Index].Green = ColorTable[Color].Green;
iut_cachan01 0:14e97aa401f3 265 m_BitmapData[Index].Blue = ColorTable[Color].Blue;
iut_cachan01 0:14e97aa401f3 266 m_BitmapData[Index].Alpha = ColorTable[Color].Alpha;
iut_cachan01 0:14e97aa401f3 267 Index++;
iut_cachan01 0:14e97aa401f3 268 LinePtr++;
iut_cachan01 0:14e97aa401f3 269 } else if (m_BitmapHeader.BitCount == 16) {
iut_cachan01 0:14e97aa401f3 270 uint32_t Color = *((uint16_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 271 m_BitmapData[Index].Red = ((Color >> 10) & 0x1f) << 3;
iut_cachan01 0:14e97aa401f3 272 m_BitmapData[Index].Green = ((Color >> 5) & 0x1f) << 3;
iut_cachan01 0:14e97aa401f3 273 m_BitmapData[Index].Blue = (Color & 0x1f) << 3;
iut_cachan01 0:14e97aa401f3 274 m_BitmapData[Index].Alpha = 255;
iut_cachan01 0:14e97aa401f3 275 Index++;
iut_cachan01 0:14e97aa401f3 276 LinePtr += 2;
iut_cachan01 0:14e97aa401f3 277 } else if (m_BitmapHeader.BitCount == 24) {
iut_cachan01 0:14e97aa401f3 278 uint32_t Color = *((uint32_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 279 m_BitmapData[Index].Blue = Color & 0xff;
iut_cachan01 0:14e97aa401f3 280 m_BitmapData[Index].Green = (Color >> 8) & 0xff;
iut_cachan01 0:14e97aa401f3 281 m_BitmapData[Index].Red = (Color >> 16) & 0xff;
iut_cachan01 0:14e97aa401f3 282 m_BitmapData[Index].Alpha = 255;
iut_cachan01 0:14e97aa401f3 283 Index++;
iut_cachan01 0:14e97aa401f3 284 LinePtr += 3;
iut_cachan01 0:14e97aa401f3 285 } else if (m_BitmapHeader.BitCount == 32) {
iut_cachan01 0:14e97aa401f3 286 uint32_t Color = *((uint32_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 287 m_BitmapData[Index].Blue = Color & 0xff;
iut_cachan01 0:14e97aa401f3 288 m_BitmapData[Index].Green = (Color >> 8) & 0xff;
iut_cachan01 0:14e97aa401f3 289 m_BitmapData[Index].Red = (Color >> 16) & 0xff;
iut_cachan01 0:14e97aa401f3 290 m_BitmapData[Index].Alpha = Color >> 24;
iut_cachan01 0:14e97aa401f3 291 Index++;
iut_cachan01 0:14e97aa401f3 292 LinePtr += 4;
iut_cachan01 0:14e97aa401f3 293 }
iut_cachan01 0:14e97aa401f3 294 }
iut_cachan01 0:14e97aa401f3 295 }
iut_cachan01 0:14e97aa401f3 296 } else if (m_BitmapHeader.Compression == 1) { // RLE 8
iut_cachan01 0:14e97aa401f3 297 uint8_t Count = 0;
iut_cachan01 0:14e97aa401f3 298 uint8_t ColorIndex = 0;
iut_cachan01 0:14e97aa401f3 299 int x = 0, y = 0;
iut_cachan01 0:14e97aa401f3 300
iut_cachan01 0:14e97aa401f3 301 while (file.eof() == false) {
iut_cachan01 0:14e97aa401f3 302 file.read((char*) &Count, sizeof(uint8_t));
iut_cachan01 0:14e97aa401f3 303 file.read((char*) &ColorIndex, sizeof(uint8_t));
iut_cachan01 0:14e97aa401f3 304
iut_cachan01 0:14e97aa401f3 305 if (Count > 0) {
iut_cachan01 0:14e97aa401f3 306 Index = x + y * GetWidth();
iut_cachan01 0:14e97aa401f3 307 for (int k = 0; k < Count; k++) {
iut_cachan01 0:14e97aa401f3 308 m_BitmapData[Index + k].Red = ColorTable[ColorIndex].Red;
iut_cachan01 0:14e97aa401f3 309 m_BitmapData[Index + k].Green = ColorTable[ColorIndex].Green;
iut_cachan01 0:14e97aa401f3 310 m_BitmapData[Index + k].Blue = ColorTable[ColorIndex].Blue;
iut_cachan01 0:14e97aa401f3 311 m_BitmapData[Index + k].Alpha = ColorTable[ColorIndex].Alpha;
iut_cachan01 0:14e97aa401f3 312 }
iut_cachan01 0:14e97aa401f3 313 x += Count;
iut_cachan01 0:14e97aa401f3 314 } else if (Count == 0) {
iut_cachan01 0:14e97aa401f3 315 int Flag = ColorIndex;
iut_cachan01 0:14e97aa401f3 316 if (Flag == 0) {
iut_cachan01 0:14e97aa401f3 317 x = 0;
iut_cachan01 0:14e97aa401f3 318 y++;
iut_cachan01 0:14e97aa401f3 319 } else if (Flag == 1) {
iut_cachan01 0:14e97aa401f3 320 break;
iut_cachan01 0:14e97aa401f3 321 } else if (Flag == 2) {
iut_cachan01 0:14e97aa401f3 322 char rx = 0;
iut_cachan01 0:14e97aa401f3 323 char ry = 0;
iut_cachan01 0:14e97aa401f3 324 file.read((char*) &rx, sizeof(char));
iut_cachan01 0:14e97aa401f3 325 file.read((char*) &ry, sizeof(char));
iut_cachan01 0:14e97aa401f3 326 x += rx;
iut_cachan01 0:14e97aa401f3 327 y += ry;
iut_cachan01 0:14e97aa401f3 328 } else {
iut_cachan01 0:14e97aa401f3 329 Count = Flag;
iut_cachan01 0:14e97aa401f3 330 Index = x + y * GetWidth();
iut_cachan01 0:14e97aa401f3 331 for (int k = 0; k < Count; k++) {
iut_cachan01 0:14e97aa401f3 332 file.read((char*) &ColorIndex, sizeof(uint8_t));
iut_cachan01 0:14e97aa401f3 333 m_BitmapData[Index + k].Red = ColorTable[ColorIndex].Red;
iut_cachan01 0:14e97aa401f3 334 m_BitmapData[Index + k].Green = ColorTable[ColorIndex].Green;
iut_cachan01 0:14e97aa401f3 335 m_BitmapData[Index + k].Blue = ColorTable[ColorIndex].Blue;
iut_cachan01 0:14e97aa401f3 336 m_BitmapData[Index + k].Alpha = ColorTable[ColorIndex].Alpha;
iut_cachan01 0:14e97aa401f3 337 }
iut_cachan01 0:14e97aa401f3 338 x += Count;
iut_cachan01 0:14e97aa401f3 339 // Attention: Current Microsoft STL implementation seems to be buggy, tellg() always returns 0.
iut_cachan01 0:14e97aa401f3 340 if (file.tellg() & 1) {
iut_cachan01 0:14e97aa401f3 341 file.seekg(1, std::ios::cur);
iut_cachan01 0:14e97aa401f3 342 }
iut_cachan01 0:14e97aa401f3 343 }
iut_cachan01 0:14e97aa401f3 344 }
iut_cachan01 0:14e97aa401f3 345 }
iut_cachan01 0:14e97aa401f3 346 } else if (m_BitmapHeader.Compression == 2) { // RLE 4
iut_cachan01 0:14e97aa401f3 347 /* RLE 4 is not supported */
iut_cachan01 0:14e97aa401f3 348 Result = false;
iut_cachan01 0:14e97aa401f3 349 } else if (m_BitmapHeader.Compression == 3) { // BITFIELDS
iut_cachan01 0:14e97aa401f3 350
iut_cachan01 0:14e97aa401f3 351 /* We assumes that mask of each color component can be in any order */
iut_cachan01 0:14e97aa401f3 352
iut_cachan01 0:14e97aa401f3 353 uint32_t BitCountRed = CColor::BitCountByMask(m_BitmapHeader.RedMask);
iut_cachan01 0:14e97aa401f3 354 uint32_t BitCountGreen = CColor::BitCountByMask(m_BitmapHeader.GreenMask);
iut_cachan01 0:14e97aa401f3 355 uint32_t BitCountBlue = CColor::BitCountByMask(m_BitmapHeader.BlueMask);
iut_cachan01 0:14e97aa401f3 356 uint32_t BitCountAlpha = CColor::BitCountByMask(m_BitmapHeader.AlphaMask);
iut_cachan01 0:14e97aa401f3 357
iut_cachan01 0:14e97aa401f3 358 for (unsigned int i = 0; i < GetHeight(); i++) {
iut_cachan01 0:14e97aa401f3 359 file.read((char*) Line, LineWidth);
iut_cachan01 0:14e97aa401f3 360
iut_cachan01 0:14e97aa401f3 361 uint8_t *LinePtr = Line;
iut_cachan01 0:14e97aa401f3 362
iut_cachan01 0:14e97aa401f3 363 for (unsigned int j = 0; j < GetWidth(); j++) {
iut_cachan01 0:14e97aa401f3 364
iut_cachan01 0:14e97aa401f3 365 uint32_t Color = 0;
iut_cachan01 0:14e97aa401f3 366
iut_cachan01 0:14e97aa401f3 367 if (m_BitmapHeader.BitCount == 16) {
iut_cachan01 0:14e97aa401f3 368 Color = *((uint16_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 369 LinePtr += 2;
iut_cachan01 0:14e97aa401f3 370 } else if (m_BitmapHeader.BitCount == 32) {
iut_cachan01 0:14e97aa401f3 371 Color = *((uint32_t*) LinePtr);
iut_cachan01 0:14e97aa401f3 372 LinePtr += 4;
iut_cachan01 0:14e97aa401f3 373 } else {
iut_cachan01 0:14e97aa401f3 374 // Other formats are not valid
iut_cachan01 0:14e97aa401f3 375 }
iut_cachan01 0:14e97aa401f3 376 m_BitmapData[Index].Red = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.RedMask), BitCountRed, 8);
iut_cachan01 0:14e97aa401f3 377 m_BitmapData[Index].Green = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.GreenMask), BitCountGreen, 8);
iut_cachan01 0:14e97aa401f3 378 m_BitmapData[Index].Blue = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.BlueMask), BitCountBlue, 8);
iut_cachan01 0:14e97aa401f3 379 m_BitmapData[Index].Alpha = CColor::Convert(CColor::ComponentByMask(Color, m_BitmapHeader.AlphaMask), BitCountAlpha, 8);
iut_cachan01 0:14e97aa401f3 380
iut_cachan01 0:14e97aa401f3 381 Index++;
iut_cachan01 0:14e97aa401f3 382 }
iut_cachan01 0:14e97aa401f3 383 }
iut_cachan01 0:14e97aa401f3 384 }
iut_cachan01 0:14e97aa401f3 385
iut_cachan01 0:14e97aa401f3 386 delete [] ColorTable;
iut_cachan01 0:14e97aa401f3 387 delete [] Line;
iut_cachan01 0:14e97aa401f3 388
iut_cachan01 0:14e97aa401f3 389 file.close();
iut_cachan01 0:14e97aa401f3 390 return Result;
iut_cachan01 0:14e97aa401f3 391 }
iut_cachan01 0:14e97aa401f3 392
iut_cachan01 0:14e97aa401f3 393 bool Save(const char* Filename, unsigned int BitCount = 32) {
iut_cachan01 0:14e97aa401f3 394 bool Result = true;
iut_cachan01 0:14e97aa401f3 395
iut_cachan01 0:14e97aa401f3 396 std::ofstream file(Filename, std::ios::out | std::ios::binary);
iut_cachan01 0:14e97aa401f3 397
iut_cachan01 0:14e97aa401f3 398 if (file.is_open() == false) {
iut_cachan01 0:14e97aa401f3 399 return false;
iut_cachan01 0:14e97aa401f3 400 }
iut_cachan01 0:14e97aa401f3 401
iut_cachan01 0:14e97aa401f3 402 BITMAP_FILEHEADER bfh;
iut_cachan01 0:14e97aa401f3 403 BITMAP_HEADER bh;
iut_cachan01 0:14e97aa401f3 404 memset(&bfh, 0, sizeof(bfh));
iut_cachan01 0:14e97aa401f3 405 memset(&bh, 0, sizeof(bh));
iut_cachan01 0:14e97aa401f3 406
iut_cachan01 0:14e97aa401f3 407 bfh.Signature = BITMAP_SIGNATURE;
iut_cachan01 0:14e97aa401f3 408 bfh.BitsOffset = BITMAP_FILEHEADER_SIZE + sizeof(BITMAP_HEADER);
iut_cachan01 0:14e97aa401f3 409 bfh.Size = (GetWidth() * GetHeight() * BitCount) / 8 + bfh.BitsOffset;
iut_cachan01 0:14e97aa401f3 410
iut_cachan01 0:14e97aa401f3 411 bh.HeaderSize = sizeof(BITMAP_HEADER);
iut_cachan01 0:14e97aa401f3 412 bh.BitCount = BitCount;
iut_cachan01 0:14e97aa401f3 413
iut_cachan01 0:14e97aa401f3 414 if (BitCount == 32) {
iut_cachan01 0:14e97aa401f3 415 bh.Compression = 3; // BITFIELD
iut_cachan01 0:14e97aa401f3 416 bh.AlphaMask = 0xff000000;
iut_cachan01 0:14e97aa401f3 417 bh.BlueMask = 0x00ff0000;
iut_cachan01 0:14e97aa401f3 418 bh.GreenMask = 0x0000ff00;
iut_cachan01 0:14e97aa401f3 419 bh.RedMask = 0x000000ff;
iut_cachan01 0:14e97aa401f3 420 } else if (BitCount == 16) {
iut_cachan01 0:14e97aa401f3 421 bh.Compression = 3; // BITFIELD
iut_cachan01 0:14e97aa401f3 422 bh.AlphaMask = 0x00000000;
iut_cachan01 0:14e97aa401f3 423 bh.BlueMask = 0x0000001f;
iut_cachan01 0:14e97aa401f3 424 bh.GreenMask = 0x000007E0;
iut_cachan01 0:14e97aa401f3 425 bh.RedMask = 0x0000F800;
iut_cachan01 0:14e97aa401f3 426 } else {
iut_cachan01 0:14e97aa401f3 427 bh.Compression = 0; // RGB
iut_cachan01 0:14e97aa401f3 428 }
iut_cachan01 0:14e97aa401f3 429
iut_cachan01 0:14e97aa401f3 430 unsigned int LineWidth = (GetWidth() + 3) & ~3;
iut_cachan01 0:14e97aa401f3 431
iut_cachan01 0:14e97aa401f3 432 bh.Planes = 1;
iut_cachan01 0:14e97aa401f3 433 bh.Height = GetHeight();
iut_cachan01 0:14e97aa401f3 434 bh.Width = GetWidth();
iut_cachan01 0:14e97aa401f3 435 bh.SizeImage = (LineWidth * BitCount * GetHeight()) / 8;
iut_cachan01 0:14e97aa401f3 436 bh.PelsPerMeterX = 3780;
iut_cachan01 0:14e97aa401f3 437 bh.PelsPerMeterY = 3780;
iut_cachan01 0:14e97aa401f3 438
iut_cachan01 0:14e97aa401f3 439 if (BitCount == 32) {
iut_cachan01 0:14e97aa401f3 440 file.write((char*) &bfh, sizeof(BITMAP_FILEHEADER));
iut_cachan01 0:14e97aa401f3 441 file.write((char*) &bh, sizeof(BITMAP_HEADER));
iut_cachan01 0:14e97aa401f3 442 file.write((char*) m_BitmapData, bh.SizeImage);
iut_cachan01 0:14e97aa401f3 443 } else if (BitCount < 16) {
iut_cachan01 0:14e97aa401f3 444 uint8_t* Bitmap = new uint8_t[bh.SizeImage];
iut_cachan01 0:14e97aa401f3 445
iut_cachan01 0:14e97aa401f3 446 BGRA *Palette = 0;
iut_cachan01 0:14e97aa401f3 447 unsigned int PaletteSize = 0;
iut_cachan01 0:14e97aa401f3 448
iut_cachan01 0:14e97aa401f3 449 if (GetBitsWithPalette(Bitmap, bh.SizeImage, BitCount, Palette, PaletteSize)) {
iut_cachan01 0:14e97aa401f3 450 bfh.BitsOffset += PaletteSize * sizeof(BGRA);
iut_cachan01 0:14e97aa401f3 451
iut_cachan01 0:14e97aa401f3 452 file.write((char*) &bfh, BITMAP_FILEHEADER_SIZE);
iut_cachan01 0:14e97aa401f3 453 file.write((char*) &bh, sizeof(BITMAP_HEADER));
iut_cachan01 0:14e97aa401f3 454 file.write((char*) Palette, PaletteSize * sizeof(BGRA));
iut_cachan01 0:14e97aa401f3 455 file.write((char*) Bitmap, bh.SizeImage);
iut_cachan01 0:14e97aa401f3 456 }
iut_cachan01 0:14e97aa401f3 457 delete [] Bitmap;
iut_cachan01 0:14e97aa401f3 458 delete [] Palette;
iut_cachan01 0:14e97aa401f3 459 } else {
iut_cachan01 0:14e97aa401f3 460 uint32_t RedMask = 0;
iut_cachan01 0:14e97aa401f3 461 uint32_t GreenMask = 0;
iut_cachan01 0:14e97aa401f3 462 uint32_t BlueMask = 0;
iut_cachan01 0:14e97aa401f3 463 uint32_t AlphaMask = 0;
iut_cachan01 0:14e97aa401f3 464
iut_cachan01 0:14e97aa401f3 465 if (BitCount == 16) {
iut_cachan01 0:14e97aa401f3 466 RedMask = 0x0000F800;
iut_cachan01 0:14e97aa401f3 467 GreenMask = 0x000007E0;
iut_cachan01 0:14e97aa401f3 468 BlueMask = 0x0000001F;
iut_cachan01 0:14e97aa401f3 469 AlphaMask = 0x00000000;
iut_cachan01 0:14e97aa401f3 470 } else if (BitCount == 24) {
iut_cachan01 0:14e97aa401f3 471 RedMask = 0x00FF0000;
iut_cachan01 0:14e97aa401f3 472 GreenMask = 0x0000FF00;
iut_cachan01 0:14e97aa401f3 473 BlueMask = 0x000000FF;
iut_cachan01 0:14e97aa401f3 474 } else {
iut_cachan01 0:14e97aa401f3 475 // Other color formats are not valid
iut_cachan01 0:14e97aa401f3 476 Result = false;
iut_cachan01 0:14e97aa401f3 477 }
iut_cachan01 0:14e97aa401f3 478
iut_cachan01 0:14e97aa401f3 479 if (Result) {
iut_cachan01 0:14e97aa401f3 480 if (GetBits(NULL, bh.SizeImage, RedMask, GreenMask, BlueMask, AlphaMask)) {
iut_cachan01 0:14e97aa401f3 481 uint8_t* Bitmap = new uint8_t[bh.SizeImage];
iut_cachan01 0:14e97aa401f3 482 if (GetBits(Bitmap, bh.SizeImage, RedMask, GreenMask, BlueMask, AlphaMask)) {
iut_cachan01 0:14e97aa401f3 483 file.write((char*) &bfh, sizeof(BITMAP_FILEHEADER));
iut_cachan01 0:14e97aa401f3 484 file.write((char*) &bh, sizeof(BITMAP_HEADER));
iut_cachan01 0:14e97aa401f3 485 file.write((char*) Bitmap, bh.SizeImage);
iut_cachan01 0:14e97aa401f3 486 }
iut_cachan01 0:14e97aa401f3 487 delete [] Bitmap;
iut_cachan01 0:14e97aa401f3 488 }
iut_cachan01 0:14e97aa401f3 489 }
iut_cachan01 0:14e97aa401f3 490 }
iut_cachan01 0:14e97aa401f3 491
iut_cachan01 0:14e97aa401f3 492 file.close();
iut_cachan01 0:14e97aa401f3 493 return Result;
iut_cachan01 0:14e97aa401f3 494 }
iut_cachan01 0:14e97aa401f3 495
iut_cachan01 0:14e97aa401f3 496 unsigned int GetWidth() {
iut_cachan01 0:14e97aa401f3 497 /* Add plausibility test */
iut_cachan01 0:14e97aa401f3 498 // if (abs(m_BitmapHeader.Width) > 8192) {
iut_cachan01 0:14e97aa401f3 499 // m_BitmapHeader.Width = 8192;
iut_cachan01 0:14e97aa401f3 500 // }
iut_cachan01 0:14e97aa401f3 501 return m_BitmapHeader.Width < 0 ? -m_BitmapHeader.Width : m_BitmapHeader.Width;
iut_cachan01 0:14e97aa401f3 502 }
iut_cachan01 0:14e97aa401f3 503
iut_cachan01 0:14e97aa401f3 504 unsigned int GetHeight() {
iut_cachan01 0:14e97aa401f3 505 /* Add plausibility test */
iut_cachan01 0:14e97aa401f3 506 // if (abs(m_BitmapHeader.Height) > 8192) {
iut_cachan01 0:14e97aa401f3 507 // m_BitmapHeader.Height = 8192;
iut_cachan01 0:14e97aa401f3 508 // }
iut_cachan01 0:14e97aa401f3 509 return m_BitmapHeader.Height < 0 ? -m_BitmapHeader.Height : m_BitmapHeader.Height;
iut_cachan01 0:14e97aa401f3 510 }
iut_cachan01 0:14e97aa401f3 511
iut_cachan01 0:14e97aa401f3 512 unsigned int GetBitCount() {
iut_cachan01 0:14e97aa401f3 513 /* Add plausibility test */
iut_cachan01 0:14e97aa401f3 514 // if (m_BitmapHeader.BitCount > 32) {
iut_cachan01 0:14e97aa401f3 515 // m_BitmapHeader.BitCount = 32;
iut_cachan01 0:14e97aa401f3 516 // }
iut_cachan01 0:14e97aa401f3 517 return m_BitmapHeader.BitCount;
iut_cachan01 0:14e97aa401f3 518 }
iut_cachan01 0:14e97aa401f3 519
iut_cachan01 0:14e97aa401f3 520 /* Copies internal RGBA buffer to user specified buffer */
iut_cachan01 0:14e97aa401f3 521
iut_cachan01 0:14e97aa401f3 522 bool GetBits(void* Buffer, unsigned int &Size) {
iut_cachan01 0:14e97aa401f3 523 bool Result = false;
iut_cachan01 0:14e97aa401f3 524 if (Size == 0 || Buffer == 0) {
iut_cachan01 0:14e97aa401f3 525 Size = m_BitmapSize * sizeof(RGBA);
iut_cachan01 0:14e97aa401f3 526 Result = m_BitmapSize != 0;
iut_cachan01 0:14e97aa401f3 527 } else {
iut_cachan01 0:14e97aa401f3 528 memcpy(Buffer, m_BitmapData, Size);
iut_cachan01 0:14e97aa401f3 529 Result = true;
iut_cachan01 0:14e97aa401f3 530 }
iut_cachan01 0:14e97aa401f3 531 return Result;
iut_cachan01 0:14e97aa401f3 532 }
iut_cachan01 0:14e97aa401f3 533
iut_cachan01 0:14e97aa401f3 534 /* Returns internal RGBA buffer */
iut_cachan01 0:14e97aa401f3 535
iut_cachan01 0:14e97aa401f3 536 void* GetBits() {
iut_cachan01 0:14e97aa401f3 537 return m_BitmapData;
iut_cachan01 0:14e97aa401f3 538 }
iut_cachan01 0:14e97aa401f3 539
iut_cachan01 0:14e97aa401f3 540 /* Copies internal RGBA buffer to user specified buffer and converts it into destination
iut_cachan01 0:14e97aa401f3 541 * bit format specified by component masks.
iut_cachan01 0:14e97aa401f3 542 *
iut_cachan01 0:14e97aa401f3 543 * Typical Bitmap color formats (BGR/BGRA):
iut_cachan01 0:14e97aa401f3 544 *
iut_cachan01 0:14e97aa401f3 545 * Masks for 16 bit (5-5-5): ALPHA = 0x00000000, RED = 0x00007C00, GREEN = 0x000003E0, BLUE = 0x0000001F
iut_cachan01 0:14e97aa401f3 546 * Masks for 16 bit (5-6-5): ALPHA = 0x00000000, RED = 0x0000F800, GREEN = 0x000007E0, BLUE = 0x0000001F
iut_cachan01 0:14e97aa401f3 547 * Masks for 24 bit: ALPHA = 0x00000000, RED = 0x00FF0000, GREEN = 0x0000FF00, BLUE = 0x000000FF
iut_cachan01 0:14e97aa401f3 548 * Masks for 32 bit: ALPHA = 0xFF000000, RED = 0x00FF0000, GREEN = 0x0000FF00, BLUE = 0x000000FF
iut_cachan01 0:14e97aa401f3 549 *
iut_cachan01 0:14e97aa401f3 550 * Other color formats (RGB/RGBA):
iut_cachan01 0:14e97aa401f3 551 *
iut_cachan01 0:14e97aa401f3 552 * Masks for 32 bit (RGBA): ALPHA = 0xFF000000, RED = 0x000000FF, GREEN = 0x0000FF00, BLUE = 0x00FF0000
iut_cachan01 0:14e97aa401f3 553 *
iut_cachan01 0:14e97aa401f3 554 * Bit count will be rounded to next 8 bit boundary. If IncludePadding is true, it will be ensured
iut_cachan01 0:14e97aa401f3 555 * that line width is a multiple of 4. padding bytes are included if necessary.
iut_cachan01 0:14e97aa401f3 556 *
iut_cachan01 0:14e97aa401f3 557 * NOTE: systems with big endian byte order may require masks in inversion order.
iut_cachan01 0:14e97aa401f3 558 */
iut_cachan01 0:14e97aa401f3 559
iut_cachan01 0:14e97aa401f3 560 bool GetBits(void* Buffer, unsigned int &Size, unsigned int RedMask, unsigned int GreenMask, unsigned int BlueMask, unsigned int AlphaMask, bool IncludePadding = true) {
iut_cachan01 0:14e97aa401f3 561 bool Result = false;
iut_cachan01 0:14e97aa401f3 562
iut_cachan01 0:14e97aa401f3 563 uint32_t BitCountRed = CColor::BitCountByMask(RedMask);
iut_cachan01 0:14e97aa401f3 564 uint32_t BitCountGreen = CColor::BitCountByMask(GreenMask);
iut_cachan01 0:14e97aa401f3 565 uint32_t BitCountBlue = CColor::BitCountByMask(BlueMask);
iut_cachan01 0:14e97aa401f3 566 uint32_t BitCountAlpha = CColor::BitCountByMask(AlphaMask);
iut_cachan01 0:14e97aa401f3 567
iut_cachan01 0:14e97aa401f3 568 unsigned int BitCount = (BitCountRed + BitCountGreen + BitCountBlue + BitCountAlpha + 7) & ~7;
iut_cachan01 0:14e97aa401f3 569
iut_cachan01 0:14e97aa401f3 570 if (BitCount > 32) {
iut_cachan01 0:14e97aa401f3 571 return false;
iut_cachan01 0:14e97aa401f3 572 }
iut_cachan01 0:14e97aa401f3 573
iut_cachan01 0:14e97aa401f3 574 unsigned int w = GetWidth();
iut_cachan01 0:14e97aa401f3 575 //unsigned int LineWidth = (w + 3) & ~3;
iut_cachan01 0:14e97aa401f3 576 unsigned int dataBytesPerLine = (w * BitCount + 7) / 8;
iut_cachan01 0:14e97aa401f3 577 unsigned int LineWidth = (dataBytesPerLine + 3) & ~3;
iut_cachan01 0:14e97aa401f3 578
iut_cachan01 0:14e97aa401f3 579 if (Size == 0 || Buffer == 0) {
iut_cachan01 0:14e97aa401f3 580 //Size = (LineWidth * GetHeight() * BitCount) / 8 + sizeof(unsigned int);
iut_cachan01 0:14e97aa401f3 581 Size = (GetWidth() * GetHeight() * BitCount) / 8 + sizeof(unsigned int);
iut_cachan01 0:14e97aa401f3 582 return true;
iut_cachan01 0:14e97aa401f3 583 }
iut_cachan01 0:14e97aa401f3 584
iut_cachan01 0:14e97aa401f3 585 uint8_t* BufferPtr = (uint8_t*) Buffer;
iut_cachan01 0:14e97aa401f3 586
iut_cachan01 0:14e97aa401f3 587 Result = true;
iut_cachan01 0:14e97aa401f3 588
iut_cachan01 0:14e97aa401f3 589 uint32_t BitPosRed = CColor::BitPositionByMask(RedMask);
iut_cachan01 0:14e97aa401f3 590 uint32_t BitPosGreen = CColor::BitPositionByMask(GreenMask);
iut_cachan01 0:14e97aa401f3 591 uint32_t BitPosBlue = CColor::BitPositionByMask(BlueMask);
iut_cachan01 0:14e97aa401f3 592 uint32_t BitPosAlpha = CColor::BitPositionByMask(AlphaMask);
iut_cachan01 0:14e97aa401f3 593
iut_cachan01 0:14e97aa401f3 594 unsigned int j = 0;
iut_cachan01 0:14e97aa401f3 595
iut_cachan01 0:14e97aa401f3 596 for (unsigned int i = 0; i < m_BitmapSize; i++) {
iut_cachan01 0:14e97aa401f3 597 *(uint32_t*) BufferPtr =
iut_cachan01 0:14e97aa401f3 598 (CColor::Convert(m_BitmapData[i].Blue, 8, BitCountBlue) << BitPosBlue) |
iut_cachan01 0:14e97aa401f3 599 (CColor::Convert(m_BitmapData[i].Green, 8, BitCountGreen) << BitPosGreen) |
iut_cachan01 0:14e97aa401f3 600 (CColor::Convert(m_BitmapData[i].Red, 8, BitCountRed) << BitPosRed) |
iut_cachan01 0:14e97aa401f3 601 (CColor::Convert(m_BitmapData[i].Alpha, 8, BitCountAlpha) << BitPosAlpha);
iut_cachan01 0:14e97aa401f3 602
iut_cachan01 0:14e97aa401f3 603 if (IncludePadding) {
iut_cachan01 0:14e97aa401f3 604 j++;
iut_cachan01 0:14e97aa401f3 605 if (j >= w) {
iut_cachan01 0:14e97aa401f3 606 for (unsigned int k = 0; k < LineWidth - dataBytesPerLine; k++) {
iut_cachan01 0:14e97aa401f3 607 BufferPtr += (BitCount >> 3);
iut_cachan01 0:14e97aa401f3 608 }
iut_cachan01 0:14e97aa401f3 609 j = 0;
iut_cachan01 0:14e97aa401f3 610 }
iut_cachan01 0:14e97aa401f3 611 }
iut_cachan01 0:14e97aa401f3 612
iut_cachan01 0:14e97aa401f3 613 BufferPtr += (BitCount >> 3);
iut_cachan01 0:14e97aa401f3 614 }
iut_cachan01 0:14e97aa401f3 615
iut_cachan01 0:14e97aa401f3 616 Size -= sizeof(unsigned int);
iut_cachan01 0:14e97aa401f3 617
iut_cachan01 0:14e97aa401f3 618 return Result;
iut_cachan01 0:14e97aa401f3 619 }
iut_cachan01 0:14e97aa401f3 620
iut_cachan01 0:14e97aa401f3 621 /* See GetBits().
iut_cachan01 0:14e97aa401f3 622 * It creates a corresponding color table (palette) which have to be destroyed by the user after usage.
iut_cachan01 0:14e97aa401f3 623 *
iut_cachan01 0:14e97aa401f3 624 * Supported Bit depths are: 4, 8
iut_cachan01 0:14e97aa401f3 625 *
iut_cachan01 0:14e97aa401f3 626 * Todo: Optimize, use optimized palette, do ditehring (see my dithering class), support padding for 4 bit bitmaps
iut_cachan01 0:14e97aa401f3 627 */
iut_cachan01 0:14e97aa401f3 628
iut_cachan01 0:14e97aa401f3 629 bool GetBitsWithPalette(void* Buffer, unsigned int &Size, unsigned int BitCount, BGRA* &Palette, unsigned int &PaletteSize, bool OptimalPalette = false, bool IncludePadding = true) {
iut_cachan01 0:14e97aa401f3 630 bool Result = false;
iut_cachan01 0:14e97aa401f3 631
iut_cachan01 0:14e97aa401f3 632 if (BitCount > 16) {
iut_cachan01 0:14e97aa401f3 633 return false;
iut_cachan01 0:14e97aa401f3 634 }
iut_cachan01 0:14e97aa401f3 635
iut_cachan01 0:14e97aa401f3 636 unsigned int w = GetWidth();
iut_cachan01 0:14e97aa401f3 637 unsigned int dataBytesPerLine = (w * BitCount + 7) / 8;
iut_cachan01 0:14e97aa401f3 638 unsigned int LineWidth = (dataBytesPerLine + 3) & ~3;
iut_cachan01 0:14e97aa401f3 639
iut_cachan01 0:14e97aa401f3 640 if (Size == 0 || Buffer == 0) {
iut_cachan01 0:14e97aa401f3 641 Size = (LineWidth * GetHeight() * BitCount) / 8;
iut_cachan01 0:14e97aa401f3 642 return true;
iut_cachan01 0:14e97aa401f3 643 }
iut_cachan01 0:14e97aa401f3 644
iut_cachan01 0:14e97aa401f3 645
iut_cachan01 0:14e97aa401f3 646 if (OptimalPalette) {
iut_cachan01 0:14e97aa401f3 647 PaletteSize = 0;
iut_cachan01 0:14e97aa401f3 648 // Not implemented
iut_cachan01 0:14e97aa401f3 649 } else {
iut_cachan01 0:14e97aa401f3 650 if (BitCount == 1) {
iut_cachan01 0:14e97aa401f3 651 PaletteSize = 2;
iut_cachan01 0:14e97aa401f3 652 // Not implemented: Who need that?
iut_cachan01 0:14e97aa401f3 653 } else if (BitCount == 4) { // 2:2:1
iut_cachan01 0:14e97aa401f3 654 PaletteSize = 16;
iut_cachan01 0:14e97aa401f3 655 Palette = new BGRA[PaletteSize];
iut_cachan01 0:14e97aa401f3 656 for (int r = 0; r < 4; r++) {
iut_cachan01 0:14e97aa401f3 657 for (int g = 0; g < 2; g++) {
iut_cachan01 0:14e97aa401f3 658 for (int b = 0; b < 2; b++) {
iut_cachan01 0:14e97aa401f3 659 Palette[r | g << 2 | b << 3].Red = r ? (r << 6) | 0x3f : 0;
iut_cachan01 0:14e97aa401f3 660 Palette[r | g << 2 | b << 3].Green = g ? (g << 7) | 0x7f : 0;
iut_cachan01 0:14e97aa401f3 661 Palette[r | g << 2 | b << 3].Blue = b ? (b << 7) | 0x7f : 0;
iut_cachan01 0:14e97aa401f3 662 Palette[r | g << 2 | b << 3].Alpha = 0xff;
iut_cachan01 0:14e97aa401f3 663 }
iut_cachan01 0:14e97aa401f3 664 }
iut_cachan01 0:14e97aa401f3 665 }
iut_cachan01 0:14e97aa401f3 666 } else if (BitCount == 8) { // 3:3:2
iut_cachan01 0:14e97aa401f3 667 PaletteSize = 256;
iut_cachan01 0:14e97aa401f3 668 Palette = new BGRA[PaletteSize];
iut_cachan01 0:14e97aa401f3 669 for (int r = 0; r < 8; r++) {
iut_cachan01 0:14e97aa401f3 670 for (int g = 0; g < 8; g++) {
iut_cachan01 0:14e97aa401f3 671 for (int b = 0; b < 4; b++) {
iut_cachan01 0:14e97aa401f3 672 Palette[r | g << 3 | b << 6].Red = r ? (r << 5) | 0x1f : 0;
iut_cachan01 0:14e97aa401f3 673 Palette[r | g << 3 | b << 6].Green = g ? (g << 5) | 0x1f : 0;
iut_cachan01 0:14e97aa401f3 674 Palette[r | g << 3 | b << 6].Blue = b ? (b << 6) | 0x3f : 0;
iut_cachan01 0:14e97aa401f3 675 Palette[r | g << 3 | b << 6].Alpha = 0xff;
iut_cachan01 0:14e97aa401f3 676 }
iut_cachan01 0:14e97aa401f3 677 }
iut_cachan01 0:14e97aa401f3 678 }
iut_cachan01 0:14e97aa401f3 679 } else if (BitCount == 16) { // 5:5:5
iut_cachan01 0:14e97aa401f3 680 // Not implemented
iut_cachan01 0:14e97aa401f3 681 }
iut_cachan01 0:14e97aa401f3 682 }
iut_cachan01 0:14e97aa401f3 683
iut_cachan01 0:14e97aa401f3 684 unsigned int j = 0;
iut_cachan01 0:14e97aa401f3 685 uint8_t* BufferPtr = (uint8_t*) Buffer;
iut_cachan01 0:14e97aa401f3 686
iut_cachan01 0:14e97aa401f3 687 for (unsigned int i = 0; i < m_BitmapSize; i++) {
iut_cachan01 0:14e97aa401f3 688 if (BitCount == 1) {
iut_cachan01 0:14e97aa401f3 689 // Not implemented: Who needs that?
iut_cachan01 0:14e97aa401f3 690 } else if (BitCount == 4) {
iut_cachan01 0:14e97aa401f3 691 *BufferPtr = ((m_BitmapData[i].Red >> 6) | (m_BitmapData[i].Green >> 7) << 2 | (m_BitmapData[i].Blue >> 7) << 3) << 4;
iut_cachan01 0:14e97aa401f3 692 i++;
iut_cachan01 0:14e97aa401f3 693 *BufferPtr |= (m_BitmapData[i].Red >> 6) | (m_BitmapData[i].Green >> 7) << 2 | (m_BitmapData[i].Blue >> 7) << 3;
iut_cachan01 0:14e97aa401f3 694 } else if (BitCount == 8) {
iut_cachan01 0:14e97aa401f3 695 *BufferPtr = (m_BitmapData[i].Red >> 5) | (m_BitmapData[i].Green >> 5) << 3 | (m_BitmapData[i].Blue >> 5) << 6;
iut_cachan01 0:14e97aa401f3 696 } else if (BitCount == 16) {
iut_cachan01 0:14e97aa401f3 697 // Not implemented
iut_cachan01 0:14e97aa401f3 698 }
iut_cachan01 0:14e97aa401f3 699
iut_cachan01 0:14e97aa401f3 700 if (IncludePadding) {
iut_cachan01 0:14e97aa401f3 701 j++;
iut_cachan01 0:14e97aa401f3 702 if (j >= w) {
iut_cachan01 0:14e97aa401f3 703 for (unsigned int k = 0; k < (LineWidth - dataBytesPerLine); k++) {
iut_cachan01 0:14e97aa401f3 704 BufferPtr += BitCount / 8;
iut_cachan01 0:14e97aa401f3 705 }
iut_cachan01 0:14e97aa401f3 706 j = 0;
iut_cachan01 0:14e97aa401f3 707 }
iut_cachan01 0:14e97aa401f3 708 }
iut_cachan01 0:14e97aa401f3 709
iut_cachan01 0:14e97aa401f3 710 BufferPtr++;
iut_cachan01 0:14e97aa401f3 711 }
iut_cachan01 0:14e97aa401f3 712
iut_cachan01 0:14e97aa401f3 713 Result = true;
iut_cachan01 0:14e97aa401f3 714
iut_cachan01 0:14e97aa401f3 715 return Result;
iut_cachan01 0:14e97aa401f3 716 }
iut_cachan01 0:14e97aa401f3 717
iut_cachan01 0:14e97aa401f3 718 /* Set Bitmap Bits. Will be converted to RGBA internally */
iut_cachan01 0:14e97aa401f3 719
iut_cachan01 0:14e97aa401f3 720 bool SetBits(void* Buffer, unsigned int Width, unsigned int Height, unsigned int RedMask, unsigned int GreenMask, unsigned int BlueMask, unsigned int AlphaMask = 0) {
iut_cachan01 0:14e97aa401f3 721 if (Buffer == 0) {
iut_cachan01 0:14e97aa401f3 722 return false;
iut_cachan01 0:14e97aa401f3 723 }
iut_cachan01 0:14e97aa401f3 724
iut_cachan01 0:14e97aa401f3 725 uint8_t *BufferPtr = (uint8_t*) Buffer;
iut_cachan01 0:14e97aa401f3 726
iut_cachan01 0:14e97aa401f3 727 Dispose();
iut_cachan01 0:14e97aa401f3 728
iut_cachan01 0:14e97aa401f3 729 m_BitmapHeader.Width = Width;
iut_cachan01 0:14e97aa401f3 730 m_BitmapHeader.Height = Height;
iut_cachan01 0:14e97aa401f3 731 m_BitmapHeader.BitCount = 32;
iut_cachan01 0:14e97aa401f3 732 m_BitmapHeader.Compression = 3;
iut_cachan01 0:14e97aa401f3 733
iut_cachan01 0:14e97aa401f3 734 m_BitmapSize = GetWidth() * GetHeight();
iut_cachan01 0:14e97aa401f3 735 m_BitmapData = new BGRA[m_BitmapSize];
iut_cachan01 0:14e97aa401f3 736
iut_cachan01 0:14e97aa401f3 737 /* Find bit count by masks (rounded to next 8 bit boundary) */
iut_cachan01 0:14e97aa401f3 738
iut_cachan01 0:14e97aa401f3 739 unsigned int BitCount = (CColor::BitCountByMask(RedMask | GreenMask | BlueMask | AlphaMask) + 7) & ~7;
iut_cachan01 0:14e97aa401f3 740
iut_cachan01 0:14e97aa401f3 741 uint32_t BitCountRed = CColor::BitCountByMask(RedMask);
iut_cachan01 0:14e97aa401f3 742 uint32_t BitCountGreen = CColor::BitCountByMask(GreenMask);
iut_cachan01 0:14e97aa401f3 743 uint32_t BitCountBlue = CColor::BitCountByMask(BlueMask);
iut_cachan01 0:14e97aa401f3 744 uint32_t BitCountAlpha = CColor::BitCountByMask(AlphaMask);
iut_cachan01 0:14e97aa401f3 745
iut_cachan01 0:14e97aa401f3 746 for (unsigned int i = 0; i < m_BitmapSize; i++) {
iut_cachan01 0:14e97aa401f3 747 unsigned int Color = 0;
iut_cachan01 0:14e97aa401f3 748 if (BitCount <= 8) {
iut_cachan01 0:14e97aa401f3 749 Color = *((uint8_t*) BufferPtr);
iut_cachan01 0:14e97aa401f3 750 BufferPtr += 1;
iut_cachan01 0:14e97aa401f3 751 } else if (BitCount <= 16) {
iut_cachan01 0:14e97aa401f3 752 Color = *((uint16_t*) BufferPtr);
iut_cachan01 0:14e97aa401f3 753 BufferPtr += 2;
iut_cachan01 0:14e97aa401f3 754 } else if (BitCount <= 24) {
iut_cachan01 0:14e97aa401f3 755 Color = *((uint32_t*) BufferPtr);
iut_cachan01 0:14e97aa401f3 756 BufferPtr += 3;
iut_cachan01 0:14e97aa401f3 757 } else if (BitCount <= 32) {
iut_cachan01 0:14e97aa401f3 758 Color = *((uint32_t*) BufferPtr);
iut_cachan01 0:14e97aa401f3 759 BufferPtr += 4;
iut_cachan01 0:14e97aa401f3 760 } else {
iut_cachan01 0:14e97aa401f3 761 /* unsupported */
iut_cachan01 0:14e97aa401f3 762 BufferPtr += 1;
iut_cachan01 0:14e97aa401f3 763 }
iut_cachan01 0:14e97aa401f3 764 m_BitmapData[i].Alpha = CColor::Convert(CColor::ComponentByMask(Color, AlphaMask), BitCountAlpha, 8);
iut_cachan01 0:14e97aa401f3 765 m_BitmapData[i].Red = CColor::Convert(CColor::ComponentByMask(Color, RedMask), BitCountRed, 8);
iut_cachan01 0:14e97aa401f3 766 m_BitmapData[i].Green = CColor::Convert(CColor::ComponentByMask(Color, GreenMask), BitCountGreen, 8);
iut_cachan01 0:14e97aa401f3 767 m_BitmapData[i].Blue = CColor::Convert(CColor::ComponentByMask(Color, BlueMask), BitCountBlue, 8);
iut_cachan01 0:14e97aa401f3 768 }
iut_cachan01 0:14e97aa401f3 769
iut_cachan01 0:14e97aa401f3 770 return true;
iut_cachan01 0:14e97aa401f3 771 }
iut_cachan01 0:14e97aa401f3 772 };
iut_cachan01 0:14e97aa401f3 773
iut_cachan01 0:14e97aa401f3 774 #endif