- UID
- 1
- 精华
- 积分
- 76361
- 威望
- 点
- 宅币
- 个
- 贡献
- 次
- 宅之契约
- 份
- 最后登录
- 1970-1-1
- 在线时间
- 小时
|
这应该被命名为libbmp。不知道各种开源的组织有没有人弄这个。我这个读取bmp文件的工具除了能读取BMP文件,还能将索引颜色或RLE压缩的BMP转换为真彩色或32位高彩色!要不然我为毛编写这个东西?
其实我写的这个东西目前只能读取位图,不能保存位图。如果要弄成支持保存位图的,我需要把颜色降级、抖动算法等都完成,目前我不需要这些功能。我需要的是把一个位图加载到内存然后丢给OpenGL。这个东西足够我玩了。
用法很简单,包含我的头文件,编译我的.c文件,然后使用我头文件导出的函数:LoadBMP,ConvToTrueColor,DestroyBMP。
其中LoadBMP函数负责把BMP位图原样加载到内存,不做任何转换。然后用ConvToTrueColor可以将其转换为24位或32位的位图。之后,调用DestroyBMP销毁内存中的位图。
大家可以使用GDI的StretchDIBits来在窗口上绘制位图,也可以用glTexImage加载转换后的真彩色位图。其中为了保证可移植性,我把BITMAPFILEHEADER和BITMAPINFOHEADER等结构体用自己的方式定义了(BitmapFileHeader、BitmapInfoHeader,把WORD、DWORD、LONG等替换成了uint16_t、uint32_t、int32_t等)。
废话不多说。上源码。
bmpfile.h- //=============================================================================
- //作者:0xAA55
- //网址:http://www.0xaa55.com
- //请保留原作者信息,否则视为侵权。
- //-----------------------------------------------------------------------------
- #ifndef _BMPFILE_HEADER_
- #define _BMPFILE_HEADER_
- #include<stdint.h>
- #pragma pack(push,1)
- //=============================================================================
- //结构:BitmapFileHeader
- //描述:位图文件头,BMP文件必须以此结构开头。
- //-----------------------------------------------------------------------------
- typedef struct
- {
- uint16_t bfType; //必须为BM
- uint32_t bfSize; //整个文件的尺寸
- uint16_t bfReserved1;//必须为0
- uint16_t bfReserved2;//必须为0
- uint32_t bfOffBits; //位图数据的偏移
- }BitmapFileHeader,*BitmapFileHeaderP;
- #define BF_BMP 0x4D42 //bfType的值
- //=============================================================================
- //结构:BitmapInfoHeader
- //描述:位图信息头,在BMP文件中紧接在BitmapFileHeader的后面。
- //-----------------------------------------------------------------------------
- typedef struct
- {
- uint32_t biSize; //位图信息头和调色板的总尺寸
- int32_t biWidth; //位图宽度
- int32_t biHeight; //位图高度
- uint16_t biPlanes; //位面数(必须为1,扯蛋的)
- uint16_t biBitCount; //颜色位数
- uint32_t biCompression; //压缩方式
- uint32_t biSizeImage; //位图部分尺寸
- int32_t biXPelsPerMeter;//宽度每米像素数(扯蛋的)
- int32_t biYPelsPerMeter;//高度每米像素数(扯蛋的)
- uint32_t biClrUsed; //使用的颜色数(扯蛋的)
- uint32_t biClrImportant; //重要的颜色数(扯蛋的)
- }BitmapInfoHeader,*BitmapInfoHeaderP;
- //=============================================================================
- //枚举:BiCompressionType
- //描述:biCompression使用的数值。
- //-----------------------------------------------------------------------------
- typedef enum
- {
- Bi_RGB =0, //无压缩
- Bi_RLE8 =1, //RLE8
- Bi_RLE4 =2, //RLE4
- Bi_BitFields=3 //位域,也就是用“调色板”的位置来存储位域信息
- }BiCompressionType,*BiCompressionTypeP;
- typedef enum
- {
- BitF_R =0, //红色的位
- BitF_G =1, //绿色的位
- BitF_B =2, //蓝色的位
- BitF_X =3 //透明通道的位
- }BitFIndex,*BitFIndexP;
- //=============================================================================
- //结构:RGBQuad
- //描述:四个字节描述红绿蓝的结构,通常用于描述调色板
- //-----------------------------------------------------------------------------
- typedef struct
- {
- uint8_t B;
- uint8_t G;
- uint8_t R;
- uint8_t X;
- }RGBQuad,*RGBQuadP;
- //=============================================================================
- //结构:RGBTriple
- //描述:三个字节描述红绿蓝的结构,通常用于读取24位BMP
- //-----------------------------------------------------------------------------
- typedef struct
- {
- uint8_t B;
- uint8_t G;
- uint8_t R;
- }RGBTriple,*RGBTripleP;
- typedef enum
- {
- TC_AutoFit =0, //如果读取的位图文件低于24位则转换为24位,否则转换为32位
- TC_24 =24,//读取的位图文件强制转换为24位
- TC_32 =32 //读取的位图文件强制转换为32位
- }TrueColorBits,*TrueColorBitsP;
- //=============================================================================
- //结构:BitmapPicture
- //描述:用于读取BMP文件的结构体
- //-----------------------------------------------------------------------------
- typedef struct
- {
- BitmapFileHeader BMFH; //位图文件头
- BitmapInfoHeader BMIF; //位图信息头
- union
- {
- RGBQuad Palette[256]; //调色板
- uint32_t BitFields[4]; //位域
- }AdditionalData;//额外数据
- size_t Width; //宽度
- size_t Height; //高度
- size_t cbPitch; //每行字节数
- void *pBits; //位图数据
- size_t cbBits; //位图数据大小
- }BitmapPicture,*BitmapPictureP;
- #pragma pack(pop)
- //=============================================================================
- //函数:LoadBMP
- //描述:读取BMP文件,建立BitmapPicture结构体
- //-----------------------------------------------------------------------------
- BitmapPictureP LoadBMP(char*szFilePath);
- //=============================================================================
- //函数:ConvToTrueColor
- //描述:将一个已读取的BMP文件转换为真彩色,返回新的位图。
- //-----------------------------------------------------------------------------
- BitmapPictureP ConvToTrueColor(BitmapPictureP pOrgBMP,TrueColorBits TCBits);
- //=============================================================================
- //函数:DestroyBMP
- //描述:销毁BitmapPicture结构体,释放内存。
- //-----------------------------------------------------------------------------
- void DestroyBMP(BitmapPictureP pBMP);
- #endif // !_BMPFILE_HEADER_
复制代码 bmpfile.c- //=============================================================================
- //作者:0xAA55
- //网址:http://www.0xaa55.com
- //请保留原作者信息,否则视为侵权。
- //-----------------------------------------------------------------------------
- #include"bmpfile.h"
- #include<stdio.h>
- #include<malloc.h>
- #include<memory.h>
- typedef int shift_t;
- #define CalcPitch(w,b) ((((w)*(b)-1)/32+1)*4)
- //=============================================================================
- //函数:LoadBMP
- //描述:读取BMP文件,建立BitmapPicture结构体
- //-----------------------------------------------------------------------------
- BitmapPictureP LoadBMP(char*szFilePath)
- {
- FILE*fp=NULL;
- BitmapPictureP pBMP;
-
- //=========================================================================
- //给要返回的结构体分配内存。
- pBMP=(BitmapPictureP)malloc(sizeof(BitmapPicture));
- if(!pBMP)
- {
- //内存不足
- goto ErrorHandler;
- }
- memset(pBMP,0,sizeof(BitmapPicture));
- //=========================================================================
- //打开文件
- fp=fopen(szFilePath,"rb");
- if(!fp)
- goto ErrorHandler;
- //=========================================================================
- //读取文件头
- if(fread(&(pBMP->BMFH),
- 1,sizeof(pBMP->BMFH),fp)!=sizeof(pBMP->BMFH))
- {
- //读取失败
- goto ErrorHandler;
- }
- //=========================================================================
- //判断文件头的结构正确性
- if( pBMP->BMFH.bfType!=BF_BMP||
- pBMP->BMFH.bfReserved1 ||
- pBMP->BMFH.bfReserved2)
- {
- //文件头格式错误
- goto ErrorHandler;
- }
- //=========================================================================
- //读取信息头
- if(fread(&(pBMP->BMIF),
- 1,sizeof(pBMP->BMIF),fp)!=sizeof(pBMP->BMIF))
- {
- //读取失败
- goto ErrorHandler;
- }
- //=========================================================================
- //判断信息头的结构正确性
- if( pBMP->BMIF.biWidth<=0//宽度必须大于0
- ||
- !(pBMP->BMIF.biHeight)//高度必须不为0(顶到下型时,值为负)
- ||
- //必须只能是这么几种压缩类型。
- (pBMP->BMIF.biCompression!=Bi_RGB &&
- pBMP->BMIF.biCompression!=Bi_RLE8 &&
- pBMP->BMIF.biCompression!=Bi_RLE4 &&
- pBMP->BMIF.biCompression!=Bi_BitFields)
- ||
- //如果是压缩位图,则必须是底到上型,并且指定大小
- ((pBMP->BMIF.biCompression==Bi_RLE8 ||
- pBMP->BMIF.biCompression==Bi_RLE4) &&
- (pBMP->BMIF.biHeight<0 ||
- !pBMP->BMIF.biSizeImage))
- ||
- //RLE8只能压缩8位BMP
- (pBMP->BMIF.biCompression==Bi_RLE8 && pBMP->BMIF.biBitCount!=8)
- ||
- //RLE4只能压缩4位BMP
- (pBMP->BMIF.biCompression==Bi_RLE4 && pBMP->BMIF.biBitCount!=4))
- {
- //文件头格式错误
- goto ErrorHandler;
- }
-
- pBMP->Width=pBMP->BMIF.biWidth;
- pBMP->Height=pBMP->BMIF.biHeight>=0?
- pBMP->BMIF.biHeight:-pBMP->BMIF.biHeight;
- //=========================================================================
- //读取调色板
- if(pBMP->BMIF.biBitCount<=8 && pBMP->BMIF.biCompression!=Bi_BitFields)
- {
- size_t NbPal=pBMP->BMIF.biClrUsed;
- if(!NbPal)
- NbPal=(size_t)1<<pBMP->BMIF.biBitCount;
- fread(pBMP->AdditionalData.Palette,
- 1,sizeof(RGBQuad)*NbPal,fp);
- }
- //或者读取位域
- else if(pBMP->BMIF.biCompression==Bi_BitFields)
- {
- fread(pBMP->AdditionalData.BitFields,
- 1,sizeof(pBMP->AdditionalData.BitFields),fp);
- }
- //=========================================================================
- //计算位图数据的大小
- if( pBMP->BMIF.biCompression==Bi_RGB ||
- pBMP->BMIF.biCompression==Bi_BitFields)
- {
- pBMP->cbPitch=//每行字节数4字节对齐
- CalcPitch(pBMP->Width,pBMP->BMIF.biBitCount);
- pBMP->cbBits=pBMP->cbPitch*pBMP->Height;
- }
- else
- pBMP->cbBits=pBMP->BMIF.biSizeImage;
-
- //=========================================================================
- //读取位图数据
- pBMP->pBits=malloc(pBMP->cbBits);
- if(!pBMP->pBits)
- {
- //内存不足
- goto ErrorHandler;
- }
- if(fread(pBMP->pBits,1,pBMP->cbBits,fp)!=pBMP->cbBits)
- {
- //读取失败
- goto ErrorHandler;
- }
-
- //读取完成
- fclose(fp);
- return pBMP;
- ErrorHandler:
- if(fp)
- fclose(fp);
- if(pBMP)
- DestroyBMP(pBMP);
- return NULL;
- }
- //=============================================================================
- //函数:GetI32Shift
- //描述:取得一个32位数右边的0的数量
- //-----------------------------------------------------------------------------
- static
- shift_t GetI32Shift(uint32_t Val)
- {
- shift_t NbShift=0;
- if(!Val)
- return 0;
- while(!(Val&1))
- {
- NbShift++;
- Val>>=1;
- }
- return NbShift;
- }
- //=============================================================================
- //函数:GetI32Bits
- //描述:取得一个32位数最左边的1的位置
- //-----------------------------------------------------------------------------
- static
- shift_t GetI32Bits(uint32_t Val)
- {
- shift_t NbBits=0;
- while(Val)
- {
- NbBits++;
- Val>>=1;
- }
- return NbBits;
- }
- //=============================================================================
- //函数:ConvToTrueColor
- //描述:将一个已读取的BMP文件转换为真彩色,返回新的位图。
- //-----------------------------------------------------------------------------
- BitmapPictureP ConvToTrueColor(BitmapPictureP pOrgBMP,TrueColorBits TCBits)
- {
- BitmapPictureP pBMP;
- size_t x,y;
- uint8_t*pOrgBitPtr;
- uint8_t*pOrgLinePtr;
- uint8_t*pBitPtr;
- uint8_t*pLinePtr;
- if( TCBits!=TC_24 &&
- TCBits!=TC_32 &&
- TCBits!=TC_AutoFit)
- {
- //参数不正确
- return NULL;
- }
-
- //=========================================================================
- //给要返回的结构体分配内存。
- pBMP=(BitmapPictureP)malloc(sizeof(BitmapPicture));
- if(!pBMP)
- {
- //内存不足
- goto ErrorHandler;
- }
- memset(pBMP,0,sizeof(BitmapPicture));
- //=========================================================================
- //补充BMP信息
- //填写BMP文件头
- pBMP->BMFH.bfType=BF_BMP;
- pBMP->BMFH.bfOffBits=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader);
- //填写BMP信息头
- pBMP->BMIF.biSize=sizeof(BitmapInfoHeader);
- pBMP->BMIF.biWidth=pOrgBMP->BMIF.biWidth;
- pBMP->BMIF.biHeight=pOrgBMP->BMIF.biHeight;
- pBMP->BMIF.biPlanes=pOrgBMP->BMIF.biPlanes;
- if(TCBits==TC_AutoFit)
- TCBits=pOrgBMP->BMIF.biBitCount>24?TC_32:TC_24;
- if(TCBits==TC_32)
- pBMP->BMIF.biBitCount=32;
- else if(TCBits==TC_24)
- pBMP->BMIF.biBitCount=24;
- pBMP->BMIF.biCompression=Bi_RGB;
- pBMP->BMIF.biSizeImage=0;
- pBMP->BMIF.biXPelsPerMeter=pOrgBMP->BMIF.biXPelsPerMeter;
- pBMP->BMIF.biYPelsPerMeter=pOrgBMP->BMIF.biYPelsPerMeter;
- pBMP->BMIF.biClrUsed=0;
- pBMP->BMIF.biClrImportant=0;
- //绝对值尺寸
- pBMP->Width=pOrgBMP->Width;
- pBMP->Height=pOrgBMP->Height;
-
- //计算位图总尺寸
- pBMP->cbPitch=CalcPitch(pBMP->BMIF.biWidth,pBMP->BMIF.biBitCount);
- pBMP->cbBits=pBMP->Height*pBMP->cbPitch;
- pBMP->pBits=malloc(pBMP->cbBits);
- if(!pBMP->pBits)
- {
- //内存不足
- goto ErrorHandler;
- }
- memset(pBMP->pBits,0,pBMP->cbBits);
- pBMP->BMFH.bfSize=(uint32_t)(pBMP->BMFH.bfOffBits+pBMP->cbBits);
- //=========================================================================
- //开始转换过程
- //判断压缩类型
- if(pOrgBMP->BMIF.biCompression==Bi_RGB)//无压缩
- {
- pOrgLinePtr=(uint8_t*)(pOrgBMP->pBits);
- pLinePtr=(uint8_t*)(pBMP->pBits);
- //=====================================================================
- //2、4、16色位图的处理方式一致。
- if( pOrgBMP->BMIF.biBitCount==1 || //双色位图(通常为黑白)
- pOrgBMP->BMIF.biBitCount==2 || //四色位图(几乎见不到)
- pOrgBMP->BMIF.biBitCount==4) //16色位图
- {
- uint8_t LastByte;
- shift_t PixelsLast=0;
- size_t PalIndex=0;
- shift_t PixelsPerBytes;
- PixelsPerBytes=8/pOrgBMP->BMIF.biBitCount;//每字节像素数
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pOrgBitPtr=pOrgLinePtr;
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每个字节
- {
- if(!PixelsLast)//如果读完这个字节
- {
- PixelsLast=PixelsPerBytes;
- LastByte=*pOrgBitPtr++;//读取新的字节
- }
- PalIndex=LastByte>>(8-pOrgBMP->BMIF.biBitCount);//查颜色表
- LastByte<<=pOrgBMP->BMIF.biBitCount;//上次读取的字节
- PixelsLast--;//能取得的像素数
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[PalIndex].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[PalIndex].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[PalIndex].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[PalIndex].X;
- }
- pOrgLinePtr+=pOrgBMP->cbPitch;//转到下一行
- pLinePtr+=pBMP->cbPitch;
- PixelsLast=0;
- }
- }
- //=====================================================================
- //256色位图,一个像素一个字节
- else if(pOrgBMP->BMIF.biBitCount==8)
- {
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pOrgBitPtr=pOrgLinePtr;
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- uint8_t Pix8=*pOrgBitPtr++;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].X;
- }
- pOrgLinePtr+=pOrgBMP->cbPitch;//转到下一行
- pLinePtr+=pBMP->cbPitch;
- }
- }
- //=====================================================================
- //没有位域定义时,16位BMP为1:5:5:5
- else if(pOrgBMP->BMIF.biBitCount==16)
- {
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pOrgBitPtr=pOrgLinePtr;
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- uint16_t Pix16=*(uint16_t*)pOrgBitPtr;
- *pBitPtr++=(uint8_t)(((Pix16&0x001F)<<3)|((Pix16&0x001F)>>2));//同时填充高位和低位
- *pBitPtr++=(uint8_t)(((Pix16&0x03E0)>>2)|((Pix16&0x03E0)>>7));
- *pBitPtr++=(uint8_t)(((Pix16&0x7C00)>>7)|((Pix16&0x7C00)>>12));
- if(TCBits==TC_32)
- *pBitPtr++=(Pix16&0x80)?0xFF:0;
- pOrgBitPtr+=2;
- }
- pOrgLinePtr+=pOrgBMP->cbPitch;
- pLinePtr+=pBMP->cbPitch;
- }
- }
- //=====================================================================
- //24位真彩色位图
- else if(pOrgBMP->BMIF.biBitCount==24)
- {
- if(TCBits==TC_24)
- memcpy(pBMP->pBits,pOrgBMP->pBits,pOrgBMP->cbBits);//无须转换
- else//转成32位
- {
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pOrgBitPtr=pOrgLinePtr;
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- *pBitPtr++=*pOrgBitPtr++;
- *pBitPtr++=*pOrgBitPtr++;
- *pBitPtr++=*pOrgBitPtr++;
- *pBitPtr++=0;
- }
- pOrgLinePtr+=pOrgBMP->cbPitch;
- pLinePtr+=pBMP->cbPitch;
- }
- }
- }
- //=====================================================================
- //32位高彩色位图,比24位多了个透明度通道。
- else if(pOrgBMP->BMIF.biBitCount==32)
- {
- if(TCBits==TC_24)//降级
- {
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pOrgBitPtr=pOrgLinePtr;
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- *pBitPtr++=*pOrgBitPtr++;
- *pBitPtr++=*pOrgBitPtr++;
- *pBitPtr++=*pOrgBitPtr++;
- pOrgBitPtr++;
- }
- pOrgLinePtr+=pOrgBMP->cbPitch;
- pLinePtr+=pBMP->cbPitch;
- }
- }
- else
- memcpy(pBMP->pBits,pOrgBMP->pBits,pOrgBMP->cbBits);//无须转换
- }
- else
- {
- //不认识的BMP格式
- goto ErrorHandler;
- }
- return pBMP;
- }
- //=========================================================================
- //RLE8压缩类型,Run-Length Encode
- else if(pOrgBMP->BMIF.biCompression==Bi_RLE8)
- {
- size_t cbPixel=(pBMP->BMIF.biBitCount-1)/8+1;//输出的每像素字节数
- size_t RightBound;//右边界
-
- //没有画过的像素都是索引0的颜色。
- pLinePtr=(uint8_t*)(pBMP->pBits);
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].X;
- }
- pLinePtr+=pBMP->cbPitch;
- }
- //然后开始准备绘图
- pOrgBitPtr=(uint8_t*)(pOrgBMP->pBits);
- pLinePtr=(uint8_t*)(pBMP->pBits);
- RightBound=(size_t)(pOrgBMP->pBits)+pOrgBMP->cbBits;
- pBitPtr=pLinePtr;
- while((size_t)pOrgBitPtr<RightBound)
- {
- if(*pOrgBitPtr)//单个像素复制模式
- {
- uint8_t NbNextPix=*pOrgBitPtr++;//要复制的次数
- uint8_t Pix8=*pOrgBitPtr++;//像素值
- while(NbNextPix--)
- {
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].X;
- }
- }
- else//转义字节
- {
- pOrgBitPtr++;
- if(*pOrgBitPtr==0)//转义0:行结尾
- {
- pOrgBitPtr++;
- pLinePtr+=pBMP->cbPitch;
- pBitPtr=pLinePtr;
- }
- else if(*pOrgBitPtr==1)//转义1:位图结尾
- break;
- else if(*pOrgBitPtr==2)//转义2:下一个像素的偏移
- {
- pBitPtr+=cbPixel**++pOrgBitPtr;//放荡不羁的代码只为好玩
- pBitPtr+=*++pOrgBitPtr*pBMP->cbPitch;
- pLinePtr+=*pOrgBitPtr++*pBMP->cbPitch;
- }
- else//转义3-0xFF:绝对模式
- {
- uint8_t NbCopy=*pOrgBitPtr++;//需要复制的像素数
- uint8_t NbCopied=0;//已经复制的像素数
- while(NbCopied++<NbCopy)
- {
- uint8_t Pix8=*pOrgBitPtr++;//像素值
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8].X;
- }
- pOrgBitPtr+=NbCopy&1;//要复制的像素数据是以字对齐的
- }
- }
- }
- return pBMP;
- }
- //=========================================================================
- //RLE8压缩类型
- else if(pOrgBMP->BMIF.biCompression==Bi_RLE4)
- {
- size_t cbPixel=(pBMP->BMIF.biBitCount-1)/8+1;
- size_t RightBound;
-
- //没有画过的像素都是索引0的颜色。
- pLinePtr=(uint8_t*)(pBMP->pBits);
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[0].X;
- }
- pLinePtr+=pBMP->cbPitch;
- }
- //然后开始准备绘图
- pOrgBitPtr=(uint8_t*)(pOrgBMP->pBits);
- pLinePtr=(uint8_t*)(pBMP->pBits);
- RightBound=(size_t)(pOrgBMP->pBits)+pOrgBMP->cbBits;
- pBitPtr=pLinePtr;
- while((size_t)pOrgBitPtr<RightBound)
- {
- if(*pOrgBitPtr)//单个像素复制模式
- {
- uint8_t NbNextPix=*pOrgBitPtr++;//要复制的次数
- uint8_t Pix8=*pOrgBitPtr++;//像素值
- while(NbNextPix--)
- {
- //RLE4模式下,一个字节两个像素交替出现。
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].X;
- if(!NbNextPix--)
- break;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].X;
- }
- }
- else//转义字节
- {
- pOrgBitPtr++;
- if(*pOrgBitPtr==0)//转义0:行结尾
- {
- pOrgBitPtr++;
- pLinePtr+=pBMP->cbPitch;
- pBitPtr=pLinePtr;
- }
- else if(*pOrgBitPtr==1)//转义1:位图结尾
- break;
- else if(*pOrgBitPtr==2)//转义2:下一个像素的偏移
- {
- pBitPtr+=cbPixel**++pOrgBitPtr;
- pBitPtr+=*++pOrgBitPtr*pBMP->cbPitch;
- pLinePtr+=*pOrgBitPtr++*pBMP->cbPitch;
- }
- else//转义3-0xFF:绝对模式
- {
- uint8_t NbCopy=*pOrgBitPtr++;//需要复制的像素数
- uint8_t NbCopied=0;//已经复制的像素数
- while(NbCopied++<NbCopy)
- {
- uint8_t Pix8=*pOrgBitPtr++;//像素值
- //RLE4模式下,一个字节两个像素交替出现。
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8>>4].X;
- if(!(NbCopied++<NbCopy))
- break;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].B;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].G;
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].R;
- if(TCBits==TC_32)
- *pBitPtr++=pOrgBMP->AdditionalData.Palette[Pix8&0x0F].X;
- }
- pOrgBitPtr+=(NbCopy&3)?1:0;//要复制的像素数据是以字对齐的
- }
- }
- }
- return pBMP;
- }
- //=========================================================================
- //位域,占用调色板的位置,通常用在16位颜色上表示每个位的意义。
- else if(pOrgBMP->BMIF.biCompression==Bi_BitFields)
- {
- size_t cbPixel=(pOrgBMP->BMIF.biBitCount-1)/8+1;//每个像素字节数
- uint32_t PixVal;//像素值
- //每种颜色的位域低位(S=Shift)
- shift_t BS=GetI32Shift(pOrgBMP->AdditionalData.BitFields[BitF_B]);
- shift_t GS=GetI32Shift(pOrgBMP->AdditionalData.BitFields[BitF_G]);
- shift_t RS=GetI32Shift(pOrgBMP->AdditionalData.BitFields[BitF_R]);
- shift_t XS=GetI32Shift(pOrgBMP->AdditionalData.BitFields[BitF_X]);
- //每种颜色的位域位数
- shift_t BBits=GetI32Bits(pOrgBMP->AdditionalData.BitFields[BitF_B])-BS;
- shift_t GBits=GetI32Bits(pOrgBMP->AdditionalData.BitFields[BitF_G])-GS;
- shift_t RBits=GetI32Bits(pOrgBMP->AdditionalData.BitFields[BitF_R])-RS;
- shift_t XBits=GetI32Bits(pOrgBMP->AdditionalData.BitFields[BitF_X])-XS;
-
- pOrgLinePtr=(uint8_t*)(pOrgBMP->pBits);
- pLinePtr=(uint8_t*)(pBMP->pBits);
- for(y=0;y<pBMP->Height;y++)//遍历每一行
- {
- pOrgBitPtr=pOrgLinePtr;
- pBitPtr=pLinePtr;
- for(x=0;x<pBMP->Width;x++)//遍历每一列
- {
- int Fill;
- uint8_t XVal,RVal,GVal,BVal;
- PixVal=*(uint32_t*)pOrgBitPtr;//取得像素值
- pOrgBitPtr+=cbPixel;//转到下一个像素
-
- //取得当前像素值每个域的颜色值
- BVal=(PixVal & pOrgBMP->AdditionalData.BitFields[BitF_B])>>BS;
- GVal=(PixVal & pOrgBMP->AdditionalData.BitFields[BitF_G])>>GS;
- RVal=(PixVal & pOrgBMP->AdditionalData.BitFields[BitF_R])>>RS;
- XVal=(PixVal & pOrgBMP->AdditionalData.BitFields[BitF_X])>>RS;
- //填充蓝色值
- *pBitPtr=0;Fill=8;
- while(Fill>0)
- {
- Fill-=BBits;
- *pBitPtr|=BVal<<Fill;
- }
- pBitPtr++;
- //填充绿色值
- *pBitPtr=0;Fill=8;
- while(Fill>0)
- {
- Fill-=GBits;
- *pBitPtr|=GVal<<Fill;
- }
- pBitPtr++;
- //填充红色值
- *pBitPtr=0;Fill=8;
- while(Fill>0)
- {
- Fill-=RBits;
- *pBitPtr|=RVal<<Fill;
- }
- pBitPtr++;
- //如果要输出32位位图,填充透明色值。
- if(TCBits==TC_32)
- {
- *pBitPtr=0;
- if(XBits)
- {
- Fill=8;
- while(Fill>0)
- {
- Fill-=XBits;
- *pBitPtr|=XVal<<Fill;
- }
- }
- pBitPtr++;
- }
- }
- pOrgLinePtr+=pOrgBMP->cbPitch;//转到下一行
- pLinePtr+=pBMP->cbPitch;
- }
- return pBMP;
- }
- //必须只能是这几种压缩类型,否则报错:不支持的压缩类型
- ErrorHandler:
- if(pBMP)
- DestroyBMP(pBMP);
- return NULL;
- }
- //=============================================================================
- //函数:DestroyBMP
- //描述:销毁BitmapPicture结构体,释放内存。
- //-----------------------------------------------------------------------------
- void DestroyBMP(BitmapPictureP pBMP)
- {
- if(pBMP->pBits)
- free(pBMP->pBits);
- free(pBMP);
- }
复制代码 基本所有的BMP都能读取了,无论是1,2,4,8,16,24,32,还是带位域的X1R5G5B5、R5G6B5、X4R4G4B4、X8R8G8B8等都能读取。无论是RLE4还是RLE8也都能读取。脱离Windows可以使用。
BIN:
ReadBMP.exe
(72 KB, 下载次数: 2)
SRC:
ReadBMP.7z
(1.73 MB, 下载次数: 10)
|
|