2
$\begingroup$

I need to invert an image running blender from the command line using the -background flag. To archive it I need to make the image active and later apply the invert operator.

I managed to select and invert the image with Blender running the UI, with the following code:

# Select the active image
m = bpy.context.area.type
bpy.context.area.type = "IMAGE_EDITOR"
bpy.context.area.spaces.active.image = myImageToInvert

# Operate over the selected image
bpy.ops.image.invert(invert_r=True, invert_g=True, invert_b=True)

But this code does not run when Blender is called from the command line with the -background flag, because the UI is not loaded so bpy.context.area is null.

How can I select the image (myImageToInvert) in the background so bpy.ops.image.invert() can operate over my image?

Thank you

$\endgroup$
3
  • $\begingroup$ Is this the only operator you'd like to use? Otherwise you might want to invert the image using image magic: superuser.com/questions/1194468/invert-colors-with-imagemagick ...? $\endgroup$
    – brockmann
    Commented Dec 14, 2020 at 8:44
  • 1
    $\begingroup$ if this is just an external program or a python script use ffmpeg or other libraries instead of bpy $\endgroup$ Commented Dec 14, 2020 at 12:42
  • $\begingroup$ Is more about the control of Blender's internally selected image. Is common to have to apply other Blender Operators over the selected image as bpy.ops.image.pack()... So I can automate all the pipeline, not just the invert process. $\endgroup$ Commented Dec 15, 2020 at 1:28

2 Answers 2

4
+25
$\begingroup$

(Edit) Deleted 1. Solution

2. Solution This code inverts, the color of a picture. Maybe a bit slower than the Operator but not by much.

It's use bpy.data so you have to input the name of the picture to get it.

import bpy

def invert(image, invert_r = True, invert_g = True, invert_b = True, invert_a = True):
    pixels = list(image.pixels)
    if invert_r: 
        for i in range(0, len(pixels), 4): # R
            pixels[i] = 1 - pixels[i]
    if invert_g:
        for i in range(1, len(pixels), 4): # G
            pixels[i] = 1 - pixels[i]
    if invert_b:
        for i in range(2, len(pixels), 4): # B
            pixels[i] = 1 - pixels[i]
    if invert_a:
        for i in range(3, len(pixels), 4): # A
            pixels[i] = 1 - pixels[i]
    image.pixels = pixels
            
#Example           
image = bpy.data.images['Untitled']     
invert(image, invert_a = False)

You could also use this code to input a sequence of images (exchange this with the code after #Example).

images = ['Untitled', 'Untitled.001']
for image in images:
    invert(image, invert_a = False)
$\endgroup$
4
  • $\begingroup$ As explained in question in background mode context.area is None hence method 1 above is also out. $\endgroup$
    – batFINGER
    Commented Dec 14, 2020 at 18:37
  • $\begingroup$ A sorry, missed that $\endgroup$ Commented Dec 14, 2020 at 19:43
  • 1
    $\begingroup$ #2 is significantly slower/more memory-hungry than the operator. You can speed it up a bit with numpy/foreach. Something like this. $\endgroup$
    – scurest
    Commented Dec 14, 2020 at 21:35
  • $\begingroup$ Thank you for your answer, but this solution (#2) still leaves the image unselected for bpy.ops.image.invert() and all other operators, so any other operation should be re-implemented. There is no way to simply select the image data so Blender can use it? $\endgroup$ Commented Dec 15, 2020 at 1:32
0
$\begingroup$
win = bpy.context.window_manager.windows[0]
area = win.screen.areas[0]
area.type = "IMAGE_EDITOR"
override = bpy.context.copy()
override['window'] = win
override['screen'] = win.screen
override['area'] = win.screen.areas[0]
override['area'].spaces.active.image = bpy.data.images['Untitled']

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

I have this as another solution, but Blender always crash with an exception_access_violation if the operator get called. If somebody has a solution for this it would probably work.

$\endgroup$
1
  • $\begingroup$ This solution still relies in the UI so running in background mode will crash. $\endgroup$ Commented Dec 28, 2020 at 1:53

You must log in to answer this question.

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