bLUe: An Extensible 3D LUT Editor
Author: Bernard Virot
The "bLUe" editor is a Python-based platform designed to simplify the
development and testing of image processing techniques. Leveraging PySide6
for GUI construction and Numpy for computational tasks, it provides a modular,
layer-based architecture that enables real-time parameter adjustments
and seamless integration with Python-compatible image libraries.
With features like stackable layers, advanced color management,
and an intuitive GUI, "bLUe" facilitates both professional and experimental
workflows for image editing. Its extensibility allows users to incorporate
new image processing techniques with ease, making it a robust tool for
developers and researchers alike.
"bLUe" is a powerful editor for 3D LUT (Look-Up Table)
manipulation, designed to bridge the gap between advanced
image processing and user-friendly interfaces.
Built on Python technologies such as PySide6 and Numpy,
the platform offers a modular, extensible framework
that supports Python-compatible libraries.
By allowing real-time visualization of adjustments, "bLUe"
enhances user productivity and enables rapid experimentation with
image processing workflows.
"bLUe" employs a layer-based processing system. Each layer represents a
processing step : it processes an
input image, and stores the output image. A layer can be visible or hidden.
Each layer holds an opacity value, a blending mode, and a mask.
Several layers can be stacked.
They act as a pipeline, computing the final image by blending the visible layers,
from bottom to top.
A background layer, holding the initial image, is added at the
bottom of the stack, and all layers must be the same size.
For large-scale images or computationally intensive tasks,
a preview mode speeds up processing without compromising the workflow.
The GUI is designed for seamless interaction with processing parameters.
Each layer has a dedicated view that reflects real-time changes,
ensuring immediate feedback. The platformโs user-friendly interface
is built with Qt for Python (PySide6), offering features like contextual
help for accessibility.
The editorโs core data structures include:
The following UML diagram illustrates the relationship between these classes:
classDiagram class `imImage` imImage: layersStack class `bImage` class `baseForm` class baseGraphicsForm class `QLayer` QLayer: execute QLayer: rPixmap QLayer: parentImage QLayer: getGraphicsForm() QLayer: getCurrentImage() QLayer: getCurrentMaskedImage() QLayer: inputImg() `bImage` --> `QLayer` `bImage` --> `imImage`
The following Python code snippet illustrates how layers are blended to
produce the final output image:
def getCurrentMaskedImage(self):
"""
Blend the layer stack up to the current layer (included), considering
blending modes, opacities and masks.
:return: Blended image
:rtype: bImage
"""
# Initialization
if self.maskedThumbContainer is None:
self.maskedThumbContainer = bImage.fromImage(self.getThumb(), parentImage=self.parentImage)
# Reset container
img = self.maskedThumbContainer
img.fill(QColor(0, 0, 0, 0))
# Blend layers
qp = QPainter(img)
for layer in self.parentImage.layersStack[:self.stackIndex + 1]:
if layer.visible:
qp.setOpacity(layer.opacity)
qp.drawPixmap(QRect(0, 0, img.width(), img.height()), layer.rPixmap)
qp.end()
return img
This approach ensures efficiency by maintaining containers that are instantiated
only once and updated dynamically.
Adding a new technique involves three steps:
Create a form for user interaction, leveraging existing forms as templates.
For example, use graphicsFormAuto3DLUT.
Input items like sliders and checkboxes can be customized as needed.
- Add items to the form attributes :
self.slider1 = QbLUeSlider(Qt.Orientation.Horizontal)
...
- For each item, connect the signal indicating that a new state or a new value
is available to self.dataChanged :
for s in sliders:
s.sliderReleased.connect(self.dataChanged)
Note. To be able to save and restore their state, input item classes
must override the methods
_getstate()_ and __setstate()__.
Define the transformation function in the QLayer class (or a subclass).
For example, the following function
builds a 3D LUT for automatic image enhancement. It uses
three user-defined parameters for testing purpose.
def applyAuto3DLUT(self):
# Get the user interface
ui = self.getGraphicsForm()
# Generate an automatic 3D LUT, applying three correction coefficients.
coeffs = [ui.slider1.value(), ui.slider2.value(), ui.slider3.value()]
lutarray = generateLUTfromQImage(self.inputImg(), coeffs)
# Interpolate the input image with LUT
interp = chosenInterp()
outputArray = interp(lutarray, self.inputImg())
# Copy outputArray to the image data buffer (alpha channel excluded)
QImageBuffer(self.getCurrentImage())[..., :3] = outputArray
# Convert the image to QPixmap.
self.updatePixmap()
Add the new functionality as an action in the menu Layer:
elif name == 'actionAuto_3D_LUT':
layer = window.label.img.addAdjustmentLayer(role='AutoLUT')
layer.execute = lambda: layer.tLayer.applyAuto3DLUT()
A dedicated class (QPresentationLayer) handles advanced color management.
It enables compatibility with image and monitor profiles,
ensuring accurate color rendering.
The "bLUe" editor offers a cutting-edge environment for developing
and testing image processing techniques.
Its modular design, real-time visualization,
and seamless extensibility make it a powerful tool for both
developers and researchers.