c++对图像文件进行滤镜处理

c++对图像文件进行滤镜处理,第1张

给你CDib class, 自己调用,可以读,写 BMP。

滤镜功能只是简单的矩阵变换。读入,变换,写出。

CDib 里的函数,看英文名和里面的注解应当能懂。

头文件:

// cdib.h declaration for Inside Visual C++ CDib class

#ifndef _INSIDE_VISUAL_CPP_CDIB

#define _INSIDE_VISUAL_CPP_CDIB

class CDib : public CObject

{

enum Alloc {noAlloc, crtAlloc, heapAlloc}

DECLARE_SERIAL(CDib)

public:

LPVOID m_lpvColorTable

HBITMAP m_hBitmap

LPBYTE m_lpImage // starting address of DIB bits

LPBITMAPINFOHEADER m_lpBMIH// buffer containing the BITMAPINFOHEADER

private:

HGLOBAL m_hGlobal// For external windows we need to free

// could be allocated by this class or allocated externally

Alloc m_nBmihAlloc

Alloc m_nImageAlloc

DWORD m_dwSizeImage// of bits -- not BITMAPINFOHEADER or BITMAPFILEHEADER

int m_nColorTableEntries

HANDLE m_hFile

HANDLE m_hMap

LPVOID m_lpvFile

HPALETTE m_hPalette

public:

CDib()

CDib(CSize size, int nBitCount)// builds BITMAPINFOHEADER

~CDib()

int GetSizeImage() {return m_dwSizeImage}

int GetSizeHeader()

{return sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries}

CSize GetDimensions()

BOOL AttachMapFile(const char* strPathname, BOOL bShare = FALSE)

BOOL CopyToMapFile(const char* strPathname)

BOOL AttachMemory(LPVOID lpvMem, BOOL bMustDelete = FALSE, HGLOBAL hGlobal = NULL)

BOOL Draw(CDC* pDC, CPoint origin, CSize size) // until we implemnt CreateDibSection

HBITMAP CreateSection(CDC* pDC = NULL)

UINT UsePalette(CDC* pDC, BOOL bBackground = FALSE)

BOOL MakePalette()

BOOL SetSystemPalette(CDC* pDC)

BOOL Compress(CDC* pDC, BOOL bCompress = TRUE)// FALSE means decompress

HBITMAP CreateBitmap(CDC* pDC)

BOOL Read(CFile* pFile)

BOOL ReadSection(CFile* pFile, CDC* pDC = NULL)

BOOL Write(CFile* pFile)

void Serialize(CArchive&ar)

void Empty()

private:

void DetachMapFile()

void ComputePaletteSize(int nBitCount)

void ComputeMetrics()

}

#endif // _INSIDE_VISUAL_CPP_CDIB

cpp 文件:

// cdib.cpp

// new version for WIN32

#include "stdafx.h"

#include "cdib.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__

#endif

IMPLEMENT_SERIAL(CDib, CObject, 0)

CDib::CDib()

{

m_hFile = NULL

m_hBitmap = NULL

m_hPalette = NULL

m_nBmihAlloc = m_nImageAlloc = noAlloc

Empty()

}

CDib::CDib(CSize size, int nBitCount)

{

m_hFile = NULL

m_hBitmap = NULL

m_hPalette = NULL

m_nBmihAlloc = m_nImageAlloc = noAlloc

Empty()

ComputePaletteSize(nBitCount)

m_lpBMIH = (LPBITMAPINFOHEADER) new

char[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries]

m_nBmihAlloc = crtAlloc

m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER)

m_lpBMIH->biWidth = size.cx

m_lpBMIH->biHeight = size.cy

m_lpBMIH->biPlanes = 1

m_lpBMIH->biBitCount = nBitCount

m_lpBMIH->biCompression = BI_RGB

m_lpBMIH->biSizeImage = 0

m_lpBMIH->biXPelsPerMeter = 0

m_lpBMIH->biYPelsPerMeter = 0

m_lpBMIH->biClrUsed = m_nColorTableEntries

m_lpBMIH->biClrImportant = m_nColorTableEntries

ComputeMetrics()

memset(m_lpvColorTable, 0, sizeof(RGBQUAD) * m_nColorTableEntries)

m_lpImage = NULL // no data yet

}

CDib::~CDib()

{

Empty()

}

CSize CDib::GetDimensions()

{

if(m_lpBMIH == NULL) return CSize(0, 0)

return CSize((int) m_lpBMIH->biWidth, (int) m_lpBMIH->biHeight)

}

BOOL CDib::AttachMapFile(const char* strPathname, BOOL bShare) // for reading

{

// if we open the same file twice, Windows treats it as 2 separate files

// doesn't work with rare BMP files where # palette entries >biClrUsed

HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ,

bShare ? FILE_SHARE_READ : 0,

NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)

ASSERT(hFile != INVALID_HANDLE_VALUE)

DWORD dwFileSize = ::GetFileSize(hFile, NULL)

HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL)

DWORD dwErr = ::GetLastError()

if(hMap == NULL) {

AfxMessageBox("Empty bitmap file")

return FALSE

}

LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0)// map whole file

ASSERT(lpvFile != NULL)

if(((LPBITMAPFILEHEADER) lpvFile)->bfType != 0x4d42) {

AfxMessageBox("Invalid bitmap file")

DetachMapFile()

return FALSE

}

AttachMemory((LPBYTE) lpvFile + sizeof(BITMAPFILEHEADER))

m_lpvFile = lpvFile

m_hFile = hFile

m_hMap = hMap

return TRUE

}

BOOL CDib::CopyToMapFile(const char* strPathname)

{

// copies DIB to a new file, releases prior pointers

// if you previously used CreateSection, the HBITMAP will be NULL (and unusable)

BITMAPFILEHEADER bmfh

bmfh.bfType = 0x4d42 // 'BM'

bmfh.bfSize = m_dwSizeImage + sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * m_nColorTableEntries + sizeof(BITMAPFILEHEADER)

// meaning of bfSize open to interpretation

bmfh.bfReserved1 = bmfh.bfReserved2 = 0

bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * m_nColorTableEntries

HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL,

CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)

ASSERT(hFile != INVALID_HANDLE_VALUE)

int nSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * m_nColorTableEntries + m_dwSizeImage

HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, nSize, NULL)

DWORD dwErr = ::GetLastError()

ASSERT(hMap != NULL)

LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0)// map whole file

ASSERT(lpvFile != NULL)

LPBYTE lpbCurrent = (LPBYTE) lpvFile

memcpy(lpbCurrent, &bmfh, sizeof(BITMAPFILEHEADER))// file header

lpbCurrent += sizeof(BITMAPFILEHEADER)

LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) lpbCurrent

memcpy(lpbCurrent, m_lpBMIH,

sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries)// info

lpbCurrent += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries

memcpy(lpbCurrent, m_lpImage, m_dwSizeImage)// bit image

DWORD dwSizeImage = m_dwSizeImage

Empty()

m_dwSizeImage = dwSizeImage

m_nBmihAlloc = m_nImageAlloc = noAlloc

m_lpBMIH = lpBMIH

m_lpImage = lpbCurrent

m_hFile = hFile

m_hMap = hMap

m_lpvFile = lpvFile

ComputePaletteSize(m_lpBMIH->biBitCount)

ComputeMetrics()

MakePalette()

return TRUE

}

BOOL CDib::AttachMemory(LPVOID lpvMem, BOOL bMustDelete, HGLOBAL hGlobal)

{

// assumes contiguous BITMAPINFOHEADER, color table, image

// color table could be zero length

Empty()

m_hGlobal = hGlobal

if(bMustDelete == FALSE) {

m_nBmihAlloc = noAlloc

}

else {

m_nBmihAlloc = ((hGlobal == NULL) ? crtAlloc : heapAlloc)

}

try {

m_lpBMIH = (LPBITMAPINFOHEADER) lpvMem

ComputeMetrics()

ComputePaletteSize(m_lpBMIH->biBitCount)

m_lpImage = (LPBYTE) m_lpvColorTable + sizeof(RGBQUAD) * m_nColorTableEntries

MakePalette()

}

catch(CException* pe) {

AfxMessageBox("AttachMemory error")

pe->Delete()

return FALSE

}

return TRUE

}

UINT CDib::UsePalette(CDC* pDC, BOOL bBackground /* = FALSE */)

{

if(m_hPalette == NULL) return 0

HDC hdc = pDC->GetSafeHdc()

::SelectPalette(hdc, m_hPalette, bBackground)

return ::RealizePalette(hdc)

}

BOOL CDib::Draw(CDC* pDC, CPoint origin, CSize size)

{

if(m_lpBMIH == NULL) return FALSE

if(m_hPalette != NULL) {

::SelectPalette(pDC->GetSafeHdc(), m_hPalette, TRUE)

}

pDC->SetStretchBltMode(COLORONCOLOR)

::StretchDIBits(pDC->GetSafeHdc(), origin.x, origin.y, size.cx, size.cy,

0, 0, m_lpBMIH->biWidth, m_lpBMIH->biHeight,

m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS, SRCCOPY)

return TRUE

}

HBITMAP CDib::CreateSection(CDC* pDC /* = NULL */)

{

if(m_lpBMIH == NULL) return NULL

if(m_lpImage != NULL) return NULL// can only do this if image doesn't exist

m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,

DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0)

ASSERT(m_lpImage != NULL)

return m_hBitmap

}

BOOL CDib::MakePalette()

{

// makes a logical palette (m_hPalette) from the DIB's color table

// this palette will be selected and realized prior to drawing the DIB

if(m_nColorTableEntries == 0) return FALSE

if(m_hPalette != NULL) ::DeleteObject(m_hPalette)

TRACE("CDib::MakePalette -- m_nColorTableEntries = %d\n", m_nColorTableEntries)

LPLOGPALETTE pLogPal = (LPLOGPALETTE) new char[2 * sizeof(WORD) +

m_nColorTableEntries * sizeof(PALETTEENTRY)]

pLogPal->palVersion = 0x300

pLogPal->palNumEntries = m_nColorTableEntries

LPRGBQUAD pDibQuad = (LPRGBQUAD) m_lpvColorTable

for(int i = 0i <m_nColorTableEntriesi++) {

pLogPal->palPalEntry[i].peRed = pDibQuad->rgbRed

pLogPal->palPalEntry[i].peGreen = pDibQuad->rgbGreen

pLogPal->palPalEntry[i].peBlue = pDibQuad->rgbBlue

pLogPal->palPalEntry[i].peFlags = 0

pDibQuad++

}

m_hPalette = ::CreatePalette(pLogPal)

delete pLogPal

return TRUE

}

BOOL CDib::SetSystemPalette(CDC* pDC)

{

// if the DIB doesn't have a color table, we can use the system's halftone palette

if(m_nColorTableEntries != 0) return FALSE

m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc())

return TRUE

}

HBITMAP CDib::CreateBitmap(CDC* pDC)

{

if (m_dwSizeImage == 0) return NULL

HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(), m_lpBMIH,

CBM_INIT, m_lpImage, (LPBITMAPINFO) m_lpBMIH, DIB_RGB_COLORS)

ASSERT(hBitmap != NULL)

return hBitmap

}

BOOL CDib::Compress(CDC* pDC, BOOL bCompress /* = TRUE */)

{

// 1. makes GDI bitmap from existing DIB

// 2. makes a new DIB from GDI bitmap with compression

// 3. cleans up the original DIB

// 4. puts the new DIB in the object

if((m_lpBMIH->biBitCount != 4) &&(m_lpBMIH->biBitCount != 8)) return FALSE

// compression supported only for 4 bpp and 8 bpp DIBs

if(m_hBitmap) return FALSE// can't compress a DIB Section!

TRACE("Compress: original palette size = %d\n", m_nColorTableEntries)

HDC hdc = pDC->GetSafeHdc()

HPALETTE hOldPalette = ::SelectPalette(hdc, m_hPalette, FALSE)

HBITMAP hBitmap // temporary

if((hBitmap = CreateBitmap(pDC)) == NULL) return FALSE

int nSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries

LPBITMAPINFOHEADER lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]

memcpy(lpBMIH, m_lpBMIH, nSize) // new header

if(bCompress) {

switch (lpBMIH->biBitCount) {

case 4:

lpBMIH->biCompression = BI_RLE4

break

case 8:

lpBMIH->biCompression = BI_RLE8

break

default:

ASSERT(FALSE)

}

// calls GetDIBits with null data pointer to get size of compressed DIB

if(!::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,

NULL, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS)) {

AfxMessageBox("Unable to compress this DIB")

// probably a problem with the color table

::DeleteObject(hBitmap)

delete [] lpBMIH

::SelectPalette(hdc, hOldPalette, FALSE)

return FALSE

}

if (lpBMIH->biSizeImage == 0) {

AfxMessageBox("Driver can't do compression")

::DeleteObject(hBitmap)

delete [] lpBMIH

::SelectPalette(hdc, hOldPalette, FALSE)

return FALSE

}

else {

m_dwSizeImage = lpBMIH->biSizeImage

}

}

else {

lpBMIH->biCompression = BI_RGB// decompress

// figure the image size from the bitmap width and height

DWORD dwBytes = ((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) / 32

if(((DWORD) lpBMIH->biWidth * lpBMIH->biBitCount) % 32) {

dwBytes++

}

dwBytes *= 4

m_dwSizeImage = dwBytes * lpBMIH->biHeight// no compression

lpBMIH->biSizeImage = m_dwSizeImage

}

// second GetDIBits call to make DIB

LPBYTE lpImage = (LPBYTE) new char[m_dwSizeImage]

VERIFY(::GetDIBits(pDC->GetSafeHdc(), hBitmap, 0, (UINT) lpBMIH->biHeight,

lpImage, (LPBITMAPINFO) lpBMIH, DIB_RGB_COLORS))

TRACE("dib successfully created - height = %d\n", lpBMIH->biHeight)

::DeleteObject(hBitmap)

Empty()

m_nBmihAlloc = m_nImageAlloc = crtAlloc

m_lpBMIH = lpBMIH

m_lpImage = lpImage

ComputeMetrics()

ComputePaletteSize(m_lpBMIH->biBitCount)

MakePalette()

::SelectPalette(hdc, hOldPalette, FALSE)

TRACE("Compress: new palette size = %d\n", m_nColorTableEntries)

return TRUE

}

BOOL CDib::Read(CFile* pFile)

{

// 1. read file header to get size of info hdr + color table

// 2. read info hdr (to get image size) and color table

// 3. read image

// can't use bfSize in file header

Empty()

int nCount, nSize

BITMAPFILEHEADER bmfh

try {

nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER))

if(nCount != sizeof(BITMAPFILEHEADER)) {

throw new CException

}

if(bmfh.bfType != 0x4d42) {

throw new CException

}

nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER)

m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]

m_nBmihAlloc = m_nImageAlloc = crtAlloc

nCount = pFile->Read(m_lpBMIH, nSize)// info hdr &color table

ComputeMetrics()

ComputePaletteSize(m_lpBMIH->biBitCount)

MakePalette()

m_lpImage = (LPBYTE) new char[m_dwSizeImage]

nCount = pFile->Read(m_lpImage, m_dwSizeImage)// image only

}

catch(CException* pe) {

AfxMessageBox("Read error")

pe->Delete()

return FALSE

}

return TRUE

}

BOOL CDib::ReadSection(CFile* pFile, CDC* pDC /* = NULL */)

{

// new function reads BMP from disk and creates a DIB section

//allows modification of bitmaps from disk

// 1. read file header to get size of info hdr + color table

// 2. read info hdr (to get image size) and color table

// 3. create DIB section based on header parms

// 4. read image into memory that CreateDibSection allocates

Empty()

int nCount, nSize

BITMAPFILEHEADER bmfh

try {

nCount = pFile->Read((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER))

if(nCount != sizeof(BITMAPFILEHEADER)) {

throw new CException

}

if(bmfh.bfType != 0x4d42) {

throw new CException

}

nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER)

m_lpBMIH = (LPBITMAPINFOHEADER) new char[nSize]

m_nBmihAlloc = crtAlloc

m_nImageAlloc = noAlloc

nCount = pFile->Read(m_lpBMIH, nSize)// info hdr &color table

if(m_lpBMIH->biCompression != BI_RGB) {

throw new CException

}

ComputeMetrics()

ComputePaletteSize(m_lpBMIH->biBitCount)

MakePalette()

UsePalette(pDC)

m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(), (LPBITMAPINFO) m_lpBMIH,

DIB_RGB_COLORS, (LPVOID*) &m_lpImage, NULL, 0)

ASSERT(m_lpImage != NULL)

nCount = pFile->Read(m_lpImage, m_dwSizeImage)// image only

}

catch(CException* pe) {

AfxMessageBox("ReadSection error")

pe->Delete()

return FALSE

}

return TRUE

}

BOOL CDib::Write(CFile* pFile)

{

BITMAPFILEHEADER bmfh

bmfh.bfType = 0x4d42 // 'BM'

int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries

bmfh.bfSize = 0

// bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage

// meaning of bfSize open to interpretation (bytes, words, dwords?) -- we won't use it

bmfh.bfReserved1 = bmfh.bfReserved2 = 0

bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +

sizeof(RGBQUAD) * m_nColorTableEntries

try {

pFile->Write((LPVOID) &bmfh, sizeof(BITMAPFILEHEADER))

pFile->Write((LPVOID) m_lpBMIH, nSizeHdr)

pFile->Write((LPVOID) m_lpImage, m_dwSizeImage)

}

catch(CException* pe) {

pe->Delete()

AfxMessageBox("write error")

return FALSE

}

return TRUE

}

void CDib::Serialize(CArchive&ar)

{

DWORD dwPos

dwPos = ar.GetFile()->GetPosition()

TRACE("CDib::Serialize -- pos = %d\n", dwPos)

ar.Flush()

dwPos = ar.GetFile()->GetPosition()

TRACE("CDib::Serialize -- pos = %d\n", dwPos)

if(ar.IsStoring()) {

Write(ar.GetFile())

}

else {

Read(ar.GetFile())

}

}

// helper functions

void CDib::ComputePaletteSize(int nBitCount)

{

if((m_lpBMIH == NULL) || (m_lpBMIH->biClrUsed == 0)) {

switch(nBitCount) {

case 1:

m_nColorTableEntries = 2

break

case 4:

m_nColorTableEntries = 16

break

case 8:

m_nColorTableEntries = 256

break

case 16:

case 24:

case 32:

m_nColorTableEntries = 0

break

default:

ASSERT(FALSE)

}

}

else {

m_nColorTableEntries = m_lpBMIH->biClrUsed

}

ASSERT((m_nColorTableEntries >= 0) &&(m_nColorTableEntries <= 256))

}

void CDib::ComputeMetrics()

{

if(m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER)) {

TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n")

throw new CException

}

m_dwSizeImage = m_lpBMIH->biSizeImage

if(m_dwSizeImage == 0) {

DWORD dwBytes = ((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) / 32

if(((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) % 32) {

dwBytes++

}

dwBytes *= 4

m_dwSizeImage = dwBytes * m_lpBMIH->biHeight// no compression

}

m_lpvColorTable = (LPBYTE) m_lpBMIH + sizeof(BITMAPINFOHEADER)

}

void CDib::Empty()

{

// this is supposed to clean up whatever is in the DIB

DetachMapFile()

if(m_nBmihAlloc == crtAlloc) {

delete [] m_lpBMIH

}

else if(m_nBmihAlloc == heapAlloc) {

::GlobalUnlock(m_hGlobal)

::GlobalFree(m_hGlobal)

}

if(m_nImageAlloc == crtAlloc) delete [] m_lpImage

if(m_hPalette != NULL) ::DeleteObject(m_hPalette)

if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap)

m_nBmihAlloc = m_nImageAlloc = noAlloc

m_hGlobal = NULL

m_lpBMIH = NULL

m_lpImage = NULL

m_lpvColorTable = NULL

m_nColorTableEntries = 0

m_dwSizeImage = 0

m_lpvFile = NULL

m_hMap = NULL

m_hFile = NULL

m_hBitmap = NULL

m_hPalette = NULL

}

void CDib::DetachMapFile()

{

if(m_hFile == NULL) return

::UnmapViewOfFile(m_lpvFile)

::CloseHandle(m_hMap)

::CloseHandle(m_hFile)

m_hFile = NULL

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/8068499.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-13
下一篇 2023-04-13

发表评论

登录后才能评论

评论列表(0条)

保存