ciderpress/util/MyDIBitmap.h
2007-03-27 17:47:10 +00:00

176 lines
6.2 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* DIB (Device-Independent Bitmap) wrapper.
*
* [ Ported back from libfadden -- there's a lot of stuff here that we don't
* want or need, but it's easier to knock the bugs out if everybody is
* using roughly the same code. ]
*/
#ifndef __LF_DIBITMAP__
#define __LF_DIBITMAP__
/*
* Wraps a device-independent bitmap.
*
* When the bitmap is initially loaded, the object may or may not allocate a
* DIB section in system memory. If the DIB handle is requested, a conversion
* will be forced. This is done for efficiency in situations where the
* bitmap isn't going to be handed off to GDI, or will only be used as a DDB.
*
* Some bitmaps have a transparent color (1-bit alpha) or a full alpha
* channel. The behavior works like this:
* - If the bitmap is <= 24 bits, alpha defaults to "off".
* - If the bitmap is 32 bits, alpha defaults to "full".
* - If the app calls SetAlphaColor, alpha is set to "transparency".
* Calling GetPixelRGB returns a 32-bit value for which the alpha value
* is always set. For "none" it's always 255, for "transparency" it's
* either set to 0 or 255, and for "full" it's set to rgbReserved in a
* 32-bit bitmap (or 255 for any other value).
*/
class MyDIBitmap {
public:
typedef enum AlphaType {
kAlphaUnknown,
kAlphaOpaque, // always stuff 255 into rgbReserved
kAlphaTransparency, // single-bit alpha
kAlphaFull // alpha channel in rgbReserved
} AlphaType;
enum { kAlphaMask = 0xff000000 }; // alpha byte in an ARGB DWORD
MyDIBitmap(void) :
mhBitmap(nil),
mpFileBuffer(nil),
mWidth(-1),
mHeight(-1),
mBpp(-1),
mPitchBytes(0),
mNumColorsUsed(0),
mpColorTable(nil),
mColorTableInitialized(false),
mpPixels(nil),
mAlphaType(kAlphaOpaque),
mTransparentColor(0)
{
memset(&mBitmapInfoHdr, 0, sizeof(mBitmapInfoHdr));
}
virtual ~MyDIBitmap(void);
// create an empty bitmap with the specified characteristics; returns a
// pointer to the pixel storage
void* Create(int width, int height, int bitsPerPixel, int colorsUsed,
bool dibSection = false);
void SetColorTable(const RGBQUAD* pColorTable);
const RGBQUAD* GetColorTable(void) const { return mpColorTable; }
// zero out the pixels
void ClearPixels(void);
HBITMAP ConvertToDDB(HDC dc) const;
// create a DIB from a file on disk
int CreateFromFile(const char* fileName);
int CreateFromFile(FILE* fp, long len);
// create from memory buffer; set "doDelete" if object should own mem
// (if "doDelete" is set, memory will be deleted if function fails)
// contents of buffer will be analyzed to determine file type
int CreateFromBuffer(void* buffer, long len, bool doDelete);
// create a DIB from an embedded resource
void* CreateFromResource(HINSTANCE hInstance, const char* rsrc);
// write bitmap to file (for FILE*, make sure it's open in "wb" mode)
int WriteToFile(const char* fileName) const;
int WriteToFile(FILE* fp) const;
// simple getters
virtual int GetWidth(void) const { return mWidth; }
virtual int GetHeight(void) const { return mHeight; }
int GetBpp(void) const { return mBpp; }
int GetNumColorsUsed(void) const { return mNumColorsUsed; }
// retrieve current alpha mode
AlphaType GetAlphaType(void) const { return mAlphaType; }
// get transparent color; returns "false" if none has been set
bool GetTransparentColor(RGBQUAD* pColor) const;
// set transparent color and change alpha to kAlphaTransparency
void SetTransparentColor(const RGBQUAD* pColor);
// return the index of the specified color (-1 if not found, -2 on err)
int LookupColor(const RGBQUAD* pRgbQuad);
// set/get individual pixel values; the "RGB" functions always set
// alpha to zero, while "RGBA" follow the current alpha mode
void FASTCALL GetPixelRGB(int x, int y, RGBQUAD* pRgbQuad) const;
void FASTCALL SetPixelRGB(int x, int y, const RGBQUAD* pRgbQuad);
void FASTCALL GetPixelRGBA(int x, int y, RGBQUAD* pRgbQuad) const;
void FASTCALL SetPixelRGBA(int x, int y, const RGBQUAD* pRgbQuad);
void FASTCALL GetPixelIndex(int x, int y, int* pIdx) const;
void FASTCALL SetPixelIndex(int x, int y, int idx);
// Return a pointer to the raw pixel storage.
void* GetPixelBuf(void) const { return mpPixels; }
// Return the DIB handle; keep in mind that this HBITMAP is different
// from a DDB HBITMAP, and many calls that take an HBITMAP will fail.
HBITMAP GetHandle(void) {
if (mhBitmap == nil && mpFileBuffer != nil)
ConvertBufToDIBSection();
return mhBitmap;
}
int GetPitch(void) const { return mPitchBytes; }
// Blit pixels from one bitmap to another.
static bool Blit(MyDIBitmap* pDstBits, const RECT* pDstRect,
const MyDIBitmap* pSrcBits, const RECT* pSrcRect);
private:
enum { kBMPMagic = 0x4d42 }; // "BM"
/* for .TGA files; does not map directly to file */
typedef struct TargaHeader {
unsigned char idLength;
unsigned char colorMapType;
unsigned char imageType;
unsigned short colorMapOrigin;
unsigned short colorMapLen;
unsigned char colorMapEntryLen;
unsigned short xOffset;
unsigned short yOffset;
unsigned short width;
unsigned short height;
unsigned char bitsPerPixel;
unsigned char imageDescriptor;
} TargaHeader;
enum {
kTargaHeaderLen = 18,
kTargaUnmappedRGB = 2, // for imageType field
};
int ImportBMP(void* vbuf, long len);
int ImportTGA(void* vbuf, long len);
int ConvertBufToDIBSection(void);
int CreateFromNewBuffer(void* vbuf, long len);
BITMAPINFOHEADER mBitmapInfoHdr;
/* either mhBitmap or mpFileContents will be non-nil, but not both */
HBITMAP mhBitmap; // DIB section handle, not DDB
void* mpFileBuffer; // buffer with contents of .BMP
int mWidth;
int mHeight;
int mBpp; // #of bits per pixel
int mPitchBytes; // memory line pitch, in bytes
int mNumColorsUsed;
RGBQUAD* mpColorTable;
bool mColorTableInitialized;
void* mpPixels; // points to system-allocated mem
AlphaType mAlphaType;
DWORD mTransparentColor; // for single-bit alpha bitmaps
};
#endif /*__LF_DIBITMAP__*/