VC++2010开发数字图像系统1

时间:2022-09-08 08:22:32

VS2010编程小技巧:1.注意在文档类C..Doc中使用和在视图类C..View中使用MessageBox函数时的参数不相同,不要用错。2.创建与控件关联的指针变量时,一定要注意初始化,不要形成垂悬指针,否则会出现“烫烫烫烫..."”屯屯屯...的乱码。

这里我们利用自己的图像函数库去处理数字图像,在掌握基本方法和基本理论后再去结合OpenCV和matlab去实现算法。

  1. 新建一基于单文档的MFC应用程序(选择SDI单文档选项,其他选择默认)。
  2. 添加自己的类库(Dib.h和Dib.cpp两个文件)

  Dib.h

 

  1 //**************************************************
2 // Name: Dib.h
3 // Purpose: ImgPro
4 // Author: sxzheng@live.cn
5 // Modified by: sxzheng@live.cn
6 // Created: 2013/3/28
7 // Copyright: (c)sxzheng@live.cn
8 // Licence:
9 //***************************************************
10 //======================================================================
11 // 文件: Dib.h
12 // 内容: 设备无关位图类-头文件
13 // 功能: (1)位图的加载与保存;
14 // (2)位图信息的获取;
15 // (3)位图数据的获取;
16 // (3)位图的显示;
17 // (4)位图的转换;
18 // (5)位图相关判断;
19 //======================================================================
20
21 #pragma once
22
23 #include "afx.h"
24
25 class CDib : public CObject
26 {
27 public:
28 // 构造函数,初始化数据成员
29 CDib(void);
30
31 // 析构函数,释放内存空间
32 ~CDib(void);
33
34 // 从文件加载位图
35 BOOL LoadFromFile(LPCTSTR lpszPath);
36
37 // 将位图保存到文件
38 BOOL SaveToFile(LPCTSTR lpszPath);
39
40 // 获取位图文件名
41 LPCTSTR GetFileName();
42
43 // 获取位图宽度
44 LONG GetWidth();
45
46 // 获取位图高度
47 LONG GetHeight();
48
49 // 获取位图的宽度和高度
50 CSize GetDimension();
51
52 // 获取位图大小
53 DWORD GetSize();
54
55 // 获取单个像素所占位数
56 WORD GetBitCount();
57
58 // 获取每行像素所占字节数
59 UINT GetLineByte();
60
61 // 获取位图颜色数
62 DWORD GetNumOfColor();
63
64 // 获取位图颜色表
65 LPRGBQUAD GetRgbQuad();
66
67 // 获取位图数据
68 LPBYTE GetData();
69
70 // 显示位图
71 BOOL Draw(CDC *pDC, CPoint origin, CSize size);
72
73 // 24位彩色位图转8位灰度位图
74 BOOL RgbToGrade();
75
76 // 8位灰度位图转24位彩色位图
77 BOOL GradeToRgb();
78
79 // 判断是否含有颜色表
80 BOOL HasRgbQuad();
81
82 // 判断是否是灰度图
83 BOOL IsGrade();
84
85 // 判断位图是否有效
86 BOOL IsValid();
87
88 protected:
89 // 计算位图颜色表长度
90 DWORD CalcRgbQuadLength();
91
92 // 根据颜色表生成调色板
93 BOOL MakePalette();
94
95 // 清理空间
96 void Empty(BOOL bFlag = TRUE);
97
98 private:
99 // 位图文件名
100 CString m_fileName;
101
102 // 位图文件头指针
103 LPBITMAPFILEHEADER m_lpBmpFileHeader; // 需要动态分配和释放
104
105 // 位图指针(包含除位图文件头的所有内容)
106 LPBYTE m_lpDib; // 需要动态分配和释放
107
108 // 位图信息指针
109 LPBITMAPINFO m_lpBmpInfo;
110
111 // 位图信息头指针
112 LPBITMAPINFOHEADER m_lpBmpInfoHeader;
113
114 // 位图颜色表指针
115 LPRGBQUAD m_lpRgbQuad;
116
117 // 位图数据指针
118 LPBYTE m_lpData;
119
120 // 调色板句柄
121 HPALETTE m_hPalette;
122
123 // 是否有颜色表
124 BOOL m_bHasRgbQuad;
125
126 // 位图是否有效
127 BOOL m_bValid;
128 };

 

Dib.cpp

  1 //**************************************************
2 // Name: Dib.cpp
3 // Purpose: ImgPro
4 // Author: sxzheng@live.cn
5 // Modified by: sxzheng@live.cn
6 // Created: 2013/3/28
7 // Copyright: (c)sxzheng@live.cn
8 // Licence:
9 //***************************************************
10 //***************************************************
11 // 文件: Dib.cpp
12 // 内容: 设备无关位图类-源文件
13 // 功能: (1)位图的加载与保存;
14 // (2)位图信息的获取;
15 // (3)位图数据的获取;
16 // (3)位图的显示;
17 // (4)位图的转换;
18 // (5)位图相关判断;
19 //***************************************************
20
21 #include "StdAfx.h"
22 #include "Dib.h"
23
24 //***************************************************
25 // 函数功能: 构造函数,初始化数据成员
26 // 输入参数: 无
27 // 返回值: 无
28 //***************************************************
29 CDib::CDib(void)
30 {
31 // 数据成员初始化
32 m_fileName="";
33 m_lpBmpFileHeader = NULL;
34 m_lpDib = NULL;
35 m_lpBmpInfo = NULL;
36 m_lpBmpInfoHeader = NULL;
37 m_lpRgbQuad = NULL;
38 m_lpData = NULL;
39 m_hPalette = NULL;
40 m_bHasRgbQuad = FALSE;
41 m_bValid = FALSE;
42 }
43
44 //***************************************************
45 // 函数功能: 析构函数,释放内存空间
46 // 输入参数: 无
47 // 返回值: 无
48 //***************************************************
49 CDib::~CDib(void)
50 {
51 // 清理空间
52 Empty();
53 }
54
55 //***************************************************
56 // 函数功能: 从文件加载位图
57 // 输入参数: LPCTSTR lpszPath-待加载位图文件路径
58 // 返回值: BOOL-TRUE 成功;FALSE 失败
59 //***************************************************
60 BOOL CDib::LoadFromFile(LPCTSTR lpszPath)
61 {
62 // 记录位图文件名
63 m_fileName=lpszPath;
64
65 // 以读模式打开位图文件
66 CFile dibFile;
67 if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite))
68 {
69 return FALSE;
70 }
71
72 // 清理空间
73 Empty(FALSE);
74
75 // 为位图文件头分配空间,并初始化为0
76 m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
77 memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
78
79 // 读取位图文件头
80 int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));
81 if(nCount != sizeof(BITMAPFILEHEADER))
82 {
83 return FALSE;
84 }
85
86 // 判断此文件是不是位图文件(“0x4d42”代表“BM”)
87 if(m_lpBmpFileHeader->bfType == 0x4d42)
88 {
89 // 是位图文件
90
91 // 计算除位图文件头的空间大小,分配空间并初始化为0
92 DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER);
93 m_lpDib = new BYTE[dwDibSize];
94 memset(m_lpDib, 0, dwDibSize);
95
96 // 读取除位图文件头的所有数据
97 dibFile.Read(m_lpDib, dwDibSize);
98
99 // 关闭位图文件
100 dibFile.Close();
101
102 // 设置位图信息指针
103 m_lpBmpInfo = (LPBITMAPINFO)m_lpDib;
104
105 // 设置位图信息头指针
106 m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib;
107
108 // 设置位图颜色表指针
109 m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize);
110
111 // 如果位图没有设置位图使用的颜色数,设置它
112 if(m_lpBmpInfoHeader->biClrUsed == 0)
113 {
114 m_lpBmpInfoHeader->biClrUsed = GetNumOfColor();
115 }
116
117 // 计算颜色表长度
118 DWORD dwRgbQuadLength = CalcRgbQuadLength();
119
120 // 设置位图数据指针
121 m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength;
122
123 // 判断是否有颜色表
124 if(m_lpRgbQuad == (LPRGBQUAD)m_lpData)
125 {
126 m_lpRgbQuad = NULL; // 将位图颜色表指针置空
127 m_bHasRgbQuad = FALSE; // 无颜色表
128 }
129 else
130 {
131 m_bHasRgbQuad = TRUE; // 有颜色表
132 MakePalette(); // 根据颜色表生成调色板
133 }
134
135 // 设置位图大小(因为很多位图文件都不设置此项)
136 m_lpBmpInfoHeader->biSizeImage = GetSize();
137
138 // 位图有效
139 m_bValid = TRUE;
140
141 return TRUE;
142 }
143 else
144 {
145 // 不是位图文件
146 m_bValid = FALSE;
147
148 return FALSE;
149 }
150
151 }
152
153 //***************************************************
154 // 函数功能: 将位图保存到文件
155 // 输入参数: LPCTSTR lpszPath-位图文件保存路径
156 // 返回值: BOOL-TRUE 成功;FALSE 失败
157 //***************************************************
158 BOOL CDib::SaveToFile(LPCTSTR lpszPath)
159 {
160 // 以写模式打开文件
161 CFile dibFile;
162 if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite
163 | CFile::shareExclusive))
164 {
165 return FALSE;
166 }
167
168 // 记录位图文件名
169 m_fileName=lpszPath;
170
171 // 将文件头结构写进文件
172 dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));
173
174 // 将文件信息头结构写进文件
175 dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER));
176
177 // 计算颜色表长度
178 DWORD dwRgbQuadlength = CalcRgbQuadLength();
179
180 // 如果有颜色表的话,将颜色表写进文件
181 if(dwRgbQuadlength != 0)
182 {
183 dibFile.Write(m_lpRgbQuad, dwRgbQuadlength);
184 }
185
186 // 将位图数据写进文件
187 DWORD dwDataSize = GetLineByte() * GetHeight();
188 dibFile.Write(m_lpData, dwDataSize);
189
190 // 关闭文件
191 dibFile.Close();
192
193 return TRUE;
194 }
195
196 //***************************************************
197 // 函数功能: 获取位图文件名
198 // 输入参数: 无
199 // 返回值: LPCTSTR-位图文件名
200 //***************************************************
201 LPCTSTR CDib::GetFileName()
202 {
203 return m_fileName;
204 }
205
206 //***************************************************
207 // 函数功能: 获取位图宽度
208 // 输入参数: 无
209 // 返回值: LONG-位图宽度
210 //***************************************************
211 LONG CDib::GetWidth()
212 {
213 return m_lpBmpInfoHeader->biWidth;
214 }
215
216 //***************************************************
217 // 函数功能: 获取位图高度
218 // 输入参数: 无
219 // 返回值: LONG-位图高度
220 //***************************************************
221 LONG CDib::GetHeight()
222 {
223 return m_lpBmpInfoHeader->biHeight;
224 }
225
226 //***************************************************
227 // 函数功能: 获取位图的宽度和高度
228 // 输入参数: 无
229 // 返回值: CSize-位图的宽度和高度
230 //***************************************************
231 CSize CDib::GetDimension()
232 {
233 return CSize(GetWidth(), GetHeight());
234 }
235
236 //***************************************************
237 // 函数功能: 获取位图大小
238 // 输入参数: 无
239 // 返回值: DWORD-位图大小
240 //***************************************************
241 DWORD CDib::GetSize()
242 {
243 if(m_lpBmpInfoHeader->biSizeImage != 0)
244 {
245 return m_lpBmpInfoHeader->biSizeImage;
246 }
247 else
248 {
249 return GetWidth() * GetHeight();
250 }
251 }
252
253 //***************************************************
254 // 函数功能: 获取单个像素所占位数
255 // 输入参数: 无
256 // 返回值: WORD-单个像素所占位数
257 //***************************************************
258 WORD CDib::GetBitCount()
259 {
260 return m_lpBmpInfoHeader->biBitCount;
261 }
262
263 //***************************************************
264 // 函数功能: 获取每行像素所占字节数
265 // 输入参数: 无
266 // 返回值: UINT-每行像素所占字节数
267 //***************************************************
268 UINT CDib::GetLineByte()
269 {
270 return (GetWidth() * GetBitCount() / 8 + 3) / 4 * 4;;
271 }
272
273 //***************************************************
274 // 函数功能: 获取位图颜色数
275 // 输入参数: 无
276 // 返回值: DWORD-位图颜色数
277 //***************************************************
278 DWORD CDib::GetNumOfColor()
279 {
280 UINT dwNumOfColor;
281
282 if ((m_lpBmpInfoHeader->biClrUsed == 0)
283 && (m_lpBmpInfoHeader->biBitCount < 9))
284 {
285 switch (m_lpBmpInfoHeader->biBitCount)
286 {
287 case 1: dwNumOfColor = 2; break;
288 case 4: dwNumOfColor = 16; break;
289 case 8: dwNumOfColor = 256;
290 }
291 }
292 else
293 {
294 dwNumOfColor = m_lpBmpInfoHeader->biClrUsed;
295 }
296
297 return dwNumOfColor;
298 }
299
300 //***************************************************
301 // 函数功能: 计算位图颜色表长度
302 // 输入参数: 无
303 // 返回值: DWORD-位图颜色表长度
304 //***************************************************
305 DWORD CDib::CalcRgbQuadLength()
306 {
307 DWORD dwNumOfColor = GetNumOfColor();
308 if(dwNumOfColor > 256)
309 {
310 dwNumOfColor = 0;
311 }
312 return dwNumOfColor * sizeof(RGBQUAD);
313 }
314
315 //***************************************************
316 // 函数功能: 获取位图颜色表
317 // 输入参数: 无
318 // 返回值: LPRGBQUAD-位图颜色表指针
319 //***************************************************
320 LPRGBQUAD CDib::GetRgbQuad()
321 {
322 return m_lpRgbQuad;
323 }
324
325 //***************************************************
326 // 函数功能: 获取位图数据
327 // 输入参数: 无
328 // 返回值: LPBYTE-位图数据指针
329 //***************************************************
330 LPBYTE CDib::GetData()
331 {
332 return m_lpData;
333 }
334
335 //***************************************************
336 // 函数功能: 根据颜色表生成调色板
337 // 输入参数: 无
338 // 返回值: BOOL-TRUE 成功;FALSE 失败
339 //***************************************************
340 BOOL CDib::MakePalette()
341 {
342 // 计算颜色表长度
343 DWORD dwRgbQuadLength = CalcRgbQuadLength();
344
345 // 如果颜色表长度为0,则不生成逻辑调色板
346 if(dwRgbQuadLength == 0)
347 {
348 return FALSE;
349 }
350
351 //删除旧的调色板对象
352 if(m_hPalette != NULL)
353 {
354 DeleteObject(m_hPalette);
355 m_hPalette = NULL;
356 }
357
358 // 申请缓冲区,初始化为0
359 DWORD dwNumOfColor = GetNumOfColor();
360 DWORD dwSize = 2 * sizeof(WORD) + dwNumOfColor * sizeof(PALETTEENTRY);
361 LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[dwSize];
362 memset(lpLogPalette, 0, dwSize);
363
364 // 生成逻辑调色板
365 lpLogPalette->palVersion = 0x300;
366 lpLogPalette->palNumEntries = dwNumOfColor;
367 LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad;
368 for(int i = 0; i < dwNumOfColor; i++)
369 {
370 lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed;
371 lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen;
372 lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue;
373 lpLogPalette->palPalEntry[i].peFlags = 0;
374 lpRgbQuad++;
375 }
376
377 // 创建逻辑调色板
378 m_hPalette = CreatePalette(lpLogPalette);
379
380 // 释放缓冲区
381 delete [] lpLogPalette;
382
383 return TRUE;
384 }
385
386 //***************************************************
387 // 函数功能: 显示位图
388 // 输入参数:
389 // CDC *pDC-设备环境指针
390 // CPoint origin-显示矩形区域的左上角
391 // CSize size-显示矩形区域的尺寸
392 // 返回值:
393 // BOOL-TRUE 成功;FALSE 失败
394 //***************************************************
395 BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size)
396 {
397 // 位图无效,无法绘制,返回错误
398 if(!IsValid())
399 {
400 return FALSE;
401 }
402
403 // 旧的调色板句柄
404 HPALETTE hOldPalette = NULL;
405
406 // 如果位图指针为空,则返回FALSE
407 if(m_lpDib == NULL)
408 {
409 return FALSE;
410 }
411
412 // 如果位图有调色板,则选进设备环境中
413 if(m_hPalette != NULL)
414 {
415 hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
416 }
417
418 // 设置位图伸缩模式
419 pDC->SetStretchBltMode(COLORONCOLOR);
420
421 // 将位图在pDC所指向的设备上进行显示
422 StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
423 0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY);
424
425 // 恢复旧的调色板
426 if(hOldPalette != NULL)
427 {
428 SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE);
429 }
430
431 return TRUE;
432 }
433
434 //***************************************************
435 // 函数功能: 24位彩色位图转8位灰度位图
436 // 输入参数: 无
437 // 返回值: BOOL-TRUE 成功;FALSE 失败
438 //***************************************************
439 BOOL CDib::RgbToGrade()
440 {
441 // 位图无效,失败返回
442 if(!IsValid())
443 {
444 return FALSE;
445 }
446
447 // 不是24位位图,失败返回
448 if(GetBitCount() != 24)
449 {
450 return FALSE;
451 }
452
453 // 是压缩位图,失败返回
454 if(m_lpBmpInfoHeader->biCompression != BI_RGB)
455 {
456 return FALSE;
457 }
458
459 // 如果不是灰度位图,才需要转换
460 if(!IsGrade())
461 {
462 // 获取原位图信息
463 LONG lHeight = GetHeight();
464 LONG lWidth = GetWidth();
465 UINT uLineByte = GetLineByte();
466
467 // 计算灰度位图数据所需空间
468 UINT uGradeBmpLineByte = (lWidth + 3) / 4 * 4;
469 DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight;
470
471 // 计算灰度位图所需空间
472 DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + dwGradeBmpDataSize;
473
474 // 设置灰度位图文件头
475 LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
476 memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
477 lpGradeBmpFileHeader->bfType = 0x4d42;
478 lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize;
479 lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
480 + sizeof(RGBQUAD) * 256;
481 lpGradeBmpFileHeader->bfReserved1 = 0;
482 lpGradeBmpFileHeader->bfReserved2 = 0;
483
484 // 为灰度位图分配空间,并初始化为0
485 LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize];
486 memset(lpGradeBmp, 0, dwGradeBmpSize);
487
488 // 设置灰度位图信息头
489 LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp);
490 lpGradeBmpInfoHeader->biBitCount = 8;
491 lpGradeBmpInfoHeader->biClrImportant = 0;
492 lpGradeBmpInfoHeader->biClrUsed = 256;
493 lpGradeBmpInfoHeader->biCompression = BI_RGB;
494 lpGradeBmpInfoHeader->biHeight = lHeight;
495 lpGradeBmpInfoHeader->biPlanes = 1;
496 lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
497 lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize;
498 lpGradeBmpInfoHeader->biWidth = lWidth;
499 lpGradeBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter;
500 lpGradeBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter;
501
502 // 设置灰度位图颜色表
503 LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER));
504
505 // 初始化8位灰度图的调色板信息
506 LPRGBQUAD lpRgbQuad;
507 for(int k = 0; k < 256; k++)
508 {
509 lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k);
510 lpRgbQuad->rgbBlue = k;
511 lpRgbQuad->rgbGreen = k;
512 lpRgbQuad->rgbRed = k;
513 lpRgbQuad->rgbReserved = 0;
514 }
515
516 // 灰度位图数据处理
517 BYTE r, g, b;
518 LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER)
519 + sizeof(RGBQUAD) * 256);
520 // 进行颜色转换
521 for(int i = 0; i < lHeight; i++)
522 {
523 for(int j = 0; j < lWidth; j++)
524 {
525 b = m_lpData[i * uLineByte + 3 * j];
526 g = m_lpData[i * uLineByte + 3 * j + 1];
527 r = m_lpData[i * uLineByte + 3 * j + 2];
528 lpGradeBmpData[i * uGradeBmpLineByte + j] = (BYTE)(0.299 * r + 0.587 * g + 0.114 * b);
529 }
530 }
531
532 // 释放原有位图空间
533 Empty(FALSE);
534
535 // 重新设定原位图指针指向
536 m_lpBmpFileHeader = lpGradeBmpFileHeader;
537 m_lpDib = lpGradeBmp;
538 m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp);
539 m_lpBmpInfoHeader = lpGradeBmpInfoHeader;
540 m_lpRgbQuad = lpGradeBmpRgbQuad;
541 m_lpData = lpGradeBmpData;
542
543 // 设置颜色表标志
544 m_bHasRgbQuad = TRUE;
545 // 设置位图有效标志
546 m_bValid = TRUE;
547 // 生成调色板
548 MakePalette();
549 }
550
551 return TRUE;
552 }
553
554 //***************************************************
555 // 函数功能: 8位灰度位图转24位彩色位图
556 // 输入参数: 无
557 // 返回值: BOOL-TRUE 成功;FALSE 失败
558 //***************************************************
559 BOOL CDib::GradeToRgb()
560 {
561 // 位图无效,失败退出
562 if(!IsValid())
563 {
564 return FALSE;
565 }
566
567 // 不是8位位图,失败退出
568 if(GetBitCount() != 8)
569 {
570 return FALSE;
571 }
572
573 // 是压缩位图,失败返回
574 if(m_lpBmpInfoHeader->biCompression != BI_RGB)
575 {
576 return FALSE;
577 }
578
579 // 是灰度图时,才需转换
580 if(IsGrade())
581 {
582 // 获取原位图信息
583 LONG lHeight = GetHeight();
584 LONG lWidth = GetWidth();
585 UINT uLineByte = GetLineByte();
586
587 // 计算彩色位图数据所需空间
588 UINT uColorBmpLineByte = (lWidth * 24 / 8 + 3) / 4 * 4;
589 DWORD dwColorBmpDataSize = uColorBmpLineByte * lHeight;
590
591 // 计算彩色位图所需空间
592 DWORD dwColorBmpSize = sizeof(BITMAPINFOHEADER) + dwColorBmpDataSize;
593
594 // 设置彩色位图文件头
595 LPBITMAPFILEHEADER lpColorBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
596 memset(lpColorBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
597 lpColorBmpFileHeader->bfType = 0x4d42;
598 lpColorBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwColorBmpSize;
599 lpColorBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
600 lpColorBmpFileHeader->bfReserved1 = 0;
601 lpColorBmpFileHeader->bfReserved2 = 0;
602
603 // 为彩色位图分配空间,并初始化为0
604 LPBYTE lpColorBmp = (LPBYTE)new BYTE[dwColorBmpSize];
605 memset(lpColorBmp, 0, dwColorBmpSize);
606
607 // 设置彩色位图信息头
608 LPBITMAPINFOHEADER lpColorBmpInfoHeader = (LPBITMAPINFOHEADER)(lpColorBmp);
609 lpColorBmpInfoHeader->biBitCount = 24;
610 lpColorBmpInfoHeader->biClrImportant = 0;
611 lpColorBmpInfoHeader->biClrUsed = 0;
612 lpColorBmpInfoHeader->biCompression = BI_RGB;
613 lpColorBmpInfoHeader->biHeight = lHeight;
614 lpColorBmpInfoHeader->biPlanes = 1;
615 lpColorBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
616 lpColorBmpInfoHeader->biSizeImage = dwColorBmpDataSize;
617 lpColorBmpInfoHeader->biWidth = lWidth;
618 lpColorBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter;
619 lpColorBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter;
620
621 // 彩色位图数据处理
622 LPBYTE lpColorBmpData = (LPBYTE)(lpColorBmp + sizeof(BITMAPINFOHEADER));
623 // 进行颜色转换
624 for(int i = 0; i < lHeight; i++)
625 {
626 for(int j = 0; j < lWidth; j++)
627 {
628 BYTE btValue = m_lpData[i * uLineByte + j];
629 lpColorBmpData[i * uColorBmpLineByte + 3 * j] = btValue;
630 lpColorBmpData[i * uColorBmpLineByte + 3 * j + 1] = btValue;
631 lpColorBmpData[i * uColorBmpLineByte + 3 * j + 2] = btValue;
632 }
633 }
634
635 // 释放原有位图空间
636 Empty(FALSE);
637
638 // 重新设定原位图指针指向
639 m_lpBmpFileHeader = lpColorBmpFileHeader;
640 m_lpDib = lpColorBmp;
641 m_lpBmpInfo = (LPBITMAPINFO)(lpColorBmp);
642 m_lpBmpInfoHeader = lpColorBmpInfoHeader;
643 m_lpRgbQuad = NULL;
644 m_lpData = lpColorBmpData;
645
646 // 设置颜色表标志
647 m_bHasRgbQuad = FALSE;
648 // 设置位图有效标志
649 m_bValid = TRUE;
650 }
651
652 return TRUE;
653 }
654
655 //***************************************************
656 // 函数功能: 判断是否含有颜色表
657 // 输入参数: 无
658 // 返回值: 判断结果:TRUE-含有颜色表;FALSE-不含颜色表
659 //***************************************************
660 BOOL CDib::HasRgbQuad()
661 {
662 return m_bHasRgbQuad;
663 }
664
665 //***************************************************
666 // 函数功能: 判断是否是灰度图
667 // 输入参数: 无
668 // 返回值: 判断结果:TRUE-是灰度图;FALSE-是彩色图
669 //***************************************************
670 BOOL CDib::IsGrade()
671 {
672 return (GetBitCount() < 9 && GetBitCount() > 0);
673 }
674
675 //***************************************************
676 // 函数功能: 判断位图是否有效
677 // 输入参数: 无
678 // 返回值: 判断结果:TRUE-位图有效;FALSE-位图无效
679 //***************************************************
680 BOOL CDib::IsValid()
681 {
682 return m_bValid;
683 }
684
685 //***************************************************
686 // 函数功能: 清理空间
687 // 输入参数: BOOL bFlag-TRUE 全部清空;FALSE 部分清空
688 // 返回值: 无
689 //***************************************************
690 void CDib::Empty(BOOL bFlag)
691 {
692 // 文件名清空
693 if(bFlag)
694 {
695 m_fileName="";
696 }
697
698 // 释放位图文件头指针空间
699 if(m_lpBmpFileHeader != NULL)
700 {
701 delete [] m_lpBmpFileHeader;
702 m_lpBmpFileHeader = NULL;
703 }
704
705 // 释放位图指针空间
706 if(m_lpDib != NULL)
707 {
708 delete [] m_lpDib;
709 m_lpDib = NULL;
710 m_lpBmpInfo = NULL;
711 m_lpBmpInfoHeader = NULL;
712 m_lpRgbQuad = NULL;
713 m_lpData = NULL;
714 }
715
716 // 释放调色板
717 if(m_hPalette != NULL)
718 {
719 DeleteObject(m_hPalette);
720 m_hPalette = NULL;
721 }
722
723 // 设置不含颜色表
724 m_bHasRgbQuad = FALSE;
725
726 // 设置位图无效
727 m_bValid = FALSE;
728
729 }

 

      3.在CImgProDoc.h文件中,添加

public:

CDib dib;

// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()//非添加语句
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
public:
CDib* GetDib(void);

在CImgProDoc.cpp中,实现上面添加的两个成员函数:

VC++2010开发数字图像系统1VC++2010开发数字图像系统1
 1 CDib* CImgProDoc::GetDib(void)
2 {
3 return &dib;
4 }
5 BOOL CImgProDoc::OnOpenDocument(LPCTSTR lpszPathName)
6 {
7 if(!CDocument::OnOpenDocument(lpszPathName))
8 return FALSE;
9 if(!dib.LoadFromFile(lpszPathName))
10 {
11 AfxMessageBox(_T("加载位图失败!"));
12 return FALSE;
13 }
14 return TRUE;
15 }
View Code

    4. 图像的显示

在CImgProView.cpp文件中将OnDraw函数修改如下:

VC++2010开发数字图像系统1VC++2010开发数字图像系统1
 1 // CImgProView 绘制
2
3 void CImgProView::OnDraw(CDC* pDC)
4 {
5 CImgProDoc* pDoc = GetDocument();
6 ASSERT_VALID(pDoc);
7 if (!pDoc)
8 return;
9
10 // TODO: 在此处为本机数据添加绘制代码
11 CDib *pDib=pDoc->GetDib();
12 if(pDib->IsValid())
13 {
14 CSize size=pDib->GetDimension();
15 pDib->Draw(pDC,CPoint(0,0),size);
16 }
17 }
View Code

       5. Ctrl+F5运行

VC++2010开发数字图像系统1