Search code examples
javascriptphotoshopextendscriptphotoshop-script

Photoshop script - Transform a rectangular selection into an oval one


I have a problem that I can't solve.
I have a rectangular selection (the size doesn't matter) I need to transform to elliptical with a script.
I would like the elliptical selection to have the same size and position as the rectangular one. I managed to put this script together:

    (NAR = new ActionReference).putProperty (stringIDToTypeID ("channel"), stringIDToTypeID ("selection"));
    (NAD = new ActionDescriptor).putReference (stringIDToTypeID ("null"), NAR);
    (NAD2 = new ActionDescriptor).putUnitDouble (stringIDToTypeID ("top"), stringIDToTypeID ("distanceUnit"), app.activeDocument.selection.bounds[1]);
    NAD2.putUnitDouble (stringIDToTypeID ("left"), stringIDToTypeID ("distanceUnit"), app.activeDocument.selection.bounds[0]);
    NAD2.putUnitDouble (stringIDToTypeID ("bottom"), stringIDToTypeID ("distanceUnit"), app.activeDocument.selection.bounds[3]);
    NAD2.putUnitDouble (stringIDToTypeID ("right"), stringIDToTypeID ("distanceUnit"), app.activeDocument.selection.bounds[2]);
    NAD.putObject (stringIDToTypeID ("to"), stringIDToTypeID ("ellipse"), NAD2);
    NAD.putBoolean (stringIDToTypeID ("antiAlias"), true);
    executeAction (stringIDToTypeID ("set"), NAD, DialogModes.NO);

The script creates an elliptical selection with the same bounds as the existing rectangular selection.
The problem is that the final measure is too small and moved elsewhere outside the document's edges.
I've already tried converting the document at 72 DPI without resampling, but it still doesn't give me the correct size.
I am attaching an image for clarity.

Image

Anyone have any ideas?


Solution

  • This is overly long and ugly, but it'll change your selection to a ellipse:

    // Switch off any dialog boxes
    displayDialogs = DialogModes.ALL; // OFF
    
    
    var sb = selection_bounds(); // LRBT
    
    selectThis(sb[0], sb[1], sb[2], sb[3], "oval");
    
    
    // Set Display Dialogs back to normal
    displayDialogs = DialogModes.ALL; // NORMAL
    
    
    // function SELECT THIS(top, left, right, bottom, ellipse or rect [default], antialias [default] )
    // --------------------------------------------------------
    function selectThis(top, left, right, bottom, shape, aa)
    {
        // =======================================================
        var id1 = charIDToTypeID( "setd" );
        var desc1 = new ActionDescriptor();
        var id2 = charIDToTypeID( "null" );
        var ref1 = new ActionReference();
        var id3 = charIDToTypeID( "Chnl" );
        var id4 = charIDToTypeID( "fsel" );
        ref1.putProperty( id3, id4 );
        desc1.putReference( id2, ref1 );
        var id5 = charIDToTypeID( "T   " );
        var desc2 = new ActionDescriptor();
        var id6 = charIDToTypeID( "Top " );
        var id7 = charIDToTypeID( "#Pxl" );
        desc2.putUnitDouble( id6, id7, top );
        var id8 = charIDToTypeID( "Left" );
        var id9 = charIDToTypeID( "#Pxl" );
        desc2.putUnitDouble( id8, id9, left );
        var id10 = charIDToTypeID( "Btom" );
        var id11 = charIDToTypeID( "#Pxl" );
        desc2.putUnitDouble( id10, id11, bottom );
        var id12 = charIDToTypeID( "Rght" );
        var id13 = charIDToTypeID( "#Pxl" );
        desc2.putUnitDouble( id12, id13, right );
    
    
        if (shape == "Elps" || shape == "oval")
        {
            var id14 = charIDToTypeID( "Elps" );
            desc1.putObject( id5, id14, desc2 );
            var id15 = charIDToTypeID( "AntA" );
            if (aa == true || aa == undefined)
            {
                desc1.putBoolean( id15, true );
            }
            else
            {
                desc1.putBoolean( id15, false );
            }
        }
        else
        {
            var id16 = charIDToTypeID( "Rctn" );
            desc1.putObject( id5, id16, desc2 );
        }
    
        executeAction( id1, desc1, DialogModes.NO );
    
    }
    
    
    
    
    function selection_bounds()
    {
      try
      {
        var x = parseFloat(app.activeDocument.selection.bounds[0]);
        var y = parseFloat(app.activeDocument.selection.bounds[1]);
        var x1 = parseFloat(app.activeDocument.selection.bounds[2]);
        var y1 = parseFloat(app.activeDocument.selection.bounds[3]);
    
        // var selectionBounds = [x, x1, y, y1]; // LRBT
        var selectionBounds = [y, x, x1, y1];    // TLBR
    
        return selectionBounds;
    
      }
    
      catch(eek)
      {
        return undefined;
      }
    }
    

    I tried unpicking your code but to no avail. I did however, note the charIDToTypeID were not four letters. ie "top should be "Top ", "bottom should be "Btom" but Adobe may have changed that.