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

Transform corners of irregular rectangle into 90 degrees

New Here ,
Apr 23, 2022 Apr 23, 2022

Copy link to clipboard

Copied

Hello.

I have 48 different irregular selections with four corners that I want to all transform into identical rectangles with 90 degree corners. I thought I could paste the selections into a new project and have the corners of the selection just snap to the corners of the canvas so I could easily just 1,2,3,4 adjust the corners, then paste the next selection 1,2,3,4 adjust the corners and so on. But the corners are never at the corner of the selection, but just outside the corner in a rectangle. It takes too much time to adjust every corner to the exact pixel before moving on. Basically I want to set a shape and have selections perspective warp to match the four corners. Is there a way to do this?

Thanks.

TOPICS
Windows

Views

1.0K

Translate

Translate

Report

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
Adobe
Community Expert ,
Apr 23, 2022 Apr 23, 2022

Copy link to clipboard

Copied

Your terminology seems off to me. 

Are you talking about Selections or Layers/Smart Objects or Paths or …? 

»But the corners are never at the corner of the selection, but just outside the corner in a rectangle.«

Do you want actually rectangular results or not? 

 

Please explain what you are actually trying to do with meaningful screenshots including all pertinent Panels. 

 

Votes

Translate

Translate

Report

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 23, 2022 Apr 23, 2022

Copy link to clipboard

Copied

Hi. Sorry that I wasn't clear.

I don't know how to describe certain things so I might be using words for other things which gets confusing.

I make a straight edge selection with four corners. I copy that selection into a new project. I do the same with 47 others. Now I have 48 layers of differently shaped 4-cornered images.

I want all of those images on all the different layers to be shaped as identical rectangles with 90 degree corners.

The only way that I know how is to create a rectangle and then, one by one, reshape each layer to fit into the rectangle.

Which wouldn't be too bad if I could get the corner of each image to snap to the corners of the rectangle i created. Since the "adjustable corner" (arrow in the attached image) doesn't line up with the "actual corner" (the corner of the red, misshaped rectangle) of the image, the only snapping thats happening is that I can get the "adjustable corner" to snap to the corners of my created rectangle instead of the "actual corner", which is what I want, but the shape of the image hasn't changed. I have to instead zoom in and do four pixel perfect movements of each corner, and then move on to the next one.

I'm wondering if there is an easier way for each image to be adjusted to have the same shape as the created rectangle.

Thank you for your help, either way.

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied

Could you please post actual screenshots of the actual image/s in question? 

Because in your example the content is a plain red area so tranforming that would seem useless and simply creating a red rectangle would be kind-of easy. 

 

Anyway, if you work with four-corner-pointed paths instead of selections it might be possible to calculate (or at least approach) the necessary »counter«-transformation to make them form a rectangle … but that math would be beyond me. 

 

@r-bin , @jazz-y , @Kukurykus , please forgive the intrusion, but has any of you ever done something like this or how complicated would you guess it to be? 

Votes

Translate

Translate

Report

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
Guide ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied

This code creates a selection along transparency of the layer, translates it into a path, determines the corner points of the object and tries to bring it to a given size using a perspective transformation. I do not take into account the possible rotation of the object (more complex code is required to determine the angle and corner points of the object)

As you can see in the video, this works satisfactorily for most objects.

 

 

#target photoshop
var lr = new AM('layer'),
    pth = new AM('path'),
    targetSize = [300, 154];//target width,  height
lr.makeSelection();
lr.createPath(1)
var pthObj = lr.convertToObject(pth.getProperty('pathContents').value, 'pathComponents'),
    bounds = getCornerPoints(getPoints(pthObj));
lr.deleteCurrentPath()
var targetRect = allignCornerPoints(calculateTargetRect(targetSize), bounds.center);
lr.perspectiveWarpTransform(bounds.bounds, bounds.corners, targetRect.corners)
function getPoints(pth) {
    var points = [];
    for (a in pth) {
        var pc = pth[a];
        if (pc.subpathListKey) {
            for (b in pc.subpathListKey) {
                var slk = pc.subpathListKey[b]
                if (slk.closedSubpath) {
                    var pts = slk.points
                    for (c in pts) {
                        points.push({ x: pts[c].anchor.horizontal._value, y: pts[c].anchor.vertical._value })
                    }
                }
            }
        }
    }
    return points;
}
function getCornerPoints(points) {
    var boundingBox = {
        left: points.sort(function (a, b) { return a.x > b.x ? 1 : -1 })[0].x,
        right: points.sort(function (a, b) { return a.x < b.x ? 1 : -1 })[0].x,
        top: points.sort(function (a, b) { return a.y > b.y ? 1 : -1 })[0].y,
        bottom: points.sort(function (a, b) { return a.y < b.y ? 1 : -1 })[0].y
    }
    with (boundingBox) {
        var center = { x: left + (right - left) / 2, y: top + (bottom - top) / 2 };
    }
    var corners = [
        points.sort(function (a, b) { return getLineLength(boundingBox.left, a.x, boundingBox.top, a.y) < getLineLength(boundingBox.left, b.x, boundingBox.top, b.y) ? 0 : 1 }).shift(),
        points.sort(function (a, b) { return getLineLength(boundingBox.right, a.x, boundingBox.top, a.y) < getLineLength(boundingBox.right, b.x, boundingBox.top, b.y) ? 0 : 1 }).shift(),
        points.sort(function (a, b) { return getLineLength(boundingBox.right, a.x, boundingBox.bottom, a.y) < getLineLength(boundingBox.right, b.x, boundingBox.bottom, b.y) ? 0 : 1 }).shift(),
        points.sort(function (a, b) { return getLineLength(boundingBox.left, a.x, boundingBox.bottom, a.y) < getLineLength(boundingBox.left, b.x, boundingBox.bottom, b.y) ? 0 : 1 }).shift()
    ]
    return { corners: corners, center: center, bounds: boundingBox }
    function getLineLength(x1, x2, y1, y2) {
        return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
    }
}
function calculateTargetRect(target) {
    var corners = [
        {
            x: 0,
            y: 0
        },
        {
            x: target[0],
            y: 0
        },
        {
            x: target[0],
            y: target[1]
        },
        {
            x: 0,
            y: target[1]
        }
    ],
        center = { x: Math.round(target[0] / 2), y: Math.round(target[1] / 2) };
    return { corners: corners, center: center }
}
function allignCornerPoints(source, target) {
    var offsetX = target.x - source.center.x,
        offsetY = target.y - source.center.y;
    for (var i = 0; i < 4; i++) {
        source.corners[i].x += offsetX
        source.corners[i].y += offsetY
    }
    return source
}
function AM(target, order) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    target = s2t(target)
    this.getProperty = function (property, descMode, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
            r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
        return descMode ? executeActionGet(r) : getDescValue(executeActionGet(r), property)
    }
    this.convertToObject = function (obj, key) {
        var d = new ActionDescriptor();
        switch (obj.typename) {
            case 'ActionList': d.putList(s2t(key), obj); break;
            case 'ActionDescriptor': d = obj; break;
        }
        (desc = new ActionDescriptor()).putObject(s2t('object'), s2t('json'), d);
        eval('var o = ' + executeAction(s2t('convertJSONdescriptor'), desc).getString(s2t('json')));
        return o[key]
    }
    this.makeSelection = function () {
        (r = new ActionReference()).putProperty(s2t('channel'), s2t('selection'));
        (d = new ActionDescriptor()).putReference(s2t('null'), r);
        r1 = new ActionReference();
        r1.putEnumerated(s2t('channel'), s2t('channel'), s2t('transparencyEnum'));
        d.putReference(s2t('to'), r1);
        executeAction(s2t('set'), d, DialogModes.NO);
    }
    this.deleteCurrentPath = function () {
        (r = new ActionReference()).putProperty(s2t('path'), s2t('workPath'));
        (d = new ActionDescriptor()).putReference(s2t('null'), r);
        executeAction(s2t('delete'), d, DialogModes.NO);
    }
    this.createPath = function (tolerance) {
        tolerance = tolerance ? tolerance : 10;
        (r = new ActionReference()).putClass(s2t('path'));
        (d = new ActionDescriptor()).putReference(s2t('null'), r);
        (r1 = new ActionReference()).putProperty(s2t('selectionClass'), s2t('selection'));
        d.putReference(s2t('from'), r1);
        d.putUnitDouble(s2t('tolerance'), s2t('pixelsUnit'), tolerance);
        executeAction(s2t('make'), d, DialogModes.NO);
    }
    this.perspectiveWarpTransform = function (referenceRect, corners, targetPoints) {
        (r = new ActionReference()).putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        d.putEnumerated(s2t("mode"), s2t("perspectiveWarpMode"), s2t("warp"));
        (d1 = new ActionDescriptor()).putUnitDouble(s2t("top"), s2t("pixelsUnit"), referenceRect.top);
        d1.putUnitDouble(s2t("left"), s2t("pixelsUnit"), referenceRect.left);
        d1.putUnitDouble(s2t("bottom"), s2t("pixelsUnit"), referenceRect.bottom);
        d1.putUnitDouble(s2t("right"), s2t("pixelsUnit"), referenceRect.right);
        d.putObject(s2t("referenceRect"), s2t("rectangle"), d1);
        var l = new ActionList();
        for (var i = 0; i < corners.length; i++) {
            var point = new ActionDescriptor();
            point.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), corners[i].x);
            point.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), corners[i].y);
            l.putObject(s2t("point"), point);
        }
        d.putList(s2t("vertices"), l);
        var l = new ActionList(),
            l1 = new ActionList();
        for (var i = 0; i < targetPoints.length; i++) {
            var point = new ActionDescriptor();
            point.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), targetPoints[i].x);
            point.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), targetPoints[i].y);
            l.putObject(s2t("point"), point);
            l1.putInteger(i);
        }
        d.putList(s2t("warpedVertices"), l);
        (d2 = new ActionDescriptor()).putList(s2t("indices"), l1);
        (l2 = new ActionList()).putObject(s2t("perspectiveWarpQuad"), d2);
        d.putList(s2t("quads"), l2);
        executeAction(s2t("perspectiveWarpTransform"), d, DialogModes.NO);
    }
    function getDescValue(d, p) {
        switch (d.getType(p)) {
            case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
            case DescValueType.LISTTYPE: return d.getList(p);
            case DescValueType.REFERENCETYPE: return d.getReference(p);
            case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
            case DescValueType.STRINGTYPE: return d.getString(p);
            case DescValueType.INTEGERTYPE: return d.getInteger(p);
            case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
            case DescValueType.DOUBLETYPE: return d.getDouble(p);
            case DescValueType.ALIASTYPE: return d.getPath(p);
            case DescValueType.CLASSTYPE: return d.getClass(p);
            case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
            case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
            default: break;
        };
    }
}

 

 

Votes

Translate

Translate

Report

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
LEGEND ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied

Use the code in linked thread from Aug 03, 2021. That's much easier method to do the same.

Votes

Translate

Translate

Report

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
Guide ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied

CropAndStraighten was the first thing I tried. But I was not able to get it to straighten the sides of the object 🤷

 

00.jpg

02.jpg

03.jpg

04.jpg

  

 

Votes

Translate

Translate

Report

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
LEGEND ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied

Loll my bad - I tried on too not enough deformed object 😉

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied


@jazz-y wrote:

CropAndStraighten was the first thing I tried. But I was not able to get it to straighten the sides of the object 🤷


 

My guess is that it’s because Crop and Straighten applies only one transformation, rotation (the “straighten” part). It probably doesn’t try to do an automatic “perspective crop.”

Votes

Translate

Translate

Report

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
LEGEND ,
Apr 24, 2022 Apr 24, 2022

Copy link to clipboard

Copied

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 25, 2022 Apr 25, 2022

Copy link to clipboard

Copied

I figured out an approach that can make a Smart Object with a four-point-Vector Mask conform to verticals and horizontals with three transformations. 

• Rotate to make the shortest side horizontal 

• Skew to make the left descending edge vertical 

• Use T-Point transformation from »stacksupport.jsx« to push in the right lower point while compensating the horizontal and vertical edges 

transformSmartObjectWithVectorMaskToRectangleScr.gif

The steps in another example: 

Screenshot 2022-04-25 at 17.44.30.pngScreenshot 2022-04-25 at 17.44.37.pngScreenshot 2022-04-25 at 17.44.41.pngScreenshot 2022-04-25 at 17.44.45.png

 

But I haven’t tested very extensively yet and I suspect I have included some pretty inefficient code, so I’m not sure if/when I will post the code. 

Votes

Translate

Translate

Report

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
Community Expert ,
Apr 27, 2022 Apr 27, 2022

Copy link to clipboard

Copied

LATEST

The below Script should transform a selected Smart Object with a four-point Vector Mask to get the Vector Mask to be rectangular via three transformations. 

One transformation would be more efficient naturally but the Math to determine the circumscribing transformed bounding box in one go is beyond me. 

Screenshot 2022-04-27 at 14.28.56.pngScreenshot 2022-04-27 at 14.29.08.png

// transform smart object with four point vector mask so that the vector mask is rectangular;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
// set to pixels;
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
////////////////////////////////////
var theID = getLayerId ();
// check for appropriate four point vector mask;
var isSO = isSmartObject();
var thePath = collectPathInfoFromVectorMask();
if (isSO == true && thePath.length == 1 && thePath[0].length == 6) {
////////////////////////////////////
// rotate shortest side to 0˚;
var theX = new Array;
// get lengths and angles;
for (var m = 0; m < 4; m++) {
    var theNext = m+1;
    if (theNext == 4) {theNext = 0};
    theX.push([getDistance(thePath[0][m][0], thePath[0][theNext][0]), getAngle(thePath[0][m][0], thePath[0][theNext][0]), thePath[0][m][0], thePath[0][theNext][0]])
};
theX.sort(sortArrayByIndexedItem);
duplicateMoveRotateScale(theID, 0, 0, 100, 100, 360-theX[0][1], 0, false);
////////////////////////////////////
// skew second shortest side to 90˚;
var thePath = collectPathInfoFromVectorMask();
var theHor = new Array;
for (var m = 0; m < 4; m++) {
    theHor.push(thePath[0][m][0])
};
theHor.sort(sortArrayByIndexedItem);
var theLeft = theHor.slice(0,2).sort(sortArrayByIndexedItem2);
var theRight = theHor.slice(2).sort(sortArrayByIndexedItem2);
var theAngle = getAngle(theLeft[0], theLeft[1]);
duplicateMoveRotateScale(theID, 0, 0, 100, 100, 0, theAngle-90, false);
////////////////////////////////////
// get target corners;
var thePath = collectPathInfoFromVectorMask();
var theHor = new Array;
for (var m = 0; m < 4; m++) {
    theHor.push(thePath[0][m][0])
};
theHor.sort(sortArrayByIndexedItem);
var theLeft = theHor.slice(0,2).sort(sortArrayByIndexedItem2);
var theRight = theHor.slice(2).sort(sortArrayByIndexedItem2);
var theA = intersectionOfLines ([theLeft[1], theRight[1]], [theRight[0], [theRight[0][0], theRight[1][1]]]);
var theB = intersectionOfLines ([theRight[0], theRight[1]], [theLeft[1], [theRight[1][0], theLeft[1][1]]]);
// define the four cornerpoints;
var aTopLeft = [theLeft[0][0], theLeft[0][1]]
var aTopRight = [theB[0], theRight[0][1]];
var aBottomRight = [theRight[0][0], theLeft[1][1]];
var aBottomLeft = [theLeft[1][0], theA[1]];
// transform to points;
transformByCornerpoints (aTopLeft, aTopRight, aBottomRight, aBottomLeft);
};
////////////////////////////////////
// reset;
app.preferences.rulerUnits = originalRulerUnits;
};
////// duplicate layer and move, rotate and scale it //////
function duplicateMoveRotateScale (theID, theX, theY, theScaleX, theScaleY, theRotation, theSkew, theDuplicate) {
selectLayerByID(theID,false);
try{
var idTrnf = charIDToTypeID( "Trnf" );
    var desc10 = new ActionDescriptor();
    var idnull = charIDToTypeID( "null" );
		var ref6 = new ActionReference();
		ref6.putIdentifier( charIDToTypeID( "Lyr " ), theID );
/*        ref6.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );*/
    desc10.putReference( idnull, ref6 );
    var idFTcs = charIDToTypeID( "FTcs" );
    var idQCSt = charIDToTypeID( "QCSt" );
    var idQcsa = charIDToTypeID( "Qcsa" );
    desc10.putEnumerated( idFTcs, idQCSt, idQcsa );
    var idOfst = charIDToTypeID( "Ofst" );
        var desc11 = new ActionDescriptor();
        var idHrzn = charIDToTypeID( "Hrzn" );
        var idPxl = charIDToTypeID( "#Pxl" );
        desc11.putUnitDouble( idHrzn, idPxl, theX );
        var idVrtc = charIDToTypeID( "Vrtc" );
        var idPxl = charIDToTypeID( "#Pxl" );
        desc11.putUnitDouble( idVrtc, idPxl, theY );
    var idOfst = charIDToTypeID( "Ofst" );
    desc10.putObject( idOfst, idOfst, desc11 );
    var idWdth = charIDToTypeID( "Wdth" );
    var idPrc = charIDToTypeID( "#Prc" );
    desc10.putUnitDouble( idWdth, idPrc, theScaleX );
    var idHght = charIDToTypeID( "Hght" );
    var idPrc = charIDToTypeID( "#Prc" );
    desc10.putUnitDouble( idHght, idPrc, theScaleY );
    var idAngl = charIDToTypeID( "Angl" );
    var idAng = charIDToTypeID( "#Ang" );
    desc10.putUnitDouble( idAngl, idAng, theRotation );

    var idskew = stringIDToTypeID( "skew" );
        var desc358 = new ActionDescriptor();
        var idhorizontal = stringIDToTypeID( "horizontal" );
        var idangleUnit = stringIDToTypeID( "angleUnit" );
        desc358.putUnitDouble( idhorizontal, idangleUnit, theSkew );
        var idvertical = stringIDToTypeID( "vertical" );
        var idangleUnit = stringIDToTypeID( "angleUnit" );
        desc358.putUnitDouble( idvertical, idangleUnit, 0.000000 );
    var idpaint = stringIDToTypeID( "paint" );
    desc10.putObject( idskew, idpaint, desc358 );

    var idIntr = charIDToTypeID( "Intr" );
    var idIntp = charIDToTypeID( "Intp" );
    var idbicubicAutomatic = stringIDToTypeID( "bicubicAutomatic" );
    desc10.putEnumerated( idIntr, idIntp, idbicubicAutomatic );
    var idCpy = charIDToTypeID( "Cpy " );
    desc10.putBoolean( idCpy, theDuplicate );
executeAction( idTrnf, desc10, DialogModes.NO );
} catch (e) {}
};
// based on code by mike hale, via paul riggott;
function selectLayerByID(id,add){ 
	add = undefined ? add = false:add 
	var ref = new ActionReference();
		ref.putIdentifier(charIDToTypeID("Lyr "), id);
		var desc = new ActionDescriptor();
		desc.putReference(charIDToTypeID("null"), ref );
		   if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) ); 
		  desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
	   try{
		executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
	}catch(e){
	alert(e.message); 
	}
};
////// bounds of active layer //////
function getBounds () {
    var ref = new ActionReference();
    ref.putProperty (stringIDToTypeID ("property"), stringIDToTypeID ("bounds"));
	ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var layerDesc = executeActionGet(ref);
    var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
    var theseBounds = [theBounds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
    var theW = theBounds.getUnitDoubleValue(stringIDToTypeID("right")) - theBounds.getUnitDoubleValue(stringIDToTypeID("left"));
    var theH = theBounds.getUnitDoubleValue(stringIDToTypeID("bottom")) - theBounds.getUnitDoubleValue(stringIDToTypeID("top"));
    var horCenter = theseBounds[0] + theW / 2;
    var verCenter = theseBounds[1] + theH / 2;
    return ([theseBounds, theW, theH, horCenter, verCenter])
};
////// get active layer’s id //////
function getLayerId () {
    var ref = new ActionReference();
    ref.putProperty (stringIDToTypeID ("property"), stringIDToTypeID ("layerID"));
    ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
    return executeActionGet(ref).getInteger(stringIDToTypeID("layerID"));
};
////// is smart object //////
function isSmartObject () {
    var ref = new ActionReference();
    ref.putProperty (stringIDToTypeID ("property"), stringIDToTypeID ("smartObject"));
    ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
    var layerDesc = executeActionGet(ref);
    var isSmartObject = layerDesc.hasKey(stringIDToTypeID("smartObject"));
    return isSmartObject
};
////// get an angle, 3:00 being 0˚, 6:00 90˚, etc. //////
function getAngle (pointOne, pointTwo) {
// calculate the triangle sides;
    var width = pointTwo[0] - pointOne[0];
    var height = pointTwo[1] - pointOne[1];
    var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); 
// calculate the angles;
    if (width+width > width) {theAngle = Math.asin(height / sideC) * 360 / 2 / Math.PI}
    else {theAngle = 180 - (Math.asin(height / sideC) * 360 / 2 / Math.PI)};
    if (theAngle < 0) {theAngle = (360 + theAngle)};
//	if (theAngle > 180) {theAngle = (360 - theAngle) * (-1)};
    return theAngle
    };
////// get a distance between two points //////
function getDistance (pointOne, pointTwo) {
// calculate the triangle sides;
    var width = pointTwo[0] - pointOne[0];
    var height = pointTwo[1] - pointOne[1];
    var sideC = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); 
    return sideC
    };
////// collect path info from actiondescriptor, smooth added //////
function collectPathInfoFromVectorMask () {
    var originalRulerUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;
    // based of functions from xbytor’s stdlib;
    var ref = new ActionReference();
    var idPath = charIDToTypeID( "Path" );
    ref.putEnumerated( idPath, idPath, stringIDToTypeID( "vectorMask" ) );
/*    for (var l = 0; l < myDocument.pathItems.length; l++) {
        var thisPath = myDocument.pathItems[l];
        if (thisPath == thePath && thisPath.kind == PathKind.WORKPATH) {
            ref.putProperty(cTID("Path"), cTID("WrPt"));
            };
        if (thisPath == thePath && thisPath.kind != PathKind.WORKPATH && thisPath.kind != PathKind.VECTORMASK) {
            ref.putIndex(cTID("Path"), l + 1);
            };
        if (thisPath == thePath && thisPath.kind == PathKind.VECTORMASK) {
            var idPath = charIDToTypeID( "Path" );
            var idPath = charIDToTypeID( "Path" );
            var idvectorMask = stringIDToTypeID( "vectorMask" );
            ref.putEnumerated( idPath, idPath, idvectorMask );
            };
        };*/
    var desc = app.executeActionGet(ref);
    var pname = desc.getString(cTID('PthN'));
    // create new array;
    var theArray = new Array;
    var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));
    // for subpathitems;
    for (var m = 0; m < pathComponents.count; m++) {
        var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));
        var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));
        switch (operation1) {
            case 1097098272:
            var operation = 1097098272 //cTID('Add ');
            break;
            case 1398961266:
            var operation = 1398961266 //cTID('Sbtr');
            break;
            case 1231975538:
            var operation = 1231975538 //cTID('Intr');
            break;
            default:
    //		case 1102:
            var operation = sTID('xor') //ShapeOperation.SHAPEXOR;
            break;
            };
    // for subpathitem’s count;
        for (var n = 0; n < listKey.count; n++) {
            theArray.push(new Array);
            var points = listKey.getObjectValue(n).getList(sTID('points'));
            try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}
            catch (e) {var closed = false};
    // for subpathitem’s segment’s number of points;
            for (var o = 0; o < points.count; o++) {
                var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));
                var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];
                var thisPoint = [anchor];
                try {
                    var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));
                    var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];
                    thisPoint.push(leftDirection)
                    }
                catch (e) {
                    thisPoint.push(anchor)
                    };
                try {
                    var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));
                    var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];
                    thisPoint.push(rightDirection)
                    }
                catch (e) {
                    thisPoint.push(anchor)
                    };
                try {
                    var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));
                    thisPoint.push(smoothOr)
                    }
                catch (e) {thisPoint.push(false)};
                theArray[theArray.length - 1].push(thisPoint);
                };
            theArray[theArray.length - 1].push(closed);
            theArray[theArray.length - 1].push(operation);
            };
        };
    // by xbytor, thanks to him;
    function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
    function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
    // reset;
    app.preferences.rulerUnits = originalRulerUnits;
    return theArray;
    };
////// sort a double array, thanks to sam, http://www.rhinocerus.net/forum/lang-javascript/ //////
function sortArrayByIndexedItem(a,b) {
    var theIndex = 0;
    if (a[theIndex]<b[theIndex]) return -1;
    if (a[theIndex]>b[theIndex]) return 1;
    return 0;
    };
function sortArrayByIndexedItem2(a,b) {
    var theIndex = 1;
    if (a[theIndex]<b[theIndex]) return -1;
    if (a[theIndex]>b[theIndex]) return 1;
    return 0;
    };
////// intersection point of linear functions //////
function intersectionOfLines (lineA, lineB) {
	try {
// process lineA;
	var wA = lineA[1][0] - lineA[0][0];
	var hA = lineA[1][1] - lineA[0][1];
	var inclineA = hA / wA ;
// process lineB;
	var wB = lineB[1][0] - lineB[0][0];
	var hB = lineB[1][1] - lineB[0][1];
	var inclineB = hB / wB ;
// break if parrallel;
	if (inclineA == inclineB) {return undefined};
// check for horizontal or vertical;
	if (wA == 0) {var theX = lineA[1][0]};
	if (hA == 0) {var theY = lineA[1][1]};
	if (wB == 0) {var theX = lineB[1][0]};
	if (hB == 0) {var theY = lineB[1][1]};
// do stuff;
	var yZeroA = lineA[0][1] - (lineA[0][0] * inclineA);
	var yZeroB = lineB[0][1] - (lineB[0][0] * inclineB);
	if (theX == undefined) {var theX = (yZeroB - yZeroA) / (inclineA - inclineB)};
	if (theY == undefined) {var theY = theX * inclineA + yZeroA};
// result;
	return [theX, theY]
	}
	catch (e) {return undefined}
	};
////// transform by corner points //////
function transformByCornerpoints () {
//////////// transformation ////////////
// from adobe’s terminology.jsx;
const classChannel = app.charIDToTypeID('Chnl');
const enumNone = app.charIDToTypeID('None');
const eventSet = app.charIDToTypeID('setd');
const eventTransform = app.charIDToTypeID('Trnf');
const keySelection = app.charIDToTypeID('fsel');
const krectangleStr = app.stringIDToTypeID("rectangle");
const kquadrilateralStr = app.stringIDToTypeID("quadrilateral");
const keyBottom = app.charIDToTypeID('Btom');
const keyLeft = app.charIDToTypeID('Left');
const keyNull = app.charIDToTypeID('null');
const keyRight = app.charIDToTypeID('Rght');
const keyTo = app.charIDToTypeID('T   ');
const keyTop = app.charIDToTypeID('Top ');
const typeOrdinal = app.charIDToTypeID('Ordn');
const unitPixels = app.charIDToTypeID('#Pxl');
// from adobe’s geometry.jsx;
//
// =================================== TPoint ===================================
//
function TPoint( x, y )
{
	this.fX = x;
	this.fY = y;
}
// TPoint Constants
const kTPointOrigion = new TPoint( 0, 0 );
TPoint.kOrigin = kTPointOrigion;

const kTPointInfinite = new TPoint( Infinity, Infinity );
TPoint.kInfinite = kTPointInfinite;
const kTPointClassname = "TPoint";
TPoint.prototype.className = kTPointClassname;
// Overloaded math operators
TPoint.prototype["=="] = function( Src )
{
	return (this.fX == Src.fX) && (this.fY == Src.fY);
}

TPoint.prototype["+"] = function( b )
{
	return new TPoint( this.fX + b.fX, this.fY + b.fY );
}

TPoint.prototype["-"] = function( b, reversed )
{
	if (typeof(b) == "undefined")		// unary minus
		return new TPoint( -this.fX, -this.fY )
	else
	{
		if (reversed)
			return new TPoint( b.fX - this.fX, by.fY - this.fY );
		else
			return new TPoint( this.fX - b.fX, this.fY - b.fY);
	}
}
//
// Multiply and divide work with scalars as well as points
//
TPoint.prototype["*"] = function( b )
{
    if (typeof(b) == 'number')
		return new TPoint( this.fX * b, this.fY * b );
	else
		return new TPoint( this.fX * b.fX, this.fY * b.fY );
}
TPoint.prototype["/"] = function( b, reversed )
{
	if (reversed)
	{
		if (typeof(b) == "number")
			debugger;
// Can't divide a number by a point
		else
			return new TPoint( b.fX / this.fX, b.fY / this.fY );
	}
	else
	{
		if (typeof(b) == 'number')
			return new TPoint( this.fX / b, this.fY / b );
		else
			return new TPoint( this.fX / b.fX, this.fY / b.fY );
	}
}
TPoint.prototype.toString = function()
{
	return "[" + this.fX.toString() + "," + this.fY.toString() + "]";
}
TPoint.prototype.vectorLength = function()
{
    return Math.sqrt( this.fX * this.fX + this.fY * this.fY );
}
//////////// the new corners ////////////
transformActiveLayer( [new TPoint(aTopLeft[0], aTopLeft[1]), new TPoint(aTopRight[0], aTopRight[1]), new TPoint(aBottomRight[0], aBottomRight[1]), new TPoint(aBottomLeft[0], aBottomLeft[1])]);
// from adobe’s stacksupport.jsx;
// Apply a perspective transform to the current layer, with the
// corner TPoints given in newCorners (starts at top left, in clockwise order)
// Potential DOM fix
function transformActiveLayer( newCorners )
{
	function pxToNumber( px )
	{
		return px.as("px");
	}
	var saveUnits = app.preferences.rulerUnits;
	app.preferences.rulerUnits = Units.PIXELS;
	var i;
	var setArgs = new ActionDescriptor();
	var chanArg = new ActionReference();
	chanArg.putProperty( classChannel, keySelection );
//	setArgs.putReference( keyNull, chanArg );
	var boundsDesc = new ActionDescriptor();
	var layerBounds = app.activeDocument.activeLayer.bounds;
	boundsDesc.putUnitDouble( keyTop, unitPixels, pxToNumber( layerBounds[1] ) );
	boundsDesc.putUnitDouble( keyLeft, unitPixels, pxToNumber( layerBounds[0] ) );
	boundsDesc.putUnitDouble( keyRight, unitPixels, pxToNumber( layerBounds[2] ) );
	boundsDesc.putUnitDouble( keyBottom, unitPixels, pxToNumber( layerBounds[3] ) );
//	executeAction( eventSet, setArgs );
	var result = new ActionDescriptor();
	var args = new ActionDescriptor();
	var quadRect = new ActionList();
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[0] ) );
// ActionList put is different from ActionDescriptor put
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[1] ) );
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[2] ) );
	quadRect.putUnitDouble( unitPixels, pxToNumber( layerBounds[3] ) );	
	var quadCorners = new ActionList();
	for (i = 0; i < 4; ++i)
	{
		quadCorners.putUnitDouble( unitPixels, newCorners[i].fX );
		quadCorners.putUnitDouble( unitPixels, newCorners[i].fY );
	}
	args.putList( krectangleStr, quadRect );
	args.putList( kquadrilateralStr, quadCorners );
	executeAction( eventTransform, args );	
	// Deselect
	deselArgs = new ActionDescriptor();
	deselRef = new ActionReference();
	deselRef.putProperty( classChannel, keySelection );
	deselArgs.putReference( keyNull, deselRef );
	deselArgs.putEnumerated( keyTo, typeOrdinal, enumNone );
	executeAction( eventSet, deselArgs );
	app.preferences.rulerUnits = saveUnits;
}
};

 

Votes

Translate

Translate

Report

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