File: //opt/resolve/Developer/Fusion Fuse/Example 3 Image Process.fuse
--[[--
Example Fuse 3 Internal Image Processing Operations
This shows how to use Fusion's image processing functions.
Copyright (c) 2018-2020, BMD, by Steve Roberts
--]]--
--******************************************************************************************************
-- This Registers the Fuse into Fusion, gives its Name, and Menu location. Location of Help. Can Fuse be edited.
FuRegisterClass("ExampleImageProcess", CT_Tool, {
REGS_Name = "Ex3 Image Process",
REGS_Category = "Fuses\\Examples",
REGS_OpIconString = "IP",
REGS_OpDescription = "Example, using internal Image Processing functions",
REGS_HelpTopic = "Example Location of Help", --This can be a URL
REGS_URL = "www.blackmagicdesign.com",
--REGS_IconID = "Icons.Tools.Icons.Example",-- This can be inline as an array of color values
REG_NoMotionBlurCtrls = true, -- diable motion blurs for this tool
REG_Fuse_NoEdit = false,
REG_Fuse_NoReload = false,
REG_Version = 1,
}) -- End of RegisterClass
--****************************************************************************************************
--Create will define all the controls, like sliders, check boxes, onscreen crosshairs etc, that will show in Inspector Tool control area
function Create()
self:BeginControlNest("Fusion Internal Image Processing Functions", "ColorWheel", true); -- Control Nests group controls with a togglable collapse/expand function
InDropList = self:AddInput("Image Process ", "DropList", {
LINKID_DataType = "Number",
INPID_InputControl = "ComboControl",
INP_Default = 0.0,
INP_Integer = true,
CC_LabelPosition = "Horizontal", -- Define where the Label Name is displayed, Horixontal is to the left, Horizontal is on the left, Vertical is on top
INP_DoNotifyChanged = true,
{ CCS_AddString = "Color Matrix", }, -- labels for each option in the list
{ CCS_AddString = "Color Functions", },
{ CCS_AddString = "ColorSpace", },
{ CCS_AddString = "Clear and Fill with color", },
{ CCS_AddString = "Color Channel Operations", },
{ CCS_AddString = "Channel Booleans", },
{ CCS_AddString = "Transform", },
{ CCS_AddString = "Crop", },
{ CCS_AddString = "Resize", },
{ CCS_AddString = "Merge", },
{ CCS_AddString = "OMerge", },
{ CCS_AddString = "Blur Glow", },
})
InLabel = self:AddInput("Fusion Internal Image functions ", "label1", {
LINKID_DataType = "Text",
INPID_InputControl = "LabelControl",
INP_External = false,
INP_Passive = true,
})
self:EndControlNest()
InImage = self:AddInput("Input", "Input", {
LINKID_DataType = "Image",
LINK_Main = 1,
})
InForeground = self:AddInput("Foreground", "Foreground", {
LINKID_DataType = "Image",
LINK_Main = 2,
INP_Required = false,
})
OutImage = self:AddOutput("Output", "Output", {
LINKID_DataType = "Image",
LINK_Main = 1,
})
end -- end of Create()
--*************************************************************************************************************
-- The Process section is the main section where the image processing rendering occurs
function Process(req)
--********** Get Input image *************************
local img = InImage:GetValue(req) --Get the image input and assignit to a pointer (img)
local foreG = InForeground:GetValue(req) --Get the foreground image input and assignit to a pointer (img)
local out = img:Copy() -- Create an output image like the input image
--****************** Image Creation ***********************************************
-- local imgTemp = Image({IMG_Like = img, IMG_Depth = IMDP_128bitFloat, IMG_CopyChannels = false}) -- Create an Image like(size) the input image (img) , set depth to 32 bit float per channel
-- local avg = Image({IMG_Like = img, IMG_Depth = 8, IMG_NoData = req:IsPreCalc()}) -- Create an Image like(size) the input image (img) , set depth to 8 bit per channel
local imgattrs = { -- Create an image. Get Preferences default image size and depth and set Attrs (Attributes) in IMG tag list
IMG_Document = self.Comp,
IMG_Width = 512, --Width,
IMG_Height = 256, --Height,
IMG_XScale = XAspect,
IMG_YScale = YAspect,
IMAT_OriginalWidth = realwidth,
IMAT_OriginalHeight = 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 -- from Prefs - Frame formats
end
local rszimg = Image(imgattrs) -- Create an image based on the Attrs (Attributes) set above
local dList = InDropList:GetValue(req).Value --Get the dropdown list of functions
print("ImageProcess Function :") -- Print to console
if dList == 0 then
--********** Color Matrix*********
print("Color Matrix") -- Print to console
local cm = ColorMatrixFull() -- Create a color matrix
--Apply Brightness to the matrix via Offset function
cm:Offset(0.1, 0.1, 0.1, 0) -- RGBA values adding 0.1 to RGB and 0 to Alpha
--Scale is the same as Gain which will multiply the Matrix by 1.1
cm:Scale(1.1, 1.1, 1.1, 1.1) -- Multiplies RGBA by 1.1 like Gain
--Apply the Color Matrix to the image img into the output image out
out = img:ApplyMatrixOf(cm, {}) --Applies the Color Matrix (cm) on image (img) outputting to another image (out)
end
if dList == 1 then
--**********Color Functions************
print("Color Functions") -- Print to console
out = img:Copy() -- copy input image to out image
out:Gain(1.1 , 1.2 , 1.3, 1)--RGBA
out:Gamma(1.5, 1.5, 1.5, 1)--RGBA
out:Saturate(1.5,1.5,1.5)--RGB
end
if dList == 2 then
--***********Color Space Conversion***********
print("Color Space Conversion") -- Print to console
--Image:CSConvert(<from>, <to>), with <from> and <to> coming from "RGB", "HLS", "YUV", "YIQ", "CMY", "HSV", "XYZ", "LAB".
out:CSConvert ("RGB", "YUV") -- Convert RGB to YUV where Y is in R, U is in G, V is in B
out:Gamma(1.0, 0.9, 1.1, 1) --Example: Apply some Gamma to UV channels
out:CSConvert ("YUV", "RGB") -- Convert YUV to RGB
end
if dList == 3 then
--***********Clear and Fill with color***********
print("Clear image and Fill with solid color") -- Print to console
out:Clear() -- Clears image set all channels to zero
out:Fill(Pixel({R = 1.0, G = 0.8, B = 0.25, A = 1.0})) --Fill image with color
end
if dList == 4 then
--***********Color Channel Math Operations***********
-- Channel Math operations, apply a value to image(img) to output (out)
-- "Add", Multiply, Subtract, Divide
out = img:ChannelOpOf("Add", nil, { R = 0.1, G = 0.1, B = 0.1, A = 0.0})
out = out:ChannelOpOf("Multiply", nil, { R = 1.1, G = 1.1, B = 1.1, A = 1.0})
out = out:ChannelOpOf("Subtract", nil, { R = 0.2, G = 0.2, B = 0.2, A = 0.0})
out = out:ChannelOpOf("Divide", nil, { R = 0.8, G = 0.8, B = 0.8, A = 1.0})
end
if dList == 5 then
--***********Channel Boolean Math Operations***********
-- Channel Boolean Math operations, pixel to pixel operations apply a value to image(img) to output (out)
-- Copy, Add, Multiply, Subtract, Divide, Threshold, And, Or, Xor, Negative, Difference, Signed Add
if fg then -- If no foreground image then set fg to img image
foreG =foreG --do nothing
else
foreG=img --no foreground so make it be the image img
end
-- fg.R
-- out = img:ChannelOpOf("Multiply", fg, {R = "fg.R", G = "fg.G", B = "fg.B", A = "fg.A"}) -- Multiply each pixel with a pixel from another image
-- out = img:ChannelOpOf("Add", fg, {R = "fg.G", G = "fg.R", B = "fg.B", A = "fg.A"}) -- Add each pixel with a pixel from another image
-- out = img:ChannelOpOf("Threshold", fg, {R = "bg.R", G = "bg.G", B = "bg.B", A = "bg.A"}, 0.1, 0.8) -- Threshold low-high
-- out = img:ChannelOpOf("Copy", fg, {R = "fg.R", G = "fg.G", B = "fg.B", A = "fg.A"}) -- Copy fg channels to output
out = img:ChannelOpOf("Copy", fg, {R = "fg.R", G = "bg.G", B = "bg.B", A = "fg.A"}) --Copy one channel to another, fg Red and bg Green and Blue
end
if dList == 6 then
--***********Transform Image***********
-- Transform image(img) to output (out)
print("\nTransform Image :") -- Print to console
out = img:Transform(nil, {
XF_XOffset = 0.65, --center.X,
XF_YOffset = 0.6, --center.Y,
XF_XAxis = 0.5, --pivot.X,
XF_YAxis = 0.5, --pivot.Y,
XF_XSize = 0.2, --sizex,
XF_YSize = 0.4,--sizey,
XF_Angle = 30.0, --angle,
XF_EdgeMode = "Canvas", --edge_modes Black, Canvas, Wrap(tile), Duplicate edges
})
end
if dList == 7 then
--***********Crop Image***********
-- Crop image(img) to output (out)
local imgattrs = { -- Create an image. Set Attrs (Attributes) in IMG tag list
IMG_Document = self.Comp,
IMG_Width = 512, --Width,
IMG_Height = 256, --Height,
IMG_Depth = 8 -- Set Depth to 8bit integer
}
out = Image(imgattrs) -- Create an image based on the Attrs (Attributes) set in IMG
img:Crop(out, {CROP_XOffset = 100, CROP_YOffset = 50}) --Original image (img) Output image (out). Offset in Pixels 0,0 is bottom left. Negative and out of bounds values are allowed
end
if dList == 8 then
--***********Resize Image***********
print("Resize") -- Print to console
--out = Image({IMG_Like = img, IMG_Width = 512, IMG_Height = 256})
img:Resize(rszimg, {RSZ_Filter = "Cubic", }) --Filter Methods: Nearest, Box, Linear, Quadratic, Cubic, Catmull-Rom, Gaussian, Mitchell, Lanczos, Sinc, Bessel
out = rszimg
end
if dList == 9 then
--*********** Merge Foreground image over Background image***********
local apply_modes = { "Merge", "Screen", "Dissolve", "Multiply", "Overlay", "SoftLight", "HardLight", "ColorDodge", "ColorBurn", "Darken", "Lighten",
"Difference", "Exclusion", "Hue", "Saturation", "Color", "Luminosity", }
local apply_operators = { "Over", "In", "Held Out", "Atop", "XOr", }
local applymode =1 --1 is Merge
local applyoperator =1 --1 is Over
--Merge will overlay the Foreground( img) over the copy Background image (out)
if foreG then -- Only do the Merge if the Foreground image is present
foreG =foreG --do nothing
else
foreG=img -- No foreground image input, make foreground the same as primary image.
end
out:Merge(foreG, { --foreG image will be on top of out image
MO_ApplyMode = apply_modes[applymode],
MO_ApplyOperator = apply_operators[applyoperator],
MO_XOffset = 0.75, --center.X,
MO_YOffset = 0.75, --center.Y,
MO_XAxis= 0.5,
MO_YAxis =0.5,
MO_XSize = 0.5 ,--xsize,
MO_YSize = 0.5, --ysize,
MO_Angle = 45, --angle,
MO_FgAddSub = additive,
MO_BgAddSub = additive,
MO_BurnIn = 0.0, --burn,
MO_FgRedGain = 1.0,
MO_FgGreenGain = 1.0,
MO_FgBlueGain = 1.0,
MO_FgAlphaGain = 1.0,
MO_Invert = 1,
MO_DoZ = false,
})
-- out:OMerge(sample, (i%step) * img2.Width, img.Height - math.floor(i/step) * img2.Height)
end
if dList == 10 then
--*********** OMerge and OXMerge a Simple Additive or Subtractive Merge with Pixel XYOffsets***********
--This can be used to reverse Crop Image
--Merge will overlay the Foreground( img) over the copy Background image (out)
if foreG then -- Only do the Merge if the Foreground image is present
foreG =foreG --do nothing
else
foreG=img -- No foreground image input, make foreground the same as primary image.
end
out:OMerge(foreG, 100, 50) -- Pixel integer offsets
--out:OXMerge(foreG, 100, 50) -- Pixel integer offsets
end
if dList == 12 then
--***********Blur Glow***********
img:Blur(out, { -- Blur will blur img into the result out
BLUR_Type = 4,
BLUR_Red = true ,
BLUR_Green = true,
BLUR_Blue = true,
BLUR_Alpha = true,
BLUR_XSize = 10/720,
BLUR_YSize = 10/720,
BLUR_Blend = 0.5,
BLUR_Normalize = 0.5,
BLUR_Passes = 0.0,
BLUR_RedScale = 1.0,
BLUR_GreenScale = 1.0,
BLUR_BlueScale = 1.0,
BLUR_AlphaScale = 1.0,
})
end
--Output the image
OutImage:Set(req, out) -- Output image
end