把hbitmap 保存至stack中

本文介绍了一个用于向HBITMAP数组(称为Stack)添加元素的方法voidAdd。此方法实现了将一个HBITMAP类型的element添加到数组中,并在数组已满的情况下进行元素的更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

void Add(HBITMAP element)
{
	m_iCurLen = m_iCurPos;
	if( m_iCurPos < m_iTotalLen )
	{
		Stock[m_iCurLen] = element;
		m_iCurLen++;
		m_iCurPos++;
	}
	else
	{
		for( int i = 0; i < m_iTotalLen - 1; i++ )
			Stock[i] = Stock[i+1];
		Stock[m_iTotalLen - 1] = element;
	}
}

把hbitmap 保存至stack中


stack为HBITMAP数组

#ifndef _WND_H_ #define _WND_H_ #define _CRT_SECURE_NO_WARNINGS #define NO_WARN_MBCS_MFC_DEPRECATION #include <SDKDDKVer.h> #include <afxwin.h> //默认情况下所有继承Wnd的控件都是透明状态,需要自己绘画, alpha通道被置0了 #define RGBA(r,g,b,a) (COLORREF)(((BYTE)(b) |((WORD)((BYTE)(g)) << 8)) |(((DWORD)((BYTE)(r)) << 16)) |(((DWORD)((BYTE)(a)) << 24))) namespace MPlus { #pragma pack(push,1) typedef struct tagWndProcThunk { DWORD mov; // 修改堆栈中的参数 mov [esp+4], 0xC7 0x44 0x24 0x04 = 0x042444C7 DWORD thiz; // 存储 this 指针 ?? ?? ?? ?? (DWORD)this BYTE jmp; // 跳转指令 jmp 0xE9 DWORD relproc; // 相对跳转地址 ?? ?? ?? ?? staic_WndProc-(thunk + sizeof WndProcThunk) }WndProcThunk; typedef WndProcThunk* LPWNDPROCTHUNK; #pragma pack(pop) template<class T> T* AllocVirtualMemory() { void* mem = VirtualAlloc(NULL, sizeof(T), MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!mem) return nullptr; memset(mem, 0, sizeof(T)); return (T*)mem; } template<class T> void Free(T* _pMemory) { if (_pMemory) { VirtualFree(_pMemory, sizeof T, MEM_RELEASE); } } class Wnd : public CWnd { DECLARE_DYNAMIC(Wnd) protected: CDC m_MemDC; //绘图二级缓存DC BITMAPINFO m_BMI; //绘图位图的基本信息 HBITMAP m_hBitmap; //位图的句柄 BYTE* m_pvBits; //位图的裸内存首地址 CRect m_rcWnd; //控件的画布范围 CFont m_Font; //二级DC所使用的字体 CPoint m_ptOrigin; //窗口当前的坐标 int* m_vecRows; //位图的行列表 public: LPCTSTR m_szClassName; //默认提供的类名,创建窗口时要使用 protected: void fast_stack_blur(unsigned char* pix, unsigned int w, unsigned int h, unsigned int comp, int radius);//快速栈模糊算法 virtual bool OnValidBlur(const CPoint& _ptPix); void SetAlphaRect(const CRect _rect, BYTE _alpha); public: Wnd(); ~Wnd(); void Clear(); DECLARE_MESSAGE_MAP() afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); }; } void _output_debug(const char* _format, ...); #ifdef _DEBUG #define outputdebug_default(_format, ...)_output_debug("[Default] "##_format, ##__VA_ARGS__) #define outputdebug_warning(_format, ...)_output_debug("[Warning] "##_format, ##__VA_ARGS__) #define outputdebug_error(_format, ...)_output_debug("[Error] "##_format, ##__VA_ARGS__) #else #define outputdebug_default(format, ...) #define outputdebug_warning(_format, ...) #define outputdebug_error(_format, ...) #endif #endif #include "Wnd.h" void _output_debug(const char* _format, ...) { #define __DstSize__ 1024 char strMsgBuffer[__DstSize__]; va_list list; va_start(list, _format); vsnprintf(strMsgBuffer, __DstSize__, _format, list); va_end(list); //强行加换行符 int last = strlen(strMsgBuffer); if (strMsgBuffer[last - 1] != '\n') { strMsgBuffer[last] = '\n'; strMsgBuffer[last + 1] = 0; } OutputDebugStringA(strMsgBuffer);//win api } namespace MPlus { IMPLEMENT_DYNAMIC(Wnd, CWnd) } MPlus::Wnd::Wnd(): m_hBitmap(NULL), m_pvBits(NULL), m_rcWnd(0, 0, 0, 0), m_ptOrigin(0, 0), m_vecRows(NULL) { m_szClassName = AfxRegisterWndClass(0); //注册默认类名 } MPlus::Wnd::~Wnd() { Wnd::Clear(); } void MPlus::Wnd::Clear() { m_Font.DeleteObject();//释放字体内存 DeleteObject(m_hBitmap);//释放位图内存 m_MemDC.DeleteDC();//二级缓存释放 m_pvBits = NULL; ZeroMemory(&m_BMI, sizeof(BITMAPINFO));//重置位图信息 if (m_vecRows) { delete[] m_vecRows; m_vecRows = NULL; } } // Stack Blur v1.1 // // Author: Mario Klingemann <mario@quasimondo.com> // http://incubator.quasimondo.com // created Feburary 29, 2004 // C version updated and performance optimization by tntmonks(http://tntmonks.cnblogs.com) // This is a compromise between Gaussian Blur and Box blur // It creates much better looking blurs than Box Blur, but is // 7x faster than my Gaussian Blur implementation. // // I called it Stack Blur because this describes best how this // filter works internally: it creates a kind of moving stack // of colors whilst scanning through the image. Thereby it // just has to add one new block of color to the right side // of the stack and remove the leftmost color. The remaining // colors on the topmost layer of the stack are either added on // or reduced by one, depending on if they are on the right or // on the left side of the stack. // // If you are using this algorithm in your code please add // the following line: // // Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com> //#define MAX(x,y) (x>y?x:y) //#define MIN(x,y) (x>y?y:x) #include <math.h> void MPlus::Wnd::fast_stack_blur(unsigned char* pix, unsigned int w, unsigned int h, unsigned int comp, int radius) { #pragma warning(disable:4018) unsigned int wm = w - 1; unsigned int hm = h - 1; unsigned int imageSize = w * h; unsigned int div = radius * 2 + 1; unsigned char* rgb = (unsigned char*)malloc(sizeof(unsigned char) * imageSize * 4); unsigned char* r = rgb; unsigned char* g = rgb + imageSize; unsigned char* b = rgb + imageSize * 2; unsigned char* a = rgb + imageSize * 3; int rsum, gsum, bsum, asum, x, y, i, p, yp, yi, yw; unsigned int* vmin = (unsigned int*)malloc(max(w, h) * sizeof(unsigned int)); int divsum = (div + 1) >> 1; divsum *= divsum; int* dv = (int*)malloc(256 * divsum * sizeof(int)); for (i = 0; i < 256 * divsum; i++) { dv[i] = (i / divsum); } yw = yi = 0; int(*stack)[4] = (int(*)[4])malloc(div * 4 * sizeof(int)); unsigned int stackpointer; unsigned int stackstart; int* sir; int rbs; int r1 = radius + 1; int routsum, goutsum, boutsum, aoutsum; int rinsum, ginsum, binsum, ainsum; for (y = 0; y < h; y++) { rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0; for (i = -radius; i <= radius; i++) { p = yi + (min(wm, max(i, 0))); sir = stack[i + radius]; sir[0] = pix[(p * comp)]; sir[1] = pix[(p * comp) + 1]; sir[2] = pix[(p * comp) + 2]; sir[3] = pix[(p * comp) + 3]; rbs = r1 - abs(i); rsum += sir[0] * rbs; gsum += sir[1] * rbs; bsum += sir[2] * rbs; asum += sir[3] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; } } stackpointer = radius; for (x = 0; x < w; x++) { r[yi] = dv[rsum]; g[yi] = dv[gsum]; b[yi] = dv[bsum]; a[yi] = dv[asum]; rsum -= routsum; gsum -= goutsum; bsum -= boutsum; asum -= aoutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; aoutsum -= sir[3]; if (y == 0) { vmin[x] = min(x + radius + 1, wm); } p = yw + vmin[x]; sir[0] = pix[(p * comp)]; sir[1] = pix[(p * comp) + 1]; sir[2] = pix[(p * comp) + 2]; sir[3] = pix[(p * comp) + 3]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; rsum += rinsum; gsum += ginsum; bsum += binsum; asum += ainsum; stackpointer = (stackpointer + 1) % div; sir = stack[(stackpointer) % div]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; ainsum -= sir[3]; yi++; } yw += w; } for (int x = 0; x < w; x++) { rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0; yp = -radius * w; for (i = -radius; i <= radius; i++) { yi = max(0, yp) + x; sir = stack[i + radius]; sir[0] = r[yi]; sir[1] = g[yi]; sir[2] = b[yi]; sir[3] = a[yi]; rbs = r1 - abs(i); rsum += r[yi] * rbs; gsum += g[yi] * rbs; bsum += b[yi] * rbs; asum += a[yi] * rbs; if (i > 0) { rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; } else { routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; } if (i < hm) { yp += w; } } yi = x; stackpointer = radius; for (y = 0; y < h; y++) { if (OnValidBlur({ x,y })) { pix[(yi * comp) + 0] = dv[rsum]; pix[(yi * comp) + 1] = dv[gsum]; pix[(yi * comp) + 2] = dv[bsum]; pix[(yi * comp) + 3] = dv[asum]; } rsum -= routsum; gsum -= goutsum; bsum -= boutsum; asum -= aoutsum; stackstart = stackpointer - radius + div; sir = stack[stackstart % div]; routsum -= sir[0]; goutsum -= sir[1]; boutsum -= sir[2]; aoutsum -= sir[3]; if (x == 0) { vmin[y] = min(y + r1, hm) * w; } p = x + vmin[y]; sir[0] = r[p]; sir[1] = g[p]; sir[2] = b[p]; sir[3] = a[p]; rinsum += sir[0]; ginsum += sir[1]; binsum += sir[2]; ainsum += sir[3]; rsum += rinsum; gsum += ginsum; bsum += binsum; asum += ainsum; stackpointer = (stackpointer + 1) % div; sir = stack[stackpointer]; routsum += sir[0]; goutsum += sir[1]; boutsum += sir[2]; aoutsum += sir[3]; rinsum -= sir[0]; ginsum -= sir[1]; binsum -= sir[2]; ainsum -= sir[3]; yi += w; } } free(rgb); free(vmin); free(dv); free(stack); #pragma warning(default:4018) } void MPlus::Wnd::SetAlphaRect(const CRect _rect, BYTE _alpha) { int iAlpha = _alpha; iAlpha <<= 24; int* pRow = NULL; for (int i = _rect.top; i < _rect.bottom; ++i) { pRow = (int*)m_vecRows[i];//取出一行数据 for (int j = _rect.left; j < _rect.right; ++j) { *(pRow + j) |= iAlpha;//设置每个ARGB颜色的alpha通道 } } } bool MPlus::Wnd::OnValidBlur(const CPoint& _ptPix) { return true; } BEGIN_MESSAGE_MAP(MPlus::Wnd, CWnd) ON_WM_CREATE() ON_WM_ERASEBKGND() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() END_MESSAGE_MAP() int MPlus::Wnd::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您专用的创建代码 m_rcWnd = { 0, 0, lpCreateStruct->cx, lpCreateStruct->cy };//保存控件画布范围 m_ptOrigin.x = lpCreateStruct->x; m_ptOrigin.y = lpCreateStruct->y; ZeroMemory(&m_BMI, sizeof(BITMAPINFO)); //初始化位置信息 m_BMI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); //给定位图信息类的大小 m_BMI.bmiHeader.biWidth = m_rcWnd.Width(); //位图的长度 m_BMI.bmiHeader.biHeight = m_rcWnd.Height(); //位图的宽度 m_BMI.bmiHeader.biPlanes = 1; m_BMI.bmiHeader.biBitCount = 32; // four 8-bit components m_BMI.bmiHeader.biCompression = BI_RGB; m_BMI.bmiHeader.biSizeImage = m_BMI.bmiHeader.biWidth * m_BMI.bmiHeader.biHeight * 4; //位图内存的大小 m_hBitmap = CreateDIBSection(NULL, &m_BMI, DIB_RGB_COLORS, (void**)&m_pvBits, NULL, 0); //创建DIB无关联位图 //二级缓存DC初始化 m_MemDC.CreateCompatibleDC(NULL); //创建二级缓存DC HGDIOBJ hdc = m_MemDC.SelectObject(m_hBitmap); //DC选择指定位图 m_Font.CreatePointFont( (m_rcWnd.Height()-2) * 5, "微软雅黑", NULL); //默认字体 m_MemDC.SelectObject(&m_Font); m_MemDC.FillSolidRect(m_rcWnd, RGBA(0,0,0,0)); ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));//修复鼠标 //开始把位图每行标记储存起来 int iRows = m_BMI.bmiHeader.biWidth; int iCols = m_BMI.bmiHeader.biHeight; m_vecRows = new int[iCols]; //m_pvBits的位图内存分布是倒序的,所以最后一行数据就是位图的第一行数据,进行倒序储存 for (int i = (iCols - 1), j=0; i >= 0; --i, ++j) { m_vecRows[i] = int(m_pvBits + (iRows * 4 * j) ); } return 0; } void MPlus::Wnd::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CWnd* pWnd = SetFocus(); CWnd::OnLButtonDown(nFlags, point); } void MPlus::Wnd::OnLButtonUp(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 CWnd::OnLButtonUp(nFlags, point); } BOOL MPlus::Wnd::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 return CWnd::OnEraseBkgnd(pDC); } 我要扩展LineTo支持alpha通道
最新发布
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值