Python script simplification

Issue

I created this python script to replace images in a psd file, but I feel that I am repeating the same code and was looking to simplify it, since I have more instances of "groups", I just pasted 2 here to make it shorter. Here is the ps file screenshot.

photoshop file screenshot

Thank you for your time.

import win32com.client

#Open Adobe Photoshop App programmatically and locate PSD file
ps = win32com.client.Dispatch("Photoshop.Application")

mainPsd = ps.Open("C:/Users/Admin/Documents/images/edit_tiling_wall.psd")


#group 5 copy
mainGrp = mainPsd.layerSets[0]

#all grps in main group
allLayerSets = mainPsd.layerSets[0].layerSets


#function to resize

def resize(layer,w,h):
    w_max = w
    h_max = h
    bounds = layer.bounds
    w = bounds[2] - bounds[0]
    h = bounds[3] - bounds[1]
    #print(w,h)
    diffw = w_max - w
    diffh = h_max - h
    #print(diffw,diffh)
    aumw = diffw + w
    aumh = diffh + h
    #print(aumw,aumh)
    moltw = 100*aumw/w
    molth = 100*aumh/h
    #print(moltw,molth)

    layer.Resize(moltw,molth)

    bounds = layer.bounds
    w = bounds[2] - bounds[0]
    h = bounds[3] - bounds[1]
    return w,h


def translate(doc,layer,goalX,goalY):

    bounds = layer.bounds
    w = bounds[2] - bounds[0]
    h = bounds[3] - bounds[1]
    posX = doc.width - round(doc.width - (bounds[0] + w / 2))
    posY = doc.height - round(doc.height - (bounds[1] + h / 2))

    layer.Translate(goalX-posX,goalY-posY)

    bounds = layer.bounds
    w = bounds[2] - bounds[0]
    h = bounds[3] - bounds[1]
    posX = doc.width - round(doc.width - (bounds[0] + w / 2))
    posY = doc.height - round(doc.height - (bounds[1] + h / 2))
    return posX, posY



for grp in allLayerSets:

    # filter first type of texture
    if grp.name.startswith('Group 1'):

        print ( grp.name )
        print ( grp.artLayers[-1].name ) #base layer name

        # base layer
        baseLayer = grp.artLayers[-1]

        #get width and height of base layer
        boundsLayer = baseLayer.bounds
        w = boundsLayer[2] - boundsLayer[0]
        h = boundsLayer[3] - boundsLayer[1]

        print(w,h)


        #get position(center of layer img) of base layer
        posX = mainPsd.width - round(mainPsd.width - (boundsLayer[0] + w / 2))
        posY = mainPsd.height - round(mainPsd.height - (boundsLayer[1] + h / 2))

        print( posX, posY )

        # new image to add
        newTexture = "C:/CG_CONTENT/TEXTURES/Wall_v2_height.exr"

        newHeightMap = ps.Open(newTexture)

        newHeightMap_layer = newHeightMap.ArtLayers.Item(1)
        newHeightMap_layer.Copy() 
        newHeightMap.Close(2)

        # Set as active image in Photoshop
        ps.ActiveDocument = mainPsd          

        # Paste 'newHeightMap' image from clipboard 
        pasted = mainPsd.Paste()

        currentLayer = mainPsd.activeLayer

        # Move the pasted layer to the correct grp
        currentLayer.Move(grp, 1)

        # resize in pixels the new texture
        resize(currentLayer, w, h)

        # IS IT FLIPPED HORIZONTALLY OR VERTICALLY? MAYBE ADD A TAG TO FLIPPED LAYERS?
        if baseLayer.name.endswith('_x'):

            # flip horizontal
            currentLayer.Resize(-100,100)

        elif baseLayer.name.endswith('_y'): 

            # flip vertical
            currentLayer.Resize(100,-100)


        elif baseLayer.name.endswith('_x_n_y'): 

            # flip horizontal and vertical
            currentLayer.Resize(-100,-100)

        #translate the texture to position
        translate(mainPsd,currentLayer,posX,posY)

        baseLayer.visible = False



    # filter first type of texture
    elif grp.name.startswith('Group 2'):

        print ( grp.name )
        print ( grp.artLayers[-1].name ) #base layer name

        # base layer
        baseLayer = grp.artLayers[-1]


        #get width and height of base layer
        boundsLayer = baseLayer.bounds
        w = boundsLayer[2] - boundsLayer[0]
        h = boundsLayer[3] - boundsLayer[1]

        print(w,h)


        #get position(center of layer img) of base layer
        posX = mainPsd.width - round(mainPsd.width - (boundsLayer[0] + w / 2))
        posY = mainPsd.height - round(mainPsd.height - (boundsLayer[1] + h / 2))

        print( posX, posY )

        # new image to add
        newTexture = "C:/CG_CONTENT/TEXTURES/Wall_v3_height.exr"

        newHeightMap = ps.Open(newTexture)

        newHeightMap_layer = newHeightMap.ArtLayers.Item(1)
        newHeightMap_layer.Copy() 
        newHeightMap.Close(2)

        # Set as active image in Photoshop
        ps.ActiveDocument = mainPsd          

        # Paste 'newHeightMap' image from clipboard 
        pasted = mainPsd.Paste()

        currentLayer = mainPsd.activeLayer

        # Move the pasted layer to the correct grp
        currentLayer.Move(grp, 1)

        # resize in pixels the new texture
        resize(currentLayer, w, h)

        # IS IT FLIPPED HORIZONTALLY OR VERTICALLY? MAYBE ADD A TAG TO FLIPPED LAYERS?
        if baseLayer.name.endswith('_x'):

            # flip horizontal
            currentLayer.Resize(-100,100)

        elif baseLayer.name.endswith('_y'): 

            # flip vertical
            currentLayer.Resize(100,-100)

        elif baseLayer.name.endswith('_both'): 

            # flip horizontal and vertical
            currentLayer.Resize(-100,-100)  

        #translate the texture to position
        translate(mainPsd,currentLayer,posX,posY)

        baseLayer.visible = False

Solution

I pasted your branches in a comparison software, and they are really almost identical.

enter image description here

The only differences are:

enter image description here

Which can be easily stored in a two variables, let’s call them texture_name and ending_name. Both will be a string.

Hence here is how I would refactor your code:

for grp in allLayerSets:
    #[ ... ]
    texture_name = ""
    ending_name = ""
   
    if grp.name.startswith('Group 1'):
       texture_name = "Wall_v2_height.exr"
       ending_name = "_x_n_y"
    elif grp.name.startswith('Group 2'):
       texture_name = "Wall_v3_height.exr"
       ending_name = "_both"
    else:
       print("Deal with this problem")

    # Now the code will be just one. 

    # [ ... ]
    newTexture = "C:/CG_CONTENT/TEXTURES/" + texture_name 
    
    # [ ... ]
    elif baseLayer.name.endswith(ending_name):

See how we have used the variables in your big chunk of code? But we write it only once!

Answered By – Fra93

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published