0
$\begingroup$

So an addon I am working on is generating a new sequence of images using numpy. My question is, what would be the best approach to saving them to disk? Python packages like imageio and PIL are not installed with Blender, so calling those raises an error for me.

I'd rather not have each image listed in the Blender file (ie, bpy.data.images having 'image01', 'image02', ... entries) unless they could all be combined as one image sequence entry of 'image##', for example. Otherwise, is there a way I could programmatically save each image to disk?

$\endgroup$
1
  • $\begingroup$ I have a similiar problem. I loaded opencv, but even using foreach_get() seems to be slow. What did you try? $\endgroup$
    – Leander
    Commented Sep 5, 2021 at 11:38

1 Answer 1

0
$\begingroup$

In summary, I just saved it within Blender, used its API to save, then removed the image. Here's my sample code:

def execute(self, context):       
    C = context.scene
    D = bpy.data
    movie_clip = D.movieclips[C.sm_src_mov]


    viewer_area = # ...get viewer area
    viewer_space = # ... get viewer space
    # ...get and set space and area

    def get_np_pixels(img):
        return np.array(img.pixels).reshape(img.size[0], img.size[1], 4)
    
    movie_image = D.images.load(movie_clip.filepath)
    w, h = movie_image.size
    viewer_space.image = movie_image
    ref_img = get_np_pixels(D.images[C.sm_ref_img])[:,:,:3]

    # get new filename
    filepath = C.sm_mov_export_filepath
    filepath = getFilePath(C.sm_mov_export_filepath, C.sm_src_mov)
    file_ext = C.sm_mov_export_format

    #the frame_offset property starts at 0 index, so first frame is actually 0
    frame = C.sm_start_frame - 1

    from math import log10, floor
    digit_mask_size = 1 + floor(log10(C.sm_end_frame))

    viewer_space.image_user.frame_duration = movie_clip.frame_duration
    for frame in range(frame, C.sm_end_frame):  
        viewer_space.image_user.frame_current = frame
        #switch back and forth to force refresh
        viewer_space.display_channels = 'COLOR'
        viewer_space.display_channels = 'COLOR_ALPHA'

        # add frame number to file name
        seq_filepath = seq_filename(filepath, file_ext.lower(), frame, digit_mask_size)
        
        result = # create 4 channel image and reshape to 1D
        
        bpy_image = D.images.new(str(frame), width=w, height=h, float_buffer=True, alpha=True)
        bpy_image.pixels = result
        bpy_image.file_format = file_ext
        bpy_image.filepath_raw = seq_filepath
        bpy_image.save()
        D.images.remove(bpy_image, do_unlink=True)
    
    # reset area and space...
        
    D.images.remove(movie_image)

    return {'FINISHED'}
$\endgroup$

You must log in to answer this question.

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