BMP图像格式
BMP图像格式位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,占用的空间也比较大,BMP格式特点r如下:
- 图形颜色深度 BitsPerPixel 可以选择为1bit,4bit,8bit,24bit
- 图像的扫描方式是按从左到右、从下到上的顺序
- 图形可以选择支持调色板,即采用颜色索引的方式
非压缩格式的BMP包含一个简单的格式头文件共54字节,包含BMP图像的宽、高、压缩方法,以及定义颜色等信息
以下面的图为例:

文件头的信息如下:

BMP文件头信息含义如下:

示例代码(读取和写入文件头):
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <jpeglib.h>
#include "utils.h"
typedef struct __attribute__ ((__packed__)) tagBITMAPFILEHEADER
{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
}BITMAPFILEHEADER;
typedef struct __attribute__ ((__packed__)) tagBITMAPINFOHEADER
{
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
unsigned int biXPelsPerMeter;
unsigned int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}BITMAPINFOHEADER;
typedef struct __attribute__ ((__packed__)) tagRGBPLATE
{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
unsigned char rgbReserved;
}RGBPLATE;
unsigned char* load_bmp(char* file_name, int *width, int *height)
{
BITMAPFILEHEADER file_header;
BITMAPINFOHEADER info_header;
int h, w, i, j, offset, bpp, stride;
FILE *file;
unsigned char* buf = NULL, *buf_ptr;
file=fopen(file_name,"rb");
if (!file){
printf("ERROR: cannot open file %s\n", file_name);
return NULL;
}
fread(&file_header,1,sizeof(BITMAPFILEHEADER), file);
fread(&info_header,1,sizeof(BITMAPINFOHEADER), file);
fseek(file, file_header.bfOffBits, SEEK_SET);
printf("bmp bfOffBits:%d biBitCount:%d biWidth:%d biHeight:%d\n",
file_header.bfOffBits, info_header.biBitCount, info_header.biWidth, info_header.biHeight);
w=info_header.biWidth;
h=info_header.biHeight;
bpp=info_header.biBitCount/8;
buf = (unsigned char*)malloc(w*h*bpp);
stride = w*bpp;
//注意bmp 是从下到上读取的
buf_ptr = buf + stride*(h-1);
for(j=0; j<h; j++){
for(i=0; i<w; i++){
fread(buf_ptr+i*bpp+2, 1, 1, file);
fread(buf_ptr+i*bpp+1, 1, 1, file);
fread(buf_ptr+i*bpp+0, 1, 1, file);
}
buf_ptr -= stride;
}
fclose(file);
if(width!=NULL)
*width = w;
if(height!=NULL)
*height = h;
return buf;
}
void store_bmp(char* file_name, unsigned char* raw_buf, int width, int height)
{
int i, j, stride;
unsigned char *buf_ptr;
FILE *file;
BITMAPFILEHEADER file_header;
BITMAPINFOHEADER info_header;
memset(&file_header, 0x0, sizeof(BITMAPFILEHEADER));
memset(&info_header, 0x0, sizeof(BITMAPINFOHEADER));
file_header.bfType = 0x4D42;
file_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
file_header.bfSize = file_header.bfOffBits + width*height*3;
info_header.biSize = sizeof(BITMAPINFOHEADER);
info_header.biWidth = width;
info_header.biHeight = height;
info_header.biPlanes = 1;
info_header.biCompression = 0;
info_header.biBitCount = 24;
info_header.biSizeImage = width*height*3;
file=fopen(file_name,"wb");
if (!file){
printf("ERROR: cannot open file %s\n", file_name);
return;
}
fwrite(&file_header, 1, sizeof(BITMAPFILEHEADER), file);
fwrite(&info_header, 1, sizeof(BITMAPINFOHEADER), file);
stride = width*3;
buf_ptr = raw_buf+(height-1)*stride;
for(j=0; j<height; j++){
for(i=0; i<width; i++){
fwrite(buf_ptr+i*3+2, 1, 1, file);
fwrite(buf_ptr+i*3+1, 1, 1, file);
fwrite(buf_ptr+i*3+0, 1, 1, file);
}
buf_ptr -= stride;
}
fclose(file);
}
TGA 图像格式
TGA(Targa)格式是计算机上应用最广泛的图象格式,在兼顾了BMP的图象质量的同时又兼顾了JPEG的体积优势,TGA 文件后缀名为 tga,主要特点如下:
- 同时支持压缩和非压缩算法
- 最该支持4个通道的颜色,支持 Alpha 通道
- 通过一个18字节的头来标志 tga 文件,文件尾是可选的
tag 文件头的格式信息如下:

以下面的图为例,对照tga 文件的头字段:


元素 | 说明 |
---|---|
第3-4个字节 0x02: | 表示非压缩RGB格式 |
第13-14个字节 0x01f4: | 图像宽度为 500 |
第15-16个字节 0x01f4: | 图像高度为 500 |
第17个字节 0x18 | 图像每个Pixel 占用3字节 |
第18个字节 0x20 | 图像描述Bit |
示例代码如下:
#pragma pack(1) //在linux C中改为__attribute__ ((__packed__))
struct TgaHeader
{
uint8_t id;
uint8_t color_map;
uint8_t image_type;
uint16_t first_map_entry;
uint16_t num_colors;
uint8_t bits_per_palette_entry;
uint16_t x_origin;
uint16_t y_origin;
uint16_t width;
uint16_t height;
uint8_t bitsPerPixel;
uint8_t descriptor_bits;
};
struct TgaFooter {
uint32_t extension_offset;
uint32_t dev_area_offset;
const char signature[18];
};
#pragma pack()
void imageDumper::dumpTgaFile(uint32_t width, uint32_t height, uint32_t stride) {
FILE *outfile = fopen(Name.c_str(), "wb");
if (outfile) {
TgaHeader header;
TgaFooter footer = { 0,0,"TRUEVISION.XFILE." };
memset(&header, 0, sizeof(header));
header.image_type = 2;
header.width = width;
header.height = height;
header.descriptor_bits = 0x20;
// RGB888:24bits ARGB8888:32bit
header.bitsPerPixel = 24;
cout << "sizeof tga header :" << sizeof(header) << endl;
cout << "sizeof tga footer :" << sizeof(footer) << endl;
fwrite(&header, sizeof(header), 1, outfile);
for (uint32_t i = 0; i < width; i++) {
for (uint32_t j = 0; j < height; j++) {
uint8_t Pixel[3];
char* Psrc = &srcMem[i*stride + 3 * j];
uint32_t nwrite;
Pixel[0] = Psrc[0];
Pixel[1] = Psrc[1];
Pixel[2] = Psrc[2];
nwrite = fwrite(Pixel, sizeof(uint8_t), sizeof(Pixel), outfile);
if (nwrite != sizeof(Pixel))
cout << "Error Write Pixels" << endl;
}
}
//fwrite(&footer, sizeof(footer), 1, outfile);
fclose(outfile);
cout << "dump to tga file success" << endl;
}
网友评论