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


    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  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中,实现上面添加的两个成员函数:

     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函数修改如下:

     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运行

  • 相关阅读:
    正则表达式--验证中国手机号
    PostgreSQ数据库安全连接请求问题
    golang时间正反格式化
    Git 分支管理和冲突解决
    golang交叉编译
    ps命令
    Redis应用场景
    SecureCRT for Mac
    Redis作者谈Redis应用场景
    redis 五种数据的应用场景
  • 原文地址:https://www.cnblogs.com/sxzheng/p/sxzheng.html
Copyright © 2020-2023  润新知