⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imageprocessors.cpp

📁 管理项目进度工具的原代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ImageProcessors.cpp: C32BitImageProcessor derivations (c) daniel godson 2002.
//
// credits: Karl Lager's 'A Fast Algorithm for Rotating Bitmaps' 
// 
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "imageprocessors.h"

#include <math.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/////////////////////////////////////////////////////////////////////
// C32BitImageProcessor derivations

const double PI = 3.14159265358979323846;

CImageRotator::CImageRotator(int nDegrees, BOOL bEnableWeighting)
	: C32BitImageProcessor(bEnableWeighting)
{
	// normalize the angle
	while (nDegrees >= 360)
		nDegrees -= 360;

	while (nDegrees < 0)
		nDegrees += 360;

	ASSERT (nDegrees >= 0 && nDegrees < 360);

	m_dRadians = nDegrees * PI / 180;
}

CImageRotator::CImageRotator(double dRadians)
{
	// normalize the angle
	while (dRadians >= 2 * PI)
		dRadians -= 2 * PI;

	while (dRadians <= 0)
		dRadians += 2 * PI;

	ASSERT (dRadians >= 0 && dRadians < 2 * PI);

	m_dRadians = dRadians;
}

CImageRotator::~CImageRotator()
{
}

CSize CImageRotator::CalcDestSize(CSize sizeSrc)
{
	if (!m_dRadians || !sizeSrc.cx || !sizeSrc.cy)
		return sizeSrc;

	// calculate the four rotated corners
	double dCosA = cos(m_dRadians);
	double dSinA = sin(m_dRadians);

	CPoint ptTopLeft, ptTopRight, ptBottomLeft, ptBottomRight;

	ptTopLeft.x = (int)(-sizeSrc.cx * dCosA / 2 + sizeSrc.cy * dSinA / 2);
	ptTopLeft.y = (int)(sizeSrc.cy * dCosA / 2 - (-sizeSrc.cx) * dSinA / 2);

	ptTopRight.x = (int)(sizeSrc.cx * dCosA / 2 + sizeSrc.cy * dSinA / 2);
	ptTopRight.y = (int)(sizeSrc.cy * dCosA / 2 - sizeSrc.cx * dSinA / 2);

	ptBottomLeft.x = (int)(-sizeSrc.cx * dCosA / 2 + (-sizeSrc.cy) * dSinA / 2);
	ptBottomLeft.y = (int)(-sizeSrc.cy * dCosA / 2 - (-sizeSrc.cx) * dSinA / 2);

	ptBottomRight.x = (int)(sizeSrc.cx * dCosA / 2 + (-sizeSrc.cy) * dSinA / 2);
	ptBottomRight.y = (int)(-sizeSrc.cy * dCosA / 2 - sizeSrc.cx * dSinA / 2);

	// find the max absolute values in each direction
	int nMaxY = max(abs(ptTopLeft.y), max(abs(ptTopRight.y), max(abs(ptBottomLeft.y), abs(ptBottomRight.y))));
	int nMaxX = max(abs(ptTopLeft.x), max(abs(ptTopRight.x), max(abs(ptBottomLeft.x), abs(ptBottomRight.x))));
	
	return CSize((nMaxX + 1) * 2, (nMaxY + 1) * 2);
}

BOOL CImageRotator::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF /*crMask*/)
{
	BOOL bRes = TRUE;

	if (!m_dRadians)
		bRes = C32BitImageProcessor::ProcessPixels(pSrcPixels, sizeSrc, pDestPixels, sizeDest);
	else
	{
		// note: we also need to translate the coords after rotating
		CSize sizeDestOffset(sizeDest.cx / 2 + sizeDest.cx % 2, sizeDest.cy / 2 + sizeDest.cy % 2);
		CSize sizeSrcOffset(sizeSrc.cx / 2 + sizeSrc.cx % 2, sizeSrc.cy / 2 + sizeSrc.cy % 2);

		CRect rSrc(0, 0, sizeSrc.cx - 1, sizeSrc.cy - 1);
		rSrc.OffsetRect(-sizeSrcOffset);

		// note: traversing the src bitmap leads to artifacts in the destination image
		// what we do is to traverse the destination bitmaps and compute the equivalent 
		// source color - credit for this observation goes to Yves Maurer (GDIRotate) 2002
		double dCosA = cos(m_dRadians);
		double dSinA = sin(m_dRadians);

		for (int nY = 0; nY < sizeDest.cy; nY++)
		{
			// calc y components of rotation
			double dCosYComponent = (nY - sizeDestOffset.cy) * dCosA;
			double dSinYComponent = (nY - sizeDestOffset.cy) * dSinA;

			double dSrcX = -sizeDestOffset.cx * dCosA + dSinYComponent;
			double dSrcY = dCosYComponent - (-sizeDestOffset.cx * dSinA);

			for (int nX = 0; nX < sizeDest.cx; nX++)
			{
				dSrcX += dCosA;
				dSrcY -= dSinA;

				CPoint ptSrc((int)dSrcX, (int)dSrcY);
				int nPixel = (nY * sizeDest.cx + nX);

				if (rSrc.PtInRect(ptSrc))
				{
					if (!m_bWeightingEnabled)
					{
						ptSrc.Offset(sizeSrcOffset);
						RGBX* pRGBSrc = &pSrcPixels[ptSrc.y * sizeSrc.cx + ptSrc.x];
						
						pDestPixels[nPixel] = *pRGBSrc;
					}
					else
						CalcWeightedColor(pSrcPixels, sizeSrc, 
										dSrcX + sizeSrcOffset.cx, dSrcY + sizeSrcOffset.cy,
										pDestPixels[nPixel]);
				}
			}
		}
	}

	return bRes;
}

///////

CImageShearer::CImageShearer(int nHorz, int nVert, BOOL bEnableWeighting)
	: C32BitImageProcessor(bEnableWeighting), m_nHorz(nHorz), m_nVert(nVert)
{
}

CImageShearer::~CImageShearer()
{
}

CSize CImageShearer::CalcDestSize(CSize sizeSrc)
{
	return CSize(sizeSrc.cx + abs(m_nHorz), sizeSrc.cy + abs(m_nVert));
}

BOOL CImageShearer::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF /*crMask*/)
{
	BOOL bRes = TRUE;

	if (!m_nHorz && !m_nVert)
		bRes = C32BitImageProcessor::ProcessPixels(pSrcPixels, sizeSrc, pDestPixels, sizeDest);
	else
	{
		// shears +ve (down) or -ve (up)
		for (int nX = 0; nX < sizeDest.cx; nX++)
		{
			double dYOffset = 0;

			// calc the offset to src Y coord
			if (m_nVert > 0)
				dYOffset = (double)m_nVert * nX / sizeDest.cx;
				
			else if (m_nVert < 0)
				dYOffset = (double)-m_nVert * (sizeDest.cx - nX) / sizeDest.cx;

			// shears +ve (right) or -ve (left)
			for (int nY = 0; nY < sizeDest.cy; nY++)
			{
				double dXOffset = 0;

				// calc the offset to src X coord
				if (m_nHorz < 0)
					dXOffset = (double)-m_nHorz * nY / sizeDest.cy;
				
				else if (m_nHorz > 0)
					dXOffset = (double)m_nHorz * (sizeDest.cy - nY) / sizeDest.cy;

				double dSrcX = nX - dXOffset;
				double dSrcY = nY - dYOffset;

				if ((int)dSrcX >= 0 && (int)dSrcX < sizeSrc.cx && (int)dSrcY >= 0 && (int)dSrcY < sizeSrc.cy)
				{
					if (!m_bWeightingEnabled)
					{
						RGBX* pRGBSrc = &pSrcPixels[(int)dSrcY * sizeSrc.cx + (int)dSrcX];
						pDestPixels[nY * sizeDest.cx + nX] = *pRGBSrc;
					}
					else
						CalcWeightedColor(pSrcPixels, sizeSrc, dSrcX, dSrcY, 
											pDestPixels[nY * sizeDest.cx + nX]);
				}
			}
		}
	}

	return bRes;
}

///////

CImageGrayer::CImageGrayer()
	: m_dRedFactor(0), m_dGreenFactor(0), m_dBlueFactor(0), m_bDefault(TRUE)
{
}

CImageGrayer::CImageGrayer(double dRedFactor, double dGreenFactor, double dBlueFactor)
	: m_dRedFactor(dRedFactor), m_dGreenFactor(dGreenFactor), m_dBlueFactor(dBlueFactor), m_bDefault(FALSE)
{
}

CImageGrayer::~CImageGrayer()
{
}

BOOL CImageGrayer::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF crMask)
{
	UNREFERENCED_PARAMETER(sizeDest);
	ASSERT (sizeSrc == sizeDest);

	for (int nX = 0; nX < sizeSrc.cx; nX++)
	{
		for (int nY = 0; nY < sizeSrc.cy; nY++)
		{
			RGBX* pRGBSrc = &pSrcPixels[nY * sizeSrc.cx + nX];
			RGBX* pRGBDest = &pDestPixels[nY * sizeSrc.cx + nX];

			if (crMask == -1 || !(crMask == *pRGBSrc))
			{
				if (m_bDefault)
					pRGBDest->MakeGray(*pRGBSrc);
				else
					pRGBDest->MakeGray(*pRGBSrc, m_dRedFactor, m_dGreenFactor, m_dBlueFactor);
			}
			else
				*pRGBDest = *pRGBSrc;
		}
	}

	return TRUE;
}

///////

CImageLightener::CImageLightener(double dAmount) : m_dAmount(dAmount)
{
}

CImageLightener::~CImageLightener()
{
}

BOOL CImageLightener::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF crMask)
{
	ASSERT (sizeSrc == sizeDest);
	BOOL bRes = TRUE;

	if (m_dAmount == 0)
		bRes = C32BitImageProcessor::ProcessPixels(pSrcPixels, sizeSrc, pDestPixels, sizeDest);
	else
	{
		for (int nX = 0; nX < sizeSrc.cx; nX++)
		{
			for (int nY = 0; nY < sizeSrc.cy; nY++)
			{
				RGBX* pRGBSrc = &pSrcPixels[nY * sizeSrc.cx + nX];
				RGBX* pRGBDest = &pDestPixels[nY * sizeSrc.cx + nX];

				if (crMask == -1 || !(crMask == *pRGBSrc))
				{
					// convert to HLS
					HLSX hls;
					RGBX::RGB2HLS(*pRGBSrc, hls);

					// then tweak the luminosity
					hls.fLuminosity = min(max(0.0f, hls.fLuminosity + (float)m_dAmount), 1.0f);
					RGBX::HLS2RGB(hls, *pRGBDest);
				}
				else
					*pRGBDest = *pRGBSrc;
			}
		}
	}

	return bRes;
}

///////

CImageBlurrer::CImageBlurrer(int nAmount)
{
	m_nAmount = max(0, min(100, nAmount));
}

CImageBlurrer::~CImageBlurrer()
{
}

BOOL CImageBlurrer::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF /*crMask*/)
{
	BOOL bRes = TRUE;

	if (m_nAmount == 0)
		bRes = C32BitImageProcessor::ProcessPixels(pSrcPixels, sizeSrc, pDestPixels, sizeDest);
	else
	{
		ASSERT (sizeSrc == sizeDest);

		char nPeak = (char)(0.5 * (110 - m_nAmount));
		char cMask[9] = { 1, 1, 1, 
						  1, nPeak, 1, 
						  1, 1, 1 };

		for (int nX = 0; nX < sizeSrc.cx; nX++)
		{
			for (int nY = 0; nY < sizeSrc.cy; nY++)
			{
				int nRed = 0, nGreen = 0, nBlue = 0, nSubCount = 0, nDivisor = 0;

				for (int nSubX = nX - 1; nSubX <= nX + 1; nSubX++)
				{
					for (int nSubY = nY - 1; nSubY <= nY + 1; nSubY++)
					{
						if (nSubX >= 0 && nSubX < sizeSrc.cx && nSubY >= 0 && nSubY < sizeSrc.cy)
						{
							RGBX* pRGBSub = &pSrcPixels[nSubY * sizeSrc.cx + nSubX];

							int nMask = cMask[nSubCount];

							nRed += pRGBSub->btRed * nMask;
							nGreen += pRGBSub->btGreen * nMask;
							nBlue += pRGBSub->btBlue * nMask;

							nDivisor += nMask;
						}

						nSubCount++;
					}
				}

				RGBX* pRGBDest = &pDestPixels[nY * sizeDest.cx + nX];

				pRGBDest->btRed = (BYTE)min(255, nRed / nDivisor);
				pRGBDest->btGreen = (BYTE)min(255, nGreen / nDivisor);
				pRGBDest->btBlue = (BYTE)min(255, nBlue / nDivisor);
			}
		}
	}

	return TRUE;
}

///////

CImageSharpener::CImageSharpener(int nAmount)
{
	m_nAmount = max(0, min(100, nAmount));
}

CImageSharpener::~CImageSharpener()
{
}

BOOL CImageSharpener::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF /*crMask*/)
{
	BOOL bRes = TRUE;

	if (m_nAmount == 0)
		bRes = C32BitImageProcessor::ProcessPixels(pSrcPixels, sizeSrc, pDestPixels, sizeDest);
	else
	{
		ASSERT (sizeSrc == sizeDest);

		double dMinMaxRatio = (double)1 / (1 + (100 - m_nAmount) * 0.5);

		double dMaxFactor = 1 / (4 * (1 + dMinMaxRatio));
		double dMinFactor = dMaxFactor * dMinMaxRatio;

		double dMask[9] = { -dMinFactor, -dMaxFactor, -dMinFactor, 
							-dMaxFactor, 2, -dMaxFactor, 
							-dMinFactor, -dMaxFactor, -dMinFactor };

		for (int nX = 0; nX < sizeSrc.cx; nX++)
		{
			for (int nY = 0; nY < sizeSrc.cy; nY++)
			{
				if (nX == 0 || nX == sizeSrc.cx - 1 || nY == 0 || nY == sizeSrc.cy - 1)
				{
					pDestPixels[nY * sizeDest.cx + nX] = pSrcPixels[nY * sizeSrc.cx + nX];
				}
				else
				{
					double dRed = 0, dGreen = 0, dBlue = 0;
					int nSubCount = 0;
					
					for (int nSubX = nX - 1; nSubX <= nX + 1; nSubX++)
					{
						for (int nSubY = nY - 1; nSubY <= nY + 1; nSubY++)
						{
							RGBX* pRGBSub = &pSrcPixels[nSubY * sizeSrc.cx + nSubX];

							double dVMask = dMask[nSubCount];
							
							dRed += pRGBSub->btRed * dVMask;
							dGreen += pRGBSub->btGreen * dVMask;
							dBlue += pRGBSub->btBlue * dVMask;
							
							nSubCount++;
						}
					}

					RGBX* pRGBDest = &pDestPixels[nY * sizeDest.cx + nX];
					
					dRed = min(255, dRed);
					dGreen = min(255, dGreen);
					dBlue = min(255, dBlue);
					dRed = max(0, dRed);
					dGreen = max(0, dGreen);
					dBlue = max(0, dBlue);

					pRGBDest->btRed = (BYTE)dRed;
					pRGBDest->btGreen = (BYTE)dGreen;
					pRGBDest->btBlue = (BYTE)dBlue;
				}
			}
		}
	}

	return TRUE;
}

////////

BOOL CImageEmbosser::ProcessPixels(RGBX* pSrcPixels, CSize sizeSrc, RGBX* pDestPixels, CSize sizeDest, 
								COLORREF crMask)
{
	ASSERT (sizeSrc == sizeDest);
	
	double dMask[9] = { -0.5, 0, 0, 
						0, 1, 0, 
						0, 0, 0 };
	
	for (int nX = 0; nX < sizeSrc.cx; nX++)
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -