2
$\begingroup$

I would like to automate the setting of a scene. I would like the image i will render has the exact same size of an image I import with the built-in add-on "import image as a plane".

For the moment, I import the image manually, but in the future I would like to wrap up in an addon... (but I'm not confident enough to write the addon right now, so let's go manually!).

First attempt

Here is what I began to write, but it seems it's going nowhere... My strategy is to identify the name of the material created when the plane is generated, find the name of the picture I imported, and then get its size...

import bpy

# use "Import image as plane"

# get the material's name of the selected object
mat = bpy.context.selected_objects[0].active_material
tex = mat.texture_paint_slots.data.name


size_x = mat.texture_paint_images['<image name>'].size[0]
size_y = mat.texture_paint_images['<image name>'].size[1]

# set render size
bpy.context.scene.render.resolution_x = size_x
bpy.context.scene.render.resolution_y = size_y

Second attempt

I am able to find the material created with the image imported as a plane. So I am looking inside this material the Image Texture. It seems to be much more clean as the first attempt.

import bpy

# identify the picture we just imported
texture = []
for ob in bpy.data.objects:
    if ob.type == "MESH":
        for mat_slot in ob.material_slots:
            if mat_slot.material:
                if mat_slot.material.node_tree:
                    texture.extend([x for x in mat_slot.material.node_tree.nodes if x.type=='TEX_IMAGE'])
pic_size = print(texture[0])

# get the size of the imported picture
size_x = pic_size.size[0]
size_y = pic_size.size[1]

# set render size
bpy.context.scene.render.resolution_x = size_x
bpy.context.scene.render.resolution_y = size_y

But something is wrong...

Thank you for your help!

$\endgroup$
1
  • $\begingroup$ For the moment, I import the image manually, but in the future I would like to wrap up in an addon... (but I'm not confident enough to write the addon right now, so let's go manually). $\endgroup$
    – ValiGrimO
    Apr 22, 2022 at 12:52

2 Answers 2

2
$\begingroup$

I'm not sure what problem you are having but this code will import an image as plane, bypass the need to find the image from the shader, and set the render resolution for the current scene to match the image:

import bpy
from pathlib import Path

image_file = Path("c:\\tmp\\0001.png")
bpy.ops.import_image.to_plane(files=[{'name':str(image_file)}])

image = bpy.data.images[image_file.name]

bpy.context.scene.render.resolution_x = image.size[0]
bpy.context.scene.render.resolution_y = image.size[1]

All you need do is replace "c:\tmp\0001.png" in the call to Path with whatever filename you want for the image.

EDIT: I've made a few changes to your solution. The biggest change is a small bug fix: your code will attempt to change the render resolution even if it never finds the plane with the image. Another change is that this version uses the first instance it finds that matches where yours will use the last. The final change is to rely on the fact I mentioned in a comment on your answer: images on planes always creates the material in the first material slot.

def change_resolution():
    """ Change the resoultion to match the first image texture found.
        This searches for image textures in mesh materials.  It assumes
        that the first material found that has an image texture has
        the image we mean to size to.
        Does nothing if no such image texture is found.
    """
    for obj in bpy.data.objects:
        if obj.type == 'MESH' and obj.material_slots and obj.material_slots[0].material:
            for node in obj.material_slots[0].material.node_tree.nodes:
                if node.type == 'TEX_IMAGE':
                    bpy.context.scene.render.resolution_x = node.image.size[0]
                    bpy.context.scene.render.resolution_y = node.image.size[1]
                    print("new resolution = ", node.image.size[0], node.image.size[1])
                    return

change_resolution()

You should definitely accept your own answer; this is just to show an alternative.

$\endgroup$
1
  • 1
    $\begingroup$ Thank you! I keep your solution as a reminder for a next version of my work :) It seems cleaner and more effective when integrated in a plugin. For the moment, I plane to run some scripts :) $\endgroup$
    – ValiGrimO
    Apr 22, 2022 at 17:23
2
$\begingroup$

I have the solution!

import bpy

# Get the size of imported image
for ob in bpy.data.objects:
    if ob.type == "MESH":
        for mat_slot in ob.material_slots:
            if mat_slot.material:
                if mat_slot.material.node_tree:
                    for x in mat_slot.material.node_tree.nodes:
                        if x.type=='TEX_IMAGE':
                            size_x = x.image.size[0]
                            size_y = x.image.size[1]

# set render size
bpy.context.scene.render.resolution_x = size_x
bpy.context.scene.render.resolution_y = size_y
$\endgroup$
1
  • 1
    $\begingroup$ You can simplify this. Images as Planes always puts the material it creates in material_slots[0] so you don't have to search the material slots. $\endgroup$ Apr 22, 2022 at 17:30

You must log in to answer this question.

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