Open Search
    Render Filter Implementation

    About

    Based on maxon::FilterContextInterface, maxon::FilterImageInterface and maxon::FilterInterface one can implement custom render filters.

    FilterContex

    A filter context is the central class to create queues, images and filters. A real-world implementation would initialize a library or a framework such as CUDA or OpenCL.

    // This example shows the declaration of a FilterContext implementation.
    namespace FilterContextClasses
    {
    MAXON_DECLARATION(maxon::FilterContextClasses::EntryType, EXAMPLECONTEXT, "net.maxonexample.render_filter.context.example");
    } // FilterContextClasses
    #define MAXON_DECLARATION(T, Name, id,...)
    Definition: module.h:847
    // This example shows a simple implementation of FilterContextInterface.
    class FilterContextImpl : public maxon::Component<FilterContextImpl, maxon::FilterContextInterface>
    {
    public:
    MAXON_METHOD maxon::Result<maxon::FilterImageRef> CreateImage(const maxon::DataDictionary& imageDesc);
    MAXON_METHOD maxon::Result<void> ExecuteCommandQueue(maxon::FilterCommandQueueRef commandQueue);
    };
    {
    // Initialize the FilterContext with optional parameters provided by the DataDictionary (e.g. the type of context)
    return maxon::OK;
    }
    maxon::Result<maxon::FilterRef> FilterContextImpl::CreateFilter(const maxon::LiteralId& filterType)
    {
    // Create the filter of type 'filterType'.
    // In a real world example the context would create some internal object and provide the FilterRef with the object, for instance.
    maxon::FilterRef filter = maxon::FilterClasses::Get(filterType.Get()).Create() iferr_return;
    return filter;
    }
    maxon::Result<maxon::FilterImageRef> FilterContextImpl::CreateImage(const maxon::DataDictionary& imageDesc)
    {
    // Create an image using the imageDesc DataDictionary
    maxon::FilterImageRef image = maxon::FilterImageClasses::EXAMPLEIMAGE().Create() iferr_return;
    // Get Image parameters...
    const maxon::UInt32 width = imageDesc.Get(maxon::FilterImageDescriptionParameters::WIDTH) iferr_return;
    const maxon::UInt32 height = imageDesc.Get(maxon::FilterImageDescriptionParameters::HEIGHT) iferr_return;
    // ... and do sanity checking!
    CheckState(width > 0 && height > 0, "Invalid Image Size!"_s);
    // Get the actual implementation of our FilterImage
    FilterImageImpl* imageImpl = FilterImageImpl::GetOrNull(image);
    CheckState(imageImpl);
    imageImpl->Init(width, height) iferr_return;
    return image;
    }
    maxon::Result<maxon::FilterCommandQueueRef> FilterContextImpl::CreateCommandQueue()
    {
    // A command queue is optional and not needed in this case.
    return maxon::FunctionNotImplementedError(MAXON_SOURCE_LOCATION, "No command queue support"_s);
    }
    maxon::Result<void> FilterContextImpl::ExecuteCommandQueue(maxon::FilterCommandQueueRef commandQueue)
    {
    // A command queue is optional and not supported in this case.
    return maxon::FunctionNotImplementedError(MAXON_SOURCE_LOCATION, "No command queue support"_s);
    }
    // register implementation
    MAXON_COMPONENT_CLASS_REGISTER(FilterContextImpl, maxon::FilterContextClasses::EXAMPLECONTEXT);
    Definition: objectbase.h:2651
    Definition: apibaseid.h:54
    const Id & Get() const
    Definition: apibaseid.h:185
    Definition: optional.h:552
    PyObject PyObject * dict
    Definition: abstract.h:150
    uint32_t UInt32
    32 bit unsigned integer datatype.
    Definition: apibase.h:177
    return OK
    Definition: apibase.h:2667
    #define CheckState(condition,...)
    Definition: errorbase.h:510
    #define MAXON_SOURCE_LOCATION
    Definition: memoryallocationbase.h:67
    #define MAXON_COMPONENT(KIND,...)
    Definition: objectbase.h:2212
    #define MAXON_COMPONENT_CLASS_REGISTER(C,...)
    Definition: objectbase.h:2409
    #define MAXON_METHOD
    Definition: interfacebase.h:1001
    const Class< R > & Get(const Id &cls)
    Definition: objectbase.h:2073
    unsigned long Py_ssize_t width
    Definition: pycore_traceback.h:88
    #define iferr_scope
    Definition: resultbase.h:1374
    #define iferr_return
    Definition: resultbase.h:1465

    FilterImage

    A filter image stores the given image data. Internally it might represent a data structure related to the underlying library or framework.

    // This example shows the declaration of a FilterImage implementation.
    namespace FilterImageClasses
    {
    MAXON_DECLARATION(maxon::FilterImageClasses::EntryType, EXAMPLEIMAGE, "net.maxonexample.render_filter.image.example");
    } // FilterImageClasses
    // This example shows a simple implementation of FilterImageInterface wrapping around a maxon::BaseArray.
    class FilterImageImpl : public maxon::Component<FilterImageImpl, maxon::FilterImageInterface>
    {
    public:
    MAXON_METHOD maxon::Result<void> WriteToFile(const maxon::Url& url);
    const maxon::BaseArray<maxon::Vector4d32>& GetImageData() const;
    private:
    // Here, the FilterImage just holds a BaseArray of Vector Data to represent and image.
    };
    {
    return buffer.CopyFrom(_imgData);
    }
    maxon::Result<void> FilterImageImpl::ReadFromCPUMemory(const maxon::BaseArray<maxon::Vector4d32>& data)
    {
    return _imgData.CopyFrom(data);
    }
    maxon::Result<void> FilterImageImpl::WriteToFile(const maxon::Url& url)
    {
    return maxon::FunctionNotImplementedError(MAXON_SOURCE_LOCATION, "Function not implemented"_s);
    }
    maxon::Result<void> FilterImageImpl::Init(const maxon::UInt32 width, const maxon::UInt32 height)
    {
    return _imgData.Resize(width * height);
    }
    const maxon::BaseArray<maxon::Vector4d32>& FilterImageImpl::GetImageData() const
    {
    return _imgData;
    }
    maxon::BaseArray<maxon::Vector4d32>& FilterImageImpl::GetImageData()
    {
    return _imgData;
    }
    // register implementation
    MAXON_COMPONENT_CLASS_REGISTER(FilterImageImpl, maxon::FilterImageClasses::EXAMPLEIMAGE);
    const char ** buffer
    Definition: abstract.h:327
    Definition: basearray.h:412
    Definition: url.h:942

    Filter

    The actual filter is based on maxon::FilterInterface. It can store various parameters and operates on the given data set.

    // This example shows the declaration of a Filter implementation.
    namespace FilterClasses
    {
    MAXON_DECLARATION(FilterClasses::EntryType, EXAMPLEINVERT, "net.maxonexample.render_filter.filter.example.invert");
    MAXON_DECLARATION(FilterClasses::EntryType, EXAMPLEPOWER, "net.maxonexample.render_filter.filter.example.power");
    } // FilterClasses
    // This example shows two simple implementations of FilterInterface. Both share functionality using a ComponentRoot.
    //-------------------------------------------------------------------------------------
    // A custom ComponentRoot that provides a base implementation for all our filters
    //-------------------------------------------------------------------------------------
    class FilterComponentRoot : public maxon::ComponentRoot
    {
    public:
    // shared implementation of Execute()
    maxon::Result<void> Execute(const maxon::FilterImageRef& input, maxon::FilterImageRef output);
    protected:
    };
    maxon::Result<void> FilterComponentRoot::Execute(const maxon::FilterImageRef& input, maxon::FilterImageRef output)
    {
    // Get the actual implementation of our FilterImage
    FilterImageImpl* inputImpl = FilterImageImpl::GetOrNull(input);
    FilterImageImpl* outputImpl = FilterImageImpl::GetOrNull(output);
    CheckState(inputImpl && outputImpl);
    const maxon::BaseArray<maxon::Vector4d32>& inputData = inputImpl->GetImageData();
    maxon::BaseArray<maxon::Vector4d32>& outputData = outputImpl->GetImageData();
    CheckState(inputData.GetCount() == outputData.GetCount(), "Input and Output image sizes do not match!"_s);
    ExecuteImpl(inputData, outputData) iferr_return;
    return maxon::OK;
    }
    //-------------------------------------------------------------------------------------
    // Filter Examples
    // Represents a filter that can be executed or attached to a filter command queue.
    // Use the Set() function to apply settings.
    //-------------------------------------------------------------------------------------
    class InvertFilterImpl : public maxon::ComponentWithBase<InvertFilterImpl, FilterComponentRoot, maxon::FilterInterface>
    {
    public:
    MAXON_METHOD maxon::Result<void> SetProgressMonitor(const maxon::FilterProgressMonitorFunction progressMonitor, void* userPtr);
    private:
    virtual maxon::Result<void> ExecuteImpl(const maxon::BaseArray<maxon::Vector4d32>& inputData, maxon::BaseArray<maxon::Vector4d32>& outputData) override;
    maxon::Bool _everyPixel = true;
    };
    class PowerFilterImpl : public maxon::ComponentWithBase<PowerFilterImpl, FilterComponentRoot, maxon::FilterInterface>
    {
    public:
    MAXON_METHOD maxon::Result<void> SetProgressMonitor(const maxon::FilterProgressMonitorFunction progressMonitor, void* userPtr);
    private:
    virtual maxon::Result<void> ExecuteImpl(const maxon::BaseArray<maxon::Vector4d32>& inputData, maxon::BaseArray<maxon::Vector4d32>& outputData) override;
    maxon::Float32 _exponent = 1.0f;
    };
    {
    // Switch on the parameter ID
    switch (ID_SWITCH(parameter))
    {
    case ID_CASE(maxonexample::FilterExampleParameter::EVERYPIXEL):
    {
    _everyPixel = data.GetOrNull<maxon::Bool>();
    break;
    }
    }
    return maxon::OK;
    }
    maxon::Result<void> InvertFilterImpl::SetProgressMonitor(const maxon::FilterProgressMonitorFunction progressMonitor, void* userPtr)
    {
    return maxon::OK;
    }
    maxon::Result<void> InvertFilterImpl::ExecuteImpl(const maxon::BaseArray<maxon::Vector4d32>& inputData, maxon::BaseArray<maxon::Vector4d32>& outputData)
    {
    for (maxon::UInt32 i = 0; i < outputData.GetCount(); ++i)
    {
    const maxon::Bool skip = _everyPixel == false && i % 2 == 0;
    outputData[i] = skip ? inputData[i] : maxon::Vector4d32(1.0f) - inputData[i];
    }
    return maxon::OK;
    }
    {
    // Switch on the parameter ID
    switch (ID_SWITCH(parameter))
    {
    case ID_CASE(maxonexample::FilterExampleParameter::EXPONENT):
    {
    _exponent = data.GetOrNull<maxon::Float32>();
    break;
    }
    }
    return maxon::OK;
    }
    maxon::Result<void> PowerFilterImpl::SetProgressMonitor(const maxon::FilterProgressMonitorFunction progressMonitor, void* userPtr)
    {
    return maxon::OK;
    }
    maxon::Result<void> PowerFilterImpl::ExecuteImpl(const maxon::BaseArray<maxon::Vector4d32>& inputData, maxon::BaseArray<maxon::Vector4d32>& outputData)
    {
    for (maxon::UInt32 i = 0; i < outputData.GetCount(); ++i)
    {
    const maxon::Vector4d32& input = inputData[i];
    maxon::Vector4d32& output = outputData[i];
    for (maxon::UInt32 c = 0; c < 4; ++c)
    {
    output[c] = maxon::Pow(input[c], _exponent);
    }
    }
    return maxon::OK;
    }
    // register implementations
    MAXON_COMPONENT_CLASS_REGISTER(InvertFilterImpl, maxon::FilterClasses::EXAMPLEINVERT);
    MAXON_COMPONENT_CLASS_REGISTER(PowerFilterImpl, maxon::FilterClasses::EXAMPLEPOWER);
    #define Set(a0, a1, a2, a3, a4, a5)
    Definition: Python-ast.h:586
    Py_ssize_t i
    Definition: abstract.h:645
    MAXON_ATTRIBUTE_FORCE_INLINE Int GetCount() const
    Definition: basearray.h:573
    Definition: datatypebase.h:1199
    ByValueParam< T >::type GetOrNull() const
    Definition: datatypebase.h:1419
    Definition: datatypelib.h:27
    Py_UNICODE c
    Definition: unicodeobject.h:1200
    Py_ssize_t char * output
    Definition: unicodeobject.h:985
    #define ID_SWITCH(key)
    Definition: fid.h:341
    #define ID_CASE(key)
    Definition: fid.h:354
    bool Bool
    boolean type, possible values are only false/true, 8 bit
    Definition: apibase.h:181
    float Float32
    32 bit floating point value (float)
    Definition: apibase.h:182
    MAXON_ATTRIBUTE_FORCE_INLINE Float32 Pow(Float32 v1, Float32 v2)
    Calculates v1^v2.
    Definition: apibasemath.h:290
    Vec4< Float32, 1 > Vector4d32
    Definition: vector4d.h:28
    Bool(*)(void *userPtr, Float progress) FilterProgressMonitorFunction
    Definition: filter.h:10
    A vector consisting of four components X, Y, Z and W.
    Definition: vec4.h:21

    Usage

    Custom filter can be used as presented:

    // Create example context
    maxon::FilterContextRef filterContext = maxon::FilterContextClasses::EXAMPLECONTEXT().Create() iferr_return;
    filterContext.Init() iferr_return;
    // Create filter
    maxon::FilterRef filterInvert = filterContext.CreateFilter(maxon::FilterClasses::EXAMPLEINVERT.GetId()) iferr_return;
    filterInvert.Set(maxonexample::FilterExampleParameter::EVERYPIXEL, maxon::Data(false)) iferr_return;
    maxon::FilterRef filterPower = filterContext.CreateFilter(maxon::FilterClasses::EXAMPLEPOWER.GetId()) iferr_return;
    filterPower.Set(maxonexample::FilterExampleParameter::EXPONENT, maxon::Data(0.42f)) iferr_return;
    // Create images
    maxon::DataDictionary imgDesc;
    imgDesc.Set(maxon::FilterImageDescriptionParameters::WIDTH, static_cast<maxon::UInt32>(width)) iferr_return;
    imgDesc.Set(maxon::FilterImageDescriptionParameters::HEIGHT, static_cast<maxon::UInt32>(height)) iferr_return;
    maxon::FilterImageRef input = filterContext.CreateImage(imgDesc) iferr_return;
    maxon::FilterImageRef output = filterContext.CreateImage(imgDesc) iferr_return;
    // Load image data
    input.ReadFromCPUMemory(bufferColor) iferr_return;
    // Execute the filters
    filterInvert.Execute(input, output) iferr_return;
    filterPower.Execute(output, input) iferr_return;
    // Get result image
    input.WriteToBuffer(bufferFiltered) iferr_return;

    Further Reading