// dibapi.h
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#ifndef _INC_DIBAPI
#define _INC_DIBAPI
/* Handle to a DIB */
DECLARE_HANDLE(HDIB);
/* DIB constants */
#define PALVERSION 0x300
/* DIB Macros*/
#define IS_WIN30_DIB(lpbi) ((*(LPDWORD)(lpbi)) == sizeof(BITMAPINFOHEADER))
#define RECTWIDTH(lpRect) ((lpRect)->right - (lpRect)->left)
#define RECTHEIGHT(lpRect) ((lpRect)->bottom - (lpRect)->top)
// WIDTHBYTES performs DWORD-aligning of DIB scanlines. The "bits"
// parameter is the bit count for the scanline (biWidth * biBitCount),
// and this macro returns the number of DWORD-aligned bytes needed
// to hold those bits.
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
/* Function prototypes */
BOOL WINAPI PaintDIB (HDC, LPRECT, HDIB, LPRECT, CPalette* pPal);
BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* cPal);
LPSTR WINAPI FindDIBBits (LPSTR lpbi);
DWORD WINAPI DIBWidth (LPSTR lpDIB);
DWORD WINAPI DIBHeight (LPSTR lpDIB);
WORD WINAPI PaletteSize (LPSTR lpbi);
WORD WINAPI DIBNumColors (LPSTR lpbi);
HGLOBAL WINAPI CopyHandle (HGLOBAL h);
BOOL WINAPI SaveDIB (HDIB hDib, CFile& file);
HDIB WINAPI ReadDIBFile(CFile& file);
HDIB WINAPI NewDIB(long width, long height, unsigned short biBitCount= 0); //add
void WINAPI ConvertShort(unsigned short *array, long length);
void WINAPI ConvertLong(unsigned long *array, long length);
BOOL WINAPI EdgeDetect(LPSTR lpDIBBits,long lWidth,long lHeight);
BOOL WINAPI ContourTrace(LPSTR lpDIBBits,long lWidth,long lHeight);
BOOL MaxImg(LPSTR img,long lWidth,long lHeight);
BOOL MinImg(LPSTR img,long lWidth,long lHeight);
BOOL MiddleImg(LPSTR img,long lWidth,long lHeight);
BOOL Erosion(LPSTR lpDIBBits,long lWidth,long lHeight,int ErosionType);
BOOL Dialation(LPSTR lpDIBBits,long lWidth,long lHeight,int DialationType);
BOOL MirrorImg(LPSTR lpDIBBits,long lWidth,long lHeight,int mirrorType);
HGLOBAL WINAPI RotateImg(LPSTR lpDIB,float angle);
BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight);
BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight);
BOOL WINAPI Template(LPSTR lpDIBBits,long lWidth,long lHeight,float *temp,int temp_w,int temp_h,float xishu);
#endif //!_INC_DIBAPI
// dibapi.cpp
//
// Source file for Device-Independent Bitmap (DIB) API. Provides
// the following functions:
//
// PaintDIB() - Painting routine for a DIB
// CreateDIBPalette() - Creates a palette from a DIB
// FindDIBBits() - Returns a pointer to the DIB bits
// DIBWidth() - Gets the width of the DIB
// DIBHeight() - Gets the height of the DIB
// PaletteSize() - Gets the size required to store the DIB's palette
// DIBNumColors() - Calculates the number of colors
// in the DIB's color table
// CopyHandle() - Makes a copy of the given global memory block
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#include "dibapi.h"
#include "math.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#define PI 3.1415926
//角度到弧度转化的宏
#define RADIAN(angle) ((angle)*PI/180.0)
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
#ifdef _MAC
#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
void ByteSwapHeader(BITMAPFILEHEADER* bmiHeader);
void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header);
#endif
/*************************************************************************
*
* PaintDIB()
*
* Parameters:
*
* HDC hDC - DC to do output to
*
* LPRECT lpDCRect - rectangle on DC to do output to
*
* HDIB hDIB - handle to global memory with a DIB spec
* in it followed by the DIB bits
*
* LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
*
* CPalette* pPal - pointer to CPalette containing DIB's palette
*
* Return Value:
*
* BOOL - TRUE if DIB was drawn, FALSE otherwise
*
* Description:
* Painting routine for a DIB. Calls StretchDIBits() or
* SetDIBitsToDevice() to paint the DIB. The DIB is
* output to the specified DC, at the coordinates given
* in lpDCRect. The area of the DIB to be output is
* given by lpDIBRect.
*
************************************************************************/
BOOL WINAPI PaintDIB(HDC hDC,
LPRECT lpDCRect,
HDIB hDIB,
LPRECT lpDIBRect,
CPalette* pPal)
{
LPSTR lpDIBHdr; // Pointer to BITMAPINFOHEADER
LPSTR lpDIBBits; // Pointer to DIB bits
BOOL bSuccess=FALSE; // Success/fail flag
HPALETTE hPal=NULL; // Our DIB's palette
HPALETTE hOldPal=NULL; // Previous palette
/* Check for valid DIB handle */
if (hDIB == NULL)
return FALSE;
/* Lock down the DIB, and get a pointer to the beginning of the bit
* buffer
*/
lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
lpDIBBits = ::FindDIBBits(lpDIBHdr);
// Get the DIB's palette, then select it into DC
if (pPal != NULL)
{
hPal = (HPALETTE) pPal->m_hObject;
// Select as background since we have
// already realized in forground if needed
hOldPal = ::SelectPalette(hDC, hPal, TRUE);
}
/* Make sure to use the stretching mode best for color pictures */
::SetStretchBltMode(hDC, COLORONCOLOR);
/* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
(RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
bSuccess = ::SetDIBitsToDevice(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
(int)DIBHeight(lpDIBHdr) -
lpDIBRect->top -
RECTHEIGHT(lpDIBRect), // SrcY
0, // nStartScan
(WORD)DIBHeight(lpDIBHdr), // nNumScans
lpDIBBits, // lpBits
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
DIB_RGB_COLORS); // wUsage
else
bSuccess = ::StretchDIBits(hDC, // hDC
lpDCRect->left, // DestX
lpDCRect->top, // DestY
RECTWIDTH(lpDCRect), // nDestWidth
RECTHEIGHT(lpDCRect), // nDestHeight
lpDIBRect->left, // SrcX
lpDIBRect->top, // SrcY
RECTWIDTH(lpDIBRect), // wSrcWidth
RECTHEIGHT(lpDIBRect), // wSrcHeight
lpDIBBits, // lpBits
(LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
DIB_RGB_COLORS, // wUsage
SRCCOPY); // dwROP
::GlobalUnlock((HGLOBAL) hDIB);
/* Reselect old palette */
if (hOldPal != NULL)
{
::SelectPalette(hDC, hOldPal, TRUE);
}
return bSuccess;
}
/*************************************************************************
*
* CreateDIBPalette()
*
* Parameter:
*
* HDIB hDIB - specifies the DIB
*
* Return Value:
*
* HPALETTE - specifies the palette
*
* Description:
*
* This function creates a palette from a DIB by allocating memory for the
* logical palette, reading and storing the colors from the DIB's color table
* into the logical palette, creating a palette from this logical palette,
* and then returning the palette's handle. This allows the DIB to be
* displayed using the best possible colors (important for DIBs with 256 or
* more colors).
*
************************************************************************/
BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
{
LPLOGPALETTE lpPal; // pointer to a logical palette
HANDLE hLogPal; // handle to a logical palette
HPALETTE hPal = NULL; // handle to a palette
int i; // loop index
WORD wNumColors; // number of colors in color table
LPSTR lpbi; // pointer to packed-DIB
LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (old)
BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB
BOOL bResult = FALSE;
/* if handle to DIB is invalid, return FALSE */
if (hDIB == NULL)
return FALSE;
lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
/* get pointer to BITMAPINFO (Win 3.0) */
lpbmi = (LPBITMAPINFO)lpbi;
/* get pointer to BITMAPCOREINFO (old 1.x) */
lpbmc = (LPBITMAPCOREINFO)lpbi;
/* get the number of colors in the DIB */
wNumColors = ::DIBNumColors(lpbi);
if (wNumColors != 0)
{
/* allocate memory block for logical palette */
hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
+ sizeof(PALETTEENTRY)
* wNumColors);
/* if not enough memory, clean up and return NULL */
if (hLogPal == 0)
{
::GlobalUnlock((HGLOBAL) hDIB);
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
/* set version and number of palette entries */
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (WORD)wNumColors;
/* is this a Win 3.0 DIB? */
bWinStyleDIB = IS_WIN30_DIB(lpbi);
for (i = 0; i < (int)wNumColors; i++)
{
if (bWinStyleDIB)
{
lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
else
{
lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
lpPal->palPalEntry[i].peFlags = 0;
}
}
/* create the palette and get handle to it */
bResult = pPal->CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal);
}
::GlobalUnlock((HGLOBAL) hDIB);
return bResult;
}
/*************************************************************************
*
* FindDIBBits()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* LPSTR - pointer to the DIB bits
*
* Description:
*
* This function calculates the address of the DIB's bits and returns a
* pointer to the DIB bits.
*
************************************************************************/
LPSTR WINAPI FindDIBBits(LPSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
}
/*************************************************************************
*
* DIBWidth()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - width of the DIB
*
* Description:
*
* This function gets the width of the DIB from the BITMAPINFOHEADER
* width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
* width field if it is an other-style DIB.
*
************************************************************************/
DWORD WINAPI DIBWidth(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
/* point to the header (whether Win 3.0 and old) */
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
/* return the DIB width if it is a Win 3.0 DIB */
if (IS_WIN30_DIB(lpDIB))
return lpbmi->biWidth;
else /* it is an other-style DIB, so return its width */
return (DWORD)lpbmc->bcWidth;
}
/*************************************************************************
*
* DIBHeight()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* DWORD - height of the DIB
*
* Description:
*
* This function gets the height of the DIB from the BITMAPINFOHEADER
* height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
* height field if it is an other-style DIB.
*
************************************************************************/
DWORD WINAPI DIBHeight(LPSTR lpDIB)
{
LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
/* point to the header (whether old or Win 3.0 */
lpbmi = (LPBITMAPINFOHEADER)lpDIB;
lpbmc = (LPBITMAPCOREHEADER)lpDIB;
/* return the DIB height if it is a Win 3.0 DIB */
if (IS_WIN30_DIB(lpDIB))
return lpbmi->biHeight;
else /* it is an other-style DIB, so return its height */
return (DWORD)lpbmc->bcHeight;
}
/*************************************************************************
*
* PaletteSize()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* WORD - size of the color palette of the DIB
*
* Description:
*
* This function gets the size required to store the DIB's palette by
* multiplying the number of colors by the size of an RGBQUAD (for a
* Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
* style DIB).
*
************************************************************************/
WORD WINAPI PaletteSize(LPSTR lpbi)
{
/* calculate the size required by the palette */
if (IS_WIN30_DIB (lpbi))
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
else
return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
/*************************************************************************
*
* DIBNumColors()
*
* Parameter:
*
* LPSTR lpbi - pointer to packed-DIB memory block
*
* Return Value:
*
* WORD - number of colors in the color table
*
* Description:
*
* This function calculates the number of colors in the DIB's color table
* by finding the bits per pixel for the DIB (whether Win3.0 or other-style
* DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
* if 24, no colors in color table.
*
************************************************************************/
WORD WINAPI DIBNumColors(LPSTR lpbi)
{
WORD wBitCount; // DIB bit count
/* If this is a Windows-style DIB, the number of colors in the
* color table can be less than the number of bits per pixel
* allows for (i.e. lpbi->biClrUsed can be set to some value).
* If this is the case, return the appropriate value.
*/
if (IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
if (dwClrUsed != 0)
return (WORD)dwClrUsed;
}
/* Calculate the number of colors in the color table based on
* the number of bits per pixel for the DIB.
*/
if (IS_WIN30_DIB(lpbi))
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
/* return number of colors based on bits per pixel */
switch (wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
/*************************************************************************
*
* SaveDIB()
*
* Saves the specified DIB into the specified CFile. The CFile
* is opened and closed by the caller.
*
* Parameters:
*
* HDIB hDib - Handle to the dib to save
*
* CFile& file - open CFile used to save DIB
*
* Return value: TRUE if successful, else FALSE or CFileException
*
*************************************************************************/
BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
{
BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
DWORD dwDIBSize;
if (hDib == NULL)
return FALSE;
/*
* Get a pointer to the DIB memory, the first of which contains
* a BITMAPINFO structure
*/
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if (lpBI == NULL)
return FALSE;
if (!IS_WIN30_DIB(lpBI))
{
::GlobalUnlock((HGLOBAL) hDib);
return FALSE; // It's an other-style DIB (save not supported)
}
/*
* Fill in the fields of the file header
*/
/* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
// Calculating the size of the DIB is a bit tricky (if we want to
// do it right). The easiest way to do this is to call GlobalSize()
// on our global handle, but since the size of our global memory may have
// been padded a few bytes, we may end up writing out a few too
// many bytes to the file (which may cause problems with some apps).
//
// So, instead let's calculate the size manually (if we can)
//
// First, find size of header plus size of color table. Since the
// first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
// the size of the structure, let's use this.
dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // Partial Calculation
// Now calculate the size of the image
if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
{
// It's an RLE bitmap, we can't calculate size, so trust the
// biSizeImage field
dwDIBSize += lpBI->biSizeImage;
}
else
{
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
lpBI->biSizeImage = dwBmBitsSize;
}
// Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
/*
* Now, calculate the offset the actual bitmap bits will be in
* the file -- It's the Bitmap file header plus the DIB header,
* plus the size of the color table.
*/
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
+ PaletteSize((LPSTR)lpBI);
#ifdef _MAC
ByteSwapHeader(&bmfHdr);
// First swap the size field
*((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
// Now swap the rest of the structure (we don't save < Win30 files)
ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
TRY
{
// Write the file header
file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
//
// Write the DIB header and the bits
//
file.WriteHuge(lpBI, dwDIBSize);
}
CATCH (CFileException, e)
{
#ifdef _MAC
// Swap everything back
*((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_CATCH
#ifdef _MAC
// Swap everything back
*((LPDWORD)lpBI) = SWAPLONG(*((LPDWORD)lpBI));
ByteSwapInfo((LPSTR)lpBI, TRUE);
#endif
::GlobalUnlock((HGLOBAL) hDib);
return TRUE;
}
/*************************************************************************
Function: ReadDIBFile (CFile&)
Purpose: Reads in the specified DIB file into a global chunk of
memory.
Returns: A handle to a dib (hDIB) if successful.
NULL if an error occurs.
Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
from the end of the BITMAPFILEHEADER structure on is
returned in the global memory handle.
*************************************************************************/
HDIB WINAPI ReadDIBFile(CFile& file)
{
BITMAPFILEHEADER bmfHeader;
DWORD dwBitsSize;
HDIB hDIB;
LPSTR pDIB;
/*
* get length of DIB in bytes for use when reading
*/
dwBitsSize = file.GetLength();
/*
* Go read the DIB file header and check if it's valid.
*/
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
return NULL;
#ifdef _MAC
ByteSwapHeader(&bmfHeader);
#endif
if (bmfHeader.bfType != DIB_HEADER_MARKER)
return NULL;
/*
* Allocate memory for DIB
*/
hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
/*
* Go read the bits.
*/
if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
dwBitsSize - sizeof(BITMAPFILEHEADER) )
{
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return NULL;
}
#ifdef _MAC
// First swap the size field
*((LPDWORD)pDIB) = SWAPLONG(*((LPDWORD)pDIB));
// Now swap the rest of the structure
ByteSwapInfo(pDIB, IS_WIN30_DIB(pDIB));
#endif
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
// add Nov.27,1999
HDIB WINAPI NewDIB(long width, long height,unsigned short biBitCount) // add "biBitCount" by hchen Jan 25,00
{
long dwindth = (width*biBitCount/8+3)/4*4; // align 4 bytes
WORD color_num;
switch(biBitCount)
{
case 1:
color_num=2;
break;
case 4:
color_num=16;
break;
case 8:
color_num=256;
break;
default:
color_num=0;
break;
}
long dwBitsSize = dwindth *height + 40 + color_num*4;// 40 LPBIMHEAD
LPSTR pDIB;
HDIB hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
if (hDIB == 0)
{
return NULL;
}
pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
LPBITMAPINFO lpmf = (LPBITMAPINFO)pDIB;
lpmf->bmiHeader.biSize = 40;//40
lpmf->bmiHeader.biWidth = width; //i_info.width;
lpmf->bmiHeader.biHeight = height;
lpmf->bmiHeader.biPlanes = 1;
lpmf->bmiHeader.biBitCount = biBitCount;// 24
lpmf->bmiHeader.biCompression = 0;
lpmf->bmiHeader.biSizeImage = dwindth *height;
lpmf->bmiHeader.biXPelsPerMeter = 2925;
lpmf->bmiHeader.biYPelsPerMeter = 2925;
lpmf->bmiHeader.biClrUsed = 0;
lpmf->bmiHeader.biClrImportant= 0;
if(color_num!=0)
{
for(int i=0;i<color_num;i++)
{
lpmf->bmiColors[i].rgbRed =(BYTE)i;
lpmf->bmiColors[i].rgbGreen =(BYTE)i;
lpmf->bmiColors[i].rgbBlue =(BYTE)i;
}
}
::GlobalUnlock((HGLOBAL) hDIB);
return hDIB;
}
#ifdef _MAC
void ByteSwapHeader(BITMAPFILEHEADER* bmfHeader)
{
bmfHeader->bfType = SWAPWORD(bmfHeader->bfType);
bmfHeader->bfSize = SWAPLONG(bmfHeader->bfSize);
bmfHeader->bfOffBits = SWAPLONG(bmfHeader->bfOffBits);
}
void ByteSwapInfo(LPSTR lpHeader, BOOL fWin30Header)
{
// Note this doesn't swap the bcSize/biSize field. It assumes that the
// size field was swapped during read or while setting the fWin30Header
// flag.
if (fWin30Header)
{
LPBITMAPINFOHEADER lpBMIH = &(LPBITMAPINFO(lpHeader)->bmiHeader);
//lpBMIH->biSize = SWAPLONG(lpBMIH->biSize);
lpBMIH->biWidth = SWAPLONG(lpBMIH->biWidth);
lpBMIH->biHeight = SWAPLONG(lpBMIH->biHeight);
lpBMIH->biPlanes = SWAPWORD(lpBMIH->biPlanes);
lpBMIH->biBitCount = SWAPWORD(lpBMIH->biBitCount);
lpBMIH->biCompression = SWAPLONG(lpBMIH->biCompression);
lpBMIH->biSizeImage = SWAPLONG(lpBMIH->biSizeImage);
lpBMIH->biXPelsPerMeter = SWAPLONG(lpBMIH->biXPelsPerMeter);
lpBMIH->biYPelsPerMeter = SWAPLONG(lpBMIH->biYPelsPerMeter);
lpBMIH->biClrUsed = SWAPLONG(lpBMIH->biClrUsed);
lpBMIH->biClrImportant = SWAPLONG(lpBMIH->biClrImportant);
}
else
{
LPBITMAPCOREHEADER lpBMCH = &(LPBITMAPCOREINFO(lpHeader)->bmciHeader);
lpBMCH->bcWidth = SWAPWORD(lpBMCH->bcWidth);
lpBMCH->bcHeight = SWAPWORD(lpBMCH->bcHeight);
lpBMCH->bcPlanes = SWAPWORD(lpBMCH->bcPlanes);
lpBMCH->bcBitCount = SWAPWORD(lpBMCH->bcBitCount);
}
}
#endif
/*************************************************************************
*
* 函数名称:
* EdgeDetect()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对图象进行轮廓提取,前提是图象数据必须是只有0和255的二值图象
* 0表示物体,255为背景,采用掏空内部点的原理
*
************************************************************************/
BOOL WINAPI EdgeDetect(LPSTR lpDIBBits,long lWidth,long lHeight)
{
LPSTR lpsrc;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=WIDTHBYTES(lWidth*8);
LPSTR lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
int i,j;
BYTE w,e,s,n,sw,nw,ne,se;
/* for(i=0;i<lHeight;i++)
for(j=0;j<lWidth;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
pixel=(BYTE)*lpsrc;
if(pixel>=120)
*lpsrc=(BYTE)255;
else
*lpsrc=(BYTE)0;
}*/
memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
for(i=1;i<lHeight-1;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*i+j;
pixel=(BYTE)*lpDst;
if(pixel!=255 && pixel!=0)
{
return FALSE;
}
if((*lpDst)==0)
{
w=(BYTE)*(lpDst-1);
e=(BYTE)*(lpDst+1);
nw=(BYTE)*(lpDst+lLineBytes-1);
n=(BYTE)*(lpDst+lLineBytes);
ne=(BYTE)*(lpDst+lLineBytes+1);
se=(BYTE)*(lpDst-lLineBytes+1);
s=(BYTE)*(lpDst-lLineBytes);
sw=(BYTE)*(lpDst-lLineBytes-1);
if(w+e+nw+n+ne+se+s+sw==0)
(*lpsrc)=(BYTE)255;
}
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* ContourTrace()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来对图象进行轮廓跟踪,前提是图象数据必须是只有0和255的二值图象
* 0表示物体,255为背景
*
************************************************************************/
BOOL WINAPI ContourTrace(LPSTR lpDIBBits,long lWidth,long lHeight)
{
LPSTR lpsrc;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=WIDTHBYTES(lWidth*8);
LPSTR lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memset(lpbuff,(BYTE)255,lLineBytes*lHeight);
int i,j;
bool IsStartPoint;
bool PointFind;
CPoint StartPoint;
CPoint CurrentPoint;
int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
int BeginDirect;
IsStartPoint=false;
for(i=1;i<lHeight-1 && !IsStartPoint;i++)
for(j=1;j<lWidth-1 && !IsStartPoint;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
pixel=(BYTE)*lpsrc;
if(pixel!=255 && pixel!=0)
{
return FALSE;
}
if(pixel==0)
{
StartPoint.x=j;
StartPoint.y=i;
IsStartPoint=true;
lpDst=lpbuff+lLineBytes*i+j;
*lpDst=(BYTE)0;
}
}
BeginDirect=0;
IsStartPoint=false;
CurrentPoint.x=StartPoint.x;
CurrentPoint.y=StartPoint.y;
while (!IsStartPoint)
{
PointFind=false;
while (!PointFind)
{
lpsrc=lpDIBBits+lLineBytes*(CurrentPoint.y+Direction[BeginDirect][1])+
(CurrentPoint.x+Direction[BeginDirect][0]);
pixel=(BYTE)*lpsrc;
if (pixel==0)
{
PointFind=true;
CurrentPoint.x=CurrentPoint.x+Direction[BeginDirect][0];
CurrentPoint.y=CurrentPoint.y+Direction[BeginDirect][1];
if(CurrentPoint.x==StartPoint.x && CurrentPoint.y==StartPoint.y)
{
IsStartPoint=true;
}
lpDst=lpbuff+lLineBytes*CurrentPoint.y+CurrentPoint.x;
*lpDst=(BYTE)0;
BeginDirect--;
if(BeginDirect==-1)
BeginDirect=7;
if(BeginDirect==-1)
BeginDirect=7;
}
else
{
BeginDirect++;
if(BeginDirect==8)
{
BeginDirect=0;
}
}
}
}
memcpy(lpDIBBits,lpbuff,lLineBytes*lHeight);
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* Template()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
* float *temp - 指向模板地址的指针
* int temp_w - 模板宽
* int temp_h - 模板高
* float xishu - 模板系数
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现模板操作(卷积运算)。
*
************************************************************************/
BOOL WINAPI Template(LPSTR lpDIBBits,long lWidth,long lHeight,float *temp,int temp_w,int temp_h,float xishu)
{
LPSTR lpsrc;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=WIDTHBYTES(lWidth*8);
LPSTR lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
int i,j,m,n;
double sum=0.0;
for(i=(temp_h-1)/2;i<lHeight-(temp_h-1)/2;i++)
for(j=temp_w/2;j<lWidth-temp_w/2;j++)
{
sum=0.0;
lpsrc=lpDIBBits+lLineBytes*i+j;
for(m=-(temp_h-1)/2;m<=(temp_h-1)/2;m++)
for(n=-(temp_w-1)/2;n<=(temp_w-1)/2;n++)
{
lpDst=lpbuff+lLineBytes*(m+i)+n+j;
pixel=(BYTE)*lpDst;
sum+=pixel*temp[(m+temp_h/2)*temp_w+(n+temp_w/2)];
}
sum=(int)(sum*xishu);
if(sum<0)
sum=0;
if(sum>255)
sum=255;
*lpsrc=(BYTE)sum;
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* MaxImg()
*
* 参数:
* LPSTR img - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
*
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现对图象的最大值滤波。
*
************************************************************************/
BOOL MaxImg(LPSTR img,long lWidth,long lHeight)
{
LPSTR lpsrc;
LPSTR lpbuff;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=(lWidth*8+31)/32*4;
lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memcpy(lpbuff,img,lLineBytes*lHeight);
int i,j,m,n;
for(i=1;i<lHeight-1;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=img+i*lLineBytes+j;
for(m=-1;m<=1;m++)
for(n=-1;n<=1;n++)
{
lpDst=lpbuff+(i+m)*lLineBytes+(j+n);
pixel=(BYTE)*lpDst;
if(*lpsrc<pixel)
*lpsrc=*lpDst;
}
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* MinImg()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现3*3模板的中值滤波
*
************************************************************************/
BOOL MinImg(LPSTR img,long lWidth,long lHeight)
{
LPSTR lpsrc;
LPSTR lpbuff;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=(lWidth*8+31)/32*4;
lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return NULL;
memcpy(lpbuff,img,lLineBytes*lHeight);
int i,j,m,n;
for(i=1;i<lHeight-1;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=img+i*lLineBytes+j;
for(m=-1;m<=1;m++)
for(n=-1;n<=1;n++)
{
lpDst=lpbuff+(i+m)*lLineBytes+(j+n);
pixel=(BYTE)*lpDst;
if(*lpsrc>pixel)
*lpsrc=*lpDst;
}
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* MiddleImg()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现3*3模板的中值滤波
*
************************************************************************/
BOOL MiddleImg(LPSTR img,long lWidth,long lHeight)
{
LPSTR lpsrc;
LPSTR lpbuff;
long lLineBytes=(lWidth*8+31)/32*4;
lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memcpy(lpbuff,img,lLineBytes*lHeight);
BYTE *temp=new BYTE[9];
BYTE mid;
int i,j,m,n;
for(i=1;i<lHeight-1;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=img+i*lLineBytes+j;
for(m=-1;m<=1;m++)
for(n=-1;n<=1;n++)
{
temp[(m+1)*3+(n+1)]=(BYTE)*(lpbuff+(i+m)*lLineBytes+(j+n));
}
for(m=0;m<5;m++)
{
for(n=0;n<8-m;n++)
{
if(temp[n]>temp[n+1])
{
mid=temp[n];
temp[n]=temp[n+1];
temp[n+1]=mid;
}
}
}
*lpsrc=temp[4];
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* Erosion()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
* int ErosionType - 腐蚀的类型
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现对图象的腐蚀处理
*
************************************************************************/
BOOL Erosion(LPSTR lpDIBBits,long lWidth,long lHeight,int ErosionType)
{
LPSTR lpsrc;
LPSTR lpbuff;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=WIDTHBYTES(lWidth*8);
lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
int i,j,m,n;
if(ErosionType==0)
{
for(i=0;i<lHeight;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*i+j;
pixel=(BYTE)*lpDst;
if(pixel==0)
{
if(*(lpDst-1)!=0 || *(lpDst+1)!=0)
*lpsrc=(BYTE)255;
}
}
}
else if (ErosionType==1)
{
for(i=1;i<lHeight-1;i++)
for(j=0;j<lWidth;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*i+j;
pixel=(BYTE)*lpDst;
if(pixel==0)
{
if(*(lpDst-lLineBytes)!=0 || *(lpDst+lLineBytes)!=0)
*lpsrc=(BYTE)255;
}
}
}
else if (ErosionType==2)
{
for(i=1;i<lHeight-1;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
pixel=(BYTE)*lpsrc;
if(pixel==0)
{
for(m=-1;m<=1;m++)
{
for(n=-1;n<=1;n++)
{
lpDst=lpbuff+lLineBytes*(m+i)+n+j;
if(*lpDst!=0)
{
*lpsrc=(BYTE)255;
break;
}
}
if(*lpsrc==255)
break;
}
}
}
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* Dialation()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
* int DialationType - 膨胀的类型
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现对图象的膨胀处理
*
************************************************************************/
BOOL Dialation(LPSTR lpDIBBits,long lWidth,long lHeight,int DialationType)
{
LPSTR lpsrc;
LPSTR lpbuff;
LPSTR lpDst;
BYTE pixel;
long lLineBytes=WIDTHBYTES(lWidth*8);
lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
int i,j,m,n;
if(DialationType==0)
{
for(i=0;i<lHeight;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*i+j;
pixel=(BYTE)*lpDst;
if(pixel==255)
{
if(*(lpDst-1)==0 || *(lpDst+1)==0)
*lpsrc=(BYTE)0;
}
}
}
else if (DialationType==1)
{
for(i=1;i<lHeight-1;i++)
for(j=0;j<lWidth;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*i+j;
pixel=(BYTE)*lpDst;
if(pixel==255)
{
if(*(lpDst-lLineBytes)==0 || *(lpDst+lLineBytes)==0)
*lpsrc=(BYTE)0;
}
}
}
else if (DialationType==2)
{
for(i=1;i<lHeight-1;i++)
for(j=1;j<lWidth-1;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
pixel=(BYTE)*lpsrc;
if(pixel==255)
{
for(m=-1;m<=1;m++)
{
for(n=-1;n<=1;n++)
{
lpDst=lpbuff+lLineBytes*(m+i)+n+j;
if(*lpDst==0)
{
*lpsrc=(BYTE)0;
break;
}
}
break;
}
}
}
}
delete[] lpbuff;
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* MirrorImg()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* long lWidth - 图象的宽度
* long lHeight - 图象的高度
* int mirrorType - 镜像的类型
* 返回值:
* BOOL - 成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用来实现对图象的水平镜像处理
*
************************************************************************/
BOOL MirrorImg(LPSTR lpDIBBits,long lWidth,long lHeight,int mirrorType)
{
LPSTR lpsrc;
LPSTR lpbuff;
LPSTR lpDst;
long lLineBytes=WIDTHBYTES(lWidth*8);
lpbuff=(LPSTR)new BYTE[lLineBytes*lHeight];
if(lpbuff==NULL)
return FALSE;
memcpy(lpbuff,lpDIBBits,lLineBytes*lHeight);
int i,j;
if(mirrorType==0)
{
for(i=0;i<lHeight;i++)
for(j=0;j<lWidth;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*i+(lWidth-1-j);
*lpsrc=*lpDst;
}
}
else if (mirrorType==1)
{
for(i=0;i<lHeight;i++)
for(j=0;j<lWidth;j++)
{
lpsrc=lpDIBBits+lLineBytes*i+j;
lpDst=lpbuff+lLineBytes*(lHeight-i-1)+j;
*lpsrc=*lpDst;
}
}
return TRUE;
}
/*************************************************************************
*
* 函数名称:
* RotateDIB()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* int iRotateAngle - 旋转的角度(0-360度)
*
* 返回值:
* HGLOBAL - 旋转成功返回新DIB句柄,否则返回NULL。
*
* 说明:
* 该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
* 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插
* 值算法进行插值。
*
************************************************************************/
HGLOBAL WINAPI RotateImg(LPSTR lpDIB, float iRotateAngle)
{
// 源图像的宽度和高度
LONG lWidth;
LONG lHeight;
// 旋转后图像的宽度和高度
LONG lNewWidth;
LONG lNewHeight;
// 图像每行的字节数
LONG lLineBytes;
// 旋转后图像的宽度(lNewWidth',必须是4的倍数)
LONG lNewLineBytes;
// 指向源图像的指针
LPSTR lpDIBBits;
// 指向源象素的指针
LPSTR lpSrc;
// 旋转后新DIB句柄
HDIB hDIB;
// 指向旋转图像对应象素的指针
LPSTR lpDst;
// 指向旋转图像的指针
LPSTR lpNewDIB;
LPSTR lpNewDIBBits;
// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFOHEADER lpbmi;
// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREHEADER lpbmc;
// 循环变量(象素在新DIB中的坐标)
LONG i;
LONG j;
// 象素在源DIB中的坐标
LONG i0;
LONG j0;
// 旋转角度(弧度)
float fRotateAngle;
// 旋转角度的正弦和余弦
float fSina, fCosa;
// 源图四个角的坐标(以图像中心为坐标系原点)
float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
// 旋转后四个角的坐标(以图像中心为坐标系原点)
float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
// 两个中间常量
float f1,f2;
// 找到源DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);
// 获取图像的"宽度"(4的倍数)
lWidth = ::DIBWidth(lpDIB);
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 获取图像的高度
lHeight = ::DIBHeight(lpDIB);
// 将旋转角度从度转换到弧度
fRotateAngle = (float) RADIAN(iRotateAngle);
// 计算旋转角度的正弦
fSina = (float) sin((double)fRotateAngle);
// 计算旋转角度的余弦
fCosa = (float) cos((double)fRotateAngle);
// 计算原图的四个角的坐标(以图像中心为坐标系原点)
fSrcX1 = (float) (- (lWidth - 1) / 2);
fSrcY1 = (float) ( (lHeight - 1) / 2);
fSrcX2 = (float) ( (lWidth - 1) / 2);
fSrcY2 = (float) ( (lHeight - 1) / 2);
fSrcX3 = (float) (- (lWidth - 1) / 2);
fSrcY3 = (float) (- (lHeight - 1) / 2);
fSrcX4 = (float) ( (lWidth - 1) / 2);
fSrcY4 = (float) (- (lHeight - 1) / 2);
// 计算新图四个角的坐标(以图像中心为坐标系原点)
fDstX1 = fCosa * fSrcX1 + fSina * fSrcY1;
fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
fDstX2 = fCosa * fSrcX2 + fSina * fSrcY2;
fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
fDstX3 = fCosa * fSrcX3 + fSina * fSrcY3;
fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
fDstX4 = fCosa * fSrcX4 + fSina * fSrcY4;
fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
// 计算旋转后的图像实际宽度
lNewWidth = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
// 计算新图像每行的字节数
lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
// 计算旋转后的图像高度
lNewHeight = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) ) + 0.5);
// 两个常数,这样不用以后每次都计算了
f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
+ 0.5 * (lWidth - 1));
f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
+ 0.5 * (lHeight - 1));
// 分配内存,以保存新DIB
hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
// 判断是否内存分配失败
if (hDIB == NULL)
{
// 分配内存失败
return NULL;
}
// 锁定内存
lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB);
// 复制DIB信息头和调色板
memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
// 找到新DIB象素起始位置
lpNewDIBBits = ::FindDIBBits(lpNewDIB);
// 获取指针
lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
// 更新DIB中图像的高度和宽度
if (IS_WIN30_DIB(lpNewDIB))
{
// 对于Windows 3.0 DIB
lpbmi->biWidth = lNewWidth;
lpbmi->biHeight = lNewHeight;
}
else
{
// 对于其它格式的DIB
lpbmc->bcWidth = (unsigned short) lNewWidth;
lpbmc->bcHeight = (unsigned short) lNewHeight;
}
// 针对图像每行进行操作
for(i = 0; i < lNewHeight; i++)
{
// 针对图像每列进行操作
for(j = 0; j < lNewWidth; j++)
{
// 指向新DIB第i行,第j个象素的指针
// 注意此处宽度和高度是新DIB的宽度和高度
lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
// 计算该象素在源DIB中的坐标
i0 = (LONG) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5);
j0 = (LONG) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5);
// 判断是否在源图范围内
if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
{
// 指向源DIB第i0行,第j0个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
// 复制象素
*lpDst = *lpSrc;
}
else
{
// 对于源图中没有的象素,直接赋值为255
* ((unsigned char*)lpDst) = 255;
}
}
}
// 返回
return hDIB;
}
/*************************************************************************
*
* 函数名称:
* ThresholdDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
*
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对图像进行阈值分割运算。
*
************************************************************************/
BOOL WINAPI ThresholdDIB(LPSTR lpDIBBits,LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向缓存图像的指针
LPSTR lpDst;
// 指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
//循环变量
long i;
long j;
//像素值
unsigned char pixel;
//直方图数组
long lHistogram[256];
//阈值,最大灰度值与最小灰度值,两个区域的平均灰度值
unsigned char iThreshold,iNewThreshold,iMaxGrayValue,iMinGrayValue,iMean1GrayValue,iMean2GrayValue;
//用于计算区域灰度平均值的中间变量
long lP1,lP2,lS1,lS2;
//迭代次数
int iIterationTimes;
// 图像每行的字节数
LONG lLineBytes;
// 暂时分配内存,以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的内存,设定初始值为255
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
for (i = 0; i < 256;i++)
{
lHistogram[i]=0;
}
//获得直方图
iMaxGrayValue = 0;
iMinGrayValue = 255;
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
lHistogram[pixel]++;
//修改最大,最小灰度值
if(iMinGrayValue > pixel)
{
iMinGrayValue = pixel;
}
if(iMaxGrayValue < pixel)
{
iMaxGrayValue = pixel;
}
}
}
//迭代求最佳阈值
iNewThreshold = (iMinGrayValue + iMaxGrayValue)/2;
iThreshold = 0;
for(iIterationTimes = 0; iThreshold != iNewThreshold && iIterationTimes < 100;iIterationTimes ++)
{
iThreshold = iNewThreshold;
lP1 =0;
lP2 =0;
lS1 = 0;
lS2 = 0;
//求两个区域的灰度平均值
for (i = iMinGrayValue;i < iThreshold;i++)
{
lP1 += lHistogram[i]*i;
lS1 += lHistogram[i];
}
iMean1GrayValue = (unsigned char)(lP1 / lS1);
for (i = iThreshold+1;i < iMaxGrayValue;i++)
{
lP2 += lHistogram[i]*i;
lS2 += lHistogram[i];
}
iMean2GrayValue = (unsigned char)(lP2 / lS2);
iNewThreshold = (iMean1GrayValue + iMean2GrayValue)/2;
}
//根据阈值将图像二值化
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
if(pixel >= iThreshold)
{
*lpDst = (unsigned char)255;
}
else
{
*lpDst = (unsigned char)0;
}
}
}
// 复制图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
/*************************************************************************
直方图均衡子函数
************************************************************************/
BOOL WINAPI InteEqualize(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
unsigned char* lpSrc;
// 临时变量
LONG lTemp;
// 循环变量
LONG i;
LONG j;
// 灰度映射表
BYTE bMap[256];
// 灰度映射表
LONG lCount[256];
// 图像每行的字节数
LONG lLineBytes;
// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);
// 重置计数为0
for (i = 0; i < 256; i ++)
{
// 清零
lCount[i] = 0;
}
// 计算各个灰度值的计数
for (i = 0; i < lHeight; i ++)
{
for (j = 0; j < lWidth; j ++)
{
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * i + j;
// 计数加1
lCount[*(lpSrc)]++;
}
}
// 计算灰度映射表
for (i = 0; i < 256; i++)
{
// 初始为0
lTemp = 0;
for (j = 0; j <= i ; j++)
{
lTemp += lCount[j];
}
// 计算对应的新灰度值
bMap[i] = (BYTE) (lTemp * 255 / lHeight / lWidth);
}
// 每行
for(i = 0; i < lHeight; i++)
{
// 每列
for(j = 0; j < lWidth; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;
// 计算新的灰度值
*lpSrc = bMap[*lpSrc];
}
}
// 返回
return TRUE;
}