當前位置:編程學習大全網 - 源碼下載 - 求C++圖像處理的程序

求C++圖像處理的程序

在MFC下自己構造壹個DIB類實現上述功能還是有很多現成的代碼~

下面就是壹個構造的DIB類,但是僅僅提供了最基本的壹些操作,代碼來自《Visual C++數字圖像處理典型算法及實現》。// DibImage.h: interface for the CDibImage class.

//

//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DIBIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_)

#define AFX_DIBIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

DECLARE_HANDLE(HDIB); // DIB句柄

#define PALVERSION 0x300 // DIB常量

/* DIB宏 */

// 判斷是否是Win 3.0的DIB

#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))

// 計算矩形區域的寬度

#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)

// 計算矩形區域的高度

#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)

// 在計算圖像大小時,采用公式:biSizeImage = biWidth' × biHeight。

// 是biWidth',而不是biWidth,這裏的biWidth'必須是4的整倍數,表示

// 大於或等於biWidth的,離4最近的整倍數。WIDTHBYTES就是用來計算

// biWidth'

#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)

// Dib文件頭標誌(字符串"BM",寫DIB時用到該常數)

#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')

class CDibImage

{

// Constructor and Destructor ///////////////////////////////

public:

CDibImage();

virtual ~CDibImage();

// function /////////////////////////////////////////////////

public:

BOOL PaintDIB (HDC, LPRECT, HDIB, LPRECT, CPalette* pPal);

BOOL CreateDIBPalette(HDIB hDIB, CPalette* cPal);

LPSTR FindDIBBits (LPSTR lpbi);

DWORD DIBWidth (LPSTR lpDIB);

DWORD DIBHeight (LPSTR lpDIB);

WORD PaletteSize (LPSTR lpbi);

WORD DIBNumColors (LPSTR lpbi);

HGLOBAL CopyHandle (HGLOBAL h);

BOOL SaveDIB (HDIB hDib, CFile& file);

HDIB ReadDIBFile(CFile& file);

};

#endif // !defined(AFX_DIBIMAGE_H__254F3D1E_BB20_40DA_AE07_E8E0219DFA8C__INCLUDED_)

///////////////////////////////////////////////////////////////////////

// DibImage.cpp: implementation of the CDibImage class.

// DIB(Independent Bitmap) 函數:

//

// PaintDIB() - 繪制DIB對象

// CreateDIBPalette() - 創建DIB對象調色板

// FindDIBBits() - 返回DIB圖像象素起始位置

// DIBWidth() - 返回DIB寬度

// DIBHeight() - 返回DIB高度

// PaletteSize() - 返回DIB調色板大小

// DIBNumColors() - 計算DIB調色板顏色數目

// CopyHandle() - 拷貝內存塊

//

// SaveDIB() - 將DIB保存到指定文件中

// ReadDIBFile() - 重指定文件中讀取DIB對象

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "DIBDisplay.h"

#include "DibImage.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CDibImage::CDibImage()

{

}

CDibImage::~CDibImage()

{

}

//////////////////////////////////////////////////////////////////////

// function

//////////////////////////////////////////////////////////////////////

/*************************************************************************

* 函數名稱:

* PaintDIB()

* 參數:

* HDC hDC - 輸出設備DC

* LPRECT lpDCRect - 繪制矩形區域

* HDIB hDIB - 指向DIB對象的指針

* LPRECT lpDIBRect - 要輸出的DIB區域

* CPalette* pPal - 指向DIB對象調色板的指針

* 返回值:

* BOOL - 繪制成功返回TRUE,否則返回FALSE。

* 說明:

* 該函數主要用來繪制DIB對象。其中調用了StretchDIBits()或者

* SetDIBitsToDevice()來繪制DIB對象。輸出的設備由由參數hDC指

* 定;繪制的矩形區域由參數lpDCRect指定;輸出DIB的區域由參數

* lpDIBRect指定。

************************************************************************/

BOOL CDibImage::PaintDIB(HDC hDC,

LPRECT lpDCRect,

HDIB hDIB,

LPRECT lpDIBRect,

CPalette* pPal)

{

LPSTR lpDIBHdr; // BITMAPINFOHEADER指針

LPSTR lpDIBBits; // DIB象素指針

BOOL bSuccess=FALSE; // 成功標誌

HPALETTE hPal=NULL; // DIB調色板

HPALETTE hOldPal=NULL; // 以前的調色板

if (hDIB == NULL)

{

return FALSE;

}

lpDIBHdr = (LPSTR)::GlobalLock((HGLOBAL) hDIB);// 鎖定DIB

lpDIBBits = FindDIBBits(lpDIBHdr); // 找到DIB圖像象素起始位置

if (pPal != NULL) // 獲取DIB調色板,並選中它

{

hPal = (HPALETTE) pPal->m_hObject;

hOldPal = ::SelectPalette(hDC, hPal, TRUE); // 選中調色板

}

::SetStretchBltMode(hDC, COLORONCOLOR); // 設置顯示模式

// 判斷是調用StretchDIBits()還是SetDIBitsToDevice()來繪制DIB對象

if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&

(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))

{

// 原始大小,不用拉伸。

bSuccess = ::SetDIBitsToDevice(hDC, // hDC

lpDCRect->left, // DestX

lpDCRect->top, // DestY

RECTWIDTH(lpDCRect), // nDestWidth

RECTHEIGHT(lpDCRect), // nDestHeight

lpDIBRect->left, // SrcX

(int)DIBHeight(lpDIBHdr) -

lpDIBRect->top -

RECTHEIGHT(lpDIBRect), // SrcY

0, // nStartScan

(WORD)DIBHeight(lpDIBHdr), // nNumScans

lpDIBBits, // lpBits

(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo

DIB_RGB_COLORS); // wUsage

}

else

{

// 非原始大小,拉伸。

bSuccess = ::StretchDIBits(hDC, // hDC

lpDCRect->left, // DestX

lpDCRect->top, // DestY

RECTWIDTH(lpDCRect), // nDestWidth

RECTHEIGHT(lpDCRect), // nDestHeight

lpDIBRect->left, // SrcX

lpDIBRect->top, // SrcY

RECTWIDTH(lpDIBRect), // wSrcWidth

RECTHEIGHT(lpDIBRect), // wSrcHeight

lpDIBBits, // lpBits

(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo

DIB_RGB_COLORS, // wUsage

SRCCOPY); // dwROP

}

::GlobalUnlock((HGLOBAL) hDIB); // 解除鎖定

if (hOldPal != NULL)

{

::SelectPalette(hDC, hOldPal, TRUE); // 恢復以前的調色板

}

return bSuccess;

}

/*************************************************************************

* 函數名稱:

* CreateDIBPalette()

* 參數:

* HDIB hDIB - 指向DIB對象的指針

* CPalette* pPal - 指向DIB對象調色板的指針

* 返回值:

* BOOL - 創建成功返回TRUE,否則返回FALSE。

* 說明:

* 該函數按照DIB創建壹個邏輯調色板,從DIB中讀取顏色表並存到調色板中,

* 最後按照該邏輯調色板創建壹個新的調色板,並返回該調色板的句柄。這樣

* 可以用最好的顏色來顯示DIB圖像。

************************************************************************/

BOOL CDibImage::CreateDIBPalette(HDIB hDIB, CPalette* pPal)

{

LPLOGPALETTE lpPal; // 指向邏輯調色板的指針

HANDLE hLogPal; // 邏輯調色板的句柄

HPALETTE hPal = NULL; // 調色板的句柄

int i; // 循環變量

WORD wNumColors; // 顏色表中的顏色數目

LPSTR lpbi; // 指向DIB的指針

LPBITMAPINFO lpbmi; // 指向BITMAPINFO結構的指針(Win3.0)

LPBITMAPCOREINFO lpbmc; // 指向BITMAPCOREINFO結構的指針

BOOL bWinStyleDIB; // 表明是否是Win3.0 DIB的標記

BOOL bResult = FALSE; // 創建結果

if (hDIB == NULL)

{

return FALSE;

}

lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB); // 鎖定DIB

lpbmi = (LPBITMAPINFO)lpbi; // 獲取指向BITMAPINFO結構的指針(Win3.0)

lpbmc = (LPBITMAPCOREINFO)lpbi; // 獲取指向BITMAPCOREINFO結構的指針

wNumColors = DIBNumColors(lpbi);// 獲取DIB中顏色表中的顏色數目

if (wNumColors != 0)

{

// 分配為邏輯調色板內存

hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)

+ sizeof(PALETTEENTRY)

* wNumColors);

// 如果內存不足,退出

if (hLogPal == 0)

{

::GlobalUnlock((HGLOBAL) hDIB); // 解除鎖定

return FALSE;

}

lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);

lpPal->palVersion = PALVERSION; // 設置版本號

lpPal->palNumEntries = (WORD)wNumColors;// 設置顏色數目

bWinStyleDIB = IS_WIN30_DIB(lpbi); // 判斷是否是WIN3.0的DIB

// 讀取調色板

for (i = 0; i < (int)wNumColors; i++)

{

if (bWinStyleDIB)

{

// 讀取紅色綠色藍色分量

lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;

lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;

lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;

// 保留位

lpPal->palPalEntry[i].peFlags = 0;

}

else

{

// 讀取紅色綠色藍色分量

lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;

lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;

lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;

// 保留位

lpPal->palPalEntry[i].peFlags = 0;

}

}

bResult = pPal->CreatePalette(lpPal);// 按照邏輯調色板創建調色板,並返回指針

::GlobalUnlock((HGLOBAL) hLogPal); // 解除鎖定

::GlobalFree((HGLOBAL) hLogPal); // 釋放邏輯調色板

}

::GlobalUnlock((HGLOBAL) hDIB); // 解除鎖定

return bResult;

}

/*************************************************************************

* 函數名稱:

* FindDIBBits()

* 參數:

* LPSTR lpbi - 指向DIB對象的指針

* 返回值:

* LPSTR - 指向DIB圖像象素起始位置

* 說明:

* 該函數計算DIB中圖像象素的起始位置,並返回指向它的指針。

************************************************************************/

LPSTR CDibImage::FindDIBBits(LPSTR lpbi)

{

return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));

}

/*************************************************************************

* 函數名稱:

* DIBWidth()

* 參數:

* LPSTR lpbi - 指向DIB對象的指針

* 返回值:

* DWORD - DIB中圖像的寬度

* 說明:

* 該函數返回DIB中圖像的寬度。對於Windows 3.0 DIB,返回BITMAPINFOHEADER

* 中的biWidth值;對於其它返回BITMAPCOREHEADER中的bcWidth值。

************************************************************************/

DWORD CDibImage::DIBWidth(LPSTR lpDIB)

{

LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO結構的指針(Win3.0)

LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO結構的指針

lpbmi = (LPBITMAPINFOHEADER)lpDIB;

lpbmc = (LPBITMAPCOREHEADER)lpDIB;

// 返回DIB中圖像的寬度

if (IS_WIN30_DIB(lpDIB))

{

return lpbmi->biWidth; // 對於Windows 3.0 DIB,返回lpbmi->biWidth

}

else

{

return (DWORD)lpbmc->bcWidth; // 對於其它格式的DIB,返回lpbmc->bcWidth

}

}

/*************************************************************************

* 函數名稱:

* DIBHeight()

* 參數:

* LPSTR lpDIB - 指向DIB對象的指針

* 返回值:

* DWORD - DIB中圖像的高度

* 說明:

* 該函數返回DIB中圖像的高度。對於Windows 3.0 DIB,返回BITMAPINFOHEADER

* 中的biHeight值;對於其它返回BITMAPCOREHEADER中的bcHeight值。

************************************************************************/

DWORD CDibImage::DIBHeight(LPSTR lpDIB)

{

LPBITMAPINFOHEADER lpbmi; // 指向BITMAPINFO結構的指針(Win3.0)

LPBITMAPCOREHEADER lpbmc; // 指向BITMAPCOREINFO結構的指針

lpbmi = (LPBITMAPINFOHEADER)lpDIB;

lpbmc = (LPBITMAPCOREHEADER)lpDIB;

// 返回DIB中圖像的寬度

if (IS_WIN30_DIB(lpDIB))

{

return lpbmi->biHeight; // 對於Windows 3.0 DIB,返回lpbmi->biHeight

}

else

{

return (DWORD)lpbmc->bcHeight; // 對於其它格式的DIB,返回lpbmc->bcHeight

}

}

/*************************************************************************

* 函數名稱:

* PaletteSize()

* 參數:

* LPSTR lpbi - 指向DIB對象的指針

* 返回值:

* WORD - DIB中調色板的大小

* 說明:

* 該函數返回DIB中調色板的大小。對於Windows 3.0 DIB,返回顏色數目×

* RGBQUAD的大小;對於其它返回顏色數目×RGBTRIPLE的大小。

************************************************************************/

WORD CDibImage::PaletteSize(LPSTR lpbi)

{

// 計算DIB中調色板的大小

if (IS_WIN30_DIB (lpbi))

{

//返回顏色數目×RGBQUAD的大小

return (WORD)(DIBNumColors(lpbi) * sizeof(RGBQUAD));

}

else

{

//返回顏色數目×RGBTRIPLE的大小

return (WORD)(DIBNumColors(lpbi) * sizeof(RGBTRIPLE));

}

}

/*************************************************************************

* 函數名稱:

* DIBNumColors()

* 參數:

* LPSTR lpbi - 指向DIB對象的指針

* 返回值:

* WORD - 返回調色板中顏色的種數

* 說明:

* 該函數返回DIB中調色板的顏色的種數。對於單色位圖,返回2,

* 對於16色位圖,返回16,對於256色位圖,返回256;對於真彩色

* 位圖(24位),沒有調色板,返回0。

************************************************************************/

WORD CDibImage::DIBNumColors(LPSTR lpbi)

{

WORD wBitCount;

// 對於Windows的DIB, 實際顏色的數目可以比象素的位數要少。

// 對於這種情況,則返回壹個近似的數值。

// 判斷是否是WIN3.0 DIB

if (IS_WIN30_DIB(lpbi))

{

DWORD dwClrUsed;

dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; // 讀取dwClrUsed值

if (dwClrUsed != 0)

{

// 如果dwClrUsed(實際用到的顏色數)不為0,直接返回該值

return (WORD)dwClrUsed;

}

}

// 讀取象素的位數

if (IS_WIN30_DIB(lpbi))

{

wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; // 讀取biBitCount值

}

else

{

wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount; // 讀取biBitCount值

}

// 按照象素的位數計算顏色數目

switch (wBitCount)

{

case 1:

return 2;

break;

case 4:

return 16;

break;

case 8:

return 256;

break;

default:

return 0;

break;

}

}

/*************************************************************************

* 函數名稱:

* CopyHandle()

* 參數:

* HGLOBAL h - 要復制的內存區域

* 返回值:

* HGLOBAL - 復制後的新內存區域

* 說明:

* 該函數復制指定的內存區域。返回復制後的新內存區域,出錯時返回0。

************************************************************************/

HGLOBAL CDibImage::CopyHandle (HGLOBAL h)

{

if (h == NULL)

{

return NULL;

}

DWORD dwLen = ::GlobalSize((HGLOBAL) h); // 獲取指定內存區域大小

HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen); // 分配新內存空間

if (hCopy != NULL) // 判斷分配是否成功

{

void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);

void* lp = ::GlobalLock((HGLOBAL) h);

memcpy(lpCopy, lp, dwLen);

::GlobalUnlock(hCopy);

::GlobalUnlock(h);

}

return hCopy;

}

/*************************************************************************

* 函數名稱:

* SaveDIB()

* 參數:

* HDIB hDib - 要保存的DIB

* CFile& file - 保存文件CFile

* 返回值:

* BOOL - 成功返回TRUE,否則返回FALSE或者CFileException

* 說明:

* 該函數將指定的DIB對象保存到指定的CFile中。該CFile由調用程序打開和關閉。

*************************************************************************/

BOOL CDibImage::SaveDIB(HDIB hDib, CFile& file)

{

BITMAPFILEHEADER bmfHdr; // Bitmap文件頭

LPBITMAPINFOHEADER lpBI; // 指向BITMAPINFOHEADER的指針

DWORD dwDIBSize; // DIB大小

if (hDib == NULL)

{

return FALSE;

}

// 讀取BITMAPINFO結構,並鎖定

lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);

if (lpBI == NULL)

{

return FALSE;

}

// 判斷是否是WIN3.0 DIB

if (!IS_WIN30_DIB(lpBI))

{

// 不支持其它類型的DIB保存

::GlobalUnlock((HGLOBAL) hDib);

return FALSE;

}

////////////////////////////////////////////////////////////////////////

// 填充文件頭///////////////////////////////////////////////////////////

bmfHdr.bfType = DIB_HEADER_MARKER; // 文件類型"BM"

// 計算DIB大小時,最簡單的方法是調用GlobalSize()函數。但是全局內存大小並

// 不是DIB真正的大小,它總是多幾個字節。這樣就需要計算壹下DIB的真實大小。

// 文件頭大小+顏色表大小

// (BITMAPINFOHEADER和BITMAPCOREHEADER結構的第壹個DWORD都是該結構的大小)

dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPSTR)lpBI);

// 計算圖像大小

if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))

{

// 對於RLE位圖,沒法計算大小,只能信任biSizeImage內的值

dwDIBSize += lpBI->biSizeImage;

}

else

{

DWORD dwBmBitsSize; // 象素的大小

dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount))

* lpBI->biHeight; // 大小為Width * Height

dwDIBSize += dwBmBitsSize; // 計算出DIB真正的大小

// 更新biSizeImage(很多BMP文件頭中biSizeImage的值是錯誤的)

lpBI->biSizeImage = dwBmBitsSize;

}

// 計算文件大小:DIB大小+BITMAPFILEHEADER結構大小

bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);

// 兩個保留字

bmfHdr.bfReserved1 = 0;

bmfHdr.bfReserved2 = 0;

// 計算偏移量bfOffBits,它的大小為Bitmap文件頭大小+DIB頭大小+顏色表大小

bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize

+ PaletteSize((LPSTR)lpBI);

/////////////////////////////////////////////////////////////////////////

// 嘗試寫文件////////////////////////////////////////////////////////////

TRY

{

file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 寫文件頭

file.WriteHuge(lpBI, dwDIBSize); // 寫DIB頭和象素

}

CATCH (CFileException, e)

{

::GlobalUnlock((HGLOBAL) hDib);

THROW_LAST();

}

END_CATCH

::GlobalUnlock((HGLOBAL) hDib);

return TRUE;

}

/*************************************************************************

* 函數名稱:

* ReadDIBFile()

* 參數:

* CFile& file - 要讀取得文件文件CFile

* 返回值:

* HDIB - 成功返回DIB的句柄,否則返回NULL。

* 說明:

* 該函數將指定的文件中的DIB對象讀到指定的內存區域中。除BITMAPFILEHEADER

* 外的內容都將被讀入內存。

*************************************************************************/

HDIB CDibImage::ReadDIBFile(CFile& file)

{

BITMAPFILEHEADER bmfHeader;

HDIB hDIB;

LPSTR pDIB;

DWORD dwBitsSize;

dwBitsSize = file.GetLength(); // 獲取DIB(文件)長度(字節)

// 嘗試讀取DIB文件頭

if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))

{

return NULL;

}

// 判斷是否是DIB對象,檢查頭兩個字節是否是"BM"

if (bmfHeader.bfType != DIB_HEADER_MARKER)

{

return NULL;

}

// 為DIB分配內存

hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);

if (hDIB == 0)

{

return NULL;

}

pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=

dwBitsSize - sizeof(BITMAPFILEHEADER) ) // 讀象素

{

::GlobalUnlock((HGLOBAL) hDIB);

::GlobalFree((HGLOBAL) hDIB);

return NULL;

}

::GlobalUnlock((HGLOBAL) hDIB);

return hDIB;

}

  • 上一篇:壹個App 從想法到開發出來的完整流程是怎麽樣的
  • 下一篇:如何把文件上傳至ftp如何把文件上傳至百度網盤
  • copyright 2024編程學習大全網