31

I'm currently trying to extract textures from a binary file, and ideally I'd like to save each texture to a file or embed in the .blend file. However, before saving an image, I need to be able to create an image in memory from an array of pixel data.

The PIL library contains the kinds of functions I need to use, but it is not included with Blender. Is there anything similar to PIL in Blender? bpy.ops.image seems to be close to what I need, but lacks necessary pixel set/manipulation functions.

MrFlamey
  • 3,839
  • 11
  • 38
  • 54

2 Answers2

50

Yes its possible, heres an example

size = 640, 480

import bpy
# blank image
image = bpy.data.images.new("MyImage", width=size[0], height=size[1])

## For white image
# pixels = [1.0] * (4 * size[0] * size[1])

pixels = [None] * size[0] * size[1]
for x in range(size[0]):
    for y in range(size[1]):
        # assign RGBA to something useful
        r = x / size[0]
        g = y / size[1]
        b = (1 - r) * g
        a = 1.0

        pixels[(y * size[0]) + x] = [r, g, b, a]

# flatten list
pixels = [chan for px in pixels for chan in px]

# assign pixels
image.pixels = pixels

# write image
image.filepath_raw = "/tmp/temp.png"
image.file_format = 'PNG'
image.save()

output of script

ideasman42
  • 47,387
  • 10
  • 141
  • 223
  • With this technic is it possible to save the image with RGBA I made some test but I can't find how to do it directly with python? – lucblender Dec 20 '15 at 10:48
  • Do you mean doing this from regular Python? (which would work outside of Blender for example) – ideasman42 Dec 20 '15 at 12:57
  • Nop inside of blender, I find the answer by myself. I can use image.save_render(...) instead of image.save() and it will take the render parameter – lucblender Dec 20 '15 at 13:10
  • If you want to save PNG images without using Blender's API, see this answer: http://stackoverflow.com/questions/902761/saving-a-numpy-array-as-an-image/19174800#19174800 – ideasman42 Aug 27 '16 at 01:48
  • A question was asked what is chan for in the line pixels = [chan for px in pixels for chan in px] - the line is an equivalent to pixels = [] \n for chan in px: \n\t for px in pixels: \n\t\t pixels.append(px) where \n and \t mean a newline and a tab. – Markus von Broady Feb 13 '22 at 20:03
  • If I have an array of pixels, can I copy data directly instead of running an expensive loop in python? – user877329 Dec 11 '22 at 15:30
  • @user877329 this should be a separate question. – ideasman42 Dec 13 '22 at 04:21
2

enter image description here

And this is if we are using Sverchok Add-On and nodes in Sverchok. I am translating IdeasMan42 example. Neat.

Blender Sushi Guy
  • 1,491
  • 11
  • 18