In this tutorial, you will learn how to create a reusable custom filter node that iterates multiple times over an image to posterize it. This tutorial teaches you how to use the Attributes node to define the attributes of the custom node, how to define the inputs and outputs of the custom node with the Image IO, and how to evaluate an image multiple using the iterations attribute of the Node Graph node.
This tutorial assumes that you read the basic tutorials.
Download the tutorial files posterize.7z and extract them in your PC.
Open the project [Posterize5Levels.pxf] project.
Activate the Reader girl_blue node. This node reads the image from disk.
Activate the To M node. This node converts the image to monochromatic color mode.
Activate the Blur node. This node smooths the image.
Activate the first Threshold node. This node converts the pixels with vales within [0.0 - 0.2] to white (1.0) and all other pixels to black (0.0).
The other 4 Threshold nodes convert the pixels with ranges [0.2 - 0.4], [0.4 - 0.6], [0.6 - 0.8] and [0.8 - 1.0].
Activate the first Value Multiply node. This node multiplies all pixels by 0.1.
The other 4 Value Multiply nodes multiplies the other images by 0.3, 0.5, 0.7 and 0.9.
Finally, the Value Add node adds the values of all the images and composes the final image.
If you need to posterize an image, you can open this project and change the path of the bitmap in the Reader node.
If you need to reuse this filter in other projects, you can add an Image IO node connected between the output of the Reader node and the input of the To M node, and a second Image IO node connected to the output of the Value Add node. This will define the input and output of the custom node. However, this will limit the effect of this Posterize custom node to only 5 levels defined by the 5 Threshold-Value Multiply nodes.
To create a custom node with a levels attribute that controls the numbers of leves we'll need to iterate through the image as many times as the number of levels.
To create the posterize custom filter node we'll need two projects, one that converts the image to mono and smooths it and a second one that takes the smooth image, finds the pixels within the range defined by the current iteration and the number of iterations and
where the number of levels is an attribute we'll need to run a loop that extracts the pixels within a range and multiplies them by the average value of the range, and that adds the level to the final image.
The Posterize Loop Body will be a PixaFlux project that takes as input a smooth monochromatic image, finds the pixels within the range defined by the current iteration and the number of iterations, multiplies these pixels by the average value of the range, and adds the pixel values to the image that will be returned by the project.
The Loop Body project doesn't need any images to work, but we'll need a monochromatic smooth image to test our loop body.
Start a new empty project. File > New Project > Empty.
Create a Reader node . [?] Load the girl_blue.png image using the Path button.
Create a To M node . Connect [Reader › image] to [image › To M]. [?]
Create a Blur node . Connect [To M › image] to [image › Blur]. Set the sizex and sizey attributes to 10.0.
Create an Image IO node . Connect [Blur › image] to [image › Image IO]. This node will define the input of the custom loop body project.
All the nodes connected to the input of the Image IO node (Reader - To M - Blur) will be ignored by the Node Graph node.
Now you'll add the Math nodes that compute the values for the Threshold and Value Multiply nodes.
Create a Loop Iterations node . This node will receive the current iteration and the number of iterations values from the Node Graph node when this project is used as a custom node.
The iterations number value is a number equal or greater than 1, and the iteration value is a number between 1 and iterations.
You'll need to add a few math nodes to obtain the ranges and average values from iteration and iterations.
We'll use this formulas:
(Smath Studio: Free mathematical program with WYSIWYG editor).
Add the low = (iteration - 1) / iterations nodes.
Create a Number Subtract node .
Connect [Loop Iterations › iteration] to [minuend › Number Subtract].
Set the subtrahend attribute to 1.0.
This node subtracts 1.0 from the iteration value.
Create a Number Divide node . Connect [Number Subtract › result] to [dividend › Number Divide]. Connect [Loop Iterations › iterations] to [divisor › Number Divide]. Rename the Divide node Low.
Create a Number Divide node . Connect [Loop Iterations › iteration] to [dividend › Number Divide]. Connect [Loop Iterations › iterations] to [divisor › Number Divide]. Rename the Divide node High.
Add the mid = (low + high) / 2.0 nodes.
Create a Number Add node . Connect [Low › result] to [numbera › Number Add]. Connect [High › result] to [numberb › Number Add].
Create a Number Divide node . Connect [Number Add › result] to [dividend › Number Divide]. Set the attribute divisor to 2.0. Rename the Divide node Mid.
To test the math you can edit the iteration and iterations attributes in the Loop Iterations node and hover over the outputs of the Number Subtract and Number Divide nodes, a tooltip will be displayed with the output name, type and value if numeric.
These are the values you should read:
|Iterations|Iteration|Low|High|Mid| |--------------|-------------|---|----|---| | 5 | 1 |0.0|0.2 |0.1| | 5 | 2 |0.2|0.4 |0.3| | 5 | 3 |0.4|0.6 |0.5| | 5 | 4 |0.6|0.8 |0.7| | 5 | 5 |0.8|1.0 |0.9|
Now you'll add the Threshold and Value Multiply nodes that will create the level image return on the current loop iteration.
Create a Threshold node . Connect [Image IO › image] to [image › Threshold].
Expose the attributes maximum and minimum in the Threshold node. In the Attributes Panel right click the label of the attribute and check the Expose As Input option in the manu.
Connect [Low › result] to [minimun › Threshold].
Connect [High › result] to [maximum › Threshold].
Threshold image at iterations = 5 and iteration = 3
Create a Value Multiply node . Connect [Threshold › image] to [image › Value Multiply].
Expose the attribute value in the Value Multiply node.
Connect [Mid › result] to [value › Value Multiply].
Value Multiply image at iterations = 5 and iteration = 3
Create an Image IO node . Connect [Value Multiply › image] to [image › Image IO].
The Loop Action attribute defines how the Node Graph node handles the images returned by this node. We need that all images get added together.
Set the Loop Action attribute to addition.
This last Image IO node defines the output of this Custom Node when used in a Node Graph node.
Save this project as Posterize_Loop.pxf. This is the project that will be loaded by the Posterize main custom node.
We'll now create the Posterize main project. This project that takes an image as input, converts it to monochromatic color, smooths it with a Blur filter and then excutes the posterize custom node in a loop. The number of iterations of the loop is defined by a levels attribute.
Start a new empty project. File > New Project > Empty.
Create a Reader node . Load the girl_blue.png image using the Path button. As with the loop body project, this Reader node will help us test our project.
Create an Image IO node . Connect [Reader › image] to [image › Image IO]. This node will define the input of the posterize custom node project.
Create a To M node . Connect [Image IO › image] to [image › To M].
Create a Blur node . Connect [To M › image] to [image › Blur].
Now we'll add and connect the attributes of the posterize filter.
Create an Attributes node .
In the Attributes panel click the Add Attribute button to add a new levels attribute. In the Add Attribute window set the new attribute properties:
Click Add Attribute button to add a new smooth attribute. In the Add Attribute window set the new attribute properties:
Expose the radiusx and radiusy on the Blur node [?].
Connect [Attributes › smooth] to [sizex › Blur]. Connect [Attributes › smooth] to [sizey › Blur].
Create a Node Graph node . Click the Path button and select the Posterize_Loop.pxf.
Double-click the Node Graph node to reativate it and display its Attributes.
Connect [Blur › image] to [image › Node Graph].
Expose the iterations attribute of the Node Graph node.
Connect [Attributes › levels] to [iterations › Node Graph].
Set the Attributes levels and smooth to posterize the image.
. levels = 4. Smooth = 5.0.
Create an Image IO node . Connect [Blur › image] to [image › Image IO]. This node will define the output of the posterize custom node project.
Set the Attributes levels and smooth to the values you'd like to have as default when the custom node is loaded.
Save this project as Posterize.pxf.
The Posterize.pxf project references the PosterizeLoop.pxf project. If these two files are moved to a different directory the Posterize.pxf needs to be able to locate the PosterizeLoop.pxf on that same directory. For this the path to the Posterize_Loop projects need to store all the paths to the files they reference as **relative paths.
In the Posterize.pxf project on the top menu go to Edit > Paths Click the Make Relative button to make all paths relative to the location of the Posterize.pxf file.
The Posterize_Loop.pxf project also has a reference to the image we used for testing, so you might also want to set the paths as relative on that project, although this is not needed for reusing this project as the reader node is ignored by the Posterize.pxf project.
We'll now create a new project with an image and load the Posterize.pxf in a Node Graph node.
Start a new empty project. File > New Project > Empty.
Create a Reader node . Load an image from your PC.
Create an Node Graph node . Load the project Posterize.pxf using the Path button. Double-click the Node Graph node to reactivate it.
Connect [Reader › image] to [image › Node Graph]. Set the attributes levels and smoth.
In this tutorial you learned how to build reusable custom nodes that iterate multiple times on images to create the desired effects.