HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/resolve/Developer/Fusion Fuse/Example 4 MultiPixel Process.fuse
--[[--
Multi Process Pixel.fuse 

--]]--

FuRegisterClass("Ex4MultiPxl", CT_Tool, {
	REGS_Category = "Fuses\\Examples",
	REGS_Name = "Ex4 MultiPixel",
	REGS_OpIconString = "MltP",
	REGS_OpDescription = "Multi-threaded pixel operations fuse",
	})

function Create()
	InOperation = self:AddInput("Operation", "Operation", {
		LINKID_DataType = "Number",
		INPID_InputControl = "MultiButtonControl",
		INP_Default = 0.0,
		{ MBTNC_AddButton = "Min", MBTNCD_ButtonWidth = 0.1, },
		{ MBTNC_AddButton = "Max", MBTNCD_ButtonWidth = 0.2, },
		{ MBTNC_AddButton = "Add", MBTNCD_ButtonWidth = 0.3, },
		{ MBTNC_AddButton = "Variables", MBTNCD_ButtonWidth = 0.4, },
		{ MBTNC_AddButton = "Copy RGBA To Aux", MBTNCD_ButtonWidth = 0.4, },
		})			

	InImage1 = self:AddInput("Input 1", "Input1", {
		LINKID_DataType = "Image",
		LINK_Main = 1,
		})

	InImage2 = self:AddInput("Input 2", "Input2", {
		LINKID_DataType = "Image",
		LINK_Main = 2,
		INP_Required = false,
		})

	OutImage = self:AddOutput("Output", "Output", {
		LINKID_DataType = "Image",
		LINK_Main = 1,
		})				
end


-- Function table for operations; p1 is a pixel from image1 and p2 is a pixel from image 2
op_funcs = 
{
	[1] =	function(x,y,p1,p2) -- min
				p1.R = math.min(p1.R, p2.R)
				p1.G = math.min(p1.G, p2.G)
				p1.B = math.min(p1.B, p2.B)
				p1.A = math.min(p1.A, p2.A)
				return p1
			end,
	[2] =	function(x,y,p1,p2) -- max
				p1.R = math.max(p1.R, p2.R)
				p1.G = math.max(p1.G, p2.G)
				p1.B = math.max(p1.B, p2.B)
				p1.A = math.max(p1.A, p2.A)
				return p1
			end,
	[3] =	function(x,y,p1,p2) -- add
				p1.R = p1.R + p2.R
				p1.G = p1.G + p2.G
				p1.B = p1.B + p2.B
				p1.A = p1.A + p2.A
				return p1
			end,
	[4] =	function(x,y,p1,p2) -- Variables. any number of variables can be named and passed to the function
				p1.R = gain * (p1.R - p2.R)
				p1.G = p1.G - p2.G - bright
				p1.B = var_C * (p1.B - p2.B) 
				p1.A = p1.A - p2.A
				return p1
			end,
			
			-- Copy Img2 RGB to Background and Normals Aux channels of img1
			-- These are the all the channels available:
			-- R, G, B, A, BgR, BgG, BgB, BgA, Z, Coverage, ObjectID, MaterialID, U, V, W, NX, NY, NZ, 
			-- VectX, VectY, BackVectX, BackVectY, DisparityX, DisparityY, PositionX, PositionY, PositionZ
	[5] =	function(x,y,p1,p2)
				p1.R = p1.R 
				p1.G = p1.G
				p1.B = p1.B
				p1.A = p1.A
				p1.BgR = p2.R
				p1.BgG = p2.G
				p1.BgB = p2.B
				p1.BgA = p2.A
				return p1
			end,
}


function Process(req) 
	local img1 = InImage1:GetValue(req)
	local img2 = InImage2:GetValue(req)
	local operation = InOperation:GetValue(req).Value+1
	if  img2 == nil then
		img2 = img1
	end
--This creates an image with 4 extra channels for function 5
    local imgattrs = {
        IMG_Document          = self.Comp,
        { IMG_Channel         = "Red", },
        { IMG_Channel         = "Green", },
        { IMG_Channel         = "Blue", },
        { IMG_Channel         = "Alpha", },
        { IMG_Channel         = "BgRed", },
        { IMG_Channel         = "BgGreen", },
        { IMG_Channel         = "BgBlue", },
        { IMG_Channel         = "BgAlpha", },
        IMG_Width             = img1.Width,
        IMG_Height            = img1.Height,
        IMG_XScale            = img1.XAspect,
        IMG_YScale            = img1.YAspect,
        IMAT_OriginalWidth    = img1.realwidth,
        IMAT_OriginalHeight   = img1.realheight,
        IMG_Quality           = not req:IsQuick(),
        IMG_MotionBlurQuality = not req:IsNoMotionBlur(),
        }
     if not req:IsStampOnly() then
        imgattrs.IMG_ProxyScale = 1
    end
     if SourceDepth ~= 0 then
        imgattrs.IMG_Depth = SourceDepth
    end
    local out = Image(imgattrs)	
	
	local func = op_funcs[operation] -- get pointer to the function from the table

		-- Must have a valid operation function, and images must be same dimensions
	if func and (img1.Width == img2.Width) and (img1.Height == img2.Height) then
	
		out = Image({IMG_Like = img1})
		
		out:MultiProcessPixels(nil, { gain = 2.0, bright = -0.3, var_C = 1.5 }, 0,0, img1.Width, img1.Height, img1, img2, func)		
		-- Note any variable names can be used and passed to the function, These { gain = 2.0, bright = -0.3, var_C = 1.5 } are used in Function 4
	end
	
	OutImage:Set(req, out)
end