C語言創建24位真彩色位圖

/* 功能: 創建一幅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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章