10
$\begingroup$

This script in the Python console:

>>> pixels = D.images[-1].pixels
>>> len(pixels)
8294400

>>> for i in range(64):
...     dummy = pixels[i]
...
>>>

takes over two seconds to run the for loop.

However, running pixels = [0 for i in range(len(pixels))] before the for loop causes the script to finish instantly.

What's going on with the Blender Python image pixel access, and how can I speed it up?

$\endgroup$
1
  • 1
    $\begingroup$ I just tested CoDEmanX's code in blender2.71 and this does not work. pixels=img.pixels[:] returns a tuple which is not editable. I had to use list(img.pixels) to do some pixel tweaking. $\endgroup$
    – Greg
    Sep 12, 2014 at 13:41

1 Answer 1

14
$\begingroup$

.pixels is a python object and pretty slow, especially if you change pixels. That is 'cause the entire buffer / python object is re-created for every single change (if you do it in a python loop). Not sure why it's that slow on read-only actions though...

You can speed it up tremendously if you cast it to a native python type (tuple) and use that copy instead:

img = bpy.data.images['Untitled']

pixels = img.pixels[:] # create a copy (tuple) for read-only access
# -- OR --
pixels = list(img.pixels) # create an editable copy (list)

# Use the tuple object, which is way faster than direct access to Image.pixels
for i in range(0, len(pixels), 4):
    pixels[i] = 1.0 - pixels[i] # invert red channel

# Write back to image.
# Slice notation here means to replace in-place, not sure if it's faster...
img.pixels[:] = pixels

# Should probably update image
img.update()
$\endgroup$
4
  • $\begingroup$ Thanks. I was casting with list(img.pixels) for temporary speedup, but this looks better. As a side note, would random access to this pixels = img.pixels[:] be decently fast? $\endgroup$
    – wchargin
    Nov 3, 2013 at 23:51
  • $\begingroup$ You can use a tuple copy if you need to read pixel values only, and cast to list if it needs to be editable. Both variants are very fast, and writing a modified copy back to Image.pixels is performing well too. Only direct access to .pixels is extremely slow. $\endgroup$
    – CodeManX
    Jul 20, 2015 at 12:33
  • $\begingroup$ Legendary comment, wow. 10 years old and still applies. I'm using it to set an asset browser thumbnail, which took like 5 seconds for a 128x128 image before, but is now instant. Using the slice notation on asset.preview.image_pixels_float is MOST DEFINITELY faster. Thank you so much. edit: 10 years EXACTLY ha. $\endgroup$
    – MACHIN3
    Nov 3, 2023 at 18:29
  • $\begingroup$ @MACHIN3 Cheers, glad it's still helpful. It's somewhat unreal to get notifications about posts I have long forgotten about. Kudos on the timing as well! $\endgroup$
    – CodeManX
    Nov 3, 2023 at 21:35

You must log in to answer this question.

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