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

📄 dibapi.cpp

📁 K均值聚类算法 C++实现的K均值聚类算法。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 *
 * 参数:
 *   HDC hDC            - 输出设备DC
 *   LPRECT lpDCRect    - 绘制矩形区域
 *   HDIB hDIB          - 指向DIB对象的指针
 *   LPRECT lpDIBRect   - 要输出的DIB区域
 *   CPalette* pPal     - 指向DIB对象调色板的指针
 *
 * 返回值:
 *   BOOL               - 绘制成功返回TRUE,否则返回FALSE。
 *
 * 说明:
 *   该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者
 * SetDIBitsToDevice()来绘制DIB对象。输出的设备由由参数hDC指
 * 定;绘制的矩形区域由参数lpDCRect指定;输出DIB的区域由参数
 * lpDIBRect指定。
 *
 ************************************************************************/

BOOL PaintDIB(HDC     hDC,
			  LPRECT  lpDCRect,
			  HDIB    hDIB,
		   	  LPRECT  lpDIBRect,
			  CPalette* pPal)
{
	LPSTR    lpDIBHdr;            // BITMAPINFOHEADER指针
	LPSTR    lpDIBBits;           // DIB象素指针
	BOOL     bSuccess=FALSE;      // 成功标志
	HPALETTE hPal=NULL;           // DIB调色板
	HPALETTE hOldPal=NULL;        // 以前的调色板

	// 判断DIB对象是否为空
	if (hDIB == NULL)
	{
		// 返回
		return FALSE;
	}

	// 锁定DIB
	lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = ::FindDIBBits(lpDIBHdr);

	// 获取DIB调色板,并选中它
	if (pPal != NULL)
	{
		hPal = (HPALETTE) pPal->m_hObject;

		// 选中调色板
		hOldPal = ::SelectPalette(hDC, hPal, TRUE);
	}

	// 设置显示模式
	::SetStretchBltMode(hDC, COLORONCOLOR);

	// 判断是调用StretchDIBits()还是SetDIBitsToDevice()来绘制DIB对象
	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);
	
	// 恢复以前的调色板
	if (hOldPal != NULL)
	{
		::SelectPalette(hDC, hOldPal, TRUE);
	}
	
	// 返回
	return bSuccess;
}
/************************************************************************* 
 * 
 * DitherDisplayDIB() 
 * 
 * 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 
 *
 * HPALETTE hPal    - Palette used to diaplsy DIB, if is NULL, 
 *					  use DIB palette to display
 *
 * DWORD dwRop      - ROP mode to display DIB
 * 
 * Return Value: 
 * 
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise 
 * 
 * Description: 
 *   Painting routine with dithering, can display accuraly a DIB with
 *   more colors than the display device can support.
 * 
 ************************************************************************/ 
BOOL DitherDisplayDIB(HDC hDC, LPRECT lpDCRect, HDIB hDIB, LPRECT lpDIBRect, 
        DWORD dwRop)
{ 
    LPSTR        lpDIBHdr;           // Pointer to BITMAPINFOHEADER 
    LPSTR        lpDIBBits;          // Pointer to DIB bits 
    BOOL          bSuccess=FALSE;     // Success/fail flag 
    HPALETTE      hPal=NULL;		  // used palette 
    HPALETTE      hOldPal=NULL;       // Previous palette 
 
    // Check for valid DIB handle 
 
    if (!hDIB) 
        return FALSE; 

	// create dithered DIB to display
	
	HDIB hDIBDisplay = CreateDither8BppDIB(hDIB);

    // Lock down the DIB, and get a pointer to the beginning of the bit 
    // buffer 
     
    lpDIBHdr  = (LPSTR)GlobalLock(hDIBDisplay); 
    lpDIBBits = FindDIBBits(lpDIBHdr); 
 
	// create palette from DIB

	hPal = CreateDIBPalette(lpDIBHdr);

    // Select and realize our palette as background 

    if (hPal) 
    { 
		hOldPal = SelectPalette(hDC, hPal, TRUE); 
        RealizePalette(hDC); 
    } 

    // Make sure to use the stretching mode best for color pictures 
 
    SetStretchBltMode(hDC, COLORONCOLOR); 
 
    // call StretchDIBits() anyway with dwRop
 
	bSuccess = StretchDIBits(hDC, 
							 lpDCRect->left, 
							 lpDCRect->top, 
							 RECTWIDTH(lpDCRect), 
							 RECTHEIGHT(lpDCRect), 
							 lpDIBRect->left, 
				             (int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect), 
							 RECTWIDTH(lpDIBRect), 
							 RECTHEIGHT(lpDIBRect), 
							 lpDIBBits, 
							 (LPBITMAPINFO)lpDIBHdr, 
							 DIB_RGB_COLORS, 
							 SRCCOPY); 

    // Unlock and free the memory block 
 
    GlobalUnlock(hDIBDisplay); 
	GlobalFree(hDIBDisplay); 

    // Reselect old palette 
 
    if (hOldPal) 
		SelectPalette(hDC, hOldPal, FALSE); 
 
    // Return with success/fail flag 
    return bSuccess; 
} 
///////////////////// local used only !!! /////////////////////////////

// create a dithered 8bpp DIB for 24bpp DIB in not true color device
HDIB CreateDither8BppDIB(HDIB hDIB)
{
	WaitCursorBegin();
	
	


	if (DIBBitCount((LPSTR)hDIB) <= 8)
	{
		WaitCursorEnd();
		return CopyHandle(hDIB);
	}

    // dithering DIB
	LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
	LPSTR lpBits = FindDIBBits(lpDIB);
	WORD wWidth = (WORD)DIBWidth(lpDIB);
	WORD wHeight = (WORD)DIBHeight(lpDIB);
    HGLOBAL hDitheredBits = DitherImage(lpBits, wWidth, wHeight);
	GlobalUnlock(hDIB);
	if (! hDitheredBits)
	{
		WaitCursorEnd();
		return NULL;
	}

	// create a new 8bpp DIB
	HDIB hNewDib = ChangeDIBFormat(hDIB, 8, BI_RGB);;
	LPBITMAPINFO lpBmi = (LPBITMAPINFO)GlobalLock(hNewDib);
	lpBmi->bmiHeader.biClrUsed = 256;
    
	// set the entries of dither palette to DIB color table
    for (int Index=0; Index < 256; Index++)  
	{
		lpBmi->bmiColors[Index].rgbRed   = DitherPalette[Index].Red;
		lpBmi->bmiColors[Index].rgbGreen = DitherPalette[Index].Green;
		lpBmi->bmiColors[Index].rgbBlue  = DitherPalette[Index].Blue;
		lpBmi->bmiColors[Index].rgbReserved = 0;
    }

	// copy dithered image bits to hNewDib
	DWORD dwSize = GlobalSize(hDitheredBits);
	LPSTR lpDitheredBits = (LPSTR)GlobalLock(hDitheredBits);
	LPSTR lpNewBits = FindDIBBits((LPSTR)lpBmi);
	memcpy(lpNewBits, lpDitheredBits, dwSize);

	// cleanup
	GlobalUnlock(hDitheredBits);
	GlobalFree(hDitheredBits);
	GlobalUnlock(hNewDib);

	// map dithered DIB to dither palette
	HPALETTE hPal = CreateDitherPalette();
	MapDIBColorsToPalette(hNewDib, hPal);
	DeleteObject(hPal);

	WaitCursorEnd();
	return hNewDib;
}

// This function dithers the image contained in this object. It returns
// a handle to a global memory block containing the dithered data.
HGLOBAL DitherImage(LPSTR lpImageData, WORD Width, WORD Height) 
{
	// Calculate width in bytes of a row of RGB data
	WORD BytesPerLine = ALIGN_DWORD(Width * 3);   // Source 24 BPP image
	// Calculate width in bytes of a row of palettized data
	WORD BytesPerLineDest = ALIGN_DWORD(Width);   // Dest 8 BPP image

	// Allocate two lines of RGB buffer for dithering
	HLOCAL hLine1Buffer = LocalAlloc(LMEM_MOVEABLE, BytesPerLine);
	if (!hLine1Buffer) 
		return NULL;

	HLOCAL hLine2Buffer = LocalAlloc(LMEM_MOVEABLE, BytesPerLine);
	if (!hLine2Buffer) 
	{
		LocalFree(hLine1Buffer);
		return NULL;
	}

	// Allocate the destination dither buffer
	HGLOBAL hMem = GlobalAlloc(GHND, (DWORD) BytesPerLineDest * Height);
	if (!hMem) 
	{
		LocalFree(hLine1Buffer);
		LocalFree(hLine2Buffer);
		return NULL;
	}

	// Now lock the pointers for access
	LPSTR Line1Buffer = (LPSTR) LocalLock(hLine1Buffer);
	LPSTR Line2Buffer = (LPSTR) LocalLock(hLine2Buffer);
	LPSTR lpDitheredRasterData = (LPSTR) GlobalLock(hMem);

	// Move the first two lines of the source image to dither buffers
	memcpy(Line1Buffer, lpImageData, BytesPerLine);
	memcpy(Line2Buffer, lpImageData + BytesPerLine, BytesPerLine);

	for (register WORD Row = 2; Row < Height; Row++) 
	{
		DitherLine(Width, Line1Buffer, Line2Buffer);
		// Copy the dithered data in Line1Buffer to destination
		memcpy(lpDitheredRasterData  + ((Row-2) * (DWORD) BytesPerLineDest),
		Line1Buffer, BytesPerLineDest);
		// Copy Line2Buffer to Line1Buffer so it can be dithered
		memcpy(Line1Buffer, Line2Buffer, BytesPerLine);

		// Move new data to Line2Buffer
		memcpy(Line2Buffer, lpImageData  + (Row * (DWORD) BytesPerLine),
		BytesPerLine);
	}
	// Must complete the two rows in the line buffers
	DitherLine(Width, Line1Buffer, Line2Buffer);
	// Copy the dithered data in Line1Buffer to destination
	memcpy(lpDitheredRasterData  + ((Height-2) * (DWORD) BytesPerLineDest),
	Line1Buffer, BytesPerLineDest);
	memcpy(Line1Buffer, Line2Buffer, BytesPerLine);

	DitherLine(Width, Line1Buffer, Line2Buffer);
	// Copy the dithered data in Line1Buffer to destination
	memcpy(lpDitheredRasterData  + ((Height-1) * (DWORD) BytesPerLineDest),
	Line1Buffer, BytesPerLineDest);

	// Free the local line buffers
	LocalUnlock(hLine1Buffer);
	LocalFree(hLine1Buffer);
	LocalUnlock(hLine2Buffer);
	LocalFree(hLine2Buffer);

	// Signal all is well
	GlobalUnlock(hMem);             // Unlock the dithered raster data
	return hMem;                    // Return the handle of the data
}
// Define temporary vars as global, try to speedup...
int  TRed, TGreen, TBlue;
int  RedError, GreenError, BlueError;
BYTE PaletteIndex;
int  BlueOffset;
LPSTR PixelAddr;
LPSTR RPixelAddr;
LPSTR DPixelAddr;

// Dither a single row of image data
void DitherLine(WORD Width, LPSTR pLine1, LPSTR pLine2) 
{
	for (register WORD Pixel=0; Pixel < Width; Pixel++) 
	{
		// Get the pixel of interest for the dither
		PixelAddr = pLine1 + (Pixel * 3);
		GetRGBPixel(PixelAddr, TRed, TGreen, TBlue);
		// Determine which blue entry from palette to use
		BlueOffset = (TBlue/85);
		if ((TBlue - (BlueOffset * 85)) > 43)
		BlueOffset += 1;
		// Calculate palette entry address from color
		// PaletteIndex = ((TRed/32)*32) + ((TGreen/32)*4) + BlueOffset;
		// For speed we will calculate the color index as follows
		PaletteIndex = (TRed & 0xE0) + ((TGreen >> 5) << 2) + BlueOffset;
		// Store the palette back into the same buffer
		*(pLine1 + Pixel) = PaletteIndex;
		/*
		Pixel is set, now distribute the error to adjacent pixels
		using a modified version of the Floyd-Steinberg algorithm.
		In this implementation the error is distributed as follows
						   Pixel
									  o 1/2->o
								 1/4 |
							 o   
		The algorithm is modified to increase performance.
		*/
		// Calculate errors between the desired color and color used
		// for this pixel. Actual error / 4. Use  pointers for speed.

		BYTE  *pColor = (BYTE  *) &DitherPalette[PaletteIndex];  // Ptr to color
		RedError   = (TRed   - *(pColor))   >> 2;
		GreenError = (TGreen - *(pColor+1)) >> 2;
		BlueError  = (TBlue  - *(pColor+2)) >> 2;

		// Do the pixel directly below target pixel
		DPixelAddr  = pLine2 + (Pixel * 3);
		GetRGBPixel(DPixelAddr, TRed, TGreen, TBlue);
		TRed   += RedError;                // 1/4 error
		TGreen += GreenError;
		TBlue  += BlueError;
		PutRGBPixel(DPixelAddr, TRed, TGreen, TBlue);
		// Do the pixel directly to the right
		if (Pixel != Width - 1)  
		{
			RPixelAddr  = PixelAddr + 3;
			GetRGBPixel(RPixelAddr, TRed, TGreen, TBlue);
			TRed   += RedError   + RedError;   // 1/2 error
			TGreen += GreenError + GreenError;
			TBlue  += BlueError  + BlueError;
			PutRGBPixel(RPixelAddr, TRed, TGreen, TBlue);
		}
	}
}

///////////////////////////////////////////////////////////////////////////////////////////////
                               //DIB operations//
///////////////////////////////////////////////////////////////////////////////////////////////
/**************************************************************************** 
* 
*     FUNCTION: DIBToDIBSection 
* 
*     PURPOSE:  Create DIBSECTION from DIB
* 
*     PARAMS:   LPSTR lpDIB - pointer to DIB data buffer
* 
*     RETURNS:  HBITMAP - handle of DIBSECTION, or NULL for failure 

⌨️ 快捷键说明

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