⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 haibmp.c

📁 一个类windows的GUI.目前已有一些基本的控件和基本的图形图像处理能力.
💻 C
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------------
// Copyright (c) Haisoft 2006-9-1
// Copyright jinhailiao 2008-2010
// E-mail:   jinhailiao@163.com
// Project:			HGui
// File:			haibmp.h
// Description:		BMP decode; reference CxImage
//-------------------------------------------------------------
// Reversion Histroy:
//-------------------------------------------------------------
// Version		date		operations				by who
// 2.0.0		2006-09-06  create                  Kingsea
// 3.0.0		2008-03-01	update					Kingsea
//---------------------------------------------------------------------------------
#include "haitype.h"
#include "haihandle.h"
#include "haimem.h"
#include "_haigdi.h"
#include "haipic.h"

typedef struct tagBITMAPFILEHEADER {
	S_WORD    bfType;
	S_DWORD   bfSize;
	S_WORD    bfReserved1;
	S_WORD    bfReserved2;
	S_DWORD   bfOffBits;
} BITMAPFILEHEADER;

typedef struct tagBITMAPCOREHEADER {
	S_DWORD   bcSize;
	S_WORD    bcWidth;
	S_WORD    bcHeight;
	S_WORD    bcPlanes;
	S_WORD    bcBitCount;
} BITMAPCOREHEADER;



#define BMP_WIDTH_LIMIT		2000
#define BMP_HEIGHT_LIMIT	2000

#define RLE_COMMAND			0
#define RLE_ENDOFLINE		0
#define RLE_ENDOFBITMAP		1
#define RLE_DELTA			2


#define WIDTHBYTES(i)           ((S_DWORD)(((i)+31)&(~31))>>3)  /* ULONG aligned ! */
#define DibWidthBytesN(lpbi, n) (S_UINT)WIDTHBYTES((S_UINT)(lpbi)->biWidth * (S_UINT)(n))
#define DibWidthBytes(lpbi)     DibWidthBytesN(lpbi, (lpbi)->biBitCount)
#define DibSizeImage(lpbi)      ((lpbi)->biSizeImage == 0 \
                                    ? ((S_DWORD)(S_UINT)DibWidthBytes(lpbi) * (S_DWORD)(S_UINT)(lpbi)->biHeight) \
                                    : (lpbi)->biSizeImage)
#define DibNumColors(lpbi)      ((lpbi)->biClrUsed == 0 && (lpbi)->biBitCount <= 8 \
                                    ? (int)(1 << (int)(lpbi)->biBitCount)          \
                                    : (int)(lpbi)->biClrUsed)
#define FixBitmapInfo(lpbi)     if ((lpbi)->biSizeImage == 0)                 \
												(lpbi)->biSizeImage = DibSizeImage(lpbi); \
                                if ((lpbi)->biClrUsed == 0)                   \
                                    (lpbi)->biClrUsed = DibNumColors(lpbi);   \


S_DWORD _hai_ReadBitmapFileHeader(S_BYTE *pBmpData, BITMAPFILEHEADER *pbf);
S_DWORD _hai_ReadBitmapInfo(S_BYTE *pBmpData, BITMAPINFOHEADER *pbih);
S_WORD _hai_ExtractBits841BI_RGB(_SP_BITMAP pBmp, BITMAPINFOHEADER *pbih, S_BYTE *pBmpData, RGBQUAD *pPalette, S_BOOL bTopDownDib);
S_WORD _hai_ExtractBits841BI_RLE4(_SP_BITMAP pBmp, S_BYTE *pBmpData, RGBQUAD *pPalette, S_BOOL bTopDownDib);
S_WORD _hai_ExtractBits841BI_RLE8(_SP_BITMAP pBmp, S_BYTE *pBmpData, RGBQUAD *pPalette, S_BOOL bTopDownDib);

SH_BITMAP hai_BmpDecode(S_VOID *pBmpData)
{
	S_BOOL bIsOldBmp;
	S_BOOL bTopDownDib;
	S_WORD i, j, ColorNum;
	S_DWORD SkipBytes, WidthBytes;
	S_BYTE *pBmpDat = (S_BYTE *)pBmpData;
	S_BYTE *pDst;
	S_BYTE *pSrc;
	RGBQUAD *pPalette;
	BITMAPFILEHEADER bf;
	BITMAPINFOHEADER bi;
	_SP_BITMAP pBitmap;
	
	if (pBmpData == S_NULL)
		return S_NULL;

	SkipBytes = _hai_ReadBitmapFileHeader(pBmpDat, &bf);
	if (SkipBytes == 0)
		return S_NULL;
	pBmpDat += SkipBytes;
	SkipBytes = _hai_ReadBitmapInfo(pBmpDat, &bi);
	if (SkipBytes == 0)
		return S_NULL;
	if (bi.biWidth > BMP_WIDTH_LIMIT || bi.biHeight > BMP_HEIGHT_LIMIT)
		return S_NULL;

	pBmpDat += SkipBytes;

	bIsOldBmp = (bi.biSize == 0x0C);//sizeof(BITMAPCOREHEADER);
	bTopDownDib = (bi.biHeight < 0);
	if (bTopDownDib) 
		bi.biHeight = -bi.biHeight;

	if (ColorNum = DibNumColors(&bi))
	{
		pPalette = hai_MemAlloc(ColorNum*sizeof(RGBQUAD));
		if (pPalette == S_NULL)
			return S_NULL;
		if (bIsOldBmp){ // convert a old color table (3 byte entries) to a new color table (4 byte entries)
			for (i = 0; i < ColorNum; i++){
				pPalette[i].rgbRed      = *pBmpDat++;
				pPalette[i].rgbGreen    = *pBmpDat++;
				pPalette[i].rgbBlue     = *pBmpDat++;
				pPalette[i].rgbReserved = (S_BYTE)0;
			}
		} else {
			for (i = 0; i < ColorNum; i++){
				pPalette[i].rgbRed      = *pBmpDat++;
				pPalette[i].rgbGreen    = *pBmpDat++;
				pPalette[i].rgbBlue     = *pBmpDat++;
				pPalette[i].rgbReserved = *pBmpDat++;
			}
			//force rgbReserved=0, to avoid problems with some WinXp bitmaps
			for (i = 0; i < bi.biClrUsed; i++)
				pPalette[i].rgbReserved=0;
		}
	}
	else
		pPalette = S_NULL;

	WidthBytes = BITMAP_WIDTHBYTES(bi.biWidth, 24);
	pBitmap = hai_MemAlloc(sizeof(*pBitmap)+WidthBytes*bi.biHeight+4);
	if (pBitmap == S_NULL)
		goto BMPDECODEERROR;

	HAI_SETHDLTYPE(pBitmap, HT_BITMAP);
	pBitmap->width     = (S_WORD)bi.biWidth;
	pBitmap->height    = (S_WORD)bi.biHeight;
	pBitmap->BitsPixel = 24;
	pBitmap->WidthBytes = (S_WORD)WidthBytes;
	pBitmap->lpImage = ((S_BYTE *)pBitmap)+sizeof(*pBitmap);
	
	pBmpDat = (S_BYTE*)pBmpData + bf.bfOffBits;
	WidthBytes = BITMAP_WIDTHBYTES(bi.biWidth, bi.biBitCount);
	switch (bi.biBitCount) {
		case 32 :
			if (bi.biCompression == BI_BITFIELDS || bi.biCompression == BI_RGB){
				for (i = 0; i < bi.biHeight; i++)
				{
					pDst = ((S_BYTE*)pBitmap->lpImage)+i*pBitmap->WidthBytes;
					if (bTopDownDib)
						pSrc = pBmpDat+i*WidthBytes;
					else
						pSrc = pBmpDat+(bi.biHeight-i-1)*WidthBytes;
					j = (bi.biWidth+7)>>3;
					switch (bi.biWidth % 8)
					{
					case 0:do{*pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 7:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 6:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 5:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 4:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 3:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 2:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
					case 1:     *pDst++ = *pSrc++;*pDst++ = *pSrc++;*pDst++ = *pSrc++;pSrc++;
							}while (--j);
					}
				}
			}
			else
				goto BMPDECODEERROR;
			break;
		case 24 :
			if (bi.biCompression == BI_RGB){
				if (bTopDownDib)
					memcpy(pBitmap->lpImage, pBmpDat, pBitmap->WidthBytes*bi.biHeight);
				else
				{
					pDst = pBitmap->lpImage;
					pSrc = pBmpDat+(bi.biHeight-1)*pBitmap->WidthBytes;
					for (i = 0; i < bi.biHeight; i++)
					{
						memcpy(pDst, pSrc, pBitmap->WidthBytes);
						pDst += pBitmap->WidthBytes;
						pSrc -= pBitmap->WidthBytes;
					}
				}
			}
			else
				goto BMPDECODEERROR;
			break;
		case 16 :
		{
			S_WORD rm, gm, bm;
			S_WORD c, rs=0, gs=0, bs=0;
			if (bi.biCompression == BI_BITFIELDS)
			{
				pDst = (S_BYTE*)pBmpData+14/*sizeof(BITMAPFILEHEADER)*/+SkipBytes;
				rm=(S_WORD)HAI_MAKEDWORD(pDst);
				gm=(S_WORD)HAI_MAKEDWORD(pDst+4);
				bm=(S_WORD)HAI_MAKEDWORD(pDst+8);
			} else {
				rm=0x1F; gm=0x3E0; bm=0x7C00; //RGB555
			}
			for (i=0;i<16;i++){
				if ((rm>>i)&0x01) rs++;
				if ((gm>>i)&0x01) gs++;
				if ((bm>>i)&0x01) bs++;
			}
			gs+=rs; bs+=gs; rs=8-rs; gs-=8; bs-=8;
			for (i = 0; i < bi.biHeight; i++)
			{
				pDst = ((S_BYTE*)pBitmap->lpImage)+i*pBitmap->WidthBytes;
				if (bTopDownDib)
					pSrc = pBmpDat+i*WidthBytes;
				else
					pSrc = pBmpDat+(bi.biHeight-i-1)*WidthBytes;
				j = (bi.biWidth+7)>>3;
				switch (bi.biWidth % 8)
				{
				case 0:do{c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 7:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 6:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 5:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 4:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 3:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 2:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
				case 1:     c=HAI_MAKEWORD(pSrc);pSrc+=2;*pDst++=(S_BYTE)((c & rm)<<rs);*pDst++=(S_BYTE)((c & gm)>>gs);*pDst++=(S_BYTE)((c & bm)>>bs);
						}while (--j);
				}
			}
			break;
		}
		case 8 :
		case 4 :
		case 1 :
		switch (bi.biCompression) 
		{
			case BI_RGB :
				_hai_ExtractBits841BI_RGB(pBitmap, &bi, pBmpDat, pPalette, bTopDownDib);
				break;
			case BI_RLE4 :
				_hai_ExtractBits841BI_RLE4(pBitmap, pBmpDat, pPalette, bTopDownDib);
				break;
			case BI_RLE8 :
				_hai_ExtractBits841BI_RLE8(pBitmap, pBmpDat, pPalette, bTopDownDib);
				break;
			default :								
				goto BMPDECODEERROR;
		}
	}

	if (pPalette)
		hai_MemFree(pPalette);
	return (SH_BITMAP)pBitmap;
BMPDECODEERROR:
	if (pPalette)
		hai_MemFree(pPalette);
	if (pBitmap)
		hai_MemFree(pBitmap);
	return S_NULL;
}

S_DWORD _hai_ReadBitmapFileHeader(S_BYTE *pBmpData, BITMAPFILEHEADER *pbf)
{
	if (pBmpData==S_NULL || pbf==S_NULL)
		return 0;
	
	pbf->bfType      = HAI_MAKEWORD(pBmpData+0); 
	pbf->bfSize      = HAI_MAKEDWORD(pBmpData+2); 
	pbf->bfReserved1 = HAI_MAKEWORD(pBmpData+6); 
	pbf->bfReserved2 = HAI_MAKEWORD(pBmpData+8); 
	pbf->bfOffBits   = HAI_MAKEDWORD(pBmpData+10); 

	if (pbf->bfType == 0x4D42) // "BM"
		return 14;
	return 0;	
}

S_DWORD _hai_ReadBitmapInfo(S_BYTE *pBmpData, BITMAPINFOHEADER *pbih)
{
	BITMAPCOREHEADER bc;
	
	if (pBmpData==S_NULL || pbih==S_NULL)
		return 0;
	
	pbih->biSize = HAI_MAKEDWORD(pBmpData);
	switch (pbih->biSize)
	{
	case 0x40: //sizeof(OS2_BMP_HEADER):
	case 0x28: //sizeof(BITMAPINFOHEADER):
		pbih->biSize          = HAI_MAKEDWORD(pBmpData+0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -