您的位置:首页 > 编程语言 > C语言/C++

C语言创建24位真彩色位图

2011-11-20 15:06 543 查看
/* 功能: 创建一幅24位真彩色位图
** 作者: mayadong7349
** 参考: MSDN(Visual Studio 2005)、(百度百科:bmp) http://baike.baidu.com/view/7671.htm#2 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define BMP_W 640L
#define BMP_H 480L

void SetBmpInfoHeader(PBITMAPINFOHEADER pbmpih)
{
/* 14~17: 本结构体所占字节数, 固定值40
MSDN: Specifies the number of bytes required by the structure.
*/
pbmpih->biSize          = 40;
/* 18~21: 位图的宽度(以像素pixel为单位)
MSDN: Specifies the width of the bitmap, in pixels.
Windows 98/Me, Windows 2000/XP: If biCompression is BI_JPEG or BI_PNG, the biWidth member specifies
the width of the decompressed JPEG or PNG image file, respectively.
*/
pbmpih->biWidth         = BMP_W;
/* 22~25: 位图的高度
MSDN: Specifies the height of the bitmap, in pixels. If biHeight is positive, the bitmap is a
bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is
a top-down DIB and its origin is the upper-left corner.
If biHeight is negative, indicating a top-down DIB, biCompression must be either BI_RGB or
BI_BITFIELDS. Top-down DIBs cannot be compressed.
Windows 98/Me, Windows 2000/XP: If biCompression is BI_JPEG or BI_PNG, the biHeight member specifies
the height of the decompressed JPEG or PNG image file, respectively.
*/
pbmpih->biHeight        = BMP_H;
/* 26~27: 目标设备的级别, 固定值:1
MSDN: Specifies the number of planes for the target device. This value must be set to 1*/
pbmpih->biPlanes        = 1;
/* 28~29: 一个像素所占bit数, 可以是:1(双色)、4(16色)、8(256色)
、16(65536色)、24(真彩色2^24种颜色)、32(真彩色2^32种颜色),具体参阅MSDN。
对于24位真彩色位图, 一个像素占用三个字节,即24 bits
MSDN: Specifies the number of bits-per-pixel. The biBitCount member of the BITMAPINFOHEADER
structure determines the number of bits that define each pixel and the maximum number
of colors in the bitmap. This member must be one of the following values.
0: Windows 98/Me, Windows 2000/XP: The number of bits-per-pixel is specified or is implied
by the JPEG or PNG format.
1: The bitmap is monochrome, and the bmiColors member of BITMAPINFO contains two entries.
Each bit in the bitmap array represents a pixel. If the bit is clear, the pixel is displayed
with the color of the first entry in the bmiColors table; if the bit is set, the pixel has
the color of the second entry in the table.
4: The bitmap has a maximum of 16 colors, and the bmiColors member of BITMAPINFO contains up to
16 entries. Each pixel in the bitmap is represented by a 4-bit index into the color table.
For example, if the first byte in the bitmap is 0x1F, the byte represents two pixels.
The first pixel contains the color in the second table entry, and the second pixel contains
the color in the sixteenth table entry.
8: The bitmap has a maximum of 256 colors, and the bmiColors member of BITMAPINFO contains up
to 256 entries. In this case, each byte in the array represents a single pixel.
16: The bitmap has a maximum of 2^16 colors. If the biCompression member of the BITMAPINFOHEADER
is BI_RGB, the bmiColors member of BITMAPINFO is NULL. Each WORD in the bitmap array represents
a single pixel. The relative intensities of red, green, and blue are represented with five bits for
each color component. The value for blue is in the least significant five bits, followed by five
bits each for green and red. The most significant bit is not used. The bmiColors color table is
used for optimizing colors used on palette-based devices, and must contain the number of entries
specified by the biClrUsed member of the BITMAPINFOHEADER.
If the biCompression member of the BITMAPINFOHEADER is BI_BITFIELDS, the bmiColors member contains
three DWORD color masks that specify the red, green, and blue components, respectively,
of each pixel. Each WORD in the bitmap array represents a single pixel.

Windows NT/Windows 2000/XP: When the biCompression member is BI_BITFIELDS, bits set in each DWORD
mask must be contiguous and should not overlap the bits of another mask.
All the bits in the pixel do not have to be used.

Windows 95/98/Me: When the biCompression member is BI_BITFIELDS, the system supports only the
following 16bpp color masks: A 5-5-5 16-bit image, where the blue mask is 0x001F,
the green mask is 0x03E0, and the red mask is 0x7C00; and a 5-6-5 16-bit image,
where the blue mask is 0x001F, the green mask is 0x07E0, and the red mask is 0xF800.
24: The bitmap has a maximum of 2^24 colors, and the bmiColors member of BITMAPINFO is NULL.
Each 3-byte triplet in the bitmap array represents the relative intensities of blue, green,
and red, respectively, for a pixel. The bmiColors color table is used for optimizing colors
used on palette-based devices, and must contain the number of entries specified by the biClrUsed
member of the BITMAPINFOHEADER.
32: The bitmap has a maximum of 2^32 colors. If the biCompression member of the BITMAPINFOHEADER is
BI_RGB, the bmiColors member of BITMAPINFO is NULL. Each DWORD in the bitmap array represents
the relative intensities of blue, green, and red, respectively, for a pixel. The high byte in
each DWORD is not used. The bmiColors color table is used for optimizing colors used on
palette-based devices, and must contain the number of entries specified by the biClrUsed member
of the BITMAPINFOHEADER.
If the biCompression member of the BITMAPINFOHEADER is BI_BITFIELDS, the bmiColors member contains
three DWORD color masks that specify the red, green, and blue components, respectively, of each pixel.
Each DWORD in the bitmap array represents a single pixel.

Windows NT/ 2000: When the biCompression member is BI_BITFIELDS, bits set in each DWORD mask must
be contiguous and should not overlap the bits of another mask. All the bits in the
pixel do not need to be used.
Windows 95/98/Me: When the biCompression member is BI_BITFIELDS, the system supports only the following
32-bpp color mask: The blue mask is 0x000000FF, the green mask is 0x0000FF00, and
the red mask is 0x00FF0000.
*/
pbmpih->biBitCount      = 24;
/* 30~33:指定是否压缩, (如果压缩了)采用的压缩格式。
可以为: BI_RGB、BI_RLE4、BI_RLE8、BI_BITFIELDS、BI_PNG、BI_JPEG
有的位图会进行游程长度编码:BI_RLE4、BI_RLE8
压缩可以节省空间, 但不便于编程读写。BI_RGB表示不进行压缩处理
MSDN: Specifies the type of compression for a compressed bottom-up bitmap
(top-down DIBs cannot be compressed). This member can be one of the following values.
BI_RGB:  An uncompressed format.
BI_RLE8: A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format
is a 2-byte format consisting of a count byte followed by a byte containing a color index.
For more information, see Bitmap Compression.
BI_RLE4: An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format
consisting of a count byte followed by two word-length color indexes.
For more information, see Bitmap Compression.
BI_BITFIELDS: Specifies that the bitmap is not compressed and that the color table consists
of three DWORD color masks that specify the red, green, and blue components,
respectively, of each pixel. This is valid when used with 16- and 32-bpp bitmaps.
BI_JPEG: Windows 98/Me, Windows 2000/XP: Indicates that the image is a JPEG image.
BI_PNG: Windows 98/Me, Windows 2000/XP: Indicates that the image is a PNG image.

*/
pbmpih->biCompression  = BI_RGB;
/* 34~37: 位图数据区所占字节数,有固定的计算公式
MSDN: Specifies the size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
Windows 98/Me, Windows 2000/XP: If biCompression is BI_JPEG or BI_PNG,
biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.*/
pbmpih->biSizeImage     = ((((pbmpih->biWidth * pbmpih->biBitCount) + 31) & ~31) / 8) * pbmpih->biHeight;
/* 38~41: 位图水平分辨率,每米像素数
MSDN: Specifies the horizontal resolution, in pixels-per-meter,
of the target device for the bitmap. An application can use this value
to select a bitmap from a resource group that best matches the characteristics of the current device. */
pbmpih->biXPelsPerMeter = 0L;
/* 42~45: 位图垂直分辨率,每米像素数
MSDN: Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap.*/
pbmpih->biYPelsPerMeter = 0L;
/* 46~49: 位图实际使用颜色表中颜色数(对于有调色板的位图来说实际上是调色板中颜色项数,
24位真彩色位图不需要调色板, 设为0, 8位灰度位图为256(2^8种颜色)。
MSDN:If this value is zero, the bitmap uses the maximum number of colors corresponding
to the value of the biBitCount member for the compression mode specified by biCompression. */
pbmpih->biClrUsed      = 0L;
/* 50~53: 显示位图所需颜色数
MSDN: Specifies the number of color indexes that are required for displaying the bitmap.
If this value is zero, all colors are required. */
pbmpih->biClrImportant = 0L;
}

void SetBmpFileHeader(PBITMAPFILEHEADER pbmpfh, const PBITMAPINFOHEADER pbmpih)
{
/* 0~1: 固定值: "BM"(或0x4D42),即表明这是位图(一般以bmp为文件名后缀)
MSDN: Specifies the file type, must be BM.
*/
pbmpfh->bfType      = *(WORD *)"BM";
/* 2~5: 位图文件总大小(占用总字节数, 包括文件头、信息头、调色板、位图数据区占用字节数)
MSDN: Specifies the size, in bytes, of the bitmap file.
*/
pbmpfh->bfSize      = pbmpih->biSizeImage + 54 + pbmpih->biClrUsed * sizeof(RGBQUAD);
/* 6~7: 固定值0: 目前没什么用, 可能留作将来扩展。也有的结构体中有这样的域是为了内存对齐
MSDN: Reserved; must be zero.
*/
pbmpfh->bfReserved1 = 0;
/* 8~9: 固定值
MSDN: Reserved; must be zero.
*/
pbmpfh->bfReserved2 = 0;
/* 10~13: 位图数据区起始位置, 计算方法为:
位图文件头14个字节+位图信息头40个字节+位图调色板所占字节数,
这里要创建的是一张24位位图(无调色板),故设置为54 也可以。
MSDN: Specifies the offset, in bytes, from the beginning of the BITMAPFILEHEADER structure to
the bitmap bits.
*/
pbmpfh->bfOffBits   = 54 + pbmpih->biClrUsed * sizeof(RGBQUAD);
}

int main(void)
{
BITMAPFILEHEADER bmpfh = { 0 }; /* 位图文件头 */
BITMAPINFOHEADER bmpih = { 0 }; /* 位图信息头 */
FILE *fpBmp = NULL;
COLORREF color = RGB(0xf0,0xca,0xa6); /* 天蓝色 */
BYTE black = 0;
int fillbits;
int w, h;

SetBmpInfoHeader(&bmpih);
SetBmpFileHeader(&bmpfh, &bmpih);
fillbits = ( 4 - ( bmpih.biWidth * 3 ) % 4 ) % 4;

fpBmp = fopen("D:\\rendering.bmp", "wb");
if (NULL == fpBmp) {
perror("fopen failed:");
system("pause>nul");
exit(EXIT_FAILURE);
}

fwrite(&bmpfh, sizeof(BITMAPFILEHEADER), 1, fpBmp); /* 写入位图文件头 */
fwrite(&bmpih, sizeof(BITMAPINFOHEADER), 1, fpBmp); /* 写入位图信息头 */
/* 写入调色板(如果有的话) */
/* 写入位图数据 */
for (h = 0; h < BMP_H; ++h) {
for (w = 0; w < BMP_W; ++w) {
fwrite(&color, 3, 1, fpBmp);  /* 将像素值颜色写入位图文件 */
}
/* 边界填充
对于24位位图每个像素占3个字节,且每个扫描行所占字节数必须是4的倍数。
比如,对于一张宽度为21个像素的24色位图, 理论上每扫描行占用21*3=63个字节,
但63不是4的倍数,所以需要在该扫描行的最后填充一个字节的0,凑到64,
这样实际上每扫描行占用64个字节。
fillbits = ( 4 - ( biheader.biWidth * 3 ) % 4 ) % 4; 参考自acepig, 作用是
计算每扫描行需要填充几个字节的0。对于宽度是4的倍数的图片, count为0。
*/
fwrite(&black, 1, fillbits, fpBmp);
}
fclose(fpBmp);

system("mspaint D:\\rendering.bmp");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息