Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

JavaScript Warp Selection (not Text)?

New Here ,
Apr 13, 2009 Apr 13, 2009

Is there a way to [script] transform/warp/arch? The TextItem object has it for text, but I want to warp an arbitrary rectangle in an ArtLayer. Thanks

TOPICS
Actions and scripting
1.3K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Guru , Apr 13, 2009 Apr 13, 2009

Use the scriptlistner plugin to record the type of transform you need. Below is a cleaned up output of the arch warp

    var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
    desc.putReference( charIDToTypeID( "null" ), ref );
    desc.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );
        var desc1 = new ActionDescriptor()

...
Translate
Adobe
Guru ,
Apr 13, 2009 Apr 13, 2009

Use the scriptlistner plugin to record the type of transform you need. Below is a cleaned up output of the arch warp

    var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
    desc.putReference( charIDToTypeID( "null" ), ref );
    desc.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );
        var desc1 = new ActionDescriptor();
        desc1.putUnitDouble( charIDToTypeID( "Hrzn" ), charIDToTypeID( "#Rlt" ), 0.000000 );
        desc1.putUnitDouble( charIDToTypeID( "Vrtc" ), charIDToTypeID( "#Rlt" ), -0.000000 );
    desc.putObject( charIDToTypeID( "Ofst" ), charIDToTypeID( "Ofst" ), desc1 );
        var desc2 = new ActionDescriptor();
        desc2.putEnumerated( stringIDToTypeID( "warpStyle" ), stringIDToTypeID( "warpStyle" ), stringIDToTypeID( "warpArch" ) );
        desc2.putDouble( stringIDToTypeID( "warpValue" ), 50.000000 );
        desc2.putDouble( stringIDToTypeID( "warpPerspective" ), 0.000000 );
        desc2.putDouble( stringIDToTypeID( "warpPerspectiveOther" ), 0.000000 );
        desc2.putEnumerated( stringIDToTypeID( "warpRotate" ), charIDToTypeID( "Ornt" ), charIDToTypeID( "Hrzn" ) );
        desc2.putInteger( stringIDToTypeID( "uOrder" ), 4 );
        desc2.putInteger( stringIDToTypeID( "vOrder" ), 2 );
    desc.putObject( stringIDToTypeID( "warp" ), stringIDToTypeID( "warp" ), desc2 );
executeAction( charIDToTypeID( "Trnf" ), desc, DialogModes.NO );

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Apr 13, 2009 Apr 13, 2009
LATEST

Thanks - This is such an arcane way to do it! Kind of like borrowing assembly code... But it works. I use the technique in the following code to split an image into multiple tiles that look like photographs tossed on a table (be sure to define the drop1 style in PS):

// tile.jsx: tile image into 4x3 (actually CELLSMAX x CELLSMIN)
// Author: Eric Onasick (with help from Michael Hale), April 2009

// This script splits an image into 12 (or 16 if square) tiles, adds an external stroke of FOREGROUND color,
// and creates a new document that looks like a bunch of photos tossed on a table (color = BACKGROUND color)
// Make sure the colors are set using a Normal blend mode (e.g. set while on the Background layer)

// Works on any aspect ratio, and indep of whatever layers are present because it merges all into a new doc.
// Assumes you have defined a Style in the style palette called "drop1" with an 8/8/8 drop shadow at 135 degrees (not global light) and 64% opacity

#target photoshop
// debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
$.level = 0;
// debugger; // launch debugger on next line

var CELLSMAX = 4 ;    // number of tiles in larger dimension (or square)
var CELLSMIN = 3 ;    // number of tiles in smaller dimension
var DROPSHADOWSTYLE = "drop1" ; // must be predefined in Adobe Photoshop
var SQUARETOLERANCE = 100 ;  // number of pixels difference between width and height to call it square

/////////////////////////////////////////////////////////////////////////////
function Select( x, y, cx, cy, type) // select a region
{
  var selRegion = Array(
   Array( x, y ),
   Array( x + cx, y ),
   Array( x + cx, y + cy ),
   Array( x, y + cy ),
   Array( x, y )
  ) ;
  doc.selection.select( selRegion, type ) ;
}

function ModifyTile()    // add style, warp, roation and jitter to a tile
{
var tile = doc.activeLayer ; // current layer
tile.applyStyle( DROPSHADOWSTYLE ) ;

// add arch (courtesy Michael L Hale) to look like a curled photo
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
desc.putReference( charIDToTypeID( "null" ), ref );
desc.putEnumerated( charIDToTypeID( "FTcs" ), charIDToTypeID( "QCSt" ), charIDToTypeID( "Qcsa" ) );

var desc1 = new ActionDescriptor();
desc1.putUnitDouble( charIDToTypeID( "Hrzn" ), charIDToTypeID( "#Rlt" ), 0.000000 );
desc1.putUnitDouble( charIDToTypeID( "Vrtc" ), charIDToTypeID( "#Rlt" ), 0.000000 );
desc.putObject( charIDToTypeID( "Ofst" ), charIDToTypeID( "Ofst" ), desc1 );

var desc2 = new ActionDescriptor();
desc2.putEnumerated( stringIDToTypeID( "warpStyle" ), stringIDToTypeID( "warpStyle" ), stringIDToTypeID( "warpArch" ) );

var archLimit = 8 ;
var arch = Math.random() * archLimit - archLimit/2 ;
desc2.putDouble( stringIDToTypeID( "warpValue" ), arch ); // amount of arch

desc2.putDouble( stringIDToTypeID( "warpPerspective" ), 0.000000 );
desc2.putDouble( stringIDToTypeID( "warpPerspectiveOther" ), 0.000000 );
desc2.putEnumerated( stringIDToTypeID( "warpRotate" ), charIDToTypeID( "Ornt" ), charIDToTypeID( "Hrzn" ) );
desc2.putInteger( stringIDToTypeID( "uOrder" ), 4 );
desc2.putInteger( stringIDToTypeID( "vOrder" ), 2 );
desc.putObject( stringIDToTypeID( "warp" ), stringIDToTypeID( "warp" ), desc2 );
executeAction( charIDToTypeID( "Trnf" ), desc, DialogModes.NO );

// rotate a small random amount
var df = 2 ;     // degrees of freedom, literally 🙂
var degrees = Math.random() * df - df/2 ; // range -df to df
tile.rotate( degrees ) ;

// translate a bit too
var xJitter = 100 ; // pixels
var yJitter = 100 ; // pixels
var dx = Math.random() * xJitter - xJitter/2 ;
var dy = Math.random() * yJitter - yJitter/2 ;
tile.translate( dx, dy ) ;
}

/// main code ///////////////////////////////////////////////////////////////////////////
app.bringToFront();      // in case we double clicked the file
app.displayDialogs = DialogModes.NO;
var strtRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;

// merge into new doc
var doc = app.activeDocument.duplicate( app.activeDocument.name + "_tiled" , true) ;

var cx = 1 ; // width of tile
var cy = 1 ; // height of tile

if (Math.abs( doc.width - doc.height ) < SQUARETOLERANCE ) // square-ish (in pixels)
{
cy = cx = doc.width / CELLSMAX ;
}
else if (doc.height < doc.width ) // LS
{
cx = doc.width / CELLSMAX;
cy = doc.height / CELLSMIN ;
}
else // PT
{
cx = doc.width / CELLSMIN ;
cy = doc.height / CELLSMAX ;
}

// divide up "source" layer:
var artLayerCurrent = doc.activeLayer ;
var strokefillcolor = app.foregroundColor ;

var dx = Math.round( cx / 16 );  // stroke width
var dy = dx ;      // isometric (can change if you like)

doc.resizeCanvas( doc.width + 2 * dx, doc.height + 2 * dy ) ; // accomodate tile strokes at edges

for( var x = dx; x < doc.width - dx; x += cx )
{
for( var y = dy; y < doc.height - dy; y += cy )
{
  Select( x, y, cx, cy ) ;
 
  doc.selection.copy() ;   // to clipboard
  doc.paste( false ) ;   // create a new tile layer
 
  // add stroke
  Select( x-dx, y-dy, cx + 2 * dx, cy + 2 * dy ) ;  // select an area bigger than pasted part
  Select( x, y, cx, cy, SelectionType.DIMINISH ) ;  // deselect pasted part leaving stroke boundary
  doc.selection.fill( strokefillcolor );
  Select( x-dx, y-dy, cx + 2 * dx, cy + 2 * dy ) ;  // select the whole thing now
 
  ModifyTile() ;  // add style, arch, rotation and jitter to each tile to simulate photographs
 
  doc.activeLayer = artLayerCurrent ; // back to where we were for another bite
}
}

// fill bkgd layer (currently active layer)
doc.selection.selectAll() ;
doc.selection.fill( app.backgroundColor ) ;
doc.selection.deselect() ;
doc.resizeCanvas( doc.width * 1.1, doc.height * 1.1 ) ; // make bigger

// restore old state
app.preferences.rulerUnits = strtRulerUnits;


// caveat: I'm still learning so this code is an early attempt

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines