cocos2dx 高性能高斯模糊(包含lua接口)

cocos2dx 高性能高斯模糊(包含lua接口),第1张

概述根据官方的帖子实现的高斯模糊当前屏幕内容  点击打开链接 1.截屏缩小压缩,减小像素采样的优化算法。默认截屏后缩小到原来的1/4。 2.C++代码进行一次性高斯模糊。避免使用shader造成的渲染掉帧 以下是C++部分代码: /* * 高斯模糊接口 缩放因子:iScale,截图会把全屏压缩为1/iScale大 */ static void gaussianBlur(const std::

根据官方的帖子实现的高斯模糊当前屏幕内容 点击打开链接


1.截屏缩小压缩,减小像素采样的优化算法。默认截屏后缩小到原来的1/4。

2.C++代码进行一次性高斯模糊。避免使用shader造成的渲染掉帧


以下是C++部分代码:

	/*	* 高斯模糊接口  缩放因子:iScale,截图会把全屏压缩为1/iScale大	*/	static voID gaussianBlur(const std::function<voID(bool,cocos2d::Image*)>& afterCaptured,int iScale = 4);

// The Stack Blur Algorithm was invented by Mario Klingemann,// mario@quasimondo.com and described here:// http://incubator.quasimondo.com/processing/fast_blur_deluxe.PHP// This is C++ RGBA (32 bit color) multi-threaded version // by Victor Laskin (victor.laskin@gmail.com)// More details: http://vitiy.info/stackblur-algorithm-multi-threaded-blur-for-cpp// This code is using MVThread class from my cross-platform framework // You can exchange it with any thread implementation you like// -------------------------------------- stackblur ----------------------------------------->static unsigned short const stackblur_mul[255] ={	512,512,456,328,335,405,271,388,292,454,364,298,496,420,360,312,273,482,428,383,345,284,259,475,437,404,374,347,323,302,282,265,497,468,441,417,394,373,354,337,320,305,291,278,507,485,465,446,412,396,381,367,341,329,318,307,297,287,269,261,505,489,461,447,435,422,411,399,389,378,368,359,350,332,324,316,309,301,294,281,274,268,262,257,501,491,480,470,460,451,442,433,424,416,408,400,392,385,377,370,363,357,344,338,326,315,310,304,299,289,285,280,275,267,263,259};static unsigned char const stackblur_shr[255] ={	9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,24};/// Stackblur algorithm bodyvoID stackblurJob(unsigned char* src,///< input image data	unsigned int w,///< image wIDth	unsigned int h,///< image height	unsigned int radius,///< blur intensity (should be in 2..254 range)	int cores,///< total number of working threads	int core,///< current thread number	int step,///< step of processing (1,2)	unsigned char* stack				///< stack buffer	){	unsigned int x,y,xp,yp,i;	unsigned int sp;	unsigned int stack_start;	unsigned char* stack_ptr;	unsigned char* src_ptr;	unsigned char* dst_ptr;	unsigned long sum_r;	unsigned long sum_g;	unsigned long sum_b;	unsigned long sum_a;	unsigned long sum_in_r;	unsigned long sum_in_g;	unsigned long sum_in_b;	unsigned long sum_in_a;	unsigned long sum_out_r;	unsigned long sum_out_g;	unsigned long sum_out_b;	unsigned long sum_out_a;	unsigned int wm = w - 1;	unsigned int hm = h - 1;	unsigned int w4 = w * 4;	unsigned int div = (radius * 2) + 1;	unsigned int mul_sum = stackblur_mul[radius];	unsigned char shr_sum = stackblur_shr[radius];	if (step == 1)	{		int minY = core * h / cores;		int maxY = (core + 1) * h / cores;		for (y = minY; y < maxY; y++)		{			sum_r = sum_g = sum_b = sum_a =				sum_in_r = sum_in_g = sum_in_b = sum_in_a =				sum_out_r = sum_out_g = sum_out_b = sum_out_a = 0;			src_ptr = src + w4 * y; // start of line (0,y)			for (i = 0; i <= radius; i++)			{				stack_ptr = &stack[4 * i];				stack_ptr[0] = src_ptr[0];				stack_ptr[1] = src_ptr[1];				stack_ptr[2] = src_ptr[2];				stack_ptr[3] = src_ptr[3];				sum_r += src_ptr[0] * (i + 1);				sum_g += src_ptr[1] * (i + 1);				sum_b += src_ptr[2] * (i + 1);				sum_a += src_ptr[3] * (i + 1);				sum_out_r += src_ptr[0];				sum_out_g += src_ptr[1];				sum_out_b += src_ptr[2];				sum_out_a += src_ptr[3];			}			for (i = 1; i <= radius; i++)			{				if (i <= wm) src_ptr += 4;				stack_ptr = &stack[4 * (i + radius)];				stack_ptr[0] = src_ptr[0];				stack_ptr[1] = src_ptr[1];				stack_ptr[2] = src_ptr[2];				stack_ptr[3] = src_ptr[3];				sum_r += src_ptr[0] * (radius + 1 - i);				sum_g += src_ptr[1] * (radius + 1 - i);				sum_b += src_ptr[2] * (radius + 1 - i);				sum_a += src_ptr[3] * (radius + 1 - i);				sum_in_r += src_ptr[0];				sum_in_g += src_ptr[1];				sum_in_b += src_ptr[2];				sum_in_a += src_ptr[3];			}			sp = radius;			xp = radius;			if (xp > wm) xp = wm;			src_ptr = src + 4 * (xp + y * w); //   img.pix_ptr(xp,y);			dst_ptr = src + y * w4; // img.pix_ptr(0,y);			for (x = 0; x < w; x++)			{				dst_ptr[0] = (sum_r * mul_sum) >> shr_sum;				dst_ptr[1] = (sum_g * mul_sum) >> shr_sum;				dst_ptr[2] = (sum_b * mul_sum) >> shr_sum;				dst_ptr[3] = (sum_a * mul_sum) >> shr_sum;				dst_ptr += 4;				sum_r -= sum_out_r;				sum_g -= sum_out_g;				sum_b -= sum_out_b;				sum_a -= sum_out_a;				stack_start = sp + div - radius;				if (stack_start >= div) stack_start -= div;				stack_ptr = &stack[4 * stack_start];				sum_out_r -= stack_ptr[0];				sum_out_g -= stack_ptr[1];				sum_out_b -= stack_ptr[2];				sum_out_a -= stack_ptr[3];				if (xp < wm)				{					src_ptr += 4;					++xp;				}				stack_ptr[0] = src_ptr[0];				stack_ptr[1] = src_ptr[1];				stack_ptr[2] = src_ptr[2];				stack_ptr[3] = src_ptr[3];				sum_in_r += src_ptr[0];				sum_in_g += src_ptr[1];				sum_in_b += src_ptr[2];				sum_in_a += src_ptr[3];				sum_r += sum_in_r;				sum_g += sum_in_g;				sum_b += sum_in_b;				sum_a += sum_in_a;				++sp;				if (sp >= div) sp = 0;				stack_ptr = &stack[sp * 4];				sum_out_r += stack_ptr[0];				sum_out_g += stack_ptr[1];				sum_out_b += stack_ptr[2];				sum_out_a += stack_ptr[3];				sum_in_r -= stack_ptr[0];				sum_in_g -= stack_ptr[1];				sum_in_b -= stack_ptr[2];				sum_in_a -= stack_ptr[3];			}		}	}	// step 2	if (step == 2)	{		int minX = core * w / cores;		int maxX = (core + 1) * w / cores;		for (x = minX; x < maxX; x++)		{			sum_r = sum_g = sum_b = sum_a =				sum_in_r = sum_in_g = sum_in_b = sum_in_a =				sum_out_r = sum_out_g = sum_out_b = sum_out_a = 0;			src_ptr = src + 4 * x; // x,0			for (i = 0; i <= radius; i++)			{				stack_ptr = &stack[i * 4];				stack_ptr[0] = src_ptr[0];				stack_ptr[1] = src_ptr[1];				stack_ptr[2] = src_ptr[2];				stack_ptr[3] = src_ptr[3];				sum_r += src_ptr[0] * (i + 1);				sum_g += src_ptr[1] * (i + 1);				sum_b += src_ptr[2] * (i + 1);				sum_a += src_ptr[3] * (i + 1);				sum_out_r += src_ptr[0];				sum_out_g += src_ptr[1];				sum_out_b += src_ptr[2];				sum_out_a += src_ptr[3];			}			for (i = 1; i <= radius; i++)			{				if (i <= hm) src_ptr += w4; // +strIDe				stack_ptr = &stack[4 * (i + radius)];				stack_ptr[0] = src_ptr[0];				stack_ptr[1] = src_ptr[1];				stack_ptr[2] = src_ptr[2];				stack_ptr[3] = src_ptr[3];				sum_r += src_ptr[0] * (radius + 1 - i);				sum_g += src_ptr[1] * (radius + 1 - i);				sum_b += src_ptr[2] * (radius + 1 - i);				sum_a += src_ptr[3] * (radius + 1 - i);				sum_in_r += src_ptr[0];				sum_in_g += src_ptr[1];				sum_in_b += src_ptr[2];				sum_in_a += src_ptr[3];			}			sp = radius;			yp = radius;			if (yp > hm) yp = hm;			src_ptr = src + 4 * (x + yp * w); // img.pix_ptr(x,yp);			dst_ptr = src + 4 * x; 			  // img.pix_ptr(x,0);			for (y = 0; y < h; y++)			{				dst_ptr[0] = (sum_r * mul_sum) >> shr_sum;				dst_ptr[1] = (sum_g * mul_sum) >> shr_sum;				dst_ptr[2] = (sum_b * mul_sum) >> shr_sum;				dst_ptr[3] = (sum_a * mul_sum) >> shr_sum;				dst_ptr += w4;				sum_r -= sum_out_r;				sum_g -= sum_out_g;				sum_b -= sum_out_b;				sum_a -= sum_out_a;				stack_start = sp + div - radius;				if (stack_start >= div) stack_start -= div;				stack_ptr = &stack[4 * stack_start];				sum_out_r -= stack_ptr[0];				sum_out_g -= stack_ptr[1];				sum_out_b -= stack_ptr[2];				sum_out_a -= stack_ptr[3];				if (yp < hm)				{					src_ptr += w4; // strIDe					++yp;				}				stack_ptr[0] = src_ptr[0];				stack_ptr[1] = src_ptr[1];				stack_ptr[2] = src_ptr[2];				stack_ptr[3] = src_ptr[3];				sum_in_r += src_ptr[0];				sum_in_g += src_ptr[1];				sum_in_b += src_ptr[2];				sum_in_a += src_ptr[3];				sum_r += sum_in_r;				sum_g += sum_in_g;				sum_b += sum_in_b;				sum_a += sum_in_a;				++sp;				if (sp >= div) sp = 0;				stack_ptr = &stack[sp * 4];				sum_out_r += stack_ptr[0];				sum_out_g += stack_ptr[1];				sum_out_b += stack_ptr[2];				sum_out_a += stack_ptr[3];				sum_in_r -= stack_ptr[0];				sum_in_g -= stack_ptr[1];				sum_in_b -= stack_ptr[2];				sum_in_a -= stack_ptr[3];			}		}	}}class MVImageUtilsstackBlurTask{public:	unsigned char* src;	unsigned int w;	unsigned int h;	unsigned int radius;	int cores;	int core;	int step;	unsigned char* stack;	inline MVImageUtilsstackBlurTask(unsigned char* src,unsigned int w,unsigned int h,unsigned int radius,int cores,int core,int step,unsigned char* stack)	{		this->src = src;		this->w = w;		this->h = h;		this->radius = radius;		this->cores = cores;		this->core = core;		this->step = step;		this->stack = stack;	}	inline voID run()	{		stackblurJob(src,w,h,radius,cores,core,step,stack);	}};/// Stackblur algorithm by Mario Klingemann/// Details here:/// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.HTML/// C++ implemenation base from:/// https://gist.github.com/benjamin9999/3809142/// http://www.antigrain.com/__code/include/agg_blur.h.HTML/// This version works only with RGBA colorvoID 			   stackblur(unsigned char* src,///< blur intensity (should be in 2..254 range)	int cores = 1						///< number of threads (1 - normal single thread)	){	if (radius > 254) return;	if (radius < 2) return;	unsigned int div = (radius * 2) + 1;	unsigned char* stack = new unsigned char[div * 4 * cores];	if (cores == 1)	{		// no multithreading		stackblurJob(src,1,stack);		stackblurJob(src,2,stack);	}	delete[] stack;}/*** Capture screen implementation,don't use it directly.*/voID onCaptureScreen(const std::function<voID(bool,Image*)>& afterCaptured,int iScale){	static bool startedCapture = false;	if (startedCapture)	{		cclOG("Screen capture is already working");		if (afterCaptured)		{			afterCaptured(false,nullptr);		}		return;	}	else	{		startedCapture = true;	}	auto glVIEw = Director::getInstance()->getopenGLVIEw();	auto frameSize = glVIEw->getFrameSize();#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) || (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_liNUX)	frameSize = frameSize * glVIEw->getFrameZoomFactor() * glVIEw->getRetinaFactor();#endif	int wIDth = static_cast<int>(frameSize.wIDth);	int height = static_cast<int>(frameSize.height);	do	{		std::shared_ptr<glubyte> buffer(new glubyte[wIDth * height * 4],[](glubyte* p){ CC_SAFE_DELETE_ARRAY(p); });		if (!buffer)		{			break;		}		glPixelStorei(GL_PACK_AlignmENT,1);		glreadPixels(0,wIDth,height,GL_RGBA,GL_UNSIGNED_BYTE,buffer.get());		std::shared_ptr<glubyte> flippedBuffer(new glubyte[wIDth * height * 4],[](glubyte* p) { CC_SAFE_DELETE_ARRAY(p); });		if (!flippedBuffer)		{			break;		}		for (int row = 0; row < height; ++row)		{			memcpy(flippedBuffer.get() + (height - row - 1) * wIDth * 4,buffer.get() + row * wIDth * 4,wIDth * 4);		}		/*-------------压缩start------------*/		unsigned long dst_wIDth = wIDth / iScale;		unsigned long dst_height = height / iScale;		std::shared_ptr<glubyte> zipFlippedBuffer(new glubyte[dst_wIDth * dst_height * 4],[](glubyte* p) { CC_SAFE_DELETE_ARRAY(p); });		if (!zipFlippedBuffer)		{			break;		}		unsigned long xrIntfloat_16 = (wIDth << 16) / dst_wIDth + 1;		unsigned long yrIntfloat_16 = (height << 16) / dst_height + 1;		unsigned long srcy_16 = 0;		unsigned long byte_wIDth = 4;//单个数据的物理宽度 4字节		unsigned long byte_shift = 2;//单个数据的物理移位		auto beginPos = zipFlippedBuffer.get();		for (unsigned long y = 0; y < dst_height; ++y)		{			//auto pSrcline = flippedBuffer.get() + wIDth * byte_wIDth * (srcy_16 >> 16);			auto pSrcline = flippedBuffer.get() + (wIDth<<2)*(srcy_16>>16);			unsigned long srcx_16 = 0;			for (unsigned long x = 0; x < dst_wIDth; ++x)			{				//memcpy(beginPos + x * byte_wIDth,pSrcline + (srcx_16 >> 16)*byte_wIDth,byte_wIDth);				memcpy(beginPos + (x<<2),pSrcline + ((srcx_16 >> 16)<<2),byte_wIDth);				srcx_16 += xrIntfloat_16;			}			srcy_16 += yrIntfloat_16;			beginPos += (dst_wIDth << byte_shift);		}		/*-------------压缩end------------*/		//使用算法一次性对图片进行高斯模糊		stackblur(zipFlippedBuffer.get(),dst_wIDth,dst_height,5);		Image* image = new (std::nothrow) Image;		if (image)		{			image->initWithRawData(zipFlippedBuffer.get(),dst_wIDth * dst_height * 4,8);			image->autorelease();			if (afterCaptured)			{				afterCaptured(true,image);			}		}		else		{			cclOG("Malloc Image memory Failed!");			if (afterCaptured)			{				afterCaptured(false,nullptr);			}			delete image;			image = nullptr;		}		startedCapture = false;	} while (0);}/** 高斯模糊接口  缩放因子:iScale,截图会把全屏压缩为1/iScale大*/static EventListenerCustom* s_captureScreenListener;static CustomCommand s_captureScreenCommand;voID Util::gaussianBlur(const std::function<voID(bool,int iScale /*= 4*/){	if (s_captureScreenListener)	{		cclOG("Warning: CaptureScreen has been called already,don't call more than once in one frame.");		return;	}	s_captureScreenCommand.init(std::numeric_limits<float>::max());	s_captureScreenCommand.func = std::bind(onCaptureScreen,afterCaptured,iScale);	s_captureScreenListener = Director::getInstance()->getEventdispatcher()->addCustomEventListener(Director::EVENT_AFTER_DRAW,[](EventCustom *event) {		auto director = Director::getInstance();		director->getEventdispatcher()->removeEventListener((EventListener*)(s_captureScreenListener));		s_captureScreenListener = nullptr;		director->getRenderer()->addCommand(&s_captureScreenCommand);		director->getRenderer()->render();	});}


以下是导出的lua接口:

#include "base/ccConfig.h"#ifndef __game_custom_h__#define __game_custom_h__#ifdef __cplusplusextern "C" {#endif#include "tolua++.h"#ifdef __cplusplus}#endifint register_all_game_custom(lua_State* tolua_S);#endif // __game_custom_h__

static int tolua_pf_common_gaussianBlur(lua_State* tolua_S){	LUA_FUNCTION callbackHander = toluafix_ref_function(tolua_S,0);	if (callbackHander == 0)	{		cclOG("tolua_pf_common_gaussianBlur : toluafix_ref_function,error");		return 0;	}	auto capture_callback = [=](bool succeed,Image* img){		auto luastack = LuaEngine::getInstance()->getLuaStack();		luastack->pushBoolean(succeed);		if (succeed){			luastack->pushObject(img,"cc.Image");		}		else{			luastack->pushNil();		}		luastack->executeFunctionByHandler(callbackHander,2);	};	int argc = lua_gettop(tolua_S) - 1;	if (argc == 2)	{		int q = 4;		if (!luaval_to_int32(tolua_S,3,&q))		{			cclOG("tolua_pf_common_gaussianBlur : luaval_to_number,error");			return 0;		}		Util::gaussianBlur(capture_callback,q);	}	else	{		Util::gaussianBlur(capture_callback);	}	return 0;}TolUA_API int register_all_game_custom(lua_State* tolua_S){	tolua_open(tolua_S);	tolua_module(tolua_S,"pf",0);	tolua_beginmodule(tolua_S,"pf");		tolua_module(tolua_S,"Common",0);		tolua_beginmodule(tolua_S,"Common");		{			tolua_function(tolua_S,"GaussianBlur",tolua_pf_common_gaussianBlur);		}		tolua_endmodule(tolua_S);	tolua_endmodule(tolua_S);	return 1;}


使用方法:

            local function onFinishCapture(ret,img)                if ret then                    local texture = cc.Director:getInstance():getTextureCache():addImage(img,"capriteadu")                    local spriteBlur = cc.Sprite:createWithTexture(texture)                    local wSize = cc.Director:getInstance():getWinSize()                    spriteBlur:setposition(cc.p(wSize.wIDth/2,wSize.height/2))                    self:addChild(spriteBlur)                    PF.UIEx.nodetoScaleForFixedSize(spriteBlur,wSize)                end            end            pf.Common:GaussianBlur(onFinishCapture,4)
总结

以上是内存溢出为你收集整理的cocos2dx 高性能高斯模糊(包含lua接口)全部内容,希望文章能够帮你解决cocos2dx 高性能高斯模糊(包含lua接口)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1082506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存