Abstract
若要做影像處理,第一件事情就是要能將圖片讀進來變成array,才能套用各種演算法,之前我的作法是用.NET的GDI+,方便雖方便,但缺點就是被綁死在.NET平台,如作SW/HW CoDesign的SystemC,不能使用.NET,又如嵌入式系統,只能在Linux上使用gcc,有沒有僅使用C/C++ standard library,就能夠讀入圖形檔的方式呢?
Introduction
以下這個範例,是個純C的程式,在C++也沒有問題,只需最基本的stdio.h和stdlib.h,唯一的缺憾是只能讀取bmp格式,但若要作影像處理或電腦視覺則已經足夠,也可在SystemC和gcc下編譯。
C語言 / BmpReadWriteC.c
2 (C) OOMusou 2007 http://oomusou.cnblogs.com
3
4 Filename : BmpReadWriteC.c
5 Compiler : Visual C++ 8.0 / ANSI C
6 Description : Demo the how to read and write bmp by standard library
7 Release : 02/03/2007 1.0
8 */
9
10 #include < stdio.h >
11 #include < stdlib.h >
12
13 int bmp_read(unsigned char * image, int xsize, int ysize, const char * filename) {
14 char fname_bmp[ 128 ];
15 FILE * fp;
16 unsigned char header[ 54 ];
17
18 sprintf(fname_bmp, " %s.bmp " , filename);
19
20 if ( ! (fp = fopen(fname_bmp, " rb " )))
21 return - 1 ;
22
23 fread(header, sizeof (unsigned char ), 54 , fp);
24 fread(image, sizeof (unsigned char ), (size_t)( long )xsize * ysize * 3 , fp);
25
26 fclose(fp);
27 return 0 ;
28 }
29
30 int bmp_write(unsigned char * image, int xsize, int ysize, char * filename) {
31 unsigned char header[ 54 ] = {
32 0x42 , 0x4d , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
33 54 , 0 , 0 , 0 , 40 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 24 , 0 ,
34 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
35 0 , 0 , 0 , 0
36 };
37 long file_size = ( long )xsize * ( long )ysize * 3 + 54 ;
38 long width, height;
39 char fname_bmp[ 128 ];
40 FILE * fp;
41
42 header[ 2 ] = (unsigned char )(file_size & 0x000000ff );
43 header[ 3 ] = (file_size >> 8 ) & 0x000000ff ;
44 header[ 4 ] = (file_size >> 16 ) & 0x000000ff ;
45 header[ 5 ] = (file_size >> 24 ) & 0x000000ff ;
46
47 width = xsize;
48 header[ 18 ] = width & 0x000000ff ;
49 header[ 19 ] = (width >> 8 ) & 0x000000ff ;
50 header[ 20 ] = (width >> 16 ) & 0x000000ff ;
51 header[ 21 ] = (width >> 24 ) & 0x000000ff ;
52
53 height = ysize;
54 header[ 22 ] = height & 0x000000ff ;
55 header[ 23 ] = (height >> 8 ) & 0x000000ff ;
56 header[ 24 ] = (height >> 16 ) & 0x000000ff ;
57 header[ 25 ] = (height >> 24 ) & 0x000000ff ;
58
59 sprintf(fname_bmp, " %s.bmp " , filename);
60
61 if ( ! (fp = fopen(fname_bmp, " wb " )))
62 return - 1 ;
63
64 fwrite(header, sizeof (unsigned char ), 54 , fp);
65 fwrite(image, sizeof (unsigned char ), (size_t)( long )xsize * ysize * 3 , fp);
66
67 fclose(fp);
68 return 0 ;
69 }
70
71 int main() {
72 unsigned char * image;
73 int xsize = 512 ;
74 int ysize = 512 ;
75
76 image = (unsigned char * )malloc((size_t)xsize * ysize * 3 );
77 if (image == NULL)
78 return - 1 ;
79
80 bmp_read(image, xsize, ysize, " clena " );
81 bmp_write(image, xsize, ysize, " clena_clone_C " );
82
83 free(image);
84 }
純C的程式好處是compiler門檻低,但現在C++的compiler已經很普遍,而且以上的寫法,缺點就是不能用image[y][x].R這種subscripting的寫法,所以我試著用vector以及C++新的fstream讀取bmp檔。
C++ / BmpReadWriteCPP.cpp
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
2
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
3
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
4
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
5
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
6
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
7
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
8
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
9
![None.gif](/Images/OutliningIndicators/None.gif)
10
![None.gif](/Images/OutliningIndicators/None.gif)
11
![None.gif](/Images/OutliningIndicators/None.gif)
12
![None.gif](/Images/OutliningIndicators/None.gif)
13
![None.gif](/Images/OutliningIndicators/None.gif)
14
![None.gif](/Images/OutliningIndicators/None.gif)
15
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
16
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
17
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
18
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
19
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
20
![None.gif](/Images/OutliningIndicators/None.gif)
21
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
22
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
23
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
24
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
25
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
26
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
27
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
28
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
29
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
30
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
31
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
32
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
33
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
34
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
35
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
36
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
37
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
38
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
39
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
40
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
41
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
42
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
43
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
44
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
45
![None.gif](/Images/OutliningIndicators/None.gif)
46
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
47
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
48
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
49
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
50
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
51
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
52
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
53
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
54
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
55
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
56
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
57
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
58
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
59
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
60
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
61
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
62
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
63
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
64
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
65
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
66
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
67
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
68
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
69
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
70
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
71
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
72
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
73
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
74
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
75
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
76
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
77
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
78
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
79
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
80
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
81
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
82
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
83
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
84
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
85
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
86
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
87
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
88
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
89
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
90
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
91
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
92
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
93
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
94
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
95
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
96
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
97
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
98
![None.gif](/Images/OutliningIndicators/None.gif)
99
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![dot.gif](/Images/dot.gif)
100
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
101
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
102
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
103
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
104
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
105
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
106
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
107
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
108
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
109
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](/Images/OutliningIndicators/ContractedSubBlock.gif)
![dot.gif](/Images/dot.gif)
110
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
111
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
112
![ExpandedSubBlockEnd.gif](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
113
![ExpandedBlockEnd.gif](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
87行
![None.gif](/Images/OutliningIndicators/None.gif)
使用了subscripting的寫法,將來做影像處理是不是更好寫呢?
22行
![None.gif](/Images/OutliningIndicators/None.gif)
![None.gif](/Images/OutliningIndicators/None.gif)
也只要傳vector reference就好了,不用再傳sizey,sizex。
原圖
Remark
若要詳細研究BMP格式,在Charles Petzold的Programming Windows[2] Ch.15有詳細完整的介紹。
Conclusion
C++的寫法還是比C人性化很多,而且可以使用subscripting方式做影像處理,若您的compiler許可,建議用C++的寫法。
See Also
(原創) 如何使用ANSI C讀寫24位元的BMP圖檔? (C/C++) (C) (Image Processing)
(原創) 如何使用ANSI C讀寫32位元的BMP圖檔? (C/C++) (C) (Image Processing)
(原創) 如何使用ANSI C讀寫24/32位元的BMP圖檔? (C/C++) (C) (Image Processing)
(原創) 如何使用C++/CLI读/写jpg檔? (C++/CLI)
(原創) 如何用程序的方式载入jpg图形文件? (C#/ASP.NET)
(原創) 由一維陣列模擬二維陣列(多維陣列) (C/C++) (C)
(原創) 如何動態建立二維陣列(多維陣列)? (C/C++) (C)
Reference
Charles Petzold 1998, Programming Windows, Microsoft Press
吳上立 / 林宏墩 編著,C語言數位影像處理, 全華
转载请注明本文地址: (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)