linux上存储和读取bmp图像文件

将图像数据写bmp文件

数字图像在外存储器设备中的存储形式是图像文件,图像必须按照某个已知的、公认的数据存储顺序和结构进行存储,才能使不同的程序对图像文件顺利进行打开或存盘操作,实现数据共享。图像数据在文件中的存储顺序和结构称为图像文件格式。

BMP文件是Windows操作系统所推荐和支持的图像文件格式,是一种将内存或显示器的图像数据不经过压缩而直接按位存盘的文件格式,所以称为位图(bitmap)文件,因其文件扩展名为BMP,故称为BMP文件格式,简称BMP文件。

BMP文件总体上由4部分组成,分别是位图文件头、位图信息头、调色板和图像数据:
位图文件头(bitmap-file header)

位图信息头(bitmap-information header)

彩色表/调色板(color table)

位图数据(bitmap-data)

 

1)位图文件头(bitmap-file header)包含了图像类型、图像大小、图像数据存放地址和两个保留未使用的字段。

typedef struct tagBITMAPFILEHEADER { 
WORD    bfType; //位图类别,不同操作系统不同,windows下为’BM’
DWORD   bfSize; //图像文件的大小(包括头+数据)
WORD    bfReserved1; //保留,为0
WORD    bfReserved2; //保留,为0
DWORD   bfOffBits; //位图数据的地址
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

2)位图信息头(bitmap-information header)包含了位图信息头的大小、图像的宽高、图像的色深、压缩说明图像数据的大小和其他一些参数。

typedef struct tagBITMAPINFOHEADER{ 
DWORD      biSize;  //本结构大小,根据操作系统不同而设置,windows上为40字节
LONG        biWidth;  //图像宽度
LONG        biHeight;  //图像高度
WORD       biPlanes;  //必须为1
WORD       biBitCount;  //BMP图像的色深,即一个像素用多少位表示
DWORD      biCompression;  //压缩方法,0表示不压缩
DWORD      biSizeImage;  //BMP图像数据大小,必须是4的倍数
LONG        biXPelsPerMeter;  //水平分辨率,单位像素/m
LONG        biYPelsPerMeter;  //垂直分辨率,单位像素/m
DWORD      biClrUsed;  //BMP图像使用的颜色,0表示使用全部颜色,对于256色位图来说,此值为256
DWORD      biClrImportant; //重要的颜色值,此值为0时,表示所有颜色都重要,对于使用调色板的BMP图像来说,当显卡不能够显示所有颜色时,此值将辅助驱动程序显示颜色。
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

3. 彩色表/调色板(color table)是单色、16色和256色图像文件所特有的,相对应的调色板大小是2、16和256,调色板以4字节为单位,每4个字节存放一个颜色值,图像 的数据是指向调色板的索引。可以将调色板想象成一个数组,每个数组元素的大小为4字节。


typedef struct tagRGBQUAD { 
BYTE    rgbBlue; 
BYTE    rgbGreen; 
BYTE    rgbRed; 
BYTE    rgbReserved; 
} RGBQUAD;

实现代码:以上是一个调色板单个元素的结构体。

struct BITMAPFILEHEADER bmfh; //bmp文件头
struct BITMAPINFOHEADER bmih; //
unsigned short wWidth, wHeight;//图像的分辨率,需要预先设置

snprintf(filename, 127, "test.bmp");
int fd = open(filename, O_WRONLY|O_CREAT, 0640);
if(-1 == fd){
    printf("open %s failure, errno %d\n", filename, errno);
    return;
}

size_t imageBuffSize= (((size_t)wWidth) * ((size_t)wHeight)) << 2;
//设置BMP文件头
bmfh.bfType = 0x4D42;//'BM'
bmfh.bfSize = sizeof(struct BITMAPFILEHEADER) + sizeof(struct BITMAPINFOHEADER) + imageBuffSize;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(struct BITMAPFILEHEADER) + sizeof(struct BITMAPINFOHEADER);
//设置BMP信息头
bmih.biSize = 0U | sizeof(struct BITMAPINFOHEADER);
bmih.biWidth = wWidth;
bmih.biHeight = wHeight;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = 0;
bmih.biSizeImage = 0U | imageBuffSize;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
//写文件
write(fd, &bmfh, sizeof(struct BITMAPFILEHEADER));
write( fd, &bmih, sizeof(struct BITMAPINFOHEADER));
write(fd, shmaddr + 128, count);
//完成
fsync(fd);
close(fd);

以上就完成了bmp文件的存储。

相应的我们可以对一个bmp文件,获取图像数据,存储到buff中:

struct BITMAPFILEHEADER bmfh; //bmp文件头
struct BITMAPINFOHEADER bmih; //bmp信息头
unsigned short wWidth, wHeight;


snprintf(filename, 127, "test.bmp");
int fd = open(filename, O_RDONLY, 0640);
if(-1 == fd){
    printf("open %s failure, errno %d\n", filename, errno);
    return;
}

size_t ret = read(fd, &bmfh, sizeof(bmfh));
if(ret < 0){
    printf(“failed to read data from bmp file, errno:%d\n”, errno);
    return;
}

ret = read(fd, &bmih, sizeof(bmih));
if(ret < 0){
    printf(“failed to read data from bmp file, errno:%d\n”, errno);
    return;
}

if(0x4D42 != bmih.bfType ){
    printf(“cur file is not bmp file.”);
    return;
}


wWidth = bmih.biWidth;
wHeight= bmih.biHeight;
int imgDataSize = wWidth*wHeight*4;
char *imgData = (char*)calloc(imgDataSize , sizeof(char));
if(NULL == imgData){
    printf(“failed to calloc buff, errno:%d”, errno);
    return;
}

ret = read(fd, imgData, imgDataSize);
if(ret < 0){
    printf(“failed to read img data, errno:%d”, errno);
    return;
}
close(fd);
free(imgData);

 

你可能感兴趣的:(linux)