I Created a Simple Image Browser for Nuke Using ChatGPT

Today, I’m going to show you how I created a simple image browser for Nuke with the help of ChatGPT. Yes, you heard it right, I used AI to code this tool in just a few steps, and trust me—it’s super cool!”

If you’re into VFX, coding might not always be your thing, but tools like ChatGPT can really speed things up. Instead of spending days figuring out Python or Nuke scripting, I got this browser up and running in just a few hours.

As a compositor, I often need to work with a lot of image elements. And, searching through folders manually or using the basic file browser is not ideal. So I thought—why not build something to preview, load, and even import these images directly into Nuke as Read nodes?

I could’ve spent hours trying to figure out the code myself, but instead, I used ChatGPT. It’s an AI that helped me write the Python code step-by-step. All I needed to do was describe what I wanted.

We started with setting up a basic PySide2 UI in Python. ChatGPT was quick to provide me with a framework to start building

The code is simple but powerful. It uses PySide2 for the UI, and it talks directly to Nuke’s API to create Read nodes and load images. This is how it works behind the scenes

ChatGPT might generate code that will do exactly what you asked for you have to iterate it improvise it and fix a little bit ,to make the you want. You might need to have basic understanding in nuke and Python to create a workable tool

Here is the full code

import nuke
import os
from PySide2 import QtWidgets, QtCore, QtGui

class DraggableThumbnail(QtWidgets.QLabel):
    """A QLabel that supports drag and drop functionality."""
    def __init__(self, image_path, parent=None):
        super(DraggableThumbnail, self).__init__(parent)
        self.image_path = image_path
        self.setAcceptDrops(False)

    def mousePressEvent(self, event):
        """Initiates the drag event when the thumbnail is clicked."""
        if event.button() == QtCore.Qt.LeftButton:
            drag = QtGui.QDrag(self)
            mime_data = QtCore.QMimeData()
            mime_data.setText(self.image_path)  # Send image path as part of the drag event
            drag.setMimeData(mime_data)

            # Use a pixmap for the drag visual
            pixmap = self.pixmap()
            drag.setPixmap(pixmap.scaled(50, 50, QtCore.Qt.KeepAspectRatio))

            # Start the drag
            drag.exec_(QtCore.Qt.CopyAction)

class ImageBrowserUI(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ImageBrowserUI, self).__init__(parent)

        # Set the window title
        self.setWindowTitle("Image Browser")

        # Initial path to the elements folder
        self.elements_dir = "D:/symbolss"  # Set default path

        # Create a vertical layout for the window
        self.layout = QtWidgets.QVBoxLayout()

        # Create a path selector
        self.path_selector_layout = QtWidgets.QHBoxLayout()
        self.path_label = QtWidgets.QLabel("Images Directory:")
        self.path_selector_layout.addWidget(self.path_label)

        self.path_input = QtWidgets.QLineEdit(self.elements_dir)
        self.path_selector_layout.addWidget(self.path_input)

        self.browse_button = QtWidgets.QPushButton("Browse")
        self.browse_button.clicked.connect(self.browse_directory)
        self.path_selector_layout.addWidget(self.browse_button)

        self.layout.addLayout(self.path_selector_layout)

        # Create a reload button
        self.reload_button = QtWidgets.QPushButton("Reload Images")
        self.reload_button.clicked.connect(self.reload_elements)
        self.layout.addWidget(self.reload_button)

        # Create a scroll area for thumbnails
        self.scroll_area = QtWidgets.QScrollArea()
        self.scroll_area.setWidgetResizable(True)
        self.scroll_area_widget = QtWidgets.QWidget()
        self.scroll_area.setWidget(self.scroll_area_widget)

        # Create a grid layout for thumbnails
        self.grid_layout = QtWidgets.QGridLayout(self.scroll_area_widget)
        self.grid_layout.setSpacing(10)
        self.grid_layout.setContentsMargins(10, 10, 10, 10)

        self.layout.addWidget(self.scroll_area)

        # Create a widget to preview images
        self.preview_label = QtWidgets.QLabel("Preview")
        self.preview_label.setAlignment(QtCore.Qt.AlignCenter)
        self.layout.addWidget(self.preview_label)

        # Add an image label for previewing images
        self.image_label = QtWidgets.QLabel()
        self.image_label.setAlignment(QtCore.Qt.AlignCenter)
        self.image_label.setFixedHeight(300)  # Set height for preview
        self.layout.addWidget(self.image_label)

        # Create import button
        self.import_button = QtWidgets.QPushButton("Import Image as Read Node")
        self.import_button.clicked.connect(self.import_image_as_read_node)
        self.layout.addWidget(self.import_button)

        # Store the currently selected image path
        self.current_image_path = None

        # Set the layout for the main window
        self.setLayout(self.layout)

        # Load images from the default path or browse if the folder doesn't exist
        if not os.path.exists(self.elements_dir):
            self.browse_directory()
        else:
            self.reload_elements()

    def browse_directory(self):
        """Allows the user to select a new images directory."""
        new_dir = QtWidgets.QFileDialog.getExistingDirectory(self, "Select Images Directory", self.elements_dir)
        if new_dir:
            self.path_input.setText(new_dir)
            self.reload_elements()  # Automatically reload images when directory changes

    def reload_elements(self):
        """Reloads the images from the specified directory."""
        self.elements_dir = self.path_input.text()

        # Check if directory exists before reloading elements
        if not os.path.exists(self.elements_dir):
            QtWidgets.QMessageBox.warning(self, "Directory Not Found", f"The folder '{self.elements_dir}' was not found.")
            return

        # Remove all widgets from the grid layout manually
        for i in reversed(range(self.grid_layout.count())):
            widget = self.grid_layout.itemAt(i).widget()
            if widget is not None:
                widget.deleteLater()

        # Get all images (e.g., jpg, png) from the directory
        image_files = [f for f in os.listdir(self.elements_dir)
                       if f.lower().endswith(('.jpg', '.png', '.jpeg'))]

        # Create thumbnails for each image
        for index, image_file in enumerate(image_files):
            image_path = os.path.join(self.elements_dir, image_file)
            pixmap = QtGui.QPixmap(image_path)
            thumbnail = pixmap.scaled(100, 100, QtCore.Qt.KeepAspectRatio)

            # Create a draggable thumbnail widget
            thumbnail_label = DraggableThumbnail(image_path)
            thumbnail_label.setPixmap(thumbnail)
            thumbnail_label.setToolTip(image_file)  # Show filename on hover

            # Connect the label's click event to the preview function
            thumbnail_label.mousePressEvent = lambda event, path=image_path: self.preview_element(path)

            # Add the thumbnail to the grid layout
            row, col = divmod(index, 5)  # Adjust the number of columns as needed
            self.grid_layout.addWidget(thumbnail_label, row, col)

    def preview_element(self, image_path):
        """Previews the selected image in the preview area."""
        self.current_image_path = image_path
        pixmap = QtGui.QPixmap(image_path)
        self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), QtCore.Qt.KeepAspectRatio))

    def import_image_as_read_node(self):
        """Imports the currently selected image as a Read node in Nuke."""
        if self.current_image_path:
            # Replace backslashes with forward slashes
            normalized_path = self.current_image_path.replace("\\", "/")
            read_node = nuke.createNode("Read")
            read_node["file"].setValue(normalized_path)
        else:
            QtWidgets.QMessageBox.warning(self, "No Image Selected", "Please select an image to import.")

def show_image_browser_ui():
    global image_browser_window  # Keep a reference to the window
    image_browser_window = ImageBrowserUI()
    image_browser_window.show()

# Uncomment the following line if you want to directly run the script in the Script Editor:
show_image_browser_ui()

Leave a Reply

Your email address will not be published. Required fields are marked *