2017-09-21

猎数博客

数据挖掘,机器学习

bmp file read c++ class

作者:江航 / 2012-05-21 / (阅读 1,891 次) /



http://www.kalytta.com/bitmap.h

/* * Windows Bitmap File Loader * Version 1.2.4 (20111211) * * 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 - 2011 * * 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
#include
#include

#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
#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;
RGBA *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;
}

/* Only full color tables are supported */

if (ColorTableSize != m_BitmapHeader.ClrUsed) {
return false;
}

BGRA* ColorTable = new BGRA[ColorTableSize]; // std::bad_alloc exception should be thrown if memory is not available

file.read((char*) ColorTable, sizeof(BGRA) * ColorTableSize);

/* … Color Table for 16 bits images are not supported yet */

m_BitmapSize = GetWidth() * GetHeight();
m_BitmapData = new RGBA[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 = {0}; BITMAP_HEADER bh = {0}; 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;

if (Size == 0 || Buffer == 0) {
Size = (LineWidth * 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].Green, 8, BitCountAlpha) << BitPosAlpha); if (IncludePadding) { j++; if (j >= w) {
for (unsigned int k = 0; k < LineWidth - w; 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 LineWidth = (w + 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 - w); 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 RGBA[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

sample for use it:
#include "bmp.h"

int main()
{
CBitmap bmp;
bmp.Load(“./tt.bmp”);
unsigned width = bmp.GetWidth();
unsigned height = bmp.GetHeight();

RGBA *data=(RGBA*) bmp.GetBits() ;
for(int i = 0 ; i



本文地址: http://www.bagualu.net/wordpress/archives/1320 转载请注明






相关文章

  • GDB 找不到源代码( 9,621 )
  • 如何识别C++编译以后的函数名(demangle)( 9,522 )
  • vim 获取当前文件名( 8,198 )
  • 程序性能分析之Valgrind( 4,568 )
  • GDB 查看内存/指针( 4,221 )
  • 怎样获得动态链接库的装载地址( 3,963 )
  • 用printf 输出64位整数( 3,849 )
  • gdb debug 信息 stabs 格式( 3,486 )
  • vim 多文件搜索并实现自动跳转( 3,471 )
  • gdb batch mode( 2,649 )
  • Leave a Reply

    您必须登录以发表评论,

    沪ICP备11036560号
    联系我: jianghang at bagualu.net