RhinoScriptSyntax.AddPictureFrame() FilePath issue

when calling rs.AddPictureFrame(plane, path, size[0], size[1], use_alpha = True) uing python3 in GH rhino8, i got the following exception:

Traceback (most recent call last):
File “rhinocode:///grasshopper/1/f4f105bb-6ee7-4f13-a2b3-dc7b8652bf87/c59d8042-f099-416c-af12-ce53ee2b548e”, line 121, in
File “rhinocode:///grasshopper/1/f4f105bb-6ee7-4f13-a2b3-dc7b8652bf87/c59d8042-f099-416c-af12-ce53ee2b548e”, line 67, in InsertHero
File “C:\Users\Steven.rhinocode\py39-rh8\site-rhinopython\rhinoscript\geometry.py”, line 90, in AddPictureFrame
if type(filename) is not System.String or not System.IO.File.Exists(filename): raise Exception(‘"{0}" does not exist or is not a file name’.format(filename))
Exception: “C:\Users\Steven\Desktop\xxxxxxx\Arcosanti\png_BW\cropped\0.png” does not exist or is not a file name

I’m very sure that “C:\Users\Steven\Desktop\xxxxxxx\Arcosanti\png_BW\cropped\0.png” exists. Any clue what could have caused this?

if i do

cmd = "_-Picture " + path + " " + “{},{},{}”.format(pt1[0],pt1[1],pt1[2]) + " " + “{},{},{}”.format(pt2[0],pt2[1],pt2[2]) + " " + “_EnterEnd”
rs.Command(cmd,True)

It works perfectly. Just wonder why rs.AddPictureFrame() behave differently?

Hi @Shengtao_Xia,

Can you post the script that throws the exception in Python3?

Thanks,

– Dale

Below is the code that currently works for me, rs.AddPictureFrame() is at line 78 and 99 which have been commented out
Is it meant to automatically layout a lot of images with discriptions and etc.
root recieve data from gh text (a path to my data folders)

# requirements: numpy
# requirements: pillow
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc
import math
import os
import numpy as np
import System.Drawing as Drawing
from PIL import Image
import textwrap



# Store the current document
ghdoc = sc.doc
# Switch to Rhino document context to insert the block
sc.doc = Rhino.RhinoDoc.ActiveDoc

def rename_space(input_path):
    output_path = input_path.replace(" ","")
    os.rename(input_path, output_path)
    return output_path

def webp_to_jpg(input_path):
    output_path = os.path.splitext(input_path)[0] + ".jpg"
    Image.open(input_path).convert("RGB").save(output_path, "JPEG")
    if os.path.exists(input_path):
        os.remove(input_path)
    return output_path

def crop_to_square(input_path):
    # Open the image
    img = Image.open(input_path)
    
    # Get image dimensions
    width, height = img.size
    
    # Determine the shortest dimension and calculate crop dimensions
    new_size = min(width, height)
    left = (width - new_size) / 2
    top = (height - new_size) / 2
    right = (width + new_size) / 2
    bottom = (height + new_size) / 2
    
    # Crop the image to the calculated box
    img_cropped = img.crop((left, top, right, bottom))
    
    directory = os.path.dirname(input_path)
    cropped_directory = os.path.join(directory, "cropped")
    os.makedirs(cropped_directory, exist_ok=True)
    
    # Define the output path as a PNG in the cropped folder
    file_root = os.path.splitext(os.path.basename(input_path))[0]
    output_path = os.path.join(cropped_directory, f"{file_root}.png")
    
    # Save the cropped image as PNG
    img_cropped.save(output_path, "PNG")
    return output_path

def InsertImage(path,centre):
    FRAMESIZE = 6
    bitmap = Drawing.Bitmap(path)
    size = np.array((bitmap.Width, bitmap.Height))
    
    size = size * FRAMESIZE / np.max(size)

    try:
        pt1 = centre + np.array((-size[0]/2,size[1]/2,0))
        pt2 = centre + np.array((size[0]/2,-size[1]/2,0))
        cmd = "_-Picture " + path + " " + "{},{},{}".format(pt1[0],pt1[1],pt1[2]) + " " + "{},{},{}".format(pt2[0],pt2[1],pt2[2]) + " " + "_EnterEnd"
        rs.Command(cmd,True)
        guid = rs.LastCreatedObjects()[0]
    except:
        guid = None

    '''plane = rs.MovePlane(rs.WorldXYPlane(), centre - np.array((size[0],size[1],0)))
    guid = rs.AddPictureFrame(plane, path, size[0], size[1], use_alpha = True)'''
    return guid

def InsertHero(path,centre):
    FRAMESIZE = 20
    path = crop_to_square(path)
    bitmap = Drawing.Bitmap(path)
    size = np.array((bitmap.Width, bitmap.Height))
    
    size = size * FRAMESIZE / np.min(size)

    try:
        pt1 = centre + np.array((-size[0]/2,size[1]/2,0))
        pt2 = centre + np.array((size[0]/2,-size[1]/2,0))
        cmd = "_-Picture " + path + " " + "{},{},{}".format(pt1[0],pt1[1],pt1[2]) + " " + "{},{},{}".format(pt2[0],pt2[1],pt2[2]) + " " + "_EnterEnd"
        rs.Command(cmd,True)
        guid = rs.LastCreatedObjects()[0]
    except:
        guid = None

    '''plane = rs.MovePlane(rs.WorldXYPlane(), centre - np.array((size[0],size[1],0)))
    guid = rs.AddPictureFrame(plane, path, size[0], size[1], use_alpha = True)'''
    return guid

TYPE_ICON = np.array((4,18,0))
STATUS_ICON = np.array((2,13,0))
PROGRAM_ICON = np.array((4,13,0))
SCALE_ICON = np.array((6,13,0))
IMAGESTART = np.array((32,18,0))
HERO = np.array((18,11,0))
TITLE = np.array((0,23,0))
DCSP = np.array((1.5,10.5,0))
DCSP2 = np.array((1.5,13.5,0))

root_path = root
item_count = 0

for content_folder_name in os.listdir(root_path):

    image_paths = []
    path = os.path.join(root_path, content_folder_name)
    folder_path = path
    meta_path = path + "\meta.txt"
    supported_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff", ".jfif"]
    webp = [".webp"]

    base = np.array((0,item_count * 30,0))
    item_count += 1

    for file_name in os.listdir(folder_path):
        # Get full path
        file_path = os.path.join(folder_path, file_name)
        
        # Check if the file is an image
        if os.path.isfile(file_path) and os.path.splitext(file_name)[1].lower() in supported_extensions:
            image_paths.append(rename_space(file_path))
        elif os.path.isfile(file_path) and os.path.splitext(file_name)[1].lower() in webp:
            image_paths.append(rename_space(webp_to_jpg(file_path)))
        

    with open(meta_path, 'r', encoding='utf-8', errors='replace') as meta:
        lines = meta.read().splitlines()
        content_name = lines[0]
        content_type = lines[1]
        content_status = lines[2]
        content_program = lines[3]
        content_scale = lines[4]
        content_dcsp = lines[5]

    group_name = rs.AddGroup(content_name)

    rs.AddObjectsToGroup(
        [
            rs.InsertBlock(content_type,base + TYPE_ICON),
            rs.AddText(content_name, base + TITLE, height = 1.5, justification = 131073)
        ],
        group_name
    )

    if content_type == 'Project':

        frame_width = (len(image_paths)-2)//3

        rs.AddObjectsToGroup(
            [
                rs.AddRectangle(rs.MovePlane(rs.WorldXYPlane(), base), 29 + (frame_width + 1) * 7, 22),
                rs.AddText(textwrap.fill(content_dcsp, width = 30), base + DCSP, height = .25, justification = 262145),
                rs.InsertBlock(content_status, base + STATUS_ICON),
                rs.InsertBlock(content_program, base + PROGRAM_ICON),
                rs.InsertBlock(content_scale, base + SCALE_ICON),
                rs.InsertBlock('HeroFrame', base),
                rs.InsertBlock('ProgramFrame', base),
                rs.InsertBlock('ProgramDcspFrame', base),
                InsertHero(image_paths[0], base + HERO)
            ],
            group_name
        )
        i_x, i_y = 0,0
        for image_path in image_paths[1:]:
            rs.AddObjectsToGroup(
                [
                    #rs.InsertBlock('ImageFrame', base + IMAGESTART + np.array((7 * i_x, -7 * i_y, 0))),
                    InsertImage(image_path, base + IMAGESTART + np.array((7 * i_x, -7 * i_y, 0)))
                ],
                group_name
            )
            i_x += 1
            if i_x > frame_width:
                i_y += 1
                i_x = 0

    else:
        rs.AddObjectsToGroup(
            [
                rs.AddRectangle(rs.MovePlane(rs.WorldXYPlane(), base), 29, 22),
                rs.AddText(textwrap.fill(content_dcsp, width = 30), base + DCSP2, height = .25, justification = 262145),
                rs.InsertBlock('HeroFrame', base),
                rs.InsertBlock('ProgramDcspFrame2', base),
                InsertHero(image_paths[0], base + HERO)
            ],
            group_name
        )

Hi @Shengtao_Xia,

I am able to repeat the issue. I’ve created a ticket so a developer can investigate.

https://mcneel.myjetbrains.com/youtrack/issue/RH-84502

In the mean time, you might consider calling ObjectTable.AddPictureFrame directly, rather than through rhinoscriptsyntax.

test_pictureframe.py (1.1 KB)

– Dale

2 Likes

Thank you