您的位置:首页 > 其它

BMP格式知识之六:对于水平像素被4整除的解释

2015-06-12 23:22 369 查看
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;

-----------------------------------------------------------------

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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: