2
$\begingroup$

I need to invert an image programmatically. However, the command:

bpy.ops.image.invert(invert_r=True, invert_g=True, invert_b=True)

fails with

RuntimeError: Operator bpy.ops.image.invert.poll() failed, context is incorrect

What should I do to make it work?

$\endgroup$

3 Answers 3

5
$\begingroup$

According to this page https://docs.blender.org/api/current/bpy.context.html there are only two possible values for "Image Context": edit_image and edit_mask. And the first one worked for me.

bpy.ops.image.invert({'edit_image': bpy.data.images['texture_name']}, invert_r=True, invert_g=True, invert_b=True))

Or the currently recommended way (without a deprecation warning):

with bpy.context.temp_override(**{'edit_image': bpy.data.images['texture_name']}):
    bpy.ops.image.invert(invert_r=True, invert_g=True, invert_b=True)

Probably, the same technique can be used with other image operators, and edit_image allows us to "select" an image we want to edit.

$\endgroup$
1
  • 1
    $\begingroup$ Thanks for the answer ! Maybe a bit easier to read, instead of unpacking a dictionary inside the arguments : with bpy.context.temp_override(edit_image=bpy.data.images['texture_name']): does the same thing $\endgroup$
    – Gorgious
    Commented Feb 2, 2023 at 17:53
3
$\begingroup$
import bpy

image = bpy.data.images.get(name) # name = image.name
override = bpy.context.copy()
override["edit_image"] = image
bpy.ops.image.invert(override, invert_r=True, invert_g=True, invert_b=True)
$\endgroup$
2
$\begingroup$

Stumbled upon a numpy implementation that doesn't require using an operator : https://blender.stackexchange.com/a/208589/86891

import bpy
import numpy

def invert(image, invert_r = False, invert_g = False, invert_b = False, invert_a = False):
    pixels = numpy.empty(len(image.pixels), dtype=numpy.float32)
    image.pixels.foreach_get(pixels)
    if invert_r: 
        pixels[0::4] = 1 - pixels[0::4]
    if invert_g: 
        pixels[1::4] = 1 - pixels[1::4]
    if invert_b: 
        pixels[2::4] = 1 - pixels[2::4]
    if invert_a: 
        pixels[3::4] = 1 - pixels[3::4]
    image.pixels.foreach_set(pixels)

image = bpy.data.images["Untitled.png"]
invert(image, invert_r=True, invert_g=True, invert_b=True)
image.update()

$\endgroup$

You must log in to answer this question.

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