处理不含调色板的BMP格式图片(24位转16位)
一、BMP图片格式头
struct Bmp_Fileheader_ST //文件头,长度为14Byte
{
unsigned short bfType; //'BM'格式 0x4D42
unsigned long bfSize; //文件大小
unsigned short bfReserved1; //保留位为0
unsigned short bfReserved2; //保留位为0
unsigned long bfOffBits; //文件头到像素数据的偏移
};
struct Bmp_Infoheader_ST //文件信息头,长度为40Byte
{
unsigned long biSize; //此结构大小
unsigned long biWidth; //图像宽度
unsigned long biHeight; //图像高度
unsigned short biPlanes;
unsigned short biBitCount; //说明比特数/像素数,文章标题中所写的24位
unsigned long biCompression;
unsigned long biSizeImage;
unsigned long biXPelsPerMeter;
unsigned long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
};
二、读取BMP图像信息
1.读取文件头与信息头
int fp = open("图片路径", O_RDONLY); //打开BMP图像
struct Bmp_Fileheader_ST head; //文件头结构体变量
struct Bmp_Infoheader_ST info;//信息头结构体变量
//这里建议先读取2字节文件类型(为了方便接着读取文件头时的字节对齐问题)
unsigned short bfType; //先读取’BM‘
FS_FRead(&bfType, sizeof(unsigned short), 1, fp);
read(fp, &head, sizeof(head)); //读取文件头
read(fp, &info, sizeof(info)); //读取文件信息
2.读取源RGB数据存入源数据内存
int rgb_size = head.bfSize -sizeof(unsigned short) - sizeof(head) - sizeof(info); //源rgb数据大小
unsigned char *src_buf;
//为了方便接来下的24位数据转成16位,申请8位大小的内存来存放一个'r'/'g'/'b'的数据
src_buf = (unsigned char*)malloc(rgb_size * sizeof(char)); //读取rgb原始数据
read(fp, src_buf, rgb_size);
三、源24位RGB数据转16位
unsigned short *dst_buf;
//申请16位大小的内存刚好存放处理后的rgb数据(dst_buf[0]就为转换成功后的第一个rgb数据)
dst_buf = (unsigned short*)malloc((rgb_size / 3) * sizeof(short));
int temp[3];
unsigned long dst_subscript = 0;
for(unsigned long src_subscript = 0; src_subscript < rgb_size; src_subscript += 3) //24位转16位
{
temp[0] = src_buf[src_subscript] >> 3; //'r''b'都保留高5位
temp[1] = src_buf[src_subscript + 1] >> 2; //'g'保留高6位
temp[2] = src_buf[src_subscript + 2] >> 3;
//经过验证,下面两种运算都能正确转换为16位rgb数据(有人说不能用加运算,大家可以去测试,我测试是成功的)
//dst_buf[dst_subscript] = (temp[0] << 11) | (temp[1] << 5) | temp[2] ;
dst_buf[dst_subscript] = (temp[0] << 11) + (temp[1] << 5) + temp[2] ;
dst_subscript ++;
}
最后别忘记释放资源…close(fp); free(src_buf); free(dst_buf);