4的倍数是像素数据的长度(按字节计)要是4的倍数,
单色位图每像素1/8字节
16色位图每像素1/2字节
256色位图每像素1字节
真彩色位图每像素3字节
每一行图象的数据的长度(按字节计)要是4的倍数,即
单色位图每一行32像素的倍数,不足的补0
16色位图每一行8像素的倍数,不足的补0
256色位图每一行4像素的倍数,不足的补0
真彩色位图麻烦些,只要补够4个字节的倍数就行
struct tagBITMAPFILEHEADER
{unsigned int bfType; // 指明文件类型, 值为 BM
unsigned long bfSize; // 文件大小
unsigned int Reserved1; // 保留字, 值为 0
unsigned int Reserved2; // 保留字, 值为 0
unsigned long bfOffset; // 位图阵列的偏移量, 以字节为单位
} bitmapfileheader;
struct tagBITMAPINFOHEADER
{unsigned long biSize; // 该结构的字节数, 值为 40
unsigned long biWidth; // 位图的宽度, 以像素为单位
unsigned long biHeight; // 位图的高度, 以像素为单位
unsigned int biPlanes; // 目标设备的位面数, 值为 1
unsigned int biBitCount; // 每个像素所占位数, 为 2色: 1,
// 16色: 4, 256色: 8, 16M色: 24
unsigned long biCompression; // BMP 的压缩方式, 分别为 BI-RGB,
// BI-REL8 或 BI-REL4, 对应值分别
// 为 0, 1, 2
unsigned long biSizeImage; // 位图大小, 以字节为单位
unsigned long biXpelsPerMeter; // 水平分辨率, 单位为像素 / 米
unsigned long biYpelsPerMeter; // 垂直分辨率, 单位为像素 / 米
unsigned long biClrUsed; // 实际使用的颜色数
unsigned long biClrImportant; // 重要颜色索引值
} bitmapinfoheader;
struct tagRGBQUAD
{unsigned char rgbBlue; // 蓝色亮度值
unsigned char rgbGreen; // 绿色亮度值
unsigned char rgbRed; // 红色亮度值
unsigned char rgbReserved; // 保留字, 为 0
} rgbquad;
-----------------------------------------------------------------
单色位图每像素1/8字节
16色位图每像素1/2字节
256色位图每像素1字节
真彩色位图每像素3字节
每一行图象的数据的长度(按字节计)要是4的倍数,即
单色位图每一行32像素的倍数,不足的补0
16色位图每一行8像素的倍数,不足的补0
256色位图每一行4像素的倍数,不足的补0
真彩色位图麻烦些,只要补够4个字节的倍数就行
struct
{unsigned
}
struct
{unsigned
//
//
//
}
struct
{unsigned
}
-----------------------------------------------------------------
void display_color2(int col, int row)
{
unsigned int Height, Width;
unsigned char info;
unsigned char color[2] = {0, 15};
int i, j, t, gap;
int k = 0x80;
int patch = 0;
fseek(fp, 0x36, SEEK_SET); // 0X36 = 54
Height = bitmapinfoheader.biHeight;
Width = bitmapinfoheader.biWidth;
if (Width / 8 * 8 != Width)
{
patch = 1;
gap = Width - Width / 8 * 8;
}
fseek(fp, bitmapfileheader.bfOffset, SEEK_SET);
for (i = 0; i < Height; i ++)
for (j = 0; j < Width / 8 + patch; j ++)
{
info = fgetc(fp); // write bitmap
for (t = 0; t < 8; t ++)
{putpoint(col + 8 * j + t, Height - (row + i),
color[(info & (k >> t)) >> (7 - t)]);
if (patch == 1 && j == Width / 8 && t == gap - 1) break;
}
}
}
void display_color16(int col, int row)
{
unsigned char pal[256][3];
unsigned int Height, Width;
char info;
unsigned int w, h, byte, gap, num, flag, n;
unsigned long biBitCount;
fseek(fp, 0x36, SEEK_SET); // 0x36 = 54
for (int i = 0; i < 64; i ++)
{fread(&rgbquad, sizeof(rgbquad), 1, fp);
pal[i][0] = rgbquad.rgbRed >> 2;
pal[i][1] = rgbquad.rgbGreen >> 2;
pal[i][2] = rgbquad.rgbBlue >> 2;
}
set_palette(pal);
fseek(fp, bitmapfileheader.bfOffset, SEEK_SET);
Width = bitmapinfoheader.biWidth;
Height = bitmapinfoheader.biHeight;
biBitCount = bitmapinfoheader.biBitCount;
n = Width * biBitCount;
if ((n / 32 * 32) == n)
{
gap = 0;
flag = 0;
}
else
{
num = n / 8;
byte = num + 4 - (num - num / 4 * 4);
if ((n / 8 * 8) == n) flag = 0;
else flag = 1;
gap = byte - num - flag;
}
for (h = 0; h < Height; h ++)
{
for (w = 0; w < Width / 2; w ++)
{
info = fgetc(fp); // write bitmap
putpoint(col + w * 2, Height - (row + h), (info & 0xf0) >> 4);
putpoint(col + w * 2 + 1, Height - (row + h), info & 0x0f);
}
if (flag == 1)
{info = fgetc(fp);
putpoint(col + Width - 1, Height - (row + h), (info & 0xf0) >> 4);
}
fseek(fp, gap, SEEK_CUR);
}
}
void display_color256(int col, int row)
{
unsigned int Height, Width;
unsigned char color;
unsigned char pal[256][3];
int i, j, gap, byte;
fseek(fp, 0x36, SEEK_SET); // 0x36 = 54
for (i = 0; i < 256; i ++)
{
fread(&rgbquad, sizeof(rgbquad), 1, fp);
pal[i][0] = rgbquad.rgbRed >> 2;
pal[i][1] = rgbquad.rgbGreen >> 2;
pal[i][2] = rgbquad.rgbBlue >> 2;
}
set_palette(pal);
Width = bitmapinfoheader.biWidth;
Height = bitmapinfoheader.biHeight;
fseek(fp, bitmapfileheader.bfOffset, SEEK_SET);
if ((Width / 4) * 4 == Width)
{
byte = Width;
gap = 0;
}
else
{byte = Width / 4 * 4 + 4;
gap = byte - Width;
}
for (i = 0; i < Height; i ++)
{
for (j = 0; j < byte - gap; j ++)
{color = fgetc(fp);
putpoint(col + j, Height - row - i, color);
}
fseek(fp, gap, SEEK_CUR);
}
}
void display_color16M(int col, int row)
{
unsigned int Height, Width;
int i, j, gap, byte;
unsigned char r, g, b;
fseek(fp, 0x36, SEEK_SET); // 0X36 = 54
Height = bitmapinfoheader.biHeight;
Width = bitmapinfoheader.biWidth;
fseek(fp, bitmapfileheader.bfOffset, SEEK_SET);
if (((Width * 3) / 4) * 4 / 3 == Width)
{
byte = Width;
gap = 0;
}
else
{byte = (Width * 3) / 4 * 4 + 4;
gap = byte - (Width * 3);
}
for (i = 0; i < Height; i ++)
{
for (j = 0; j < Width; j ++)
{
b = fgetc(fp);
g = fgetc(fp);
r = fgetc(fp);
putpoint(col + j, Height - row - i, r, g, b);
}
fseek(fp, gap, SEEK_CUR);
}
}
//基本的程序片段, 调色板的数据只有16色,256色使用,其他单色,真彩色都省略简化了
void main()
{
fseek(fp, 0, SEEK_SET);
fread(&bitmapfileheader, sizeof(bitmapfileheader), 1, fp);
fread(&bitmapinfoheader, sizeof(bitmapinfoheader), 1, fp);
switch (bitmapinfoheader.biBitCount)
{
case 1 :
display_color2(0, 0);
break;
case 4 :
display_color16(0, 0);
break;
case 8 :
display_color256(0, 0);
break;
case 24:
display_color16M(0, 0);
break;
}
}