VS2010编程小技巧:1.注意在文档类C..Doc中使用和在视图类C..View中使用MessageBox函数时的参数不相同,不要用错。2.创建与控件关联的指针变量时,一定要注意初始化,不要形成垂悬指针,否则会出现“烫烫烫烫..."”屯屯屯...的乱码。
这里我们利用自己的图像函数库去处理数字图像,在掌握基本方法和基本理论后再去结合OpenCV和matlab去实现算法。
- 新建一基于单文档的MFC应用程序(选择SDI单文档选项,其他选择默认)。
- 添加自己的类库(Dib.h和Dib.cpp两个文件)
Dib.h
1 //************************************************** 2 // Name: Dib.h 3 // Purpose: ImgPro 6 // Created: 2013/3/28 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中,实现上面添加的两个成员函数:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
4. 图像的显示
在CImgProView.cpp文件中将OnDraw函数修改如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
5. Ctrl+F5运行