skip to Main Content

My goal is to define scale bars programmatically, that have a fixed length, but may be changed afterwards by the graphic designer.

I have come sofar as to define a closed path within the document:

def addLine(doc):
    
    def point(x, y):
        result      = Dispatch("Photoshop.PathPointInfo")
        result.Kind = 2 # for PsPointKind --> 2 (psCornerPoint)
        result.LeftDirection = result.rightDirection = result.Anchor = (x, y)
        return result

    points = [    
              point(100, 100),
              point(200, 100),
              point(200, 110),
              point(100, 110)
              ]

    lineSubPathArray               = Dispatch("Photoshop.SubPathInfo")
    lineSubPathArray.Operation     = 1 #for PsShapeOperation --> 1 (psShapeAdd
    lineSubPathArray.Closed        = True
    lineSubPathArray.EntireSubPath = points
    
    myPathItem = doc.PathItems.Add("bar-path", [lineSubPathArray])

From here, I can load the saved document back into photoshop (CS6) and then create a shape layer manually: Layer | New fill layer | solid color …

This results in a shape layer, similar to what I get by using the line tool, in which the line effectively is a rectangle whose height may be changed later.

First question: how to create the fill layer by using the API?

Second: I defined a rectangle 100pixels wide, but I get one 418 pixels wide. The doc has its doc.application.preferences.rulerUnits set to psPixels (1). Why is this?

Last: Isn’t it possible to define a line as true line defined by two end points and set its stroke width instead of it’s height?

2

Answers


  1. Chosen as BEST ANSWER

    There are two lessons I have learned form translating the solution by Ghoul Fool into Python:

    1. using COM in python, one can make a lot of mistakes that go unnoticed, otherwise than cryptic error messages far beside the point. Thies include syntactic errors such as missing/redundant parentheses and wrong capitalisation.
    2. solutions that work with COM in python do not work the same with the Python-Photoshop-API and vice versa, even though, following the source code of the library, apparently exactly the same thing is happening. I have not always been able to divine solutions that work both ways.

    Here is, for those who have come to this question later, what I have come to to get a shape layer with a bar that can be changed in height afterwards. The action that is called is nothing more than a recording of New Fill Layer from the layer-menu (CS6):

    def makeBar(doc):
        app = doc.parent    
        app.preferences.rulerUnits = Units.Pixels
        
        def point(x, y):
            result               = Dispatch("Photoshop.PathPointInfo")
            result.Kind          = PointKind.CornerPoint
            result.LeftDirection = result.rightDirection = result.Anchor = (x, y)
            return result
    
        points = [    
                  point(100, 100),
                  point(200, 100),
                  point(200, 110),
                  point(100, 110)
                  ]
    
        lineSubPathArray               = Dispatch("Photoshop.SubPathInfo")
        lineSubPathArray.Operation     = ShapeOperation.ShapeAdd
        lineSubPathArray.Closed        = True
        lineSubPathArray.EntireSubPath = points
        
        doc.PathItems.Add("bar-path", [lineSubPathArray])
    
    
    
    app = Dispatch("Photoshop.Application")
    doc = app.Open(self.fileName)
    

    As for my second question: The unit of the path's cornerpoints are invariantly in Points, no matter what he rulers are set to.


  2. This may be of use:

    You can define a new colour with new SolidColor()

       // define fillColor 
       var fillColor = new SolidColor();
       var myColour = [57, 181,74];
       fillColor.rgb.red   = myColour[0];
       fillColor.rgb.green = myColour[1];
       fillColor.rgb.blue  = myColour[2];
    

    and then fill your path by adding myPathItem.fillPath(fillColor,ColorBlendMode.NORMAL,100,false,0,true,true);

    // Switch off any dialog boxes
    displayDialogs = DialogModes.NO; // OFF
    
    var originalUnits = app.preferences.rulerUnits;
    
    app.preferences.rulerUnits = Units.PIXELS;
    
    // call the source document
    var srcDoc = app.activeDocument;
    
    create_path("bar-path");
    
    function create_path(linename)
    {
    
       var points = [    
       [100, 100],
       [200, 100],
       [200, 110],
       [100, 110]
       ];
    
    
       // create the array of PathPointInfo objects
       var lineArray = new Array();
    
       for (var i = 0; i < points.length; i++)
       {
          lineArray[i] = new PathPointInfo;
          lineArray[i].kind = PointKind.CORNERPOINT;
          lineArray[i].anchor = points[i];
          lineArray[i].leftDirection = lineArray[i].anchor;
          lineArray[i].rightDirection = lineArray[i].anchor;
       }
    
    
       // create a SubPathInfo object, which holds the line array in its entireSubPath property.
       var lineSubPathArray = new Array();
       lineSubPathArray.push(new SubPathInfo());
       lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
       lineSubPathArray[0].closed = true;
       lineSubPathArray[0].entireSubPath = lineArray;
    
       //create the path item, passing subpath to add method
       var myPathItem = srcDoc.pathItems.add(linename, lineSubPathArray);
    
       // define fillColor 
       var fillColor = new SolidColor();
       var myColour = [57, 181,74];
       fillColor.rgb.red   = myColour[0];
       fillColor.rgb.green = myColour[1];
       fillColor.rgb.blue  = myColour[2];
    
       //fill the path so we can see something also
       myPathItem.fillPath(fillColor,ColorBlendMode.NORMAL,100,false,0,true,true);
    
       // deselect path
       deselect_path();
    }
    
    // switch back to normal
    app.preferences.rulerUnits = originalUnits;
    
    
    // Set Display Dialogs back to normal
    displayDialogs = DialogModes.ALL; // NORMAL
    
    
    function deselect_path()
    {
       // =======================================================
       var idslct = charIDToTypeID( "slct" );
       var desc76 = new ActionDescriptor();
       var idnull = charIDToTypeID( "null" );
       var ref63 = new ActionReference();
       var idPath = charIDToTypeID( "Path" );
       var idOrdn = charIDToTypeID( "Ordn" );
       var idTrgt = charIDToTypeID( "Trgt" );
       ref63.putEnumerated( idPath, idOrdn, idTrgt );
       desc76.putReference( idnull, ref63 );
       var idselectionModifier = stringIDToTypeID( "selectionModifier" );
       var idselectionModifierType = stringIDToTypeID( "selectionModifierType" );
       var idremoveFromSelection = stringIDToTypeID( "removeFromSelection" );
       desc76.putEnumerated( idselectionModifier, idselectionModifierType, idremoveFromSelection );
       executeAction( idslct, desc76, DialogModes.NO );
    
    }
    

    As for rectangle being too large: What resolution and units do you have the psd file set to? The script below will switch to pixels, and set the resolution of your document to 72dpi

    As for doing a stroke to replace the line. Well… you’ve got options.
    You can do a brush stroke with a two point line:

    var idStrk = charIDToTypeID( "Strk" );
    var desc105 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
    var ref35 = new ActionReference();
    var idPath = charIDToTypeID( "Path" );
    var idOrdn = charIDToTypeID( "Ordn" );
    var idTrgt = charIDToTypeID( "Trgt" );
    ref35.putEnumerated( idPath, idOrdn, idTrgt );
    desc105.putReference( idnull, ref35 );
    var idUsng = charIDToTypeID( "Usng" );
    var idPbTl = charIDToTypeID( "PbTl" );
    desc105.putClass( idUsng, idPbTl );
    executeAction( idStrk, desc105, DialogModes.NO );
    

    However, I don’t think that’s what your after. You can turn your path into a shape and then have a stroke and fill colour assigned. However… you need a minimum of 3 points for that to work.

    As a suggestion, instead of a path create a shape from start – which oddly will work with a minimum of two points. But I have no idea how to do that in code!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search