Python scripts for adding pictureframes, and writing a JSON file?


#1

Hi…,

I would like to write scripts (I am a script newbie) for

  1. adding pictureframes to one layer, e.g. layer “pictureframes”
  • the size (width, height) of the pictureframes should be defined automatically by the width and height of our picture files (PNG)
  • the starting width, height, and filename should be stored with the pictureframe
  1. Write a JSON file
  • collect all pictureframes from our layer and write the added values ( width, height, filename, real location(which we calculate from the 4 edgepoints, rotation, scale factor,…) to a JSON file

So my questions are:

  • Is Python right for this task and where to start?
  • How to open a pictureframe in Python and use the width and height of the picture file? (pixel of PNG should be mm of pictureframe)
  • What’s an easy way to add data (width, hight, name,…) to the pictureframe?
  • How to collect the added data, and write the JSON-file?

Thanks

Michael
www.flexiCAD.com


#2

Hi scripters,

it seams I am on the right track. I have written this little Python script, to answer my first two questions:

import rhinoscriptsyntax as rs
import struct
import imghdr

def get_image_size(fname):
    with open(fname, 'rb') as fhandle:
        head = fhandle.read(24)
        if len(head) != 24:
            return
        if imghdr.what(fname) == 'png':
            check = struct.unpack('>i', head[4:8])[0]
            if check != 0x0d0a1a0a:
                return
            width, height = struct.unpack('>ii', head[16:24])
        elif imghdr.what(fname) == 'gif':
            width, height = struct.unpack('<HH', head[6:10])
        elif imghdr.what(fname) == 'jpeg':
            try:
                fhandle.seek(0) # Read 0xff next
                size = 2
                ftype = 0
                while not 0xc0 <= ftype <= 0xcf:
                    fhandle.seek(size, 1)
                    byte = fhandle.read(1)
                    while ord(byte) == 0xff:
                        byte = fhandle.read(1)
                    ftype = ord(byte)
                    size = struct.unpack('>H', fhandle.read(2))[0] - 2
                # We are at a SOFn block
                fhandle.seek(1, 1)  # Skip `precision' byte.
                height, width = struct.unpack('>HH', fhandle.read(4))
            except Exception: #IGNORE:W0703
                return
        else:
            return
        return width, height

def ToJSON():
    filter = "PNG files (*.png)|*.png"
    filename = rs.OpenFileName("Open PNG file", filter)
    if not filename: return

    width, height = get_image_size(filename)
    
    rs.Command(''.join(['-_PictureFrame ',filename,' _AutoName=_Yes _AlphaTransparency=_Yes 0 ',str(width),',0']))

##########################################################################
# Check to see if this file is being executed as the "main" python
# script instead of being used as a module by some other python script
# This allows us to use the module which ever way we want.
if( __name__ == "__main__" ):
    ToJSON()

I hope to find also answers for these two remaining questions. Happy if someone has an idea.

  • What’s an easy way to add data (width, hight, name,…) to the pictureframe?
  • How to collect the added data, and write the JSON-file?

Thanks

Michael
www.flexiCAD.com


#3

Hi @Michael_Meyer,

Yes :wink: for point 1 you might take a look here, it looks related and has a simple example, but without getting the width and height from the png image. To get this, you might just use this:

import rhinoscriptsyntax as rs
from System.Drawing import Bitmap

def DoSomething():
    filename = rs.OpenFileName("Open", "PNG Files (*.png)|*.png||")
    if not filename: return
    
    bitmap = Bitmap.FromFile(filename)
    if not bitmap: return
    
    print "Width: {}, Height: {}".format(bitmap.Width, bitmap.Height)
    
DoSomething()

You could use rs.SetUserText and rs.GetUserText methods which can be found in the python helpfile.

Just loop trough your picture frame objects once imported and detect them eg. with a name or custom usertext or by layer, collect the info in some lists and write the JSON file. Of course you can read things like width and height from the geometry (or png) directly, i guess even the path to the image can be read from the material texture. Here and here is some info about the json module.

c.


#4

Hi clement,

great, thank you very very much, this helps and motivates a lot :wink:

Michael
www.flexiCAD.com


#5

Hi clement and all,

Rhino Python is great, I’ve got my (simple) task finished, even as a newbie.

Cheers

Michael
www.flexiCAD.com