我是靠谱客的博主 疯狂方盒,最近开发中收集的这篇文章主要介绍数字图像处理技术--学习笔记2--vc++处理数字图像的基本方法,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

【1】使用DIB处理数字图像

DIB是外部的位图格式,存储为BMP后缀的位图文件。
DIB可以在不同的机器或系统中显示位图所固有的图像。
但是MFC不提供对DIB的支持,单纯使用DIB只能进行面向过程编程。
操作函数:
在这里插入图片描述

【2】使用自定义CDib类处理数字图像

设计一个设备无关类CDib,封装DIB位图处理所需要的基本成员变量和成员函数。

** Dib.h**

//======================================================================
// 文件: Dib.h
// 内容: 设备无关位图类-头文件
// 功能: (1)位图的加载与保存;
//        (2)位图信息的获取;
//        (3)位图数据的获取;
//        (3)位图的显示;
//        (4)位图的转换;
//        (5)位图相关判断;
//======================================================================

#pragma once

#include "afx.h"

class CDib : public CObject
{
public:
    // 构造函数,初始化数据成员
    CDib(void);

    // 析构函数,释放内存空间
    ~CDib(void);

    // 从文件加载位图
    BOOL LoadFromFile(LPCTSTR lpszPath);

    // 将位图保存到文件
    BOOL SaveToFile(LPCTSTR lpszPath);

    // 获取位图文件名
    LPCTSTR GetFileName();

    // 获取位图宽度
    LONG GetWidth();

    // 获取位图高度
    LONG GetHeight();

    // 获取位图的宽度和高度
    CSize GetDimension();  
    
    // 获取位图大小
    DWORD GetSize();

    // 获取单个像素所占位数
    WORD GetBitCount();

    // 获取每行像素所占字节数
    UINT GetLineByte();

    // 获取位图颜色数
    DWORD GetNumOfColor();

    // 获取位图颜色表
    LPRGBQUAD GetRgbQuad();

    // 获取位图数据
    LPBYTE GetData();
      
    // 显示位图
    BOOL Draw(CDC *pDC, CPoint origin, CSize size);

    // 24位彩色位图转8位灰度位图
    BOOL RgbToGrade();

    // 8位灰度位图转24位彩色位图
    BOOL GradeToRgb();

    // 判断是否含有颜色表
    BOOL HasRgbQuad();

    // 判断是否是灰度图
    BOOL IsGrade();

    // 判断位图是否有效
    BOOL IsValid();  

protected:
    // 计算位图颜色表长度
    DWORD CalcRgbQuadLength();

    // 根据颜色表生成调色板
    BOOL MakePalette();

    // 清理空间
    void Empty(BOOL bFlag = TRUE);

private:
    // 位图文件名
    char m_fileName[_MAX_PATH];

    // 位图文件头指针    
    LPBITMAPFILEHEADER m_lpBmpFileHeader; // 需要动态分配和释放 

    // 位图指针(包含除位图文件头的所有内容)
	LPBYTE m_lpDib;                       // 需要动态分配和释放

    // 位图信息指针
    LPBITMAPINFO m_lpBmpInfo;

	// 位图信息头指针
	LPBITMAPINFOHEADER m_lpBmpInfoHeader;  

    // 位图颜色表指针
	LPRGBQUAD m_lpRgbQuad; 

    // 位图数据指针
	LPBYTE m_lpData; 

    // 调色板句柄
	HPALETTE m_hPalette;

    // 是否有颜色表
    BOOL m_bHasRgbQuad;

    // 位图是否有效
    BOOL m_bValid;
};

//======================================================================
// 文件: Dib.cpp
// 内容: 设备无关位图类-源文件
// 功能: (1)位图的加载与保存;
//        (2)位图信息的获取;
//        (3)位图数据的获取;
//        (3)位图的显示;
//        (4)位图的转换;
//        (5)位图相关判断;
//======================================================================

#include "StdAfx.h"
#include "Dib.h"

//=======================================================
// 函数功能: 构造函数,初始化数据成员
// 输入参数: 无
// 返回值:   无
//=======================================================
CDib::CDib(void)
{
    // 数据成员初始化
    strcpy(m_fileName, "");
    m_lpBmpFileHeader = NULL;
    m_lpDib = NULL;   
    m_lpBmpInfo = NULL;
    m_lpBmpInfoHeader = NULL;
    m_lpRgbQuad = NULL;
    m_lpData = NULL;
    m_hPalette = NULL;
    m_bHasRgbQuad = FALSE;
    m_bValid = FALSE;
}

//=======================================================
// 函数功能: 析构函数,释放内存空间
// 输入参数: 无
// 返回值:   无
//=======================================================
CDib::~CDib(void)
{
    // 清理空间
    Empty();
}

//=======================================================
// 函数功能: 从文件加载位图
// 输入参数: LPCTSTR lpszPath-待加载位图文件路径
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::LoadFromFile(LPCTSTR lpszPath)
{
    // 记录位图文件名
    strcpy(m_fileName, lpszPath);

    // 以读模式打开位图文件
    CFile dibFile;
    if(!dibFile.Open(m_fileName, CFile::modeRead | CFile::shareDenyWrite))
    {
        return FALSE;
    }

    // 清理空间
    Empty(FALSE); 
    
    // 为位图文件头分配空间,并初始化为0
    m_lpBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
    memset(m_lpBmpFileHeader, 0, sizeof(BITMAPFILEHEADER)); 

    // 读取位图文件头
    int nCount = dibFile.Read((void *)m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));
    if(nCount != sizeof(BITMAPFILEHEADER)) 
    {
        return FALSE;
    } 

    // 判断此文件是不是位图文件(“0x4d42”代表“BM”)
    if(m_lpBmpFileHeader->bfType == 0x4d42)
    {
        // 是位图文件

        // 计算除位图文件头的空间大小,分配空间并初始化为0
        DWORD dwDibSize = dibFile.GetLength() - sizeof(BITMAPFILEHEADER);
        m_lpDib = new BYTE[dwDibSize];
        memset(m_lpDib, 0, dwDibSize);

        // 读取除位图文件头的所有数据
        dibFile.Read(m_lpDib, dwDibSize);

        // 关闭位图文件
        dibFile.Close();

        // 设置位图信息指针
        m_lpBmpInfo = (LPBITMAPINFO)m_lpDib;

        // 设置位图信息头指针
        m_lpBmpInfoHeader = (LPBITMAPINFOHEADER)m_lpDib;

        // 设置位图颜色表指针
        m_lpRgbQuad = (LPRGBQUAD)(m_lpDib + m_lpBmpInfoHeader->biSize);

        // 如果位图没有设置位图使用的颜色数,设置它
        if(m_lpBmpInfoHeader->biClrUsed == 0)
        {
            m_lpBmpInfoHeader->biClrUsed = GetNumOfColor();
        }

        // 计算颜色表长度
        DWORD dwRgbQuadLength = CalcRgbQuadLength();

        // 设置位图数据指针
        m_lpData = m_lpDib + m_lpBmpInfoHeader->biSize + dwRgbQuadLength;

        // 判断是否有颜色表
        if(m_lpRgbQuad == (LPRGBQUAD)m_lpData)
        {
            m_lpRgbQuad = NULL;    // 将位图颜色表指针置空
            m_bHasRgbQuad = FALSE; // 无颜色表
        }
        else
        {
            m_bHasRgbQuad = TRUE;  // 有颜色表
            MakePalette();         // 根据颜色表生成调色板
        }        

        // 设置位图大小(因为很多位图文件都不设置此项)
        m_lpBmpInfoHeader->biSizeImage = GetSize();

        // 位图有效
        m_bValid = TRUE;

        return TRUE;
    }
    else
    {
        // 不是位图文件
        m_bValid = FALSE;

        return FALSE;
    }     

}

//=======================================================
// 函数功能: 将位图保存到文件
// 输入参数: LPCTSTR lpszPath-位图文件保存路径
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::SaveToFile(LPCTSTR lpszPath)
{
    // 以写模式打开文件
	CFile dibFile;
	if(!dibFile.Open(lpszPath, CFile::modeCreate | CFile::modeReadWrite 
		| CFile::shareExclusive))
    {
        return FALSE;
    }

    // 记录位图文件名
    strcpy(m_fileName, lpszPath);

    // 将文件头结构写进文件
    dibFile.Write(m_lpBmpFileHeader, sizeof(BITMAPFILEHEADER));

    // 将文件信息头结构写进文件
    dibFile.Write(m_lpBmpInfoHeader, sizeof(BITMAPINFOHEADER));

    // 计算颜色表长度
    DWORD dwRgbQuadlength = CalcRgbQuadLength();

    // 如果有颜色表的话,将颜色表写进文件
    if(dwRgbQuadlength != 0)
    {
        dibFile.Write(m_lpRgbQuad, dwRgbQuadlength);
    }                                                        

    // 将位图数据写进文件
    DWORD dwDataSize = GetLineByte() * GetHeight();
    dibFile.Write(m_lpData, dwDataSize);

    // 关闭文件
    dibFile.Close();
		
    return TRUE;
}

//=======================================================
// 函数功能: 获取位图文件名
// 输入参数: 无
// 返回值:   LPCTSTR-位图文件名
//=======================================================
LPCTSTR CDib::GetFileName()
{
    return m_fileName;
}

//=======================================================
// 函数功能: 获取位图宽度
// 输入参数: 无
// 返回值:   LONG-位图宽度
//=======================================================
LONG CDib::GetWidth()
{
    return m_lpBmpInfoHeader->biWidth;
}

//=======================================================
// 函数功能: 获取位图高度
// 输入参数: 无
// 返回值:   LONG-位图高度
//=======================================================
LONG CDib::GetHeight()
{
    return m_lpBmpInfoHeader->biHeight;
}

//=======================================================
// 函数功能: 获取位图的宽度和高度
// 输入参数: 无
// 返回值:   CSize-位图的宽度和高度
//=======================================================
CSize CDib::GetDimension()
{
    return CSize(GetWidth(), GetHeight());
}

//=======================================================
// 函数功能: 获取位图大小
// 输入参数: 无
// 返回值:   DWORD-位图大小
//=======================================================
DWORD CDib::GetSize()
{
    if(m_lpBmpInfoHeader->biSizeImage != 0)
    {
        return m_lpBmpInfoHeader->biSizeImage;
    }
    else
    {       
        return GetWidth() * GetHeight();
    }
}

//=======================================================
// 函数功能: 获取单个像素所占位数
// 输入参数: 无
// 返回值:   WORD-单个像素所占位数
//=======================================================
WORD CDib::GetBitCount()
{
    return m_lpBmpInfoHeader->biBitCount;
}       

//=======================================================
// 函数功能: 获取每行像素所占字节数
// 输入参数: 无
// 返回值:   UINT-每行像素所占字节数
//=======================================================
UINT CDib::GetLineByte()
{ 
    return (GetWidth() * GetBitCount() / 8 + 3) / 4 * 4;;
}

//=======================================================
// 函数功能: 获取位图颜色数
// 输入参数: 无
// 返回值:   DWORD-位图颜色数
//=======================================================
DWORD CDib::GetNumOfColor()
{
    UINT dwNumOfColor;     

    if ((m_lpBmpInfoHeader->biClrUsed == 0) 
        && (m_lpBmpInfoHeader->biBitCount < 9))
	{
		switch (m_lpBmpInfoHeader->biBitCount)
		{
		    case 1: dwNumOfColor = 2; break;
		    case 4: dwNumOfColor = 16; break;
		    case 8: dwNumOfColor = 256;
		}
	}
    else
    {
        dwNumOfColor = m_lpBmpInfoHeader->biClrUsed;
    }  		

    return dwNumOfColor; 
}

//=======================================================
// 函数功能: 计算位图颜色表长度
// 输入参数: 无
// 返回值:   DWORD-位图颜色表长度
//=======================================================
DWORD CDib::CalcRgbQuadLength()
{
    DWORD dwNumOfColor = GetNumOfColor();
    if(dwNumOfColor > 256)
    {
        dwNumOfColor = 0;
    }
    return  dwNumOfColor * sizeof(RGBQUAD);
}

//=======================================================
// 函数功能: 获取位图颜色表
// 输入参数: 无
// 返回值:   LPRGBQUAD-位图颜色表指针
//=======================================================
LPRGBQUAD CDib::GetRgbQuad()
{
    return m_lpRgbQuad;
}

//=======================================================
// 函数功能: 获取位图数据
// 输入参数: 无
// 返回值:   LPBYTE-位图数据指针
//=======================================================
LPBYTE CDib::GetData()
{
    return m_lpData;
}

//=======================================================
// 函数功能: 根据颜色表生成调色板
// 输入参数: 无
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::MakePalette()
{
    // 计算颜色表长度
    DWORD dwRgbQuadLength = CalcRgbQuadLength();

    // 如果颜色表长度为0,则不生成逻辑调色板
	if(dwRgbQuadLength == 0) 
    {
        return FALSE;
    }

	//删除旧的调色板对象
	if(m_hPalette != NULL) 
    {
        DeleteObject(m_hPalette);
        m_hPalette = NULL;
    }

	// 申请缓冲区,初始化为0
    DWORD dwNumOfColor = GetNumOfColor();
    DWORD dwSize = 2 * sizeof(WORD) + dwNumOfColor * sizeof(PALETTEENTRY);
	LPLOGPALETTE lpLogPalette = (LPLOGPALETTE) new BYTE[dwSize];
    memset(lpLogPalette, 0, dwSize);

    // 生成逻辑调色板
	lpLogPalette->palVersion = 0x300;
	lpLogPalette->palNumEntries = dwNumOfColor;
	LPRGBQUAD lpRgbQuad = (LPRGBQUAD) m_lpRgbQuad;
	for(int i = 0; i < dwNumOfColor; i++) 
    {
		lpLogPalette->palPalEntry[i].peRed = lpRgbQuad->rgbRed;
		lpLogPalette->palPalEntry[i].peGreen = lpRgbQuad->rgbGreen;
		lpLogPalette->palPalEntry[i].peBlue = lpRgbQuad->rgbBlue;
		lpLogPalette->palPalEntry[i].peFlags = 0;
		lpRgbQuad++;
	}

	// 创建逻辑调色板
	m_hPalette = CreatePalette(lpLogPalette);

	// 释放缓冲区
	delete [] lpLogPalette;

    return TRUE;
}

//=======================================================
// 函数功能: 显示位图
// 输入参数:
//            CDC *pDC-设备环境指针
//            CPoint origin-显示矩形区域的左上角
//            CSize size-显示矩形区域的尺寸
// 返回值:
//            BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::Draw(CDC *pDC, CPoint origin, CSize size)
{
    // 位图无效,无法绘制,返回错误
    if(!IsValid())
    {
        return FALSE;
    }

    // 旧的调色板句柄
	HPALETTE hOldPalette = NULL;

	// 如果位图指针为空,则返回FALSE
	if(m_lpDib == NULL) 
    {
        return FALSE;
    }

	// 如果位图有调色板,则选进设备环境中
	if(m_hPalette != NULL) 
    {
		hOldPalette = SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE);
	}

	// 设置位图伸缩模式
	pDC->SetStretchBltMode(COLORONCOLOR);

	// 将位图在pDC所指向的设备上进行显示
	StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,
		0, 0, GetWidth(), GetHeight(), m_lpData, m_lpBmpInfo, DIB_RGB_COLORS, SRCCOPY);

	// 恢复旧的调色板
	if(hOldPalette != NULL)
    {
        SelectPalette(pDC->GetSafeHdc(), hOldPalette, TRUE);
    }

    return TRUE;
}

//=======================================================
// 函数功能: 24位彩色位图转8位灰度位图
// 输入参数: 无
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::RgbToGrade()
{
    // 位图无效,失败返回
    if(!IsValid())
    {
        return FALSE;
    }

    // 不是24位位图,失败返回
    if(GetBitCount() != 24)
    {
        return FALSE;
    }

    // 是压缩位图,失败返回
    if(m_lpBmpInfoHeader->biCompression != BI_RGB)
    {
        return FALSE;
    }

    // 如果不是灰度位图,才需要转换
    if(!IsGrade())
    {
        // 获取原位图信息
        LONG lHeight = GetHeight();
        LONG lWidth = GetWidth();
        UINT uLineByte = GetLineByte();

        // 计算灰度位图数据所需空间
        UINT uGradeBmpLineByte = (lWidth + 3) / 4 * 4;
        DWORD dwGradeBmpDataSize = uGradeBmpLineByte * lHeight; 

        // 计算灰度位图所需空间
        DWORD dwGradeBmpSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256 + dwGradeBmpDataSize;

        // 设置灰度位图文件头
        LPBITMAPFILEHEADER lpGradeBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
        memset(lpGradeBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
        lpGradeBmpFileHeader->bfType = 0x4d42;
        lpGradeBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwGradeBmpSize;
        lpGradeBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
                                          + sizeof(RGBQUAD) * 256;
        lpGradeBmpFileHeader->bfReserved1 = 0;
        lpGradeBmpFileHeader->bfReserved2 = 0;            

        // 为灰度位图分配空间,并初始化为0
        LPBYTE lpGradeBmp = (LPBYTE)new BYTE[dwGradeBmpSize];
        memset(lpGradeBmp, 0, dwGradeBmpSize);

        // 设置灰度位图信息头
        LPBITMAPINFOHEADER lpGradeBmpInfoHeader = (LPBITMAPINFOHEADER)(lpGradeBmp);
        lpGradeBmpInfoHeader->biBitCount = 8;
        lpGradeBmpInfoHeader->biClrImportant = 0;
        lpGradeBmpInfoHeader->biClrUsed = 256;
        lpGradeBmpInfoHeader->biCompression = BI_RGB;
        lpGradeBmpInfoHeader->biHeight = lHeight;
        lpGradeBmpInfoHeader->biPlanes = 1;
        lpGradeBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
        lpGradeBmpInfoHeader->biSizeImage = dwGradeBmpDataSize;
        lpGradeBmpInfoHeader->biWidth = lWidth;
        lpGradeBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter;
        lpGradeBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter;

        // 设置灰度位图颜色表
        LPRGBQUAD lpGradeBmpRgbQuad = (LPRGBQUAD)(lpGradeBmp + sizeof(BITMAPINFOHEADER));

        // 初始化8位灰度图的调色板信息
        LPRGBQUAD lpRgbQuad;               
        for(int k = 0; k < 256; k++)
        {
            lpRgbQuad = (LPRGBQUAD)(lpGradeBmpRgbQuad + k);
            lpRgbQuad->rgbBlue = k; 
            lpRgbQuad->rgbGreen = k;
            lpRgbQuad->rgbRed = k;
            lpRgbQuad->rgbReserved = 0;
        }

        // 灰度位图数据处理
        BYTE r, g, b; 
        LPBYTE lpGradeBmpData = (LPBYTE)(lpGradeBmp + sizeof(BITMAPINFOHEADER) 
                                         + sizeof(RGBQUAD) * 256);
        // 进行颜色转换
        for(int i = 0; i < lHeight; i++)
        {
            for(int j = 0; j < lWidth; j++)
            {
                b = m_lpData[i * uLineByte + 3 * j];
                g = m_lpData[i * uLineByte + 3 * j + 1];
                r = m_lpData[i * uLineByte + 3 * j + 2];
                lpGradeBmpData[i * uGradeBmpLineByte + j] = (BYTE)(0.299 * r + 0.587 * g + 0.114 * b); 
            }
        }

        // 释放原有位图空间
        Empty(FALSE);

        // 重新设定原位图指针指向
        m_lpBmpFileHeader = lpGradeBmpFileHeader;
        m_lpDib = lpGradeBmp;
        m_lpBmpInfo = (LPBITMAPINFO)(lpGradeBmp);
        m_lpBmpInfoHeader = lpGradeBmpInfoHeader;
        m_lpRgbQuad = lpGradeBmpRgbQuad;
        m_lpData = lpGradeBmpData;

        // 设置颜色表标志
        m_bHasRgbQuad = TRUE;  
        // 设置位图有效标志
        m_bValid = TRUE;
        // 生成调色板
        MakePalette();
    }

    return TRUE;   
}   

//=======================================================
// 函数功能: 8位灰度位图转24位彩色位图
// 输入参数: 无
// 返回值:   BOOL-TRUE 成功;FALSE 失败
//=======================================================
BOOL CDib::GradeToRgb()
{
    // 位图无效,失败退出
    if(!IsValid())
    {
        return FALSE;
    }

    // 不是8位位图,失败退出
    if(GetBitCount() != 8)
    {
        return FALSE;
    }

    // 是压缩位图,失败返回
    if(m_lpBmpInfoHeader->biCompression != BI_RGB)
    {
        return FALSE;
    }

    // 是灰度图时,才需转换
    if(IsGrade())
    {
        // 获取原位图信息
        LONG lHeight = GetHeight();
        LONG lWidth = GetWidth();
        UINT uLineByte = GetLineByte();

        // 计算彩色位图数据所需空间
        UINT uColorBmpLineByte = (lWidth * 24 / 8 + 3) / 4 * 4;
        DWORD dwColorBmpDataSize = uColorBmpLineByte * lHeight; 

        // 计算彩色位图所需空间
        DWORD dwColorBmpSize = sizeof(BITMAPINFOHEADER) + dwColorBmpDataSize;

        // 设置彩色位图文件头
        LPBITMAPFILEHEADER lpColorBmpFileHeader = (LPBITMAPFILEHEADER)new BYTE[sizeof(BITMAPFILEHEADER)];
        memset(lpColorBmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
        lpColorBmpFileHeader->bfType = 0x4d42;
        lpColorBmpFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + dwColorBmpSize;
        lpColorBmpFileHeader->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
        lpColorBmpFileHeader->bfReserved1 = 0;
        lpColorBmpFileHeader->bfReserved2 = 0;    

        // 为彩色位图分配空间,并初始化为0
        LPBYTE lpColorBmp = (LPBYTE)new BYTE[dwColorBmpSize];
        memset(lpColorBmp, 0, dwColorBmpSize);

        // 设置彩色位图信息头
        LPBITMAPINFOHEADER lpColorBmpInfoHeader = (LPBITMAPINFOHEADER)(lpColorBmp);
        lpColorBmpInfoHeader->biBitCount = 24;
        lpColorBmpInfoHeader->biClrImportant = 0;
        lpColorBmpInfoHeader->biClrUsed = 0;
        lpColorBmpInfoHeader->biCompression = BI_RGB;
        lpColorBmpInfoHeader->biHeight = lHeight;
        lpColorBmpInfoHeader->biPlanes = 1;
        lpColorBmpInfoHeader->biSize = sizeof(BITMAPINFOHEADER);
        lpColorBmpInfoHeader->biSizeImage = dwColorBmpDataSize;
        lpColorBmpInfoHeader->biWidth = lWidth;
        lpColorBmpInfoHeader->biXPelsPerMeter = m_lpBmpInfoHeader->biXPelsPerMeter;
        lpColorBmpInfoHeader->biYPelsPerMeter = m_lpBmpInfoHeader->biYPelsPerMeter;

        // 彩色位图数据处理
        LPBYTE lpColorBmpData = (LPBYTE)(lpColorBmp + sizeof(BITMAPINFOHEADER));
        // 进行颜色转换
        for(int i = 0; i < lHeight; i++)
        {
            for(int j = 0; j < lWidth; j++)
            {
                BYTE btValue = m_lpData[i * uLineByte + j]; 
                lpColorBmpData[i * uColorBmpLineByte + 3 * j] = btValue;
                lpColorBmpData[i * uColorBmpLineByte + 3 * j + 1] = btValue;
                lpColorBmpData[i * uColorBmpLineByte + 3 * j + 2] = btValue;  
            }
        }

        // 释放原有位图空间
        Empty(FALSE);

        // 重新设定原位图指针指向
        m_lpBmpFileHeader = lpColorBmpFileHeader;
        m_lpDib = lpColorBmp;
        m_lpBmpInfo = (LPBITMAPINFO)(lpColorBmp);
        m_lpBmpInfoHeader = lpColorBmpInfoHeader;
        m_lpRgbQuad = NULL;
        m_lpData = lpColorBmpData;

        // 设置颜色表标志
        m_bHasRgbQuad = FALSE;  
        // 设置位图有效标志
        m_bValid = TRUE;        
    }        

    return TRUE;   
}   
 
//=======================================================
// 函数功能: 判断是否含有颜色表
// 输入参数: 无
// 返回值:   判断结果:TRUE-含有颜色表;FALSE-不含颜色表
//=======================================================
BOOL CDib::HasRgbQuad()
{
    return m_bHasRgbQuad;
}

//=======================================================
// 函数功能: 判断是否是灰度图
// 输入参数: 无
// 返回值:   判断结果:TRUE-是灰度图;FALSE-是彩色图
//=======================================================
BOOL CDib::IsGrade()
{
    return (GetBitCount() < 9 && GetBitCount() > 0);
}

//=======================================================
// 函数功能: 判断位图是否有效
// 输入参数: 无
// 返回值:   判断结果:TRUE-位图有效;FALSE-位图无效
//=======================================================
BOOL CDib::IsValid()
{
    return m_bValid;
}

//=======================================================
// 函数功能: 清理空间
// 输入参数: BOOL bFlag-TRUE 全部清空;FALSE 部分清空
// 返回值:   无
//=======================================================
void CDib::Empty(BOOL bFlag)
{
    // 文件名清空
    if(bFlag)
    {
        strcpy(m_fileName, "");
    }      

    // 释放位图文件头指针空间
    if(m_lpBmpFileHeader != NULL)
    {
        delete [] m_lpBmpFileHeader;
        m_lpBmpFileHeader = NULL;
    }    

    // 释放位图指针空间
    if(m_lpDib != NULL)
    {
        delete [] m_lpDib;
        m_lpDib = NULL;
        m_lpBmpInfo = NULL;
        m_lpBmpInfoHeader = NULL;
        m_lpRgbQuad = NULL;
        m_lpData = NULL;           
    }       

    // 释放调色板
    if(m_hPalette != NULL)
    {
        DeleteObject(m_hPalette);
        m_hPalette = NULL;
    }    

    // 设置不含颜色表
    m_bHasRgbQuad = FALSE;
    
    // 设置位图无效
    m_bValid = FALSE;

}  

【3】使用GDI+处理数字图像

GDI+接口时MS Whistler操作系统中的一部分,是GDI的一个新版本。
1.GDI+的新特性
与GDI相比,GDI+增加了下列的新特性:
(1)渐变画刷
(2)样条曲线
(3)持久的路径对象
(4)矩阵和矩阵变换
(5)Alpha混色
2.GDI+编程模块的变化
(1)不在使用设备环境或句柄
(2)绘图方式变化
3.Graphics绘图方法直接将Pen,Brush等对象作为自己的参数
4.不再使用“当前位置“
5.形状轮廓绘制和填充采用不同的方法
6.简化区域的创建

[例子】使用GDI+绘图

新建个mfc的单文档程序。
注意 我使用的vs2019,新建的MFC,没有stdafx.h,而是改成pch.h了

(1)添加包含文件gdiplus.h以及类库gdiplus.lib

在pch.h中添加gdiplus.h,
在链接器-输入-附加依赖项中添加gdiplus.lib,或者在pch.h中添加#pragma comment(lib,“gdiplus.lib”)

(2)app里添加变量 ULONG_PTR m_gdiplusToken;

保存GDI+被初始化后,在应用程序中的GDI+标识,以便引用该标识来调用Gdiplus::GdiplusShutdown以关闭GDI+

(3)app中添加ExitInstance的重载
Gdiplus::GdiplusShutdown(m_gdiplusToken);
return CWinApp::ExitInstance();
(4)在app的InitInstance中添加初始话GDI+的代码
CWinApp::InitInstance();
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&m_gdiplusToken,&gdiplusStartupInput,NULL);
(5)在需要绘图的窗口或者视图类中,添加GDI+的绘图代码
//添加GDI+的绘制代码
	using namespace Gdiplus;
	Graphics graphics(pDC->m_hDC);
	Pen newPen(Color(0, 255, 0), 3);
	//创建填充画刷,前景色为绿色,背景色为蓝色
	HatchBrush newBrush(HatchStyleCross, Color(100, 0, 255, 0), Color(100, 0, 0, 255));
	//绘制矩形
	graphics.DrawRectangle(&newPen, 50, 50, 800, 600);//在(50,50)处绘制长100,高60的矩形
	//填充矩形
	graphics.FillRectangle(&newBrush, 50, 50, 800, 600);//在(50,50)处填充长100,高60的区域

GDI+绘制直线
void CMyView::OnDraw(CDCpDC)
{
CMyDoc
pDoc=GetDocument();
ASSWET_VALID(pDoc);
using namespace Gdiplus;
Graphics graphics(pDc->m_hDC);
Pen newPen(Color(255,0,0),3);//颜色,线宽度
graphics.DrawLine(&newPen,20,10,200,100);//起始点和终点坐标
}

最后

以上就是疯狂方盒为你收集整理的数字图像处理技术--学习笔记2--vc++处理数字图像的基本方法的全部内容,希望文章能够帮你解决数字图像处理技术--学习笔记2--vc++处理数字图像的基本方法所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部