Copy link to clipboard
Copied
I have an object inside a layer, the initial boundaries of which are known, but I cannot get them directly (this is part of the image) . Object are described in the standard way in document coordinates - top, left, right, bottom. I need to perform a series of transformations of the entire layer and after that get the new coordinates of the object inside it (transformation in this case is only a change in scale, image rotation is not performed). I easily coped with move (x+dx) (y+dy), but I got stuck on the transformation with the center set manually (the coordinates of this point are known - x, y). It seems that I understand this combination of move + scale and a proportional change coordinates is required depending on their distance from the point x,y, but I cannot deduce the correct formula for calculating the new values ​​of top, left, right, bottom. Can someone help me with this?
P.S. it is clear that we can copy an object to a new layer and perform its transformation with the same parameters as the main layer (this is how the script works at the moment), but I want to speed up the script and get rid of unnecessary transformations (that is, get coordinates by calculation )
this.transform = function (dX, dY, scale, x, y, subject) {
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putEnumerated(s2t('freeTransformCenterState'), s2t('quadCenterState'), s2t('QCSIndependent'));
((d1 = new ActionDescriptor())).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), x);
d1.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), y);
...
Copy link to clipboard
Copied
this.transform = function (dX, dY, scale, x, y, subject) {
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putEnumerated(s2t('freeTransformCenterState'), s2t('quadCenterState'), s2t('QCSIndependent'));
((d1 = new ActionDescriptor())).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), x);
d1.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), y);
d.putObject(s2t('position'), s2t('paint'), d1);
(d2 = new ActionDescriptor()).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), dX);
d2.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), dY);
d.putObject(s2t('offset'), s2t('offset'), d2);
d.putUnitDouble(s2t('width'), s2t('percentUnit'), scale);
d.putUnitDouble(s2t('height'), s2t('percentUnit'), scale);
d.putEnumerated(s2t('interfaceIconFrameDimmed'), s2t('interpolationType'), s2t('bicubic'));
executeAction(s2t('transform'), d, DialogModes.NO);
if (subject) {
with (subject) {
var dV = (height * scale / 100 - (bottom - top)),
dH = (width * scale / 100 - (right - left));
top = top - (dV * (y - top) / height) + dY
bottom = bottom + (dV * (bottom - y) / height) + dY
left = left - (dH * (x - left) / width) + dX
right = right + (dH * (right - x) / width) + dX
height = height * scale / 100
width = width * scale / 100
}
}
* where subject is object with bounding box coordinates
Copy link to clipboard
Copied
Can you edit your code to working version to let me try out it on some layer with an object inside?
Copy link to clipboard
Copied
It is difficult for me to provide a working code, since I am getting the coordinates of the object with the layer from another program. But there is no difference, you can just calculate the bounding rect of the current layer after transformation.
var lr = new AM('layer'),
subject = lr.descToObject(lr.getProperty('boundsNoEffects'));
lr.transform(100, 200, 150, 70, 120, subject)
var newBounds = lr.descToObject(lr.getProperty('boundsNoEffects'));
alert ('calculated:\ntop: '+subject.top +', left: ' +subject.left + ', right: ' + subject.right + ', bottom: ' + subject.bottom + '\nreal:\ntop: '
+newBounds.top +', left: ' +newBounds.left + ', right: ' +newBounds.right + ', bottom: ' + newBounds.bottom + '\nreal:\n')
function AM(target, order) {
var s2t = stringIDToTypeID,
t2s = typeIDToStringID;
target = s2t(target)
this.getProperty = function (property, descMode, id, idxMode, parent, parentIdx) {
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'));
if (parent) r.putIndex(s2t(parent), parentIdx);
return descMode ? executeActionGet(r) : getDescValue(executeActionGet(r), property)
}
this.descToObject = function (d) {
var o = {}
for (var i = 0; i < d.count; i++) {
var k = d.getKey(i)
o[t2s(k)] = getDescValue(d, k)
}
return o
}
this.transform = function (dX, dY, scale, x, y, subject) {
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
d.putEnumerated(s2t('freeTransformCenterState'), s2t('quadCenterState'), s2t('QCSIndependent'));
((d1 = new ActionDescriptor())).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), x);
d1.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), y);
d.putObject(s2t('position'), s2t('paint'), d1);
(d2 = new ActionDescriptor()).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), dX);
d2.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), dY);
d.putObject(s2t('offset'), s2t('offset'), d2);
d.putUnitDouble(s2t('width'), s2t('percentUnit'), scale);
d.putUnitDouble(s2t('height'), s2t('percentUnit'), scale);
d.putEnumerated(s2t('interfaceIconFrameDimmed'), s2t('interpolationType'), s2t('bicubic'));
executeAction(s2t('transform'), d, DialogModes.NO);
if (subject) {
with (subject) {
var dV = (height * scale / 100 - (bottom - top)),
dH = (width * scale / 100 - (right - left));
top = top - (dV * (y - top) / height) + dY
bottom = bottom + (dV * (bottom - y) / height) + dY
left = left - (dH * (x - left) / width) + dX
right = right + (dH * (right - x) / width) + dX
height = height * scale / 100
width = width * scale / 100
}
}
}
function getDescValue(d, p) {
switch (d.getType(p)) {
case DescValueType.OBJECTTYPE: return (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 [t2s(d.getEnumerationType(p)), t2s(d.getEnumerationValue(p))];
default: break;
};
}
}
PS. I would like to recalculate coordinates after rotation. Now I don't need it, but one day it might come in handy.
Copy link to clipboard
Copied
What kind of layer is it? Do you mean by layer the entire gray area, while the blue square is an object with some x, y point inside? Or gray area is some background of other layer while the mentioned layer is a blue square, that said, the x, y object would be then an object?
Copy link to clipboard
Copied
gray area - layer, blue square - object in this layer