📄 ip.cpp
字号:
}
/*************************************************************************
*
* MedianFilterDIB()
*
* Parameters:
*
* HDIB hDib - objective DIB handle
*
* Return Value:
*
* BOOL - True is success, else False
*
* Description:
*
* This is the media filtering function to DIB
*
************************************************************************/
BOOL MedianFilterDIB(HDIB hDib)
{
WaitCursorBegin();
HDIB hNewDib = NULL;
// we only convolute 24bpp DIB, so first convert DIB to 24bpp
WORD wBitCount = DIBBitCount(hDib);
if (wBitCount != 24)
hNewDib = ConvertDIBFormat(hDib, 24, NULL);
else
hNewDib = CopyHandle(hDib);
if (! hNewDib)
{
WaitCursorEnd();
return FALSE;
}
// new DIB attributes
WORD wDIBWidth = (WORD)DIBWidth(hNewDib);
WORD wDIBHeight = (WORD)DIBHeight(hNewDib);
WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib);
DWORD dwImageSize = wBytesPerLine * wDIBHeight;
// Allocate and lock memory for filtered image data
HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize);
if (!hFilteredBits)
{
WaitCursorEnd();
return FALSE;
}
LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits);
// get bits address in DIB
LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
LPBYTE lpDIBits = FindDIBBits(lpDIB);
// convolute...
for (int i=1; i<wDIBHeight-1; i++)
for (int j=1; j<wDIBWidth-1; j++)
{
int red=0, green=0, blue=0;
DoMedianFilterDIB(&red, &green, &blue, i, j, wBytesPerLine, lpDIBits);
LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
*(lpDestImage + lOffset++) = BOUND(blue, 0, 255);
*(lpDestImage + lOffset++) = BOUND(green, 0, 255);
*(lpDestImage + lOffset) = BOUND(red, 0, 255);
}
// a filtered image is available in lpDestImage
// copy it to DIB bits
memcpy(lpDIBits, lpDestImage, dwImageSize);
// cleanup temp buffers
GlobalUnlock(hFilteredBits);
GlobalFree(hFilteredBits);
GlobalUnlock(hNewDib);
// rebuild hDib
HDIB hTmp = NULL;
if (wBitCount != 24)
hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL);
else
hTmp = CopyHandle(hNewDib);
GlobalFree(hNewDib);
DWORD dwSize = GlobalSize(hTmp);
memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize);
GlobalUnlock(hTmp);
GlobalFree(hTmp);
GlobalUnlock(hDib);
WaitCursorEnd();
return TRUE;
}
/*************************************************************************
*
* ConvoluteDIB()
*
* Parameters:
*
* HDIB hDib - objective DIB handle
* KERNEL *lpKernel - pointer of kernel used to convolute with DIB
* int Strength - operation strength set to the convolute
* int nKernelNum - kernel number used to convolute
*
* Return Value:
*
* BOOL - True is success, else False
*
* Description:
*
* This is the generic convolute function to DIB
*
************************************************************************/
BOOL ConvoluteDIB(HDIB hDib, KERNEL *lpKernel, int Strength, int nKernelNum)
{
WaitCursorBegin();
HDIB hNewDib = NULL;
// we only convolute 24bpp DIB, so first convert DIB to 24bpp
WORD wBitCount = DIBBitCount(hDib);
if (wBitCount != 24)
hNewDib = ConvertDIBFormat(hDib, 24, NULL);
else
hNewDib = CopyHandle(hDib);
if (! hNewDib)
{
WaitCursorEnd();
return FALSE;
}
// new DIB attributes
WORD wDIBWidth = (WORD)DIBWidth(hNewDib);
WORD wDIBHeight = (WORD)DIBHeight(hNewDib);
WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib);
DWORD dwImageSize = wBytesPerLine * wDIBHeight;
// Allocate and lock memory for filtered image data
HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize);
if (!hFilteredBits)
{
WaitCursorEnd();
return FALSE;
}
LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits);
// get bits address in DIB
LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
LPBYTE lpDIBits = FindDIBBits(lpDIB);
// convolute...
for (int i=1; i<wDIBHeight-1; i++)
for (int j=1; j<wDIBWidth-1; j++)
{
int red=0, green=0, blue=0;
for (int k=0; k<nKernelNum; ++k)
{
int r=0, g=0, b=0;
DoConvoluteDIB(&r, &g, &b, i, j,
wBytesPerLine, lpDIBits, lpKernel+k);
if (r > red)
red = r;
if (g > green)
green = g;
if (b > blue)
blue = b;
//red += r; green += g; blue += b;
}
// original RGB value in center pixel (j, i)
LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
BYTE OldB = *(lpDIBits + lOffset++);
BYTE OldG = *(lpDIBits + lOffset++);
BYTE OldR = *(lpDIBits + lOffset);
// When we get here, red, green and blue have the new RGB value.
if (Strength != 10)
{
// Interpolate pixel data
red = OldR + (((red - OldR) * Strength) / 10);
green = OldG + (((green - OldG) * Strength) / 10);
blue = OldB + (((blue - OldB) * Strength) / 10);
}
lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
*(lpDestImage + lOffset++) = BOUND(blue, 0, 255);
*(lpDestImage + lOffset++) = BOUND(green, 0, 255);
*(lpDestImage + lOffset) = BOUND(red, 0, 255);
}
// a filtered image is available in lpDestImage
// copy it to DIB bits
memcpy(lpDIBits, lpDestImage, dwImageSize);
// cleanup temp buffers
GlobalUnlock(hFilteredBits);
GlobalFree(hFilteredBits);
GlobalUnlock(hNewDib);
// rebuild hDib 为什么要重建。
HDIB hTmp = NULL;
if (wBitCount != 24)
hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL);
else
hTmp = CopyHandle(hNewDib);
GlobalFree(hNewDib);
DWORD dwSize = GlobalSize(hTmp);
memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize);
GlobalUnlock(hTmp);
GlobalFree(hTmp);
GlobalUnlock(hDib);
WaitCursorEnd();
return TRUE;
}
// local function: perform convolution to DIB with a kernel
void DoConvoluteDIB(int *red, int *green, int *blue, int i, int j,
WORD wBytesPerLine, LPBYTE lpDIBits, KERNEL *lpKernel)
{
BYTE b[9], g[9], r[9];
LONG lOffset;
lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine);
b[0] = *(lpDIBits + lOffset++);
g[0] = *(lpDIBits + lOffset++);
r[0] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine);
b[1] = *(lpDIBits + lOffset++);
g[1] = *(lpDIBits + lOffset++);
r[1] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine);
b[2] = *(lpDIBits + lOffset++);
g[2] = *(lpDIBits + lOffset++);
r[2] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine);
b[3] = *(lpDIBits + lOffset++);
g[3] = *(lpDIBits + lOffset++);
r[3] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
b[4] = *(lpDIBits + lOffset++);
g[4] = *(lpDIBits + lOffset++);
r[4] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine);
b[5] = *(lpDIBits + lOffset++);
g[5] = *(lpDIBits + lOffset++);
r[5] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine);
b[6] = *(lpDIBits + lOffset++);
g[6] = *(lpDIBits + lOffset++);
r[6] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine);
b[7] = *(lpDIBits + lOffset++);
g[7] = *(lpDIBits + lOffset++);
r[7] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine);
b[8] = *(lpDIBits + lOffset++);
g[8] = *(lpDIBits + lOffset++);
r[8] = *(lpDIBits + lOffset);
*red = *green = *blue = 0;
for (int k=0; k<8; ++k)
{
*red += lpKernel->Element[k]*r[k];
*green += lpKernel->Element[k]*g[k];
*blue += lpKernel->Element[k]*b[k];
}
if (lpKernel->Divisor != 1)
{
*red /= lpKernel->Divisor;
*green /= lpKernel->Divisor;
*blue /= lpKernel->Divisor;
}
// getoff opposite
*red = abs(*red);
*green = abs(*green);
*blue = abs(*blue);
}
// local function: perform median filter to DIB
void DoMedianFilterDIB(int *red, int *green, int *blue, int i, int j,
WORD wBytesPerLine, LPBYTE lpDIBits)
{
BYTE b[9], g[9], r[9];
LONG lOffset;
lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine);
b[0] = *(lpDIBits + lOffset++);
g[0] = *(lpDIBits + lOffset++);
r[0] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine);
b[1] = *(lpDIBits + lOffset++);
g[1] = *(lpDIBits + lOffset++);
r[1] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine);
b[2] = *(lpDIBits + lOffset++);
g[2] = *(lpDIBits + lOffset++);
r[2] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine);
b[3] = *(lpDIBits + lOffset++);
g[3] = *(lpDIBits + lOffset++);
r[3] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
b[4] = *(lpDIBits + lOffset++);
g[4] = *(lpDIBits + lOffset++);
r[4] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine);
b[5] = *(lpDIBits + lOffset++);
g[5] = *(lpDIBits + lOffset++);
r[5] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine);
b[6] = *(lpDIBits + lOffset++);
g[6] = *(lpDIBits + lOffset++);
r[6] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine);
b[7] = *(lpDIBits + lOffset++);
g[7] = *(lpDIBits + lOffset++);
r[7] = *(lpDIBits + lOffset);
lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine);
b[8] = *(lpDIBits + lOffset++);
g[8] = *(lpDIBits + lOffset++);
r[8] = *(lpDIBits + lOffset);
qsort(r, 9, 1, compare);
qsort(g, 9, 1, compare);
qsort(b, 9, 1, compare);
*red = r[0];
*green = g[0];
*blue = b[0];
}
// function used to sort in the call of qsort
int compare(const void *e1, const void *e2)
{
if (*(BYTE *)e1 < *(BYTE *)e2)
return -1;
if (*(BYTE *)e1 > *(BYTE *)e2)
return 1;
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -