2

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?

Peter Mortensen
  • 681
  • 4
  • 11
RussCoder
  • 241
  • 1
  • 4

3 Answers3

5

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.

RussCoder
  • 241
  • 1
  • 4
  • 1
    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 – Gorgious Feb 02 '23 at 17:53
3
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)
Gorgious
  • 30,723
  • 2
  • 44
  • 101
Karan
  • 1,984
  • 5
  • 21
1

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()

Gorgious
  • 30,723
  • 2
  • 44
  • 101