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
    Feb 2 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$
1
$\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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.