www.pudn.com > XRayImg.rar > dibimage.cpp
/*
Module : DIBIMAGE.CPP
Purpose: Implementation for an MFC class that encapsulates DIBs
and supports a variety of image manipulation functions on it
Created: PJN / 23-07-1997
History: PJN / 23-07-1999 1. Unicode enabled the code + provision of Unicode configurations in the workspace
2. ColorsUsed function has now been implemented
Major update by Fabio Angelini. Changes include:
1. Inclusion of a C3By3MeanFilter.
2. Tidy up of how CDibImage disposes of its resources
3. Addition of a Detach method
4. Pixel access is now supported for 1, 4, 8 and 24 bit pixel formats
5. Function to convert from a HBITMAP to a DIB
6. Function to convert to a HBITMAP
7. Function to screen capture a specified area of a specified window
8. Function to convert to 24 bits.
9. Unified all the low-level API to manage DIB files into as single source code
PJN / 06-09-1999 1. Provision of a IsRunLengthEncoded function.
2. Updates to the DataFormatSupported function to prevent access violations in the
dibedit sample application
PJN / 12-09-1999 1. Added support for Jpeg loading or saving by means of the Intel Jpeg Library
PJN / 21-09-1999 1. Fixed a bug in the function WindowToDIB which is used by CDibImage::CopyFromWindow
PJN / 03-10-1999 1. Optimized memory usage when loading and saving JPEG images from file.
PJN / 25-01-2000 1. Updated code to use Intel Jpeg Library v1.1
PJN / 07-03-2000 1. Added support for True color targa (.tga) file loading and saving
2. jpeg loading and saving code thoroughly reviewed and optimized
3. The sample app now clears the histogram correctly when there are no
views visible
PJN / 20-03-2000 1. Modified some code in CDibImage which was causing the VC++ 6 compiler to bomb out
2. Removed a number of unreferenced variables detected by VC++ 6.
3. Removed a number of useless comments in tgaapi.cpp
PJN / 02-04-2000 1. Fixed an access violation in ::ReadJPegFile
2. Added a call to GlobalUnlock which was missing in CDibImage::UserDefinedFilter
Copyright (c) 1997 - 2000 by PJ Naughter.
All rights reserved.
*/
///////////////////////////////// Includes //////////////////////////////////
#include "stdafx.h"
#include "math.h"
#include "dibimage.h"
#ifndef DIBIMAGE_NO_JPEG
#include "jpegapi.h"
#endif
#include "..\resource.h"
#include "tgaapi.h"
#include "..\XRayImg.h"
///////////////////////////////// defines /////////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////// Implementation ///////////////////////////////
C3By3Filter::C3By3Filter()
{
//Default filter is a filter which will not do anything to the image
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
m_nValues[i][j] = 0;
m_nValues[1][1] = 1;
m_nDivision = 1;
m_nBias = 0;
}
COLORREF C3By3Filter::Filter(CDibImage&amt; dibImage, LPSTR lpDibBits, int x, int y)
{
int r = 0;
int g = 0;
int b = 0;
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
{
COLORREF c;
if (dibImage.GetPixel(x+i-1, y+j-1, c, lpDibBits))
{
r += (m_nValues[i][j] * GetRValue(c));
g += (m_nValues[i][j] * GetGValue(c));
b += (m_nValues[i][j] * GetBValue(c));
}
}
}
ASSERT(m_nDivision);
r = min(r/m_nDivision + m_nBias, 255);
g = min(g/m_nDivision + m_nBias, 255);
b = min(b/m_nDivision + m_nBias, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
return RGB(r, g, b);
}
C3By3MedianFilter::C3By3MedianFilter()
{
}
COLORREF C3By3MedianFilter::Filter(CDibImage&amt; dibImage, LPSTR lpDibBits, int x, int y)
{
int nPixels = 0;
for (int k=0; k<9; k++)
m_Ordered[k] = 0;
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
{
COLORREF c;
if (dibImage.GetPixel(x+i-1, y+j-1, c, lpDibBits))
{
m_Ordered[nPixels] = c;
nPixels++;
}
}
}
qsort(&amt;m_Ordered, nPixels, sizeof(COLORREF), CompareFunc);
return m_Ordered[nPixels/2];
}
int C3By3MedianFilter::CompareFunc(const void *elem1, const void *elem2)
{
COLORREF c1 = *(COLORREF*)elem1;
COLORREF c2 = *(COLORREF*)elem2;
if (c1 == c2)
return 0;
else
{
BYTE r1 = GetRValue(c1);
BYTE g1 = GetGValue(c1);
BYTE b1 = GetBValue(c1);
BYTE r2 = GetRValue(c2);
BYTE g2 = GetGValue(c2);
BYTE b2 = GetBValue(c2);
if ((r1 + g1 + b1) > (r2 + g2 + b2))
return 1;
else
return -1;
}
}
C3By3MeanFilter::C3By3MeanFilter()
{
}
COLORREF C3By3MeanFilter::Filter(CDibImage&amt; dibImage, LPSTR lpDibBits, int x, int y)
{
COLORREF r=0,g=0,b=0;
COLORREF co;
COLORREF c;
dibImage.GetPixel(x, y, co, lpDibBits);
for (int j=-1; j<2; j++)
{
for (int i=-1; i<2; i++)
{
if ( dibImage.GetPixel(x+i, y-j, c, lpDibBits) )
{
r += GetRValue(c);
g += GetGValue(c);
b += GetBValue(c);
}
}
}
return RGB(r/9, g/9, b/9 );
}
C5By5Filter::C5By5Filter()
{
//Default filter is a filter which will not do anything to the image
for (int i=0; i<5; i++)
for (int j=0; j<5; j++)
m_nValues[i][j] = 0;
m_nValues[2][2] = 1;
m_nDivision = 1;
m_nBias = 0;
}
COLORREF C5By5Filter::Filter(CDibImage&amt; dibImage, LPSTR lpDibBits, int x, int y)
{
int r = 0;
int g = 0;
int b = 0;
for (int i=0; i<5; i++)
{
for (int j=0; j<5; j++)
{
COLORREF c;
if (dibImage.GetPixel(x+i-2, y+j-2, c, lpDibBits))
{
r += (m_nValues[i][j] * GetRValue(c));
g += (m_nValues[i][j] * GetGValue(c));
b += (m_nValues[i][j] * GetBValue(c));
}
}
}
ASSERT(m_nDivision);
r = min(r/m_nDivision + m_nBias, 255);
g = min(g/m_nDivision + m_nBias, 255);
b = min(b/m_nDivision + m_nBias, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
return RGB(r, g, b);
}
C7By7Filter::C7By7Filter()
{
//Default filter is a filter which will not do anything to the image
for (int i=0; i<7; i++)
for (int j=0; j<7; j++)
m_nValues[i][j] = 0;
m_nValues[3][3] = 1;
m_nDivision = 1;
m_nBias = 0;
}
COLORREF C7By7Filter::Filter(CDibImage&amt; dibImage, LPSTR lpDibBits, int x, int y)
{
int r = 0;
int g = 0;
int b = 0;
for (int i=0; i<7; i++)
{
for (int j=0; j<7; j++)
{
COLORREF c;
if (dibImage.GetPixel(x+i-3, y+j-3, c, lpDibBits))
{
r += (m_nValues[i][j] * GetRValue(c));
g += (m_nValues[i][j] * GetGValue(c));
b += (m_nValues[i][j] * GetBValue(c));
}
}
}
ASSERT(m_nDivision);
r = min(r/m_nDivision + m_nBias, 255);
g = min(g/m_nDivision + m_nBias, 255);
b = min(b/m_nDivision + m_nBias, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
return RGB(r, g, b);
}
CUndoNode::CUndoNode(CDibImage* pImage, const CString&amt; sDescription)
{
m_pImage = pImage;
m_sDescription = sDescription;
}
CUndoNode::~CUndoNode()
{
delete m_pImage;
m_pImage = NULL;
}
CDibImage::CDibImage()
{
m_hDib = NULL;
m_pWorkingArea = NULL;
m_nWidth = 0;
m_nHeight = 0;
m_nScanWidth = 0;
m_nBitsPerPixel = 0;
m_Pal = NULL;
m_nUndoSize = 4; //By default, we support 4 levels of undo, if you
//want more (at the expense of memory usage) just
//call SetUndoSize will the level you want
}
CDibImage::CDibImage(const CDibImage&amt; ds)
{
m_hDib = NULL;
m_pWorkingArea = NULL;
m_nWidth = 0;
m_nHeight = 0;
m_nScanWidth = 0;
m_nBitsPerPixel = 0;
m_Pal = NULL;
m_nUndoSize = 4; //By default, we support 4 levels of undo, if you
//want more (at the expense of memory usage) just
//call SetUndoSize will the level you want
Attach((HDIB) CopyHandle(ds.m_hDib));
SetWorkingArea(ds.m_pWorkingArea->Clone());
}
CDibImage::~CDibImage()
{
Destroy();
//empty stack
// 徐卫华添加 2005.8.31
this->RemoveAllUndoItems();
this->RemoveAllRedoItems();
}
CDibImage&amt; CDibImage::operator=(const CDibImage&amt; ds)
{
Attach((HDIB) CopyHandle(ds.m_hDib));
SetWorkingArea(ds.m_pWorkingArea->Clone());
return *this;
}
BOOL CDibImage::Create(CSize size, WORD nBitCount)
{
Destroy();
BOOL bSuccess = TRUE;
CWindowDC dcScreen(NULL);
// should not already have palette
ASSERT(m_Pal == NULL);
// Select specified palette
m_Pal = ::CreateHalftonePalette(dcScreen.m_hDC);
if (m_Pal == NULL)
return FALSE;
// Fill in the BITMAPINFO Structure
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = size.cx;
bmi.bmiHeader.biHeight = size.cy;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = nBitCount;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
int nPaletteSize = ComputePaletteSize(nBitCount);
bmi.bmiHeader.biClrUsed = nPaletteSize;
bmi.bmiHeader.biClrImportant = nPaletteSize;
m_nWidth = size.cx;
m_nHeight = size.cy;
m_nBitsPerPixel = nBitCount;
m_nScanWidth = WIDTHBYTES(m_nWidth*m_nBitsPerPixel);
m_pWorkingArea = new CRectWorkingArea(Rect());
DWORD dwSize = sizeof(bmi) + m_nScanWidth*m_nHeight;
m_hDib = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize);
if (m_hDib == NULL)
return FALSE;
LPSTR pDib = (LPSTR) ::GlobalLock((HGLOBAL) m_hDib);
memcpy(pDib, &amt;bmi, sizeof(bmi));
::GlobalUnlock((HGLOBAL) m_hDib);
return bSuccess;
}
int CDibImage::ComputePaletteSize(DWORD nBitCount)
{
int nSize = 0;
switch (nBitCount)
{
case 1: nSize = 2; break;
case 4: nSize = 16; break;
case 8: nSize = 256; break;
case 16:
case 24:
case 32: nSize = 0; break;
default: ASSERT(FALSE); break;
}
return nSize;
}
void CDibImage::Destroy()
{
DestroyWorkingArea();
DestroyHPALLETTE();
DestroyHDIB();
}
void CDibImage::DestroyWorkingArea()
{
if (m_pWorkingArea)
{
delete m_pWorkingArea;
m_pWorkingArea = NULL;
}
}
void CDibImage::DestroyHDIB()
{
UINT nFlags;
if (m_hDib)
{
//判断标志 徐卫华 2005.8.31
nFlags=::GlobalFlags(m_hDib);
if( nFlags &amt; GMEM_INVALID_HANDLE ) return;
if( (nFlags &amt; GMEM_LOCKCOUNT)>0 )
{
::GlobalUnlock(m_hDib);
}
GlobalFree(m_hDib);
m_hDib = NULL;
}
}
void CDibImage::DestroyHPALLETTE()
{
if ( m_Pal != NULL )
{
DeleteObject(m_Pal);
m_Pal = NULL;
}
}
BOOL CDibImage::Attach(HDIB hDib)
{
Destroy();
BOOL bSuccess = FALSE;
if (hDib)
{
m_hDib = hDib;
DWORD dwSize = GlobalSize(m_hDib);
ASSERT(dwSize);
LPSTR lpDib = (LPSTR) ::GlobalLock(m_hDib);
ASSERT(lpDib);
m_nWidth = ::DIBWidth(lpDib);
m_nHeight = ::DIBHeight(lpDib);
::GlobalUnlock((HGLOBAL) m_hDib);
m_nBitsPerPixel = GetBitsPerPixel();
m_nScanWidth = WIDTHBYTES(m_nWidth*m_nBitsPerPixel);
m_pWorkingArea = new CRectWorkingArea(Rect());
CPalette pal;
::CreateDIBPalette(m_hDib, &amt;pal);
m_Pal = (HPALETTE) pal.Detach();
bSuccess = TRUE;
}
return bSuccess;
}
HDIB CDibImage::Detach(void)
{
DestroyWorkingArea();
DestroyHPALLETTE();
HDIB hDib = m_hDib;
m_hDib = NULL;
return hDib;
}
BOOL CDibImage::Load(LPCTSTR lpszPathName)
{
CFile f;
if (!f.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))
return FALSE;
//Determine what image type it is based on the filename extension
TCHAR pszExt[_MAX_EXT];
_tsplitpath(lpszPathName, NULL, NULL, NULL, pszExt);
CString sExt(pszExt);
BOOL bRst;
if ((sExt.CompareNoCase(_T(".bmp")) == 0) || (sExt.CompareNoCase(_T(".dib")) == 0) )
{
bRst=Attach(::ReadDIBFile(f));
f.Close();
return bRst;
}
#ifndef DIBIMAGE_NO_JPEG
else if ((sExt.CompareNoCase(_T(".jpg")) == 0) || (sExt.CompareNoCase(_T(".jpeg")) == 0))
{
bRst=Attach(::ReadJPEGFile(f));
f.Close();
return bRst;
}
#endif
else if (sExt.CompareNoCase(_T(".tga")) == 0)
{
bRst=Attach(::ReadTGAFile(f));
f.Close();
return bRst;
}
else if (sExt.CompareNoCase(_T(".dat"))==0 )
{
bRst=ReadDATFile(f);
f.Close();
return bRst;
}
else
{
TRACE(_T("Could not detemine what file type to load based on the filename extension\n"));
f.Close();
return FALSE;
}
}
BOOL CDibImage::Load(HINSTANCE hInst, LPCTSTR lpResourceName)
{
HRSRC hSrc = FindResource(hInst, lpResourceName, RT_BITMAP);
BOOL bSuccess = FALSE;
if (hSrc)
{
HGLOBAL hResData = LoadResource(hInst, hSrc);
if (hResData)
{
LPVOID lpResData = LockResource(hResData);
if (lpResData)
{
DWORD dwSize = SizeofResource(hInst, hSrc);
if (dwSize)
{
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwSize);
if (hGlobal)
{
LPVOID lpBitmapData = GlobalLock(hGlobal);
if (lpBitmapData)
{
CopyMemory(lpBitmapData, lpResData, dwSize);
GlobalUnlock(hGlobal);
bSuccess = Attach((HDIB) hGlobal);
}
}
}
}
}
}
return bSuccess;
}
int CDibImage::GetBitsPerPixel() const
{
int nBitCount;
if (m_hDib == NULL)
nBitCount = 0;
else
{
LPSTR lpDib = (LPSTR) ::GlobalLock(m_hDib);
// Calculate the number of bits per pixel for the DIB.
if (IS_WIN30_DIB(lpDib))
{
LPBITMAPINFOHEADER pBih = (LPBITMAPINFOHEADER)lpDib;
nBitCount = pBih->biBitCount;
}
else
{
LPBITMAPCOREHEADER pbic = (LPBITMAPCOREHEADER)lpDib;
nBitCount = pbic->bcBitCount;
}
::GlobalUnlock((HGLOBAL) m_hDib);
}
return nBitCount;
}
BOOL CDibImage::IsRunLengthEncoded() const
{
BOOL bEncoded = FALSE;
if (m_hDib)
{
LPSTR lpDib = (LPSTR) ::GlobalLock(m_hDib);
// Calculate the number of bits per pixel for the DIB.
if (IS_WIN30_DIB(lpDib))
{
LPBITMAPINFOHEADER lpbih = (LPBITMAPINFOHEADER) lpDib;
bEncoded = (lpbih->biCompression == BI_RLE8) || (lpbih->biCompression == BI_RLE4);
}
::GlobalUnlock((HGLOBAL) m_hDib);
}
return bEncoded;
}
//***************************************************************
//函数功能: 绘制函数
// 1)
// 2)
//
//说明: dc->目标dc, rcDst->实际需要的尺寸
// rcSrc->dib图片尺寸 pPal->调色板
// rcClient->当前客户区域( 新增加的,目的是使显示居中 )
//
//***************************************************************
BOOL CDibImage::Draw(CDC&amt; dc, const CRect* rcDst, const CRect* rcSrc,
CPalette* pPal,CRect *rcClient)
{
CRect DCRect(Rect());
if (rcDst)
DCRect = *rcDst;
CRect DibRect(Rect());
if (rcSrc)
DibRect = *rcSrc;
CPalette pal;
pal.Attach(m_Pal);
CPalette* pPalette = NULL;
if (pPal)
pPalette = pPal;
else
pPalette = &amt;pal;
BOOL bSuccess = ::DrawDIB(dc.m_hDC, &amt;DCRect, m_hDib, &amt;DibRect,pPalette,rcClient);
pal.Detach();
return bSuccess;
}
// Currently only support pixel access for 1, 4, 8 &amt; 24 images.
// Also note that access to RLE images is not supported
BOOL CDibImage::DataFormatSupported(void) const
{
if (!IsRunLengthEncoded() &amt;&amt;
((m_nBitsPerPixel == 1) ||
(m_nBitsPerPixel == 4) ||
(m_nBitsPerPixel == 8) ||
(m_nBitsPerPixel == 24)) )
return TRUE;
else
return FALSE;
}
BOOL CDibImage::FilteringFormatSupported(void) const
{
if (m_nBitsPerPixel == 24)
return TRUE;
else
return FALSE;
}
//***************************************************************
//函数功能: 得到当前像素点的颜色指针
// 1)
// 2)
//
//说明:DIB图形中,显示的第一行是实际保存文件的最后行
//***************************************************************
LPBYTE CDibImage::GetPixelAddress(int x, int y, LPBYTE lpDibBits) const
{
BYTE* pData = NULL;
if (!IsRunLengthEncoded())
{
switch (m_nBitsPerPixel)
{
case 1:
{
pData = lpDibBits + ((m_nHeight - 1) - y) * m_nScanWidth + (x/8);
break;
}
case 4:
{
pData = lpDibBits + ((m_nHeight - 1) - y) * m_nScanWidth + (x/2);
break;
}
case 8:
{
pData = lpDibBits + ((m_nHeight - 1) - y) * m_nScanWidth + (x);
break;
}
case 24:
{
pData = lpDibBits + ((m_nHeight - 1) - y) * m_nScanWidth + (x*3);
break;
}
default:
{
pData = NULL;
break;
}
}
}
return pData;
}
inline BYTE GetLoNibble(BYTE Data)
{
return (BYTE) (Data &amt; 0x0F);
}
inline BYTE GetHiNibble(BYTE Data)
{
return (BYTE) ((Data >> 4) &amt; 0x0F);
}
inline void SetLoNibble( BYTE&amt; DstData ,BYTE SrcData )
{
DstData = (BYTE) ((DstData &amt; 0xF0) | (SrcData &amt; 0x0F));
}
inline void SetHiNibble( BYTE&amt; DstData ,BYTE SrcData )
{
DstData = (BYTE) ((DstData &amt; 0x0F) | ((SrcData << 4) &amt; 0xF0));
}
//***************************************************************
//函数功能: 得到显示的图像的某一点的RGB数值
// 1) 得到DIB图像开始位置
// 2) 找到某一点的颜色指针
// 3) 计算出该点RGB
//说明:
//***************************************************************
BOOL CDibImage::GetPixelData(int x, int y, ULONG&amt; value, LPSTR lpDibBits) const
{
if (m_hDib == NULL)
return FALSE;
if (DataFormatSupported() == FALSE)
return FALSE;
//position is out of range
if (x >= m_nWidth || x < 0 || y >= m_nHeight || y < 0)
return FALSE;
BOOL bLocked = FALSE;
if (lpDibBits == NULL)
{
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
lpDibBits = ::FindDIBBits(lpDibHdr);
bLocked = TRUE;
}
BYTE* pData = GetPixelAddress(x,y,(BYTE*) lpDibBits);
switch (m_nBitsPerPixel)
{
case 1:
{
x = x > 8;
value = ( pData[0] << x ) &amt; 0x80 ? 1 : 0;
break;
}
case 4:
{
if (x > 2)
value = GetLoNibble(pData[0]);
else
value = GetHiNibble(pData[0]);
break;
}
case 8:
{
value = pData[0];
break;
}
case 24:
{
value = RGB(pData[2], pData[1], pData[0]);
break;
}
default:
{
return FALSE;
break;
}
}
if (bLocked)
::GlobalUnlock((HGLOBAL) m_hDib);
return TRUE;
}
BOOL CDibImage::SetPixelData(int x, int y, const ULONG&amt; value, LPSTR lpDibBits)
{
if (m_hDib == NULL)
return FALSE;
if (DataFormatSupported() == FALSE)
return FALSE;
//check the position
ASSERT(x < m_nWidth &amt;&amt; x >= 0 &amt;&amt; y < m_nHeight &amt;&amt; y >= 0);
BOOL bLocked = FALSE;
if (lpDibBits == NULL)
{
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
lpDibBits = ::FindDIBBits(lpDibHdr);
bLocked = TRUE;
}
BYTE* pData = GetPixelAddress(x, y, (BYTE*)lpDibBits);
switch (m_nBitsPerPixel)
{
case 1:
{
x = x > 8;
if ( value )
pData[0] = (BYTE) (pData[0] | (0x80 >> x));
else
pData[0] = (BYTE) (pData[0] &amt; ~(0x80 >> x));
break;
}
case 4:
{
if (x > 2)
SetLoNibble(pData[0], (BYTE)value);
else
SetHiNibble(pData[0], (BYTE)value);
break;
}
case 8:
{
pData[0] = (BYTE) value;
break;
}
case 24:
{
pData[0] = GetBValue(value);
pData[1] = GetGValue(value);
pData[2] = GetRValue(value);
break;
}
default:
{
return FALSE;
}
}
if (bLocked)
::GlobalUnlock((HGLOBAL) m_hDib);
return TRUE;
}
BOOL CDibImage::GetPixel(int x, int y, COLORREF&amt; value, LPSTR lpDibBits) const
{
if (m_hDib == NULL)
return FALSE;
if (m_nBitsPerPixel != 24)
return FALSE;
//position is out of range
if (x >= m_nWidth || x < 0 || y >= m_nHeight || y < 0)
return FALSE;
BOOL bLocked = FALSE;
if (lpDibBits == NULL)
{
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
lpDibBits = ::FindDIBBits(lpDibHdr);
bLocked = TRUE;
}
BYTE* pData = (LPBYTE) lpDibBits + (m_nHeight - 1 - y ) * m_nScanWidth + (x * 3);
value = RGB(pData[2], pData[1], pData[0]);
if (bLocked)
::GlobalUnlock((HGLOBAL) m_hDib);
return TRUE;
}
BOOL CDibImage::SetPixel(int x, int y, const COLORREF&amt; value, LPSTR lpDibBits)
{
if (m_hDib == NULL)
return FALSE;
if ((m_nBitsPerPixel != 24))
return FALSE;
//check the position
ASSERT(x < m_nWidth &amt;&amt; x >= 0 &amt;&amt; y < m_nHeight &amt;&amt; y >= 0);
BOOL bLocked = FALSE;
if (lpDibBits == NULL)
{
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
lpDibBits = ::FindDIBBits(lpDibHdr);
bLocked = TRUE;
}
BOOL bSuccess = SetPixelData(x, y, value, lpDibBits);
if (bLocked)
::GlobalUnlock((HGLOBAL) m_hDib);
return bSuccess;
}
BOOL CDibImage::Save(LPCTSTR lpszPathName)
{
if (m_hDib == NULL)
return FALSE;
//Determine the file format to use based on the filename extension
TCHAR pszExt[_MAX_EXT];
_tsplitpath(lpszPathName, NULL, NULL, NULL, pszExt);
CString sExt(pszExt);
if ((sExt.CompareNoCase(_T(".bmp")) == 0) || (sExt.CompareNoCase(_T(".dib")) == 0) )
{
CFile f;
if ( !f.Open(lpszPathName,
CFile::shareDenyWrite | CFile::modeCreate | CFile::modeWrite) )
return FALSE;
else
return SaveDIBFile(m_hDib, f);
}
#ifndef DIBIMAGE_NO_JPEG
else if ((sExt.CompareNoCase(_T(".jpg")) == 0) || (sExt.CompareNoCase(_T(".jpeg")) == 0))
{
CFile f;
if (!f.Open(lpszPathName, CFile::shareDenyWrite | CFile::modeCreate | CFile::modeWrite))
return FALSE;
else
return SaveJPEGFile(m_hDib, f);
}
#endif
else if (sExt.CompareNoCase(_T(".tga")) == 0)
{
CFile f;
if (!f.Open(lpszPathName, CFile::shareDenyWrite | CFile::modeCreate | CFile::modeWrite))
return FALSE;
else
return SaveTGAFile(m_hDib, f);
}
else
{
TRACE(_T("Could not determine what file format to save as\n"));
return FALSE; //unknown file format
}
}
BOOL CDibImage::CopySelection(CDibImage&amt; dib)
{
if (m_hDib == NULL)
return FALSE;
BOOL bSuccess = FALSE;
ASSERT(m_pWorkingArea);
CRect r = m_pWorkingArea->BoundingRectangle();
bSuccess = dib.Create(CSize(r.Width(), r.Height()), 24);
if (bSuccess)
{
LPSTR lpDibHdrSrc = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBitsSrc = ::FindDIBBits(lpDibHdrSrc);
LPSTR lpDibHdrDest = (LPSTR) ::GlobalLock(dib.m_hDib);
LPSTR lpDibBitsDest = ::FindDIBBits(lpDibHdrDest);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
bSuccess = GetPixel(x, y, c, lpDibBitsSrc);
bSuccess = bSuccess &amt;&amt; dib.SetPixel(x-r.left, y-r.top, c, lpDibBitsDest);
}
}
}
GlobalUnlock((HGLOBAL) dib.m_hDib);
GlobalUnlock((HGLOBAL) m_hDib);
}
return bSuccess;
}
LPSTR CDibImage::GetDIBBits()
{
LPSTR lpDibHdrSrc = (LPSTR) ::GlobalLock(m_hDib);
return ::FindDIBBits(lpDibHdrSrc);
}
BOOL CDibImage::CopyToClipboard()
{
if (m_hDib == NULL)
return FALSE;
BOOL bSuccess = FALSE;
if (OpenClipboard(NULL))
{
if (EmptyClipboard())
{
CDibImage DibCopy;
bSuccess = CopySelection(DibCopy);
if (bSuccess)
{
HDIB hNewDib = (HDIB) CopyHandle(DibCopy.m_hDib);
bSuccess = (::SetClipboardData(CF_DIB, hNewDib) != NULL);
}
}
CloseClipboard();
}
return bSuccess;
}
BOOL CDibImage::PasteFromClipboard()
{
BOOL bSuccess = FALSE;
if (OpenClipboard(NULL))
{
HDIB hNewDib = (HDIB) CopyHandle(::GetClipboardData(CF_DIB));
CloseClipboard();
if (hNewDib != NULL)
bSuccess = Attach(hNewDib);
}
return bSuccess;
}
BOOL CDibImage::PasteAvailable()
{
return IsClipboardFormatAvailable(CF_DIB);
}
void CDibImage::SetUndoSize(int nUndoSize)
{
m_nUndoSize = nUndoSize;
if (m_nUndoSize < m_UndoStack.GetSize())
TRACE(_T("Losing some of the undo stack in CDibImage::SetUndoSize\n"));
for (int i=m_nUndoSize; i<m_UndoStack.GetSize(); i++)
{
CUndoNode* pNode = m_UndoStack.GetAt(i);
delete pNode;
}
for (i=m_nUndoSize; i<m_RedoStack.GetSize(); i++)
{
CUndoNode* pNode = m_RedoStack.GetAt(i);
delete pNode;
}
//Trim back the size of the arrays if necessary
if (m_UndoStack.GetSize() > nUndoSize)
m_UndoStack.SetSize(m_nUndoSize);
if (m_RedoStack.GetSize() > nUndoSize)
m_RedoStack.SetSize(m_nUndoSize);
}
BOOL CDibImage::SaveState(UINT nID)
{
CString sDescription;
sDescription.LoadString(nID);
return SaveState(sDescription);
}
BOOL CDibImage::SaveState(const CString&amt; sDescription)
{
//if there is no undo stack then return immediately
if (m_nUndoSize == 0)
return FALSE;
//If we have reached the limit of the undo stack
//then drop the oldest undo by moving all the items
//down in the stack
if (m_UndoStack.GetSize() == m_nUndoSize)
{
TRACE(_T("Undo stack size exceeded, discarding oldest\n"));
CUndoNode* pNode = m_UndoStack.GetAt(0);
delete pNode;
for (int i=1; i<m_UndoStack.GetSize(); i++)
{
CUndoNode* pNode = m_UndoStack.GetAt(i);
m_UndoStack.SetAt(i-1, pNode);
}
m_UndoStack.SetSize(m_nUndoSize-1);
}
CDibImage* pCopy = new CDibImage(*this);
CUndoNode* pNode = new CUndoNode(pCopy, sDescription);
m_UndoStack.Add(pNode);
return TRUE;
}
BOOL CDibImage::UndoAvailable()
{
return (m_UndoStack.GetSize() > 0);
}
BOOL CDibImage::Undo()
{
BOOL bSuccess = FALSE;
int nIndex = m_UndoStack.GetUpperBound();
if (nIndex >= 0)
{
//Add the current image to the redo stack
CDibImage* pCopy = new CDibImage(*this);
CUndoNode* pNode1 = new CUndoNode(pCopy, m_sCurrentDescription);
m_RedoStack.Add(pNode1);
//Remove from the undo stack and
//reinstate the current value
CUndoNode* pNode2 = m_UndoStack.GetAt(nIndex);
operator=(*pNode2->GetImage());
pNode1->SetDescription(pNode2->GetDescription());
delete pNode2;
m_UndoStack.RemoveAt(nIndex);
bSuccess = TRUE;
}
return bSuccess;
}
void CDibImage::RemoveAllUndoItems()
{
for(int iIndex=0;iIndex<m_UndoStack.GetUpperBound();)
{
CUndoNode* pNode = m_UndoStack.GetAt(iIndex);
/*
UINT nFlags;
//判断标志 徐卫华 2005.8.31
nFlags=::GlobalFlags( pNode->GetImage()->GetHDIB() );
if( !(nFlags &amt; GMEM_INVALID_HANDLE) )
{
if( (nFlags &amt; GMEM_LOCKCOUNT)>0 )
{
::GlobalUnlock( pNode->GetImage()->GetHDIB() );
}
GlobalFree( pNode->GetImage()->GetHDIB() );
}
*/
m_UndoStack.RemoveAt(iIndex);
}
m_UndoStack.SetSize(0);
}
BOOL CDibImage::Redo()
{
BOOL bSuccess = FALSE;
int nIndex = m_RedoStack.GetUpperBound();
if (nIndex >= 0)
{
//Add the current image to the undo stack
CDibImage* pCopy = new CDibImage(*this);
CUndoNode* pNode1 = new CUndoNode(pCopy, m_sCurrentDescription);
m_UndoStack.Add(pNode1);
//Remove from the redo stack and
//reinstate the current value
CUndoNode* pNode2 = m_RedoStack.GetAt(nIndex);
operator=(*pNode2->GetImage());
pNode1->SetDescription(pNode2->GetDescription());
delete pNode2;
m_RedoStack.RemoveAt(nIndex);
bSuccess = TRUE;
}
return bSuccess;
}
BOOL CDibImage::RedoAvailable()
{
return (m_RedoStack.GetSize() > 0);
}
void CDibImage::RemoveAllRedoItems()
{
for(int iIndex=0;iIndex<m_RedoStack.GetUpperBound();)
{
CUndoNode* pNode = m_RedoStack.GetAt(iIndex);
/*
UINT nFlags;
//判断标志 徐卫华 2005.8.31
nFlags=::GlobalFlags( pNode->GetImage()->GetHDIB() );
if( !(nFlags &amt; GMEM_INVALID_HANDLE) )
{
if( (nFlags &amt; GMEM_LOCKCOUNT)>0 )
{
::GlobalUnlock( pNode->GetImage()->GetHDIB() );
}
GlobalFree( pNode->GetImage()->GetHDIB() );
}
*/
delete pNode->GetImage();
m_RedoStack.RemoveAt(iIndex);
}
m_RedoStack.SetSize(0);
}
CString CDibImage::UndoDescription() const
{
CString rVal;
int nIndex = m_UndoStack.GetUpperBound();
if (nIndex >= 0)
{
CUndoNode* pNode = m_UndoStack.GetAt(nIndex);
rVal = pNode->GetDescription();
}
return rVal;
}
CString CDibImage::RedoDescription() const
{
CString rVal;
int nIndex = m_RedoStack.GetUpperBound();
if (nIndex >= 0)
{
CUndoNode* pNode = m_RedoStack.GetAt(nIndex);
rVal = pNode->GetDescription();
}
return rVal;
}
CWorkingArea* CDibImage::GetWorkingArea()
{
return m_pWorkingArea;
}
void CDibImage::SetWorkingArea(CWorkingArea* pWorkingArea)
{
if (m_pWorkingArea)
{
delete m_pWorkingArea;
m_pWorkingArea = NULL;
}
m_pWorkingArea = pWorkingArea;
}
BOOL CDibImage::SetColor(COLORREF color)
{
if (m_hDib == NULL)
return FALSE;
SaveState(IDS_DI_UNDO_SETCOLOR);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
bSuccess = SetPixel(x, y, color, lpDibBits);
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
//***************************************************************
//函数功能: 水平镜像图片
// 1) 找到选择的区域
// 2) 找到X中心对称轴
// 3) 将水平对称的两个Y点颜色对调
//
//说明:
//***************************************************************
BOOL CDibImage::Flip(BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_FLIP);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
int nMiddle = r.Height()/2 + r.top;
for (int y=nMiddle; bSuccess &amt;&amt; y>r.top; y--)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c1;
int y1 = nMiddle + (nMiddle - y);
bSuccess = GetPixelData(x, y1, c1, lpDibBits);
COLORREF c2;
bSuccess = bSuccess &amt;&amt; GetPixelData(x, y, c2, lpDibBits);
bSuccess = bSuccess &amt;&amt; SetPixelData(x, y, c1, lpDibBits);
bSuccess = bSuccess &amt;&amt; SetPixelData(x, y1, c2, lpDibBits);
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
//***************************************************************
//函数功能: 垂直镜像图片
// 1) 找到选择的区域
// 2) 找到中心对称Y轴
// 3) 将水平对称的两个X点颜色对调
//
//说明:
//***************************************************************
BOOL CDibImage::Mirror(BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_MIRROR);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
int nMiddle = r.Width()/2 + r.left;
for (int x=nMiddle; bSuccess &amt;&amt; x>r.left; x--)
{
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c1;
int x1 = nMiddle + (nMiddle - x);
bSuccess = GetPixelData(x1, y, c1, lpDibBits);
COLORREF c2;
bSuccess = bSuccess &amt;&amt; GetPixelData(x, y, c2, lpDibBits);
bSuccess = bSuccess &amt;&amt; SetPixelData(x, y, c1, lpDibBits);
bSuccess = bSuccess &amt;&amt; SetPixelData(x1, y, c2, lpDibBits);
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
//***************************************************************
//函数功能: 反时针90度
// 1) 建立新的临时空间
// 2) 填充新的临时区域
// 3) 删除原来图像 建立新的图像
// 4) 复制临时结果到新建立的图像中
//说明: 仅仅支持真彩色24BIT
//***************************************************************
BOOL CDibImage::Rotate90Unclock(BOOL bNeedBack)
{
if ((m_hDib == NULL) || (m_nBitsPerPixel!=24) ) return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ROTATE_90UNCLOCK);
/*
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
*/
BOOL bSuccess = TRUE;
//建立新的临时空间
DWORD dwScanWidth,dwBytesSize;
DWORD dwWidth,dwHeight;
dwScanWidth=WIDTHBYTES(m_nHeight*m_nBitsPerPixel);
dwWidth=m_nHeight;
dwHeight=m_nWidth;
dwBytesSize=dwScanWidth*dwHeight;
LPSTR pCopy=new char[dwBytesSize];
memset(pCopy,0,dwBytesSize);
//填充新的临时区域
int x,y;
LPSTR pRGB=NULL;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for(y=0;bSuccess &amt;&amt; y<m_nHeight;y++ )
{
for(x=0;bSuccess &amt;&amt; x<m_nWidth;x++)
{
/*
原理:
*/
*( pCopy+dwScanWidth*x+(dwWidth-1-y)*3 )=
*( lpDibBits+y*m_nScanWidth+x*3 );
*( pCopy+dwScanWidth*x+(dwWidth-1-y)*3+1 )=
*( lpDibBits+y*m_nScanWidth+x*3 +1);
*( pCopy+dwScanWidth*x+(dwWidth-1-y)*3+2)=
*( lpDibBits+y*m_nScanWidth+x*3 +2);
}
}
//删除原来图像 建立新的图像
bSuccess=Create(CSize(dwWidth,dwHeight),24);
if (!bSuccess)
{
delete []pCopy;
pCopy=NULL;
GlobalUnlock((HGLOBAL) m_hDib);
Undo();
return bSuccess;
}
//复制临时结果到新建立的图像中
lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
lpDibBits = ::FindDIBBits(lpDibHdr);
int i=m_nScanWidth*m_nHeight;
::memcpy( lpDibBits,pCopy,m_nScanWidth*m_nHeight );
GlobalUnlock((HGLOBAL) m_hDib);
delete []pCopy;
pCopy=NULL;
return bSuccess;
}
//***************************************************************
//函数功能: 顺时针90度
// 1) 通过三次 90度实现
//说明: 仅仅支持真彩色24BIT
//***************************************************************
BOOL CDibImage::Rotate90Clock(BOOL bNeedBack)
{
if ((m_hDib == NULL) || (m_nBitsPerPixel!=24) ) return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ROTATE_90CLOCK);
/*
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
*/
BOOL bSuccess = TRUE;
//连续转动三次逆时针的90度
for(int iCounter=0;iCounter<3;iCounter++)
{
//建立新的临时空间
DWORD dwScanWidth,dwBytesSize;
DWORD dwWidth,dwHeight;
dwScanWidth=WIDTHBYTES(m_nHeight*m_nBitsPerPixel);
dwWidth=m_nHeight;
dwHeight=m_nWidth;
dwBytesSize=dwScanWidth*dwHeight;
LPSTR pCopy=new char[dwBytesSize];
memset(pCopy,0,dwBytesSize);
//填充新的临时区域
int x,y;
LPSTR pRGB=NULL;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for(y=0;bSuccess &amt;&amt; y<m_nHeight;y++ )
{
for(x=0;bSuccess &amt;&amt; x<m_nWidth;x++)
{
/*
原理:
*/
*( pCopy+dwScanWidth*x+(dwWidth-1-y)*3 )=
*( lpDibBits+y*m_nScanWidth+x*3 );
*( pCopy+dwScanWidth*x+(dwWidth-1-y)*3+1 )=
*( lpDibBits+y*m_nScanWidth+x*3 +1);
*( pCopy+dwScanWidth*x+(dwWidth-1-y)*3+2)=
*( lpDibBits+y*m_nScanWidth+x*3 +2);
}
}
//删除原来图像 建立新的图像
bSuccess=Create(CSize(dwWidth,dwHeight),24);
if (!bSuccess)
{
delete []pCopy;
pCopy=NULL;
GlobalUnlock((HGLOBAL) m_hDib);
Undo();
return bSuccess;
}
//复制临时结果到新建立的图像中
lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
lpDibBits = ::FindDIBBits(lpDibHdr);
int i=m_nScanWidth*m_nHeight;
::memcpy( lpDibBits,pCopy,m_nScanWidth*m_nHeight );
GlobalUnlock((HGLOBAL) m_hDib);
delete []pCopy;
pCopy=NULL;
}
return bSuccess;
}
//***************************************************************
//函数功能: 调整亮度/对比度/GAMMA
// 1) 通过三次 分别实现
// 2)
//说明: 取消操作按照一个处理
//***************************************************************
BOOL CDibImage::AdjustBrightness(int nValue,BOOL bNeedBack)
{
if (m_hDib == NULL) return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_BRIGHTNESS);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int r = min(GetRValue(c)+nValue, 255);
int g = min(GetGValue(c)+nValue, 255);
int b = min(GetBValue(c)+nValue, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
c = RGB(r, g, b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess) Undo();
return bSuccess;
}
//nValue:-100~100
BOOL CDibImage::AdjustContrast(int nValue,BOOL bNeedBack)
{
if (m_hDib == NULL) return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_CONTRAST);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
bSuccess = GetPixel(x, y, c, lpDibBits);
int r = min(128 + ((GetRValue(c) - 128)*nValue/100), 255);
int g = min(128 + ((GetGValue(c) - 128)*nValue/100), 255);
int b = min(128 + ((GetBValue(c) - 128)*nValue/100), 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
c = RGB(r, g, b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess) Undo();
return bSuccess;
}
BOOL CDibImage::AdjustGammaCorrection(float Value,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_GAMMA);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
double MaxRange = pow((double) 255, (double) Value) / 255;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
bSuccess = GetPixel(x, y, c, lpDibBits);
double dblR = pow((double) GetRValue(c), (double) Value) / MaxRange;
double dblG = pow((double) GetGValue(c), (double) Value) / MaxRange;
double dblB = pow((double) GetBValue(c), (double) Value) / MaxRange;
int r = min((int) (dblR+0.5), 255);
int g = min((int) (dblG+0.5), 255);
int b = min((int) (dblB+0.5), 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
c = RGB(r, g, b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustHighLight(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_HIGHLIGHT);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
bSuccess = GetPixel(x, y, c, lpDibBits);
int r = GetRValue(c);
int g = GetGValue(c);
int b = GetBValue(c);
int l = r+g+b;
if ((l > (170*3)))
{
r = min(r*Percentage/100, 255);
g = min(g*Percentage/100, 255);
b = min(b*Percentage/100, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
c = RGB(r, g, b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustMidtone(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_MIDTONE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
bSuccess = GetPixel(x, y, c, lpDibBits);
int r = GetRValue(c);
int g = GetGValue(c);
int b = GetBValue(c);
int l = r+g+b;
if ((l >= (85*3)) &amt;&amt; (l <= (170*3)))
{
r = min(r*Percentage/100, 255);
g = min(g*Percentage/100, 255);
b = min(b*Percentage/100, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
c = RGB(r, g, b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustShadow(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_SHADOW);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
bSuccess = GetPixel(x, y, c, lpDibBits);
int r = GetRValue(c);
int g = GetGValue(c);
int b = GetBValue(c);
int l = r+g+b;
if (l < (85*3))
{
r = min(r*Percentage/100, 255);
g = min(g*Percentage/100, 255);
b = min(b*Percentage/100, 255);
r = max(r, 0);
g = max(g, 0);
b = max(b, 0);
c = RGB(r, g, b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustHue(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if (Percentage < 0)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_HUE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
double H;
double S;
double L;
RGBtoHSL(c, &amt;H, &amt;S, &amt;L);
H = (H*Percentage/100);
bSuccess = SetPixel(x, y, HLStoRGB(H, L, S), lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustSaturation(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if (Percentage < 0)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_SATURATION);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
double H;
double S;
double L;
RGBtoHSL(c, &amt;H, &amt;S, &amt;L);
S = (S*Percentage/100);
bSuccess = SetPixel(x, y, HLStoRGB(H, L, S), lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustHSL(int PercentHue, int PercentSaturation,
int PercentLuminosity,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if (PercentHue < 0)
return FALSE;
if (PercentSaturation < 0)
return FALSE;
if (PercentLuminosity < 0)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_HSL);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
double H;
double S;
double L;
RGBtoHSL(c, &amt;H, &amt;S, &amt;L);
S = (S*PercentSaturation/100);
H = (H*PercentHue/100);
L = (L*PercentLuminosity/100);
bSuccess = SetPixel(x, y, HLStoRGB(H, L, S), lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
WORD CDibImage::GetVersion()
{
return 0x011B; //ie v1.27
}
void CDibImage::RGBtoHSL(COLORREF rgb, double* H, double* S, double* L)
{
double delta;
double r = (double)GetRValue(rgb)/255;
double g = (double)GetGValue(rgb)/255;
double b = (double)GetBValue(rgb)/255;
double cmax = max(r,max(g,b));
double cmin = min(r,min(g,b));
*L = (cmax+cmin)/2.0;
if (cmax == cmin)
{
*S = 0;
*H = 0; // it's really undefined
}
else
{
if (*L < 0.5)
*S = (cmax-cmin)/(cmax+cmin);
else
*S = (cmax-cmin)/(2.0-cmax-cmin);
delta = cmax - cmin;
if (r==cmax)
*H = (g-b)/delta;
else if (g==cmax)
*H = 2.0 +(b-r)/delta;
else
*H = 4.0+(r-g)/delta;
*H /= 6.0;
if (*H < 0.0)
*H += 1;
}
}
double CDibImage::HuetoRGB(double m1, double m2, double h)
{
if (h < 0)
h += 1.0;
if (h > 1)
h -= 1.0;
if (6.0*h < 1)
return (m1+(m2-m1)*h*6.0);
if (2.0*h < 1)
return m2;
if (3.0*h < 2.0)
return (m1+(m2-m1)*((2.0/3.0)-h)*6.0);
return m1;
}
COLORREF CDibImage::HLStoRGB(const double&amt; H, const double&amt; L, const double&amt; S)
{
double r,g,b;
double m1, m2;
if (S==0)
{
r=g=b=L;
}
else
{
if (L <= 0.5)
m2 = L*(1.0+S);
else
m2 = L+S-L*S;
m1 = 2.0*L-m2;
r = HuetoRGB(m1, m2, H+1.0/3.0);
g = HuetoRGB(m1, m2, H);
b = HuetoRGB(m1, m2, H-1.0/3.0);
}
return RGB((BYTE)(r*255),(BYTE)(g*255),(BYTE)(b*255));
}
BOOL CDibImage::AdjustRed(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if (Percentage < 0)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_RED);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int r = min(GetRValue(c)*Percentage/100, 255);
r = max(r, 0);
c = RGB(r, GetGValue(c), GetBValue(c));
bSuccess = SetPixel(x, y, c, lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustGreen(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if (Percentage < 0)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_GREEN);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int g = min(GetGValue(c)*Percentage/100, 255);
g = max(g, 0);
c = RGB(GetRValue(c), g, GetBValue(c));
bSuccess = SetPixel(x, y, c, lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustBlue(int Percentage,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if (Percentage < 0)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_BLUE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int b = min(GetBValue(c)*Percentage/100, 255);
b = max(b, 0);
c = RGB(GetRValue(c), GetGValue(c), b);
bSuccess = SetPixel(x, y, c, lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::AdjustGrayscale(int iGrayType,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_GREYSCALE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int iValue ;
switch(iGrayType)
{
case GRAY_MAX_VALUE:
iValue=max(GetRValue(c), GetGValue(c));
iValue=max(GetBValue(c), iValue);
break;
case GRAY_AVERAGE_VALUE:
iValue=( int )( ( GetRValue(c)+GetGValue(c)+ GetBValue(c)) /3 );
break;
default :
iValue=(int)( ( GetRValue(c)*0.3 + GetGValue(c)*0.59+ GetBValue(c))*0.11 );
break;
}
bSuccess = SetPixel(x, y, RGB(iValue,iValue , iValue), lpDibBits);
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::Negate(BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADJUST_NEGATE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
bSuccess = SetPixel(x, y, RGB(255 - GetRValue(c), 255 - GetGValue(c), 255 - GetBValue(c)), lpDibBits);
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::FindEdgesFilter(BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
C3By3Filter Filter1;
Filter1.m_nValues[0][0] = -1;
Filter1.m_nValues[0][1] = 0;
Filter1.m_nValues[0][2] = 1;
Filter1.m_nValues[1][0] = -2;
Filter1.m_nValues[1][1] = 0;
Filter1.m_nValues[1][2] = 2;
Filter1.m_nValues[2][0] = -1;
Filter1.m_nValues[2][1] = 0;
Filter1.m_nValues[2][2] = 1;
C3By3Filter Filter2;
Filter2.m_nValues[0][0] = -1;
Filter2.m_nValues[0][1] = -2;
Filter2.m_nValues[0][2] = -1;
Filter2.m_nValues[1][0] = 0;
Filter2.m_nValues[1][1] = 0;
Filter2.m_nValues[1][2] = 0;
Filter2.m_nValues[2][0] = 1;
Filter2.m_nValues[2][1] = 2;
Filter2.m_nValues[2][2] = 1;
CDibImage dibCopy;
CopySelection(dibCopy);
SaveState(IDS_DI_UNDO_FILTER);
ASSERT(dibCopy.m_pWorkingArea);
CRect rectSrc(dibCopy.m_pWorkingArea->BoundingRectangle());
CRect rectDest(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdrSrc = (LPSTR) ::GlobalLock(dibCopy.m_hDib);
LPSTR lpDibBitsSrc = ::FindDIBBits(lpDibHdrSrc);
LPSTR lpDibHdrDest = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBitsDest = ::FindDIBBits(lpDibHdrDest);
for (int y=0; bSuccess &amt;&amt; y<rectSrc.Height(); y++)
{
for (int x=0; bSuccess &amt;&amt; x<rectSrc.Width(); x++)
{
if (dibCopy.m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c1 = Filter1.Filter(dibCopy, lpDibBitsSrc, x, y);
COLORREF c2 = Filter2.Filter(dibCopy, lpDibBitsSrc, x, y);
int r = max(GetRValue(c1), GetRValue(c2));
int g = max(GetGValue(c1), GetGValue(c2));
int b = max(GetBValue(c1), GetBValue(c2));
bSuccess = SetPixel(x+rectDest.left, y+rectDest.top, RGB(r, g, b), lpDibBitsDest);
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::FindVerticalEdgesFilter(BOOL bNeedBack)
{
C3By3Filter Filter;
Filter.m_nValues[0][0] = -1;
Filter.m_nValues[0][1] = -2;
Filter.m_nValues[0][2] = -1;
Filter.m_nValues[1][0] = 0;
Filter.m_nValues[1][1] = 0;
Filter.m_nValues[1][2] = 0;
Filter.m_nValues[2][0] = 1;
Filter.m_nValues[2][1] = 2;
Filter.m_nValues[2][2] = 1;
return UserDefinedFilter(Filter);
}
BOOL CDibImage::FindHorizontalEdgesFilter(BOOL bNeedBack)
{
C3By3Filter Filter;
Filter.m_nValues[0][0] = -1;
Filter.m_nValues[0][1] = 0;
Filter.m_nValues[0][2] = 1;
Filter.m_nValues[1][0] = -2;
Filter.m_nValues[1][1] = 0;
Filter.m_nValues[1][2] = 2;
Filter.m_nValues[2][0] = -1;
Filter.m_nValues[2][1] = 0;
Filter.m_nValues[2][2] = 1;
return UserDefinedFilter(Filter);
}
BOOL CDibImage::BlurFilter(BOOL bNeedBack)
{
C7By7Filter Filter;
for (int i=0; i<7; i++)
for (int j=0; j<7; j++)
Filter.m_nValues[i][j] = 0;
Filter.m_nValues[3][3] = -4;
Filter.m_nValues[2][2] = 1;
Filter.m_nValues[2][3] = 4;
Filter.m_nValues[2][4] = 1;
Filter.m_nValues[3][2] = 4;
Filter.m_nValues[3][4] = 4;
Filter.m_nValues[4][2] = 1;
Filter.m_nValues[4][3] = 4;
Filter.m_nValues[4][4] = 1;
Filter.m_nDivision = 16;
return UserDefinedFilter(Filter);
}
BOOL CDibImage::AddNoiseFilter(int Percentage,BOOL bNeedBack)
{
if (Percentage <= 0 || Percentage > 100)
return FALSE;
if (m_hDib == NULL)
return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_ADD_NOISE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
int test = rand();
BOOL bPass = test < (RAND_MAX*Percentage/100);
if (bPass &amt;&amt; m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
int r = rand()*256/RAND_MAX - 128;
int g = rand()*256/RAND_MAX - 128;
int b = rand()*256/RAND_MAX - 128;
if (GetPixel(x, y, c, lpDibBits))
bSuccess = SetPixel(x, y, RGB(GetRValue(c) + r, GetGValue(c) + g, GetBValue(c) + b), lpDibBits);
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
BOOL CDibImage::MedianFilter(BOOL bNeedBack)
{
C3By3MedianFilter Filter;
return UserDefinedFilter(Filter);
}
BOOL CDibImage::MeanFilter(BOOL bNeedBack)
{
C3By3MeanFilter Filter;
return UserDefinedFilter(Filter);
}
BOOL CDibImage::UserDefinedFilter(CUserDefinedFilter&amt; Filter,BOOL bNeedBack)
{
if (m_hDib == NULL)
return FALSE;
CDibImage dibCopy;
CopySelection(dibCopy);
SaveState(IDS_DI_UNDO_FILTER);
ASSERT(dibCopy.m_pWorkingArea);
CRect rectSrc(dibCopy.m_pWorkingArea->BoundingRectangle());
CRect rectDest(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdrSrc = (LPSTR) ::GlobalLock(dibCopy.m_hDib);
LPSTR lpDibBitsSrc = ::FindDIBBits(lpDibHdrSrc);
LPSTR lpDibHdrDest = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBitsDest = ::FindDIBBits(lpDibHdrDest);
for (int y=0; bSuccess &amt;&amt; y<rectSrc.Height(); y++)
{
for (int x=0; bSuccess &amt;&amt; x<rectSrc.Width(); x++)
{
if (dibCopy.m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c = Filter.Filter(dibCopy, lpDibBitsSrc, x, y);
bSuccess = SetPixel(x+rectDest.left, y+rectDest.top, c, lpDibBitsDest);
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
GlobalUnlock((HGLOBAL) dibCopy.m_hDib);
if (!bSuccess)
Undo();
return bSuccess;
}
int CDibImage::ColorsUsed() const
{
if (m_hDib == NULL)
return 0;
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
//Use a hash table to keep previously found colors, The
//most ideal method would be to use a sorted array with
//a binary chop but MFC does not provide one and I don't
//feel like coding up one just for the sake of this function <g>!.
CMap<COLORREF, COLORREF, COLORREF, COLORREF> colorsTable;
colorsTable.InitHashTable(r.Width() * r.Height());
//Iterate through the working area to find all its colors
BOOL bSuccess = TRUE;
int nColors = 0;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixelData(x, y, c, lpDibBits))
{
//If the color is not already in the table,
//then increment the number of colors and
//add it to the hash table
COLORREF cFound;
if (!colorsTable.Lookup(c, cFound))
{
++nColors;
colorsTable.SetAt(c, c);
}
}
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
return nColors;
}
BOOL CDibImage::SplitChannels(CDibImage&amt; RedChannel, CDibImage&amt; GreenChannel, CDibImage&amt; BlueChannel)
{
if (m_hDib == NULL)
return FALSE;
if (!RedChannel.Create(Size(), 24))
return FALSE;
if (!GreenChannel.Create(Size(), 24))
return FALSE;
if (!BlueChannel.Create(Size(), 24))
return FALSE;
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
LPSTR lpDibHdrRed = (LPSTR) ::GlobalLock(RedChannel.m_hDib);
LPSTR lpDibBitsRed = ::FindDIBBits(lpDibHdrRed);
LPSTR lpDibHdrGreen = (LPSTR) ::GlobalLock(GreenChannel.m_hDib);
LPSTR lpDibBitsGreen = ::FindDIBBits(lpDibHdrGreen);
LPSTR lpDibHdrBlue = (LPSTR) ::GlobalLock(BlueChannel.m_hDib);
LPSTR lpDibBitsBlue = ::FindDIBBits(lpDibHdrBlue);
CRect r(Rect());
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int r = GetRValue(c);
int g = GetGValue(c);
int b = GetBValue(c);
bSuccess = bSuccess &amt;&amt; RedChannel.SetPixel(x, y, RGB(r, r, r), lpDibBitsRed);
bSuccess = bSuccess &amt;&amt; GreenChannel.SetPixel(x, y, RGB(g, g, g), lpDibBitsGreen);
bSuccess = bSuccess &amt;&amt; BlueChannel.SetPixel(x, y, RGB(b, b, b), lpDibBitsBlue);
}
else
bSuccess = FALSE;
}
}
GlobalUnlock((HGLOBAL) m_hDib);
GlobalUnlock((HGLOBAL) RedChannel.m_hDib);
GlobalUnlock((HGLOBAL) GreenChannel.m_hDib);
GlobalUnlock((HGLOBAL) BlueChannel.m_hDib);
return bSuccess;
}
BOOL CDibImage::GetRedChannel(CDibImage&amt; red)
{
if (m_hDib == NULL)
return FALSE;
if (!red.Create(Size(), 24))
return FALSE;
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
LPSTR lpDibHdrRed = (LPSTR) ::GlobalLock(red.m_hDib);
LPSTR lpDibBitsRed = ::FindDIBBits(lpDibHdrRed);
CRect r(Rect());
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int r = GetRValue(c);
bSuccess = red.SetPixel(x, y, RGB(r, r, r), lpDibBitsRed);
}
else
bSuccess = FALSE;
}
}
GlobalUnlock((HGLOBAL) m_hDib);
GlobalUnlock((HGLOBAL) red.m_hDib);
return bSuccess;
}
BOOL CDibImage::GetGreenChannel(CDibImage&amt; green)
{
if (m_hDib == NULL)
return FALSE;
if (!green.Create(Size(), 24))
return FALSE;
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
LPSTR lpDibHdrGreen = (LPSTR) ::GlobalLock(green.m_hDib);
LPSTR lpDibBitsGreen = ::FindDIBBits(lpDibHdrGreen);
CRect r(Rect());
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int g = GetGValue(c);
bSuccess = green.SetPixel(x, y, RGB(g, g, g), lpDibBitsGreen);
}
else
bSuccess = FALSE;
}
}
GlobalUnlock((HGLOBAL) m_hDib);
GlobalUnlock((HGLOBAL) green.m_hDib);
return bSuccess;
}
BOOL CDibImage::GetBlueChannel(CDibImage&amt; blue)
{
if (m_hDib == NULL)
return FALSE;
if (!blue.Create(Size(), 24))
return FALSE;
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
LPSTR lpDibHdrBlue = (LPSTR) ::GlobalLock(blue.m_hDib);
LPSTR lpDibBitsBlue = ::FindDIBBits(lpDibHdrBlue);
CRect r(Rect());
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int b = GetBValue(c);
bSuccess = blue.SetPixel(x, y, RGB(b, b, b), lpDibBitsBlue);
}
else
bSuccess = FALSE;
}
}
GlobalUnlock((HGLOBAL) m_hDib);
GlobalUnlock((HGLOBAL) blue.m_hDib);
return bSuccess;
}
BOOL CDibImage::CombineChannels(const CDibImage&amt; red, const CDibImage&amt; green, const CDibImage&amt; blue)
{
if (red.m_hDib == NULL || green.m_hDib == NULL || blue.m_hDib == NULL)
return FALSE;
//All the images should be the same size
if (red.Rect() != green.Rect() || green.Rect() != blue.Rect() || red.Rect() != blue.Rect())
return FALSE;
if (!Create(red.Size(), 24))
return FALSE;
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
LPSTR lpDibHdrRed = (LPSTR) ::GlobalLock(red.m_hDib);
LPSTR lpDibBitsRed = ::FindDIBBits(lpDibHdrRed);
LPSTR lpDibHdrGreen = (LPSTR) ::GlobalLock(green.m_hDib);
LPSTR lpDibBitsGreen = ::FindDIBBits(lpDibHdrGreen);
LPSTR lpDibHdrBlue = (LPSTR) ::GlobalLock(blue.m_hDib);
LPSTR lpDibBitsBlue = ::FindDIBBits(lpDibHdrBlue);
CRect r(Rect());
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
COLORREF r;
COLORREF g;
COLORREF b;
if (red.GetPixel(x, y, r, lpDibBitsRed) &amt;&amt;
green.GetPixel(x, y, g, lpDibBitsGreen) &amt;&amt;
blue.GetPixel(x, y, b, lpDibBitsBlue))
{
COLORREF c = RGB(GetRValue(r), GetGValue(g), GetBValue(b));
bSuccess = bSuccess &amt;&amt; SetPixel(x, y, c, lpDibBits);
}
else
bSuccess = FALSE;
}
}
GlobalUnlock((HGLOBAL) m_hDib);
GlobalUnlock((HGLOBAL) red.m_hDib);
GlobalUnlock((HGLOBAL) green.m_hDib);
GlobalUnlock((HGLOBAL) blue.m_hDib);
return bSuccess;
}
BOOL CDibImage::GetRedHistogram(int* RedChannel, int nSize)
{
if (m_hDib == NULL)
return FALSE;
for (int i=0; i<nSize; i++)
RedChannel[i] = 0;
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int r = GetRValue(c);
if (r < nSize)
RedChannel[r]++;
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
return bSuccess;
}
BOOL CDibImage::GetGreenHistogram(int* GreenChannel, int nSize)
{
if (m_hDib == NULL)
return FALSE;
for (int i=0; i<nSize; i++)
GreenChannel[i] = 0;
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int g = GetGValue(c);
if (g < nSize)
GreenChannel[g]++;
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
return bSuccess;
}
BOOL CDibImage::GetBlueHistogram(int* BlueChannel, int nSize)
{
if (m_hDib == NULL)
return FALSE;
for (int i=0; i<nSize; i++)
BlueChannel[i] = 0;
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int b = GetBValue(c);
if (b < nSize)
BlueChannel[b]++;
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
return bSuccess;
}
BOOL CDibImage::GetHistogram(int* RedChannel, int nRedSize, int* GreenChannel, int nGreenSize, int* BlueChannel, int nBlueSize)
{
if (m_hDib == NULL)
return FALSE;
for (int i=0; i<nRedSize; i++)
RedChannel[i] = 0;
for (i=0; i<nGreenSize; i++)
GreenChannel[i] = 0;
for (i=0; i<nBlueSize; i++)
BlueChannel[i] = 0;
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bSuccess = TRUE;
LPSTR lpDibHdr = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBits = ::FindDIBBits(lpDibHdr);
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
COLORREF c;
if (GetPixel(x, y, c, lpDibBits))
{
int r = GetRValue(c);
int g = GetGValue(c);
int b = GetBValue(c);
if (r < nRedSize)
RedChannel[r]++;
if (g < nGreenSize)
GreenChannel[g]++;
if (b < nBlueSize)
BlueChannel[b]++;
}
else
bSuccess = FALSE;
}
}
}
GlobalUnlock((HGLOBAL) m_hDib);
return bSuccess;
}
BOOL CDibImage::CopyFromBitmap(HBITMAP hBitmap, HPALETTE hPal)
{
HDIB hDib = BitmapToDIB(hBitmap,hPal);
if (hDib == NULL)
return FALSE;
return Attach(hDib);
}
HBITMAP CDibImage::CopyToBitmap(void)
{
return DIBToBitmap(m_hDib, m_Pal);
}
BOOL CDibImage::CopyFromMemBmpFile(HMEMBMPFILE hMemBmpFile)
{
HDIB hDib = MemBmpFileToDIB(hMemBmpFile);
if (hDib == NULL)
return FALSE;
return Attach(hDib);
}
HMEMBMPFILE CDibImage::CopyToMemBmpFile(void)
{
return DIBToMemBmpFile(m_hDib);
}
BOOL CDibImage::CopyFromWindow(CWnd *pWnd, CRect* pScreenRect)
{
HDIB hDib = WindowToDIB(pWnd, pScreenRect);
if (hDib == NULL)
return FALSE;
return Attach(hDib);
}
BOOL CDibImage::ConvertTo24Bits(void)
{
if (m_hDib == NULL)
return FALSE;
if (m_Pal == NULL)
return FALSE;
// check if it is just a 24 bits image
if (m_nBitsPerPixel == 24)
return TRUE;
LOGPALETTE* pLogPalette = CreateLogPalette(m_Pal);
if (pLogPalette == NULL)
return FALSE;
SaveState(IDS_DI_UNDO_CONVERT24BITS);
CDibImage dib;
ASSERT(m_pWorkingArea);
CRect r = m_pWorkingArea->BoundingRectangle();
BOOL bSuccess = dib.Create(CSize(r.Width(), r.Height()), 24);
if (bSuccess)
{
LPSTR lpDibHdrSrc = (LPSTR) ::GlobalLock(m_hDib);
LPSTR lpDibBitsSrc = ::FindDIBBits(lpDibHdrSrc);
LPSTR lpDibHdrDest = (LPSTR) ::GlobalLock(dib.m_hDib);
LPSTR lpDibBitsDest = ::FindDIBBits(lpDibHdrDest);
for (int x=r.left; bSuccess &amt;&amt; x<r.right; x++)
{
for (int y=r.top; bSuccess &amt;&amt; y<r.bottom; y++)
{
if (m_pWorkingArea->PointInSelection(CPoint(x, y)))
{
ULONG PixelData = 0;
bSuccess = GetPixelData(x, y, PixelData, lpDibBitsSrc);
PALETTEENTRY pe = pLogPalette->palPalEntry[PixelData];
COLORREF ColorData = RGB( pe.peRed, pe.peGreen, pe.peBlue );
bSuccess = bSuccess &amt;&amt; dib.SetPixel(x-r.left, y-r.top, ColorData, lpDibBitsDest);
}
}
}
GlobalUnlock((HGLOBAL) dib.m_hDib);
GlobalUnlock((HGLOBAL) m_hDib);
if (Attach(dib.m_hDib))
dib.m_hDib = NULL;
}
if (!bSuccess)
Undo();
DestroyLogPalette( pLogPalette );
return bSuccess;
}
//简单实现尺寸调整
// 徐卫华 2005.8.31
BOOL CDibImage::ResizeImageSize(int xNew, int yNew,BOOL bNeedBack)
{
if (m_hDib == NULL) return FALSE;
if( bNeedBack ) SaveState(IDS_DI_UNDO_RESIZE);
ASSERT(m_pWorkingArea);
CRect r(m_pWorkingArea->BoundingRectangle());
BOOL bRst;
//建立规定尺寸的DIB
CDibImage dib;
bRst=dib.Create(CSize(xNew,yNew),this->m_nBitsPerPixel);
if( !bRst ) return FALSE;
int iX,iY,iXSource,iYSource;
COLORREF color;
//得到缩小比例
int iXFactor,iYFactor;
iXFactor=(int)( m_nWidth /xNew );
iYFactor=(int)( m_nHeight / yNew );
//设置新的区域的像素数据
for(iY=0;iY<yNew;iY++)
{
//得到Y坐标
if( m_nHeight > yNew )
iYSource=iY*iYFactor;
else
iYSource=(iY-iY>iYFactor)/iYFactor;
for(iX=0;iX<xNew;iX++)
{
//得到x坐标
if( m_nWidth > xNew )
iXSource=iX*iXFactor;
else
iXSource=(iX-iX>iXFactor)/iXFactor;
bRst=GetPixel( iXSource,iYSource,color);
if ( bRst )
{
dib.SetPixel(iX, iY, color);
}
}
}
this->Attach(dib.m_hDib);
dib.Detach();
return TRUE;
}
//***************************************************************
//函数功能: 读取"*.dat"格式文件中数据
// 1) 读取缓冲区
// 2) 处理数据
// 3) 象素点处理
//
//说明:
//**************************************************************
BOOL CDibImage::ReadDATFile(CFile&amt; f)
{
//读数据
UINT iLen1=(int)( g_sysSet.nPicWidthBytes *
g_sysSet.nPicHeightBytes * g_sysSet.nBitsPerPix/8 );
UINT iLen2=(int)( g_sysSet.nPicWidthBytes *
g_sysSet.nPicHeightBytes );
UCHAR *pRevBuff=new UCHAR[iLen1];
WORD *pRevBuff1=new WORD[iLen2];
WORD *pRevBuff2=new WORD[iLen2];
if ( f.Read( pRevBuff1, sizeof(WORD)*iLen2 ) != sizeof(WORD)*iLen2 ||
(f.Read( pRevBuff2, sizeof(WORD)*iLen2 ) != sizeof(WORD)*iLen2 ) )
{
delete pRevBuff;
delete pRevBuff1;
delete pRevBuff2;
return FALSE;
}
//处理数据
pRevBuff=DealDatFileData(pRevBuff,pRevBuff1,pRevBuff2);
//接受数据 并复制到m_dib的各个对应单元中
// 创建
BOOL bRst=Create( CSize(g_sysSet.nPicWidthBytes,g_sysSet.nPicHeightBytes),
g_sysSet.nBitsPerPix );
if( !bRst )
{
delete pRevBuff;
delete pRevBuff1;
delete pRevBuff2;
return FALSE;
}
// 填充象素点
UINT iXIndex,iYIndex,iBufferIndex;
COLORREF color;
for(iYIndex=0;iYIndex<g_sysSet.nPicHeightBytes;iYIndex++)
{
for(iXIndex=0;iXIndex<g_sysSet.nPicWidthBytes;iXIndex++)
{
//得到数据在缓冲区的位置
iBufferIndex= g_sysSet.nPicWidthBytes*iYIndex + iXIndex;
//假设三个字节依次是B G R
color=RGB( *(pRevBuff+iBufferIndex*3+2),
*(pRevBuff+iBufferIndex*3+1),
*(pRevBuff+iBufferIndex*3) );
//接收的缓冲区数据第一行为显示的最后一行
SetPixel(iXIndex,g_sysSet.nPicHeightBytes-1-iYIndex,color);
}
}
delete pRevBuff;
delete pRevBuff1;
delete pRevBuff2;
return TRUE;
}
// 处理"*.dat"格式文件
UCHAR* CDibImage::DealDatFileData(UCHAR *pRevBuff,WORD *pRevBuff1,WORD *pRevBuff2)
{
int iMaxWidth=g_sysSet.nPicWidthBytes;
int iMaxHeight=g_sysSet.nPicHeightBytes;
for(int h=0;h<iMaxHeight;h++)
{
for(int w=0;w<iMaxWidth;w++)
{
double x = (double)( *(pRevBuff1+(iMaxHeight-1-h)*iMaxWidth+w) );
double y = (double)(*(pRevBuff2+(iMaxHeight-1-h)*iMaxWidth+w));
x/=64; y/=64;
x=1024-x; y=1024-y;
double q1=4.3966762+0.6536144*x-0.0002024918*x*x;
double q2=79.073631+1.2750791*x-0.00073554182*x*x;
//get high part of word
unsigned char ds = (unsigned char)
( ( *(pRevBuff1+(iMaxHeight-h-1)*iMaxWidth+w) )>>8 );
int i=h*iMaxWidth*3+w*3;
if(y<q1)
{
if(ds>180 || ds<90)
{
pRevBuff[i] = ds;
pRevBuff[i+1] = ds;
pRevBuff[i+2] = ds;
}
else
{
pRevBuff[i] = (unsigned char)(ds * 0.8);
pRevBuff[i+1] = ds;
pRevBuff[i+2] = 0;
}
}
else if(y<q2)
{
if(ds>180 || ds<90)
{
pRevBuff[i] = ds;
pRevBuff[i+1] = ds;
pRevBuff[i+2] = ds;
}
else
{
pRevBuff[i] = 0;
pRevBuff[i+1] = ds;
pRevBuff[i+2] = (unsigned char)(ds * 0.8);
}
}
else
{
if(ds>180 || ds<90)
{
pRevBuff[i] = (unsigned char)(ds*0.6);
pRevBuff[i+1] = (unsigned char)(ds*0.6);
pRevBuff[i+2] = (unsigned char)(ds*0.6);
}
else
{
pRevBuff[i] = ds;
pRevBuff[i+1] = (unsigned char)(ds*0.5);
pRevBuff[i+2] = (unsigned char)(ds*0.6);
}
}
}
}
return pRevBuff;
}