1
$\begingroup$

Created a custom node for image modification. Cannot retrieve the image data in any way from the socket, it's always None. Do you know whats the issue here?

The code:

import bpy


class ImageModifyNode(bpy.types.Node):
    """A custom node"""

    bl_idname = "ImageModifyNode"
    bl_label = "Modify image"
    bl_description = "Modify image by changing colors"

    def init(self, context):
        self.inputs.new("NodeSocketImage", "Image")
        self.inputs.new("NodeSocketColor", "Color 1")
        self.inputs.new("NodeSocketColor", "Color 2")

        self.outputs.new("NodeSocketImage", "Image")

    # Copy function to initialize a copied node from an existing one.
    def copy(self, node):
        print(f"Copying from node {node}")

    # Free function to clean up on removal.
    def free(self):
        print(f"Removing node {self}, Goodbye!")

    def socket_value_update(self, context):
        source_image = self.inputs.get("Image").default_value

        print(f"socket_value_update {source_image=}")

    def update(self):
        source_image = self.inputs.get("Image").default_value
        self.outputs.get("Image").default_value = source_image

        print(f"update {source_image}")


class ImageModifyNodeAdd(bpy.types.Operator):
    """ImageModify node operator"""

    bl_idname = "node.add_image_modify"
    bl_label = "Add modify image node"
    bl_description = "Modify image"
    bl_options = {"REGISTER", "UNDO"}

    def execute(self, context):
        bpy.ops.node.add_node(type=ImageModifyNode.bl_idname)

        return {"FINISHED"}

    def invoke(self, context, event):
        bpy.ops.node.add_node(type=ImageModifyNode.bl_idname)

        return {"FINISHED"}


# -----------------------------------------------------------------------------
# Node menu list


class NodeMenu(bpy.types.Menu):
    """AI node menu container"""

    bl_idname = "NODE_MT_nodes"
    bl_label = "Nodes"

    def draw(self, context):
        layout = self.layout

        layout.operator(ImageModifyNodeAdd.bl_idname)


def add_node_button(self, context):
    self.layout.separator()
    self.layout.menu(NodeMenu.bl_idname, icon="PLUGIN")


classes = (ImageModifyNode, ImageModifyNodeAdd, NodeMenu)


def register():
    for cls in classes:
        bpy.utils.register_class(cls)

    bpy.types.NODE_MT_add.append(add_node_button)


def unregister():
    for cls in classes:
        bpy.utils.unregister_class(cls)

    bpy.types.NODE_MT_add.remove(add_node_button)


if __name__ == "__main__":
    register()

Expected:

enter image description here

Result of code:

enter image description here

$\endgroup$

1 Answer 1

1
$\begingroup$

For future devs experiencing issues. To get values from the parent nodes you need to navigate the node tree using links. Image will be stored not in the socket but on the node itself.

Here is an example code:

class ImageModifyNode(bpy.types.CompositorNodeImage):
"""A custom node"""

bl_idname = "ImageModifyNode"
bl_label = "Modify image"
bl_description = "Modify image by changing colors to the ones which are closest to the provided"

def init(self, context):
    self.inputs.new("NodeSocketImage", "Image")
    self.inputs.new("NodeSocketColor", "Color 1")
    self.inputs.new("NodeSocketColor", "Color 2")

    self.outputs.new("NodeSocketImage", "Image")

def update(self):
    in_socket_image = self.inputs.get("Image")
    out_socket_image = self.outputs.get("Image")

    if in_socket_image.is_linked:
        linked_image = in_socket_image.links[0].from_socket.node.image

        print(linked_image.pixels)
$\endgroup$
4
  • $\begingroup$ Yes, but if you have a node after the image, it will modify the data, but you will still be reading the original image data. So the answer simply is: you can't read the link/socket data in Python, as already explained by me in the other question of yours: blender.stackexchange.com/q/308347/60486 $\endgroup$ Commented Dec 20, 2023 at 19:54
  • $\begingroup$ Could you clarify few things? Not sure if I correctly understand | 1. you can't read the link/socket data in Python - but I was able to receive the image as seen in the example. Flattened image pixels will be printed. | 2. you will still be reading the original image data - what if we create new image in the environment after the modification so we are not referencing the same image? modified_image = bpy.data.images.new("ModifiedImage.png", width, height) $\endgroup$
    – Tadas P42
    Commented Dec 21, 2023 at 9:17
  • $\begingroup$ You're probably using chatGPT which would explain why you don't understand your own code: the only information you get from your link is what nodes it is connected to. No actual information is transferred through the link. $\endgroup$ Commented Dec 21, 2023 at 10:01
  • $\begingroup$ Yes I understand that link is only connector. But using the link we can get to the image node, get the image from that node, make a copy and store it in the data with bpy.data.images.new(). That way we are no longer reading original image $\endgroup$
    – Tadas P42
    Commented Dec 21, 2023 at 10:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .