c語言數字圖像處理(一):bmp圖片格式及灰度圖片轉換


本篇文章首先介紹了bmp圖片格式,主要參考wiki上的內容,包括bmp文件的存儲方式,對於一些常見的bmp文件格式都給了例子,並且對8位 16位RGB555 16位RGB565格式的bmp文件進行了簡單分析,最后的代碼可以將8位,16位,24位,32位色彩深度的bmp文件轉化位8位灰度圖片,用作后續文章中算法的測試圖片。

Bmp file structure

Bitmap file header

DIB header (bitmap information header)

compression method

 

色彩深度  1bpp = 1位色彩深度,存儲一個像素點使用1位,可以表示兩種顏色

bpp <= 8 必須有調色板(color table)

bpp = 1 調色板 2 * 4 字節

bpp = 4 調色板 16 * 4 字節

bpp = 8 調色板 256 * 4 字節

In most cases, each entry in the color table occupies 4 bytes, in the order blue, green, red, 0x00 (see below for exceptions).The color table is a block of bytes (a table) listing the colors used by the image. Each pixel in an indexed color image is described by a number of bits (1, 4, or 8) which is an index of a single color described by this table. The purpose of the color palette in indexed color bitmaps is to inform the application about the actual color that each of these index values corresponds to. The purpose of the color table in non-indexed (non-palettized) bitmaps is to list the colors used by the bitmap for the purposes of optimization on devices with limited color display capability and to facilitate future conversion to different pixel formats and paletization.

<https://en.wikipedia.org/wiki/BMP_file_format>

調色板數據格式 [blue][green][red][alpha = 0x00]

 

 位圖格式分析

1bpp(單色位圖)        

 

4bpp(16色位圖)

 

8bpp(256色位圖)

bmp頭文件和DIB頭

 

0x00000436                  位圖數據偏移1078字節 調色板1078 - 54 = 1024字節 調色板為256個數據的數組,每個數組4字節

54字節之后的內容為調色板,1078字節之后的內容為位圖數據

調色板數據為這副圖片中用到的所有顏色數據,位圖數據塊的內容為調色板數據的索引

 

16bpp(RGB555 無壓縮compression = BI_RGB,無調色板,無掩碼bitmask)

二進制文件為

Bmp頭文件

0x424d                      bmp文件開頭

0x004b0038                  bmp文件大小 為4915256字節

四個字節保留位

0x00000036                  位圖數據地址偏移   54字節

 

DIB頭

0x00000028                  DIB頭大小  40字節

0x00000780                  寬度1920像素

0x00000500                  高度1280像素(有符號整數,若<0,解析圖片時上下翻轉)

0x0001                      調色板的數量1

0x0010                      每個像素點的位數 16位

0x00000000                  壓縮方式,無壓縮

0x004b0002                  像素數據大小 4915202 = 4915256 - 54

0x00000b12                  橫向分辨率每米2834像素

0x00000b12                  縱向分辨率

0x00000000                  調色板顏色數

0x00000000                  重要顏色數

其余為位圖數據

 

16bpp(RGB565 壓縮方式BI_BITFIELDS 無調色板 有附加掩碼位bitmask)

 

0x00000042                         位圖數據偏移66字節  存在66 - 54 = 12字節的附加掩碼位

0x00000003                         壓縮方式BI_BITFIELDS

0x0000f800[R]                      附加掩碼位,讀取一個像素之后,可以分別用掩碼“與”上像素值,

0x000007e0[G]                      從而提取出想要的顏色分量

0x0000001f[B]                      例如 像素值 & 0xf800  為紅色分量的值

66字節以后為位圖數據

算法實現

8位色彩深度轉灰度圖片

 1 void bpp82grayscale(long height, long width, FILE* fp, short** the_image, int pad, 
 2                     const char* file_name, struct bitmapheader* bmheader)
 3 {
 4     union colortable_union* colortable = NULL;
 5     unsigned char pixel_index;
 6 
 7     printf("bpp8\n");
 8     colortable = read_allocate_colortable(file_name, bmheader);
 9     for(int i=0; i<height; i++){
10         for(int j=0; j<width; j++){
11             fread(&pixel_index, 1, 1, fp);
12             // printf("%u\n", pixel_index);
13             the_image[i][j] = ((colortable[pixel_index].colortable.red) + 
14                                (colortable[pixel_index].colortable.blue) + 
15                                (colortable[pixel_index].colortable.green)) / 3;
16         }  /* ends loop over j */
17         if(pad != 0){
18             fseek(fp, pad, SEEK_CUR);
19         }  /* ends if pad 1= 0 */
20     }  /* ends loop over i */
21     free_colortable(colortable);
22 }

rgb565轉灰度圖

 1 void rgb5652grayscale(long height, long width, FILE* fp, short** the_image, int pad)
 2 {
 3     union rgb565_union pixel;
 4 
 5     printf("rgb565\n");
 6     for(int i=0; i<height; i++){
 7         for(int j=0; j<width; j++){
 8             fread(&pixel, 1, 2, fp);
 9 
10             the_image[i][j] = ((pixel.rgb565_struct.red<<3) + 
11                                (pixel.rgb565_struct.green<<2) + 
12                                (pixel.rgb565_struct.blue<<3)) / 3;
13         }  /* ends loop over j */
14         if(pad != 0){
15             fseek(fp, pad, SEEK_CUR);
16         }  /* ends if pad 1= 0 */
17     }  /* ends loop over i */
18 }

rgb555轉灰度圖

 1 void rgb5552grayscale(long height, long width, FILE* fp, short** the_image, int pad)
 2 {
 3     union rgb555_union pixel;
 4 
 5     printf("rgb555\n");
 6     for(int i=0; i<height; i++){
 7         for(int j=0; j<width; j++){
 8             fread(&pixel, 1, 2, fp);
 9             the_image[i][j] = ((pixel.rgb555_struct.red<<3) + 
10                                (pixel.rgb555_struct.green<<3) + 
11                                (pixel.rgb555_struct.blue<<3)) / 3;
12         }  /* ends loop over j */
13         if(pad != 0){
14             fseek(fp, pad, SEEK_CUR);
15         }  /* ends if pad 1= 0 */
16     }  /* ends loop over i */
17 }

24位色彩深度轉灰度圖

 1 void bpp242grayscale(long height, long width, FILE* fp, short** the_image, int pad)
 2 {
 3     union bpp24_union pixel;
 4 
 5     printf("bpp24\n");
 6     for(int i=0; i<height; i++){
 7         for(int j=0; j<width; j++){
 8             fread(&pixel, 1, 3, fp);
 9             the_image[i][j] = ((pixel.bpp24_struct.red) + 
10                                (pixel.bpp24_struct.green) + 
11                                (pixel.bpp24_struct.blue)) / 3;
12         }  /* ends loop over j */
13         if(pad != 0){
14             fseek(fp, pad, SEEK_CUR);
15         }  /* ends if pad 1= 0 */
16     }  /* ends loop over i */
17 }

 

32位色彩深度轉灰度圖

 1 void bpp322grayscale(long height, long width, FILE* fp, short** the_image, int pad)
 2 {
 3     union bpp32_union pixel;
 4 
 5     printf("bpp32\n");
 6     for(int i=0; i<height; i++){
 7         for(int j=0; j<width; j++){
 8             fread(&pixel, 1, 4, fp);
 9             the_image[i][j] = ((pixel.bpp32_struct.red) + 
10                                (pixel.bpp32_struct.green) + 
11                                (pixel.bpp32_struct.blue)) / 3;
12         }  /* ends loop over j */
13         if(pad != 0){
14             fseek(fp, pad, SEEK_CUR);
15         }  /* ends if pad 1= 0 */
16     }  /* ends loop over i */
17 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM