Copy link to clipboard
Copied
Hello!
I work in Printing and we have a little problem - our printer gives an arc-like distortion to images on canvas
the distortion is like 1.8mm
so we use Transform-Warp-Arc Upper and input the distortion value in %, manually on each layer (
but this %value to make 1.8mm distortion differs from image to image
e.g. HxW 23.54x16.12 cm, value is -1.9%
HxW 40.16x27.84 cm, value is -2.2%
so wee put Guides and use Measure Tool to be sure about those 1.8mm
i need:
To write script, that will calculate the Warp-Upper Arc distorion %value (based on image size), to make this 1.8mm image correction, and then apply it to current selected layer
Can someone help me please? In any way
I`m very new to scripting T_T
Copy link to clipboard
Copied
So guys, i installed Script Listener, to see Warp tool settings, but i could get any mathematic formula for this process
var desc3 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idRlt = charIDToTypeID( "#Rlt" );
desc3.putUnitDouble( idHrzn, idRlt, 0.000000 );
var idVrtc = charIDToTypeID( "Vrtc" );
var idRlt = charIDToTypeID( "#Rlt" );
desc3.putUnitDouble( idVrtc, idRlt, 0.000000 );
var idOfst = charIDToTypeID( "Ofst" );
desc2.putObject( idOfst, idOfst, desc3 );
var idwarp = stringIDToTypeID( "warp" );
var desc4 = new ActionDescriptor();
var idwarpStyle = stringIDToTypeID( "warpStyle" );
var idwarpStyle = stringIDToTypeID( "warpStyle" );
var idwarpArcUpper = stringIDToTypeID( "warpArcUpper" );
desc4.putEnumerated( idwarpStyle, idwarpStyle, idwarpArcUpper );
var idwarpValue = stringIDToTypeID( "warpValue" );
desc4.putDouble( idwarpValue, -1.800000 );
var idwarpPerspective = stringIDToTypeID( "warpPerspective" );
desc4.putDouble( idwarpPerspective, 0.000000 );
var idwarpPerspectiveOther = stringIDToTypeID( "warpPerspectiveOther" );
desc4.putDouble( idwarpPerspectiveOther, 0.000000 );
var idwarpRotate = stringIDToTypeID( "warpRotate" );
var idOrnt = charIDToTypeID( "Ornt" );
var idHrzn = charIDToTypeID( "Hrzn" );
desc4.putEnumerated( idwarpRotate, idOrnt, idHrzn );
var iduOrder = stringIDToTypeID( "uOrder" );
desc4.putInteger( iduOrder, 4 );
var idvOrder = stringIDToTypeID( "vOrder" );
desc4.putInteger( idvOrder, 2 );
var idwarp = stringIDToTypeID( "warp" );
desc2.putObject( idwarp, idwarp, desc4 );
Do u have any ideas? How am i about to figure out the formula and where to place it?
Copy link to clipboard
Copied
Worst case you could check the bounds, apply the operation, then have the Script check the bounds again and undo and retry with a new value until the height difference is roughly the intended 1,8mm.
Copy link to clipboard
Copied
can you be more specific, from your problem I see that you need for every image with different WxH to distort the image with 1.8 mm, but from your example I see something else, because the first example truly gives an distortion of 1.8mm, the second one " HxW 40.16x27.84 cm, value is -2.2%" gives a distortion of 3.5mm not 1.8mm
Copy link to clipboard
Copied
Hello cbuliarca!
I really need 1.8mm distortion for every image ( no matter WxH)
about that mistake - excuse me, misspelled it seems, double-cheked HxW 40.16x27.84 cm value should be -1.2%
all images should be 127 dpi (if that matters)
Copy link to clipboard
Copied
So, mates, have someone come to a any solution? (((
Copy link to clipboard
Copied
I am digging now for 3-4 days, it's a hard one, till now I don't have a solution to find the percent, I'm still looking.... but to be honest I am really discouraged...
Any way maybe in the end I will take another approach and create a custom wrap, this is the easiest solution.
Copy link to clipboard
Copied
Thank you for your time investment, bro!
If u feel thats hard, please do not go too deep into this and dont waste ur time! Cause im myself not sure if its solvable at all, i think that maybe just not worth it!
Copy link to clipboard
Copied
Don't worry about this, I'he managed to do some custom warp, I still have to clean and add some things, but the ideea is that maybe tomorrow I will have the script ready for you.
Copy link to clipboard
Copied
This seems to get close, I wonder if you could test it?
#target photoshop;
app.bringToFront();
main();
function main(){
if(!documents.length) return;
try{
var doc = app.activeDocument;
app.displayDialogs = DialogModes.NO;
var strtRulerUnits = app.preferences.rulerUnits;
var strtTypeUnits = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
var res = doc.resolution;
var inch = res;
var cm = inch / 2.54;
var mm = cm /10;
var warpFactor = mm * 1.8;
//$.writeln("1.8mm = " + warpFactor + " pixels");
var bnds = doc.activeLayer.bounds;
var Height = bnds[3].value - bnds[1].value;
//$.writeln("Height = " + Height);
var warpValue = warpFactor/Height * 100;
//$.writeln("WarpValue = " + warpValue);
warpArcUpper(warpValue + (warpValue/1.75) );
/*
bnds = doc.activeLayer.bounds;
Height = bnds[3].value - bnds[1].value;
$.writeln("Height = " + Height);
*/
}catch(e){
}
finally{
app.preferences.rulerUnits = strtRulerUnits;
app.preferences.typeUnits = strtTypeUnits;
};
};
function warpArcUpper(warpValue) {
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('Qcs6') );
var desc2 = new ActionDescriptor();
desc2.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Rlt'), 0.000000 );
desc2.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Rlt'), -0.000000 );
desc.putObject( charIDToTypeID('Ofst'), charIDToTypeID('Ofst'), desc2 );
desc.putUnitDouble( charIDToTypeID('Hght'), charIDToTypeID('#Prc'), 100 );
var desc3 = new ActionDescriptor();
desc3.putEnumerated( stringIDToTypeID('warpStyle'), stringIDToTypeID('warpStyle'), stringIDToTypeID('warpArcUpper') );
desc3.putDouble( stringIDToTypeID('warpValue'), warpValue );
desc3.putDouble( stringIDToTypeID('warpPerspective'), 0.000000 );
desc3.putDouble( stringIDToTypeID('warpPerspectiveOther'), 0.000000 );
desc3.putEnumerated( stringIDToTypeID('warpRotate'), charIDToTypeID('Ornt'), charIDToTypeID('Hrzn') );
desc3.putInteger( stringIDToTypeID('uOrder'), 4 );
desc3.putInteger( stringIDToTypeID('vOrder'), 2 );
desc.putObject( stringIDToTypeID('warp'), stringIDToTypeID('warp'), desc3 );
desc.putEnumerated( charIDToTypeID('Intr'), charIDToTypeID('Intp'), charIDToTypeID('Bcbc') );
executeAction( charIDToTypeID('Trnf'), desc, DialogModes.NO );
};
Edit: No it doesn't work, but it did for a few tests.
So looking forward to the answer
Copy link to clipboard
Copied
Here is a script that creates a custom wrap, maybe before running it you can make the layer a smart object,
so you can see the wrap after.
function Vector(x, y){
this.x = x;
this.y = y;
}
Vector.prototype = {
add: function(other){
if( other instanceof Vector){
return new Vector(this.x + other.x, this.y + other.y);
}else{
return new Vector(this.x + parseFloat(other), this.y + parseFloat(other));
}
},
sub: function(other){
if( other instanceof Vector){
return new Vector(this.x - other.x, this.y - other.y);
}else{
return new Vector(this.x - parseFloat(other), this.y - parseFloat(other));
}
},
mul: function(scalar){
return new Vector(this.x * scalar, this.y * scalar);
},
mag: function(){
return (Math.sqrt(this.x*this.x + this.y*this.y));
},
normalize: function(){
vectorLength = this.mag();
return new Vector(this.x/vectorLength, this.y/vectorLength);
},
dot:function (other){
return other.x * this.x + other.y * this.y;
},
angle:function(other){
rr = (Math.atan2((other.x-this.x),(this.y-other.y))) * (360.0/(2.0*Math.PI));
qq = rr;
return qq;
},
rotate:function( angle ){
theta = angle * ((2.0*Math.PI)/360);// to radians
cs = Math.cos(theta);
sn = Math.sin(theta);
px = this.x * cs - this.y * sn;
py = this.x * sn + this.y * cs;
return new Vector(px, py);
},
perpendicular:function(dir){// 1 or -1
if(dir == 1){
return new Vector(this.y, -this.x);
}else{
return new Vector(-this.y, this.x);
}
}
}
function Bezier(a, b, c, d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.len = 500;//precision
this.arcLengths = new Array(this.len + 1);
this.arcLengths[0] = 0;
var ox = this.x(0);
var oy = this.y(0);
var clen = 0;
for(var i = 1; i <= this.len; i += 1) {
var x = this.x(i/this.len), y = this.y(i/this.len);
var dx = ox - x, dy = oy - y;
clen += Math.sqrt(dx * dx + dy * dy);
this.arcLengths = clen;
ox = x, oy = y;
}
this.length = clen;
}
Bezier.prototype = {
map: function(u) {
var targetLength = u * this.arcLengths[this.len];
var low = 0, high = this.len, index = 0;
while (low < high) {
index = low + (((high - low) / 2) | 0);
if (this.arcLengths[index] < targetLength) {
low = index + 1;
} else {
high = index;
}
}
if (this.arcLengths[index] > targetLength) {
index--;
}
var lengthBefore = this.arcLengths[index];
if (lengthBefore === targetLength) {
return index / this.len;
} else {
return (index + (targetLength - lengthBefore) / (this.arcLengths[index + 1] - lengthBefore)) / this.len;
}
},
mx: function (u) {
return this.x(this.map(u));
// return this.x(u);
},
my: function (u) {
return this.y(this.map(u));
// return this.y(u);
},
x: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.x
+ 3 * ((1 - t) * (1 - t)) * t * this.b.x
+ 3 * (1 - t) * (t * t) * this.c.x
+ (t * t * t) * this.d.x;
},
y: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.y
+ 3 * ((1 - t) * (1 - t)) * t * this.b.y
+ 3 * (1 - t) * (t * t) * this.c.y
+ (t * t * t) * this.d.y;
},
tan:function(t){
t = this.map(t);
var C1x = ( this.d.x - (3.0 * this.c.x) + (3.0 * this.b.x) - this.a.x );
var C2x = ( (3.0 * this.c.x) - (6.0 * this.b.x) + (3.0 * this.a.x) );
var C3x = ( (3.0 * this.b.x) - (3.0 * this.a.x) );
var C4x = ( this.a.x );
var C1y = ( this.d.y - (3.0 * this.c.y) + (3.0 * this.b.y) - this.a.y );
var C2y = ( (3.0 * this.c.y) - (6.0 * this.b.y) + (3.0 * this.a.y) );
var C3y = ( (3.0 * this.b.y) - (3.0 * this.a.y) );
var C4y = ( this.a.y );
return new Vector((( 3.0 * C1x * t * t ) + ( 2.0 * C2x * t ) + C3x),(( 3.0 * C1y * t * t ) + ( 2.0 * C2y * t ) + C3y));
},
// http://blog.avangardo.com/2010/10/c-implementation-of-bezier-curvature-calculation/::
getDerivate:function(t){
tSquared = t * t;
s0 = -3 + 6 * t - 3 * tSquared;
s1 = 3 - 12 * t + 9 * tSquared;
s2 = 6 * t - 9 * tSquared;
s3 = 3 * tSquared;
resultX = this.a.x * s0 + this.b.x * s1 + this.c.x * s2 + this.d.x * s3;
resultY = this.a.y * s0 + this.b.y * s1 + this.c.y * s2 + this.d.y * s3;
return new Vector(resultX, resultY);
},
getSecondDerivate:function(t){
s0 = 6 - 6 * t;
s1 = -12 + 18 * t;
s2 = 6 - 18 * t;
s3 = 6 * t;
resultX = this.a.x * s0 + this.b.x * s1 + this.c.x * s2 + this.d.x * s3;
resultY = this.a.y * s0 + this.b.y * s1 + this.c.y * s2 + this.d.y * s3;
return new Vector(resultX, resultY);
},
getCurvatureRadius:function(t){
d1 = this.getDerivate(t);
d2 = this.getSecondDerivate(t);
r1 = Math.sqrt(Math.pow(d1.x * d1.x + d1.y * d1.y, 3));
r2 = Math.abs(d1.x * d2.y - d2.x * d1.y);
return r1 / r2;
},
toPSPath:function( add ){// true or false if I want to add the path
//to psd path
var lineArray3 = new Array()
lineArray3[0] = new PathPointInfo
lineArray3[0].kind = PointKind.CORNERPOINT
lineArray3[0].anchor = Array(this.a.x, this.a.y)
lineArray3[0].leftDirection = Array(this.b.x, this.b.y)
lineArray3[0].rightDirection = Array(this.a.x, this.a.y)
lineArray3[1] = new PathPointInfo
lineArray3[1].kind = PointKind.CORNERPOINT
lineArray3[1].anchor = Array(this.d.x, this.d.y)
lineArray3[1].rightDirection = Array(this.c.x, this.c.y)
lineArray3[1].leftDirection = Array(this.d.x, this.d.y)
var lineSubPathArray = new Array()
lineSubPathArray[0] = new SubPathInfo()
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR
lineSubPathArray[0].closed = false
lineSubPathArray[0].entireSubPath = lineArray3
if( add == true){
var suffix = 0;
for( var i=0; i<app.activeDocument.pathItems.length; i++){
var pth = app.activeDocument.pathItems.name.toString();
if( pth.search("BCM_Bezier_") != -1 ){
var ss = pth.split("BCM_Bezier_");
suffix = parseInt(ss[1]) + 1;
}
}
var myPathItem = app.activeDocument.pathItems.add(("BCM_Bezier_"+suffix), lineSubPathArray);
kk = app.activeDocument.pathItems.length -1;
if(kk < 1){//no path to add to
alert('no path to add to');
}else{
tcPthN = app.activeDocument.pathItems[kk].name;
ttrgPthN = app.activeDocument.pathItems[kk - 1].name;
// =======================================================select the new path
var desc264 = new ActionDescriptor();
var ref206 = new ActionReference();
ref206.putName( charIDToTypeID( "Path" ), tcPthN );
desc264.putReference( charIDToTypeID( "null" ), ref206 );
executeAction( charIDToTypeID( "slct" ), desc264, DialogModes.NO );
// =======================================================copy
var idcopy = charIDToTypeID( "copy" );
executeAction( idcopy, undefined, DialogModes.NO );
// =======================================================select the targhet path
var desc264 = new ActionDescriptor();
var ref206 = new ActionReference();
ref206.putName( charIDToTypeID( "Path" ), ttrgPthN );
desc264.putReference( charIDToTypeID( "null" ), ref206 );
executeAction( charIDToTypeID( "slct" ), desc264, DialogModes.NO );
// =======================================================paste the paths
var idpast = charIDToTypeID( "past" );
executeAction( idpast, undefined, DialogModes.NO );
// =======================================================delete the new path
var idDlt = charIDToTypeID( "Dlt " );
var desc48 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref42 = new ActionReference();
ref42.putName( charIDToTypeID( "Path" ), tcPthN );
desc48.putReference( idnull, ref42 );
executeAction( idDlt, desc48, DialogModes.NO );
}
}else{
var suffix = 0;
for( var i=0; i<app.activeDocument.pathItems.length; i++){
var pth = app.activeDocument.pathItems.name.toString();
if( pth.search("BCM_Bezier_") != -1 ){
var ss = pth.split("BCM_Bezier_");
suffix = parseInt(ss[1]) + 1;
}
}
var myPathItem = app.activeDocument.pathItems.add(("BCM_Bezier_"+suffix), lineSubPathArray);
}
}
};
// http://polymathprogrammer.com/downloads/bezierinterpolation.c
// http://polymathprogrammer.com/2007/06/27/reverse-engineering-bezier-curves/
function getControlPolyPoints( p0x, p0y, u, p1x, p1y, v, p2x, p2y, p3x, p3y){
pos = [{x:0,y:0},{x:0,y:0},{x:0,y:0},{x:0,y:0}];
q1 = {x:0,y:0}
q2 = {x:0,y:0}
if ( (u<=0.0) || (u>=1.0) || (v<=0.0) || (v>=1.0) || (u>=v) ){
return 0; /* failure */
}
a = 3*(1-u)*(1-u)*u;
b = 3*(1-u)*u*u;
c = 3*(1-v)*(1-v)*v;
d = 3*(1-v)*v*v;
det = a*d - b*c;
/* unnecessary, but just in case... */
if (det == 0.0){ return 0;} /* failure */
pos[0].x = p0x; pos[0].y = p0y;
pos[3].x = p3x; pos[3].y = p3y;
q1.x = p1x - ( (1-u)*(1-u)*(1-u)*p0x + u*u*u*p3x );
q1.y = p1y - ( (1-u)*(1-u)*(1-u)*p0y + u*u*u*p3y );
q2.x = p2x - ( (1-v)*(1-v)*(1-v)*p0x + v*v*v*p3x );
q2.y = p2y - ( (1-v)*(1-v)*(1-v)*p0y + v*v*v*p3y );
pos[1].x = d*q1.x - b*q2.x;
pos[1].y = d*q1.y - b*q2.y;
pos[1].x /= det;
pos[1].y /= det;
pos[2].x = (-c)*q1.x + a*q2.x;
pos[2].y = (-c)*q1.y + a*q2.y;
pos[2].x /= det;
pos[2].y /= det;
return pos; /* success */
}
// https://www.particleincell.com/2013/cubic-line-intersection/
function cubicRoots(P)
{
var a=P[0];
var b=P[1];
var c=P[2];
var d=P[3];
var A=b/a;
var B=c/a;
var C=d/a;
var Q, R, D, S, T, Im;
var Q = (3*B - Math.pow(A, 2))/9;
var R = (9*A*B - 27*C - 2*Math.pow(A, 3))/54;
var D = Math.pow(Q, 3) + Math.pow(R, 2); // polynomial discriminant
var t=Array();
if (D >= 0) // complex or duplicate roots
{
var S = sgn(R + Math.sqrt(D))*Math.pow(Math.abs(R + Math.sqrt(D)),(1/3));
var T = sgn(R - Math.sqrt(D))*Math.pow(Math.abs(R - Math.sqrt(D)),(1/3));
t[0] = -A/3 + (S + T); // real root
t[1] = -A/3 - (S + T)/2; // real part of complex root
t[2] = -A/3 - (S + T)/2; // real part of complex root
Im = Math.abs(Math.sqrt(3)*(S - T)/2); // complex part of root pair
/*discard complex roots*/
if (Im!=0)
{
t[1]=-1;
t[2]=-1;
}
}
else // distinct real roots
{
var th = Math.acos(R/Math.sqrt(-Math.pow(Q, 3)));
t[0] = 2*Math.sqrt(-Q)*Math.cos(th/3) - A/3;
t[1] = 2*Math.sqrt(-Q)*Math.cos((th + 2*Math.PI)/3) - A/3;
t[2] = 2*Math.sqrt(-Q)*Math.cos((th + 4*Math.PI)/3) - A/3;
Im = 0.0;
}
/*discard out of spec roots*/
for (var i=0;i<3;i++)
if (t<0 || t>1.0) t=-1;
/*sort but place -1 at the end*/
t=sortSpecial(t);
// console.log(t[0]+" "+t[1]+" "+t[2]);
return t;
}
/*computes intersection between a cubic spline and a line segment*/
function computeIntersections(px,py,lx,ly)
// px is array of 4 bezier control points at x
// lx is array of the 2 points of the line at x
{
var X=Array();
var A=ly[1]-ly[0]; //A=y2-y1
var B=lx[0]-lx[1]; //B=x1-x2
var C=lx[0]*(ly[0]-ly[1]) +
ly[0]*(lx[1]-lx[0]); //C=x1*(y1-y2)+y1*(x2-x1)
var bx = bezierCoeffs(px[0],px[1],px[2],px[3]);
var by = bezierCoeffs(py[0],py[1],py[2],py[3]);
var P = Array();
P[0] = A*bx[0]+B*by[0]; /*t^3*/
P[1] = A*bx[1]+B*by[1]; /*t^2*/
P[2] = A*bx[2]+B*by[2]; /*t*/
P[3] = A*bx[3]+B*by[3] + C; /*1*/
var r=cubicRoots(P);
/*verify the roots are in bounds of the linear segment*/
returned = [];
for (var i=0;i<3;i++)
{
t=r;
X[0]=bx[0]*t*t*t+bx[1]*t*t+bx[2]*t+bx[3];
X[1]=by[0]*t*t*t+by[1]*t*t+by[2]*t+by[3];
/*above is intersection point assuming infinitely long line segment,
make sure we are also in bounds of the line*/
var s;
if ((lx[1]-lx[0])!=0) /*if not vertical line*/
s=(X[0]-lx[0])/(lx[1]-lx[0]);
else
s=(X[1]-ly[0])/(ly[1]-ly[0]);
/*in bounds?*/
if (t<0 || t>1.0 || s<0 || s>1.0)
{
X[0]=-100; /*move off screen*/
X[1]=-100;
}
returned.push({x:X[0], y:X[1]});
}
return returned;
}
function sortSpecial(a)
{
var flip;
var temp;
do {
flip=false;
for (var i=0;i<a.length-1;i++)
{
if ((a[i+1]>=0 && a>a[i+1]) ||
(a<0 && a[i+1]>=0))
{
flip=true;
temp=a;
a=a[i+1];
a[i+1]=temp;
}
}
} while (flip);
return a;
}
// sign of number
function sgn( x )
{
if (x < 0.0) return -1;
return 1;
}
function bezierCoeffs(P0,P1,P2,P3)
{
var Z = Array();
Z[0] = -P0 + 3*P1 + -3*P2 + P3;
Z[1] = 3*P0 - 6*P1 + 3*P2;
Z[2] = -3*P0 + 3*P1;
Z[3] = P0;
return Z;
}
function warpUpperArcUntilMM( value ){
theDistnaceInPx = convertFromMMToPx( value );
var strtRulerUnits = app.preferences.rulerUnits;
var strtTypeUnits = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.PIXELS;
W = parseFloat(app.activeDocument.width);
H = parseFloat(app.activeDocument.height);
var a1 = {x:0, y:0};
var m1 = {x:W/2, y:theDistnaceInPx};
var d1 = {x:W, y:0};
resC = getCubicBezierControlPointsWithCenterAt(a1, m1, d1);
var b1 = {x:resC[0][0], y:resC[0][1]};
var c1 = {x:resC[1][0], y:resC[1][1]};
mmBz = new Bezier(a1, b1, c1, d1);
//the Correction curve::
var a2 = {x:W*(1/3), y:0};
var b2 = {x:calculateFromProc(29.8142398589065,W), y:calculateFromProc(43.3226251146384,W/2)};
var c2 = {x:calculateFromProc(20.8158404938272,W), y:calculateFromProc(81.7067695238095, W/2)};
var d2 = {x:calculateFromProc(0.00000232804233,W), y:calculateFromProc(133.333328606702, W/2)};
sb2 = getControlPolyPoints( a2.x, a2.y, 0.433778236216, b2.x, b2.y, 0.7, c2.x, c2.y, d2.x, d2.y);
mmBz2Ref = new Bezier(sb2[0], sb2[1], sb2[2], sb2[3]);
// for the intersections:::
bmmBzPx = [mmBz2Ref.a.x,mmBz2Ref.b.x,mmBz2Ref.c.x, mmBz2Ref.d.x];
bmmBzPy = [mmBz2Ref.a.y,mmBz2Ref.b.y,mmBz2Ref.c.y, mmBz2Ref.d.y];
lPx = [0, mmBz.b.x];
lPy = [mmBz.b.y, mmBz.b.y];
inters = computeIntersections(bmmBzPx,bmmBzPy,lPx,lPy);
for( var a = 0; a<inters.length; a++){
if( inters.x != -100){
// addCountAt( inters.x, inters.y);
mmBz.b = {x:inters.x, y:inters.y};
mmBz.c = {x:W - inters.x, y:inters.y};
}
}
// the vertical lines:
var al0 = {x:mmBz.b.x, y:mmBz.b.y};
var bl0 = {x:mmBz.b.x, y:mmBz.b.y};
var cl0 = {x:W*(1/3), y:H};
var dl0 = {x:W*(1/3), y:H};
var mmBzLine0 = new Bezier(al0, bl0, cl0, dl0);
var al1 = {x:mmBz.c.x, y:mmBz.c.y};
var bl1 = {x:mmBz.c.x, y:mmBz.c.y};
var cl1 = {x:W*(2/3), y:H};
var dl1 = {x:W*(2/3), y:H};
var mmBzLine1 = new Bezier(al1, bl1, cl1, dl1);
// the other 2 lines:
var a3 = {x:0,y:H*(1/3)};
var b3 = {x:mmBzLine0.mx(1/3),y:mmBzLine0.my(1/3)};
var c3 = {x:mmBzLine1.mx(1/3),y:mmBzLine1.my(1/3)};
var d3 = {x:W,y:H*(1/3)};
var mmBz1 = new Bezier(a3, b3,c3, d3);
var a4 = {x:0,y:H*(2/3)};
var b4 = {x:mmBzLine0.mx(2/3),y:mmBzLine0.my(2/3)};
var c4 = {x:mmBzLine1.mx(2/3),y:mmBzLine1.my(2/3)};
var d4 = {x:W,y:H*(2/3)};
var mmBz2 = new Bezier(a4, b4,c4, d4);
var a5 = {x:0,y:H};
var b5 = {x:W*(1/3),y:H};
var c5 = {x:W*(2/3),y:H};
var d5 = {x:W,y:H};
var mmBz3 = new Bezier(a5, b5,c5, d5);
bnds = {top:0, left:0, bottom:H, right:W};
points = [ mmBz.a, mmBz.b, mmBz.c, mmBz.d,
mmBz1.a, mmBz1.b, mmBz1.c, mmBz1.d,
mmBz2.a, mmBz2.b, mmBz2.c, mmBz2.d,
mmBz3.a, mmBz3.b, mmBz3.c, mmBz3.d
];
warpTransf(bnds, points);
app.preferences.rulerUnits = strtRulerUnits;
app.preferences.typeUnits = strtTypeUnits;
}
function calculateFromProc(val, relTo){
return (relTo*val)/100;
}
function calculateToProc(val, relTo){
return (100*val)/relTo;
}
function getCubicBezierControlPointsWithCenterAt( a, m, d ){
bx = (m.x - (1 - .75)* d.x) / .75;
by = (m.y - (1 - .75)* d.y) / .75;
cx = (m.x - (1 - .75)* a.x) / .75;
cy = (m.y - (1 - .75)* a.y) / .75;
pos = []
pos.push([bx, by]);
pos.push([cx, cy]);
return pos;
}
function convertFromMMToPx( mm ){
var doc = app.activeDocument;
var strtRulerUnits = app.preferences.rulerUnits;
var strtTypeUnits = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.MM;
app.activeDocument.guides.add(Direction.HORIZONTAL, mm);
app.preferences.rulerUnits = Units.PIXELS;
var PxVal = app.activeDocument.guides[app.activeDocument.guides.length -1 ].coordinate;
app.activeDocument.guides[app.activeDocument.guides.length -1 ].remove();
app.preferences.rulerUnits = strtRulerUnits;
app.preferences.typeUnits = strtTypeUnits;
return parseFloat(PxVal);
}
function warpTransf(bounds, points){
// =======================================================
var idTrnf = charIDToTypeID( "Trnf" );
var desc259 = new ActionDescriptor();
var idFTcs = charIDToTypeID( "FTcs" );
var idQCSt = charIDToTypeID( "QCSt" );
var idQcsa = charIDToTypeID( "Qcsa" );
desc259.putEnumerated( idFTcs, idQCSt, idQcsa );
var idwarp = stringIDToTypeID( "warp" );
var desc261 = new ActionDescriptor();
var idwarpStyle = stringIDToTypeID( "warpStyle" );
var idwarpStyle = stringIDToTypeID( "warpStyle" );
var idwarpCustom = stringIDToTypeID( "warpCustom" );
desc261.putEnumerated( idwarpStyle, idwarpStyle, idwarpCustom );
var idwarpValue = stringIDToTypeID( "warpValue" );
desc261.putDouble( idwarpValue, 0.000000 );
var idwarpPerspective = stringIDToTypeID( "warpPerspective" );
desc261.putDouble( idwarpPerspective, 0.000000 );
var idwarpPerspectiveOther = stringIDToTypeID( "warpPerspectiveOther" );
desc261.putDouble( idwarpPerspectiveOther, 0.000000 );
var idwarpRotate = stringIDToTypeID( "warpRotate" );
var idOrnt = charIDToTypeID( "Ornt" );
var idHrzn = charIDToTypeID( "Hrzn" );
desc261.putEnumerated( idwarpRotate, idOrnt, idHrzn );
var idbounds = stringIDToTypeID( "bounds" );
var desc262 = new ActionDescriptor();
var idTop = charIDToTypeID( "Top " );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idTop, idPxl, bounds.top );
var idLeft = charIDToTypeID( "Left" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idLeft, idPxl, bounds.left );
var idBtom = charIDToTypeID( "Btom" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idBtom, idPxl, bounds.bottom );
var idRght = charIDToTypeID( "Rght" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idRght, idPxl, bounds.right );
var idRctn = charIDToTypeID( "Rctn" );
desc261.putObject( idbounds, idRctn, desc262 );
var iduOrder = stringIDToTypeID( "uOrder" );
desc261.putInteger( iduOrder, 4 );
var idvOrder = stringIDToTypeID( "vOrder" );
desc261.putInteger( idvOrder, 4 );
var idcustomEnvelopeWarp = stringIDToTypeID( "customEnvelopeWarp" );
var desc263 = new ActionDescriptor();
var idmeshPoints = stringIDToTypeID( "meshPoints" );
var list81 = new ActionList();
var desc264 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc264.putUnitDouble( idHrzn, idPxl, points[0].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc264.putUnitDouble( idVrtc, idPxl, points[0].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc264 );
var desc265 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc265.putUnitDouble( idHrzn, idPxl, points[4].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc265.putUnitDouble( idVrtc, idPxl, points[4].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc265 );
var desc266 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc266.putUnitDouble( idHrzn, idPxl, points[8].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc266.putUnitDouble( idVrtc, idPxl, points[8].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc266 );
var desc267 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc267.putUnitDouble( idHrzn, idPxl, points[12].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc267.putUnitDouble( idVrtc, idPxl, points[12].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc267 );
var desc268 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc268.putUnitDouble( idHrzn, idPxl, points[1].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc268.putUnitDouble( idVrtc, idPxl, points[1].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc268 );
var desc269 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc269.putUnitDouble( idHrzn, idPxl, points[5].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc269.putUnitDouble( idVrtc, idPxl, points[5].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc269 );
var desc270 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc270.putUnitDouble( idHrzn, idPxl, points[9].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc270.putUnitDouble( idVrtc, idPxl, points[9].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc270 );
var desc271 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc271.putUnitDouble( idHrzn, idPxl, points[13].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc271.putUnitDouble( idVrtc, idPxl, points[13].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc271 );
var desc272 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc272.putUnitDouble( idHrzn, idPxl, points[2].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc272.putUnitDouble( idVrtc, idPxl, points[2].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc272 );
var desc273 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc273.putUnitDouble( idHrzn, idPxl, points[6].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc273.putUnitDouble( idVrtc, idPxl, points[6].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc273 );
var desc274 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc274.putUnitDouble( idHrzn, idPxl, points[10].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc274.putUnitDouble( idVrtc, idPxl, points[10].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc274 );
var desc275 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc275.putUnitDouble( idHrzn, idPxl, points[14].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc275.putUnitDouble( idVrtc, idPxl, points[14].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc275 );
var desc276 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc276.putUnitDouble( idHrzn, idPxl, points[3].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc276.putUnitDouble( idVrtc, idPxl, points[3].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc276 );
var desc277 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc277.putUnitDouble( idHrzn, idPxl, points[7].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc277.putUnitDouble( idVrtc, idPxl, points[7].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc277 );
var desc278 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc278.putUnitDouble( idHrzn, idPxl, points[11].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc278.putUnitDouble( idVrtc, idPxl, points[11].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc278 );
var desc279 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc279.putUnitDouble( idHrzn, idPxl, points[15].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc279.putUnitDouble( idVrtc, idPxl, points[15].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc279 );
desc263.putList( idmeshPoints, list81 );
var idcustomEnvelopeWarp = stringIDToTypeID( "customEnvelopeWarp" );
desc261.putObject( idcustomEnvelopeWarp, idcustomEnvelopeWarp, desc263 );
var idwarp = stringIDToTypeID( "warp" );
desc259.putObject( idwarp, idwarp, desc261 );
executeAction( idTrnf, desc259, DialogModes.NO );
}
app.activeDocument.suspendHistory("bcmWarpCustomUpperArc", "warpUpperArcUntilMM( 1.8 )");
Copy link to clipboard
Copied
Just tested your code on windows 7 and Photoshop cs6 and it dosen't make any change whatsoever to the layer, no arc at all.
Copy link to clipboard
Copied
It's wierd, I've just tested the code I've posted on a mac in Cs6 and also in windows7 and cs6 and it works fine. Maybe you are testing it on a locked Background layer? Does it gives any errors?
Copy link to clipboard
Copied
I've modified the script to work with CS4 as well:
function Vector(x, y){
this.x = x;
this.y = y;
}
Vector.prototype = {
add: function(other){
if( other instanceof Vector){
return new Vector(this.x + other.x, this.y + other.y);
}else{
return new Vector(this.x + parseFloat(other), this.y + parseFloat(other));
}
},
sub: function(other){
if( other instanceof Vector){
return new Vector(this.x - other.x, this.y - other.y);
}else{
return new Vector(this.x - parseFloat(other), this.y - parseFloat(other));
}
},
mul: function(scalar){
return new Vector(this.x * scalar, this.y * scalar);
},
mag: function(){
return (Math.sqrt(this.x*this.x + this.y*this.y));
},
normalize: function(){
vectorLength = this.mag();
return new Vector(this.x/vectorLength, this.y/vectorLength);
},
dot:function (other){
return other.x * this.x + other.y * this.y;
},
angle:function(other){
rr = (Math.atan2((other.x-this.x),(this.y-other.y))) * (360.0/(2.0*Math.PI));
qq = rr;
return qq;
},
rotate:function( angle ){
theta = angle * ((2.0*Math.PI)/360);// to radians
cs = Math.cos(theta);
sn = Math.sin(theta);
px = this.x * cs - this.y * sn;
py = this.x * sn + this.y * cs;
return new Vector(px, py);
},
perpendicular:function(dir){// 1 or -1
if(dir == 1){
return new Vector(this.y, -this.x);
}else{
return new Vector(-this.y, this.x);
}
}
}
function Bezier(a, b, c, d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
this.len = 500;//precision
this.arcLengths = new Array(this.len + 1);
this.arcLengths[0] = 0;
var ox = this.x(0);
var oy = this.y(0);
var clen = 0;
for(var i = 1; i <= this.len; i += 1) {
var x = this.x(i/this.len), y = this.y(i/this.len);
var dx = ox - x, dy = oy - y;
clen += Math.sqrt(dx * dx + dy * dy);
this.arcLengths = clen;
ox = x, oy = y;
}
this.length = clen;
}
Bezier.prototype = {
map: function(u) {
var targetLength = u * this.arcLengths[this.len];
var low = 0, high = this.len, index = 0;
while (low < high) {
index = low + (((high - low) / 2) | 0);
if (this.arcLengths[index] < targetLength) {
low = index + 1;
} else {
high = index;
}
}
if (this.arcLengths[index] > targetLength) {
index--;
}
var lengthBefore = this.arcLengths[index];
if (lengthBefore === targetLength) {
return index / this.len;
} else {
return (index + (targetLength - lengthBefore) / (this.arcLengths[index + 1] - lengthBefore)) / this.len;
}
},
mx: function (u) {
return this.x(this.map(u));
// return this.x(u);
},
my: function (u) {
return this.y(this.map(u));
// return this.y(u);
},
x: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.x
+ 3 * ((1 - t) * (1 - t)) * t * this.b.x
+ 3 * (1 - t) * (t * t) * this.c.x
+ (t * t * t) * this.d.x;
},
y: function (t) {
return ((1 - t) * (1 - t) * (1 - t)) * this.a.y
+ 3 * ((1 - t) * (1 - t)) * t * this.b.y
+ 3 * (1 - t) * (t * t) * this.c.y
+ (t * t * t) * this.d.y;
},
tan:function(t){
t = this.map(t);
var C1x = ( this.d.x - (3.0 * this.c.x) + (3.0 * this.b.x) - this.a.x );
var C2x = ( (3.0 * this.c.x) - (6.0 * this.b.x) + (3.0 * this.a.x) );
var C3x = ( (3.0 * this.b.x) - (3.0 * this.a.x) );
var C4x = ( this.a.x );
var C1y = ( this.d.y - (3.0 * this.c.y) + (3.0 * this.b.y) - this.a.y );
var C2y = ( (3.0 * this.c.y) - (6.0 * this.b.y) + (3.0 * this.a.y) );
var C3y = ( (3.0 * this.b.y) - (3.0 * this.a.y) );
var C4y = ( this.a.y );
return new Vector((( 3.0 * C1x * t * t ) + ( 2.0 * C2x * t ) + C3x),(( 3.0 * C1y * t * t ) + ( 2.0 * C2y * t ) + C3y));
},
// http://blog.avangardo.com/2010/10/c-implementation-of-bezier-curvature-calculation/::
getDerivate:function(t){
tSquared = t * t;
s0 = -3 + 6 * t - 3 * tSquared;
s1 = 3 - 12 * t + 9 * tSquared;
s2 = 6 * t - 9 * tSquared;
s3 = 3 * tSquared;
resultX = this.a.x * s0 + this.b.x * s1 + this.c.x * s2 + this.d.x * s3;
resultY = this.a.y * s0 + this.b.y * s1 + this.c.y * s2 + this.d.y * s3;
return new Vector(resultX, resultY);
},
getSecondDerivate:function(t){
s0 = 6 - 6 * t;
s1 = -12 + 18 * t;
s2 = 6 - 18 * t;
s3 = 6 * t;
resultX = this.a.x * s0 + this.b.x * s1 + this.c.x * s2 + this.d.x * s3;
resultY = this.a.y * s0 + this.b.y * s1 + this.c.y * s2 + this.d.y * s3;
return new Vector(resultX, resultY);
},
getCurvatureRadius:function(t){
d1 = this.getDerivate(t);
d2 = this.getSecondDerivate(t);
r1 = Math.sqrt(Math.pow(d1.x * d1.x + d1.y * d1.y, 3));
r2 = Math.abs(d1.x * d2.y - d2.x * d1.y);
return r1 / r2;
},
toPSPath:function( add ){// true or false if I want to add the path
//to psd path
var lineArray3 = new Array()
lineArray3[0] = new PathPointInfo
lineArray3[0].kind = PointKind.CORNERPOINT
lineArray3[0].anchor = Array(this.a.x, this.a.y)
lineArray3[0].leftDirection = Array(this.b.x, this.b.y)
lineArray3[0].rightDirection = Array(this.a.x, this.a.y)
lineArray3[1] = new PathPointInfo
lineArray3[1].kind = PointKind.CORNERPOINT
lineArray3[1].anchor = Array(this.d.x, this.d.y)
lineArray3[1].rightDirection = Array(this.c.x, this.c.y)
lineArray3[1].leftDirection = Array(this.d.x, this.d.y)
var lineSubPathArray = new Array()
lineSubPathArray[0] = new SubPathInfo()
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR
lineSubPathArray[0].closed = false
lineSubPathArray[0].entireSubPath = lineArray3
if( add == true){
var suffix = 0;
for( var i=0; i<app.activeDocument.pathItems.length; i++){
var pth = app.activeDocument.pathItems.name.toString();
if( pth.search("BCM_Bezier_") != -1 ){
var ss = pth.split("BCM_Bezier_");
suffix = parseInt(ss[1]) + 1;
}
}
var myPathItem = app.activeDocument.pathItems.add(("BCM_Bezier_"+suffix), lineSubPathArray);
kk = app.activeDocument.pathItems.length -1;
if(kk < 1){//no path to add to
alert('no path to add to');
}else{
tcPthN = app.activeDocument.pathItems[kk].name;
ttrgPthN = app.activeDocument.pathItems[kk - 1].name;
// =======================================================select the new path
var desc264 = new ActionDescriptor();
var ref206 = new ActionReference();
ref206.putName( charIDToTypeID( "Path" ), tcPthN );
desc264.putReference( charIDToTypeID( "null" ), ref206 );
executeAction( charIDToTypeID( "slct" ), desc264, DialogModes.NO );
// =======================================================copy
var idcopy = charIDToTypeID( "copy" );
executeAction( idcopy, undefined, DialogModes.NO );
// =======================================================select the targhet path
var desc264 = new ActionDescriptor();
var ref206 = new ActionReference();
ref206.putName( charIDToTypeID( "Path" ), ttrgPthN );
desc264.putReference( charIDToTypeID( "null" ), ref206 );
executeAction( charIDToTypeID( "slct" ), desc264, DialogModes.NO );
// =======================================================paste the paths
var idpast = charIDToTypeID( "past" );
executeAction( idpast, undefined, DialogModes.NO );
// =======================================================delete the new path
var idDlt = charIDToTypeID( "Dlt " );
var desc48 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref42 = new ActionReference();
ref42.putName( charIDToTypeID( "Path" ), tcPthN );
desc48.putReference( idnull, ref42 );
executeAction( idDlt, desc48, DialogModes.NO );
}
}else{
var suffix = 0;
for( var i=0; i<app.activeDocument.pathItems.length; i++){
var pth = app.activeDocument.pathItems.name.toString();
if( pth.search("BCM_Bezier_") != -1 ){
var ss = pth.split("BCM_Bezier_");
suffix = parseInt(ss[1]) + 1;
}
}
var myPathItem = app.activeDocument.pathItems.add(("BCM_Bezier_"+suffix), lineSubPathArray);
}
}
};
// http://polymathprogrammer.com/downloads/bezierinterpolation.c
// http://polymathprogrammer.com/2007/06/27/reverse-engineering-bezier-curves/
function getControlPolyPoints( p0x, p0y, u, p1x, p1y, v, p2x, p2y, p3x, p3y){
pos = [{x:0,y:0},{x:0,y:0},{x:0,y:0},{x:0,y:0}];
q1 = {x:0,y:0}
q2 = {x:0,y:0}
if ( (u<=0.0) || (u>=1.0) || (v<=0.0) || (v>=1.0) || (u>=v) ){
return 0; /* failure */
}
a = 3*(1-u)*(1-u)*u;
b = 3*(1-u)*u*u;
c = 3*(1-v)*(1-v)*v;
d = 3*(1-v)*v*v;
det = a*d - b*c;
/* unnecessary, but just in case... */
if (det == 0.0){ return 0;} /* failure */
pos[0].x = p0x; pos[0].y = p0y;
pos[3].x = p3x; pos[3].y = p3y;
q1.x = p1x - ( (1-u)*(1-u)*(1-u)*p0x + u*u*u*p3x );
q1.y = p1y - ( (1-u)*(1-u)*(1-u)*p0y + u*u*u*p3y );
q2.x = p2x - ( (1-v)*(1-v)*(1-v)*p0x + v*v*v*p3x );
q2.y = p2y - ( (1-v)*(1-v)*(1-v)*p0y + v*v*v*p3y );
pos[1].x = d*q1.x - b*q2.x;
pos[1].y = d*q1.y - b*q2.y;
pos[1].x /= det;
pos[1].y /= det;
pos[2].x = (-c)*q1.x + a*q2.x;
pos[2].y = (-c)*q1.y + a*q2.y;
pos[2].x /= det;
pos[2].y /= det;
return pos; /* success */
}
// https://www.particleincell.com/2013/cubic-line-intersection/
function cubicRoots(P)
{
var a=P[0];
var b=P[1];
var c=P[2];
var d=P[3];
var A=b/a;
var B=c/a;
var C=d/a;
var Q, R, D, S, T, Im;
var Q = (3*B - Math.pow(A, 2))/9;
var R = (9*A*B - 27*C - 2*Math.pow(A, 3))/54;
var D = Math.pow(Q, 3) + Math.pow(R, 2); // polynomial discriminant
var t=Array();
if (D >= 0) // complex or duplicate roots
{
var S = sgn(R + Math.sqrt(D))*Math.pow(Math.abs(R + Math.sqrt(D)),(1/3));
var T = sgn(R - Math.sqrt(D))*Math.pow(Math.abs(R - Math.sqrt(D)),(1/3));
t[0] = -A/3 + (S + T); // real root
t[1] = -A/3 - (S + T)/2; // real part of complex root
t[2] = -A/3 - (S + T)/2; // real part of complex root
Im = Math.abs(Math.sqrt(3)*(S - T)/2); // complex part of root pair
/*discard complex roots*/
if (Im!=0)
{
t[1]=-1;
t[2]=-1;
}
}
else // distinct real roots
{
var th = Math.acos(R/Math.sqrt(-Math.pow(Q, 3)));
t[0] = 2*Math.sqrt(-Q)*Math.cos(th/3) - A/3;
t[1] = 2*Math.sqrt(-Q)*Math.cos((th + 2*Math.PI)/3) - A/3;
t[2] = 2*Math.sqrt(-Q)*Math.cos((th + 4*Math.PI)/3) - A/3;
Im = 0.0;
}
/*discard out of spec roots*/
for (var i=0;i<3;i++)
if (t<0 || t>1.0) t=-1;
/*sort but place -1 at the end*/
t=sortSpecial(t);
// console.log(t[0]+" "+t[1]+" "+t[2]);
return t;
}
/*computes intersection between a cubic spline and a line segment*/
function computeIntersections(px,py,lx,ly)
// px is array of 4 bezier control points at x
// lx is array of the 2 points of the line at x
{
var X=Array();
var A=ly[1]-ly[0]; //A=y2-y1
var B=lx[0]-lx[1]; //B=x1-x2
var C=lx[0]*(ly[0]-ly[1]) +
ly[0]*(lx[1]-lx[0]); //C=x1*(y1-y2)+y1*(x2-x1)
var bx = bezierCoeffs(px[0],px[1],px[2],px[3]);
var by = bezierCoeffs(py[0],py[1],py[2],py[3]);
var P = Array();
P[0] = A*bx[0]+B*by[0]; /*t^3*/
P[1] = A*bx[1]+B*by[1]; /*t^2*/
P[2] = A*bx[2]+B*by[2]; /*t*/
P[3] = A*bx[3]+B*by[3] + C; /*1*/
var r=cubicRoots(P);
/*verify the roots are in bounds of the linear segment*/
returned = [];
for (var i=0;i<3;i++)
{
t=r;
X[0]=bx[0]*t*t*t+bx[1]*t*t+bx[2]*t+bx[3];
X[1]=by[0]*t*t*t+by[1]*t*t+by[2]*t+by[3];
/*above is intersection point assuming infinitely long line segment,
make sure we are also in bounds of the line*/
var s;
if ((lx[1]-lx[0])!=0) /*if not vertical line*/
s=(X[0]-lx[0])/(lx[1]-lx[0]);
else
s=(X[1]-ly[0])/(ly[1]-ly[0]);
/*in bounds?*/
if (t<0 || t>1.0 || s<0 || s>1.0)
{
X[0]=-100; /*move off screen*/
X[1]=-100;
}
returned.push({x:X[0], y:X[1]});
}
return returned;
}
function sortSpecial(a)
{
var flip;
var temp;
do {
flip=false;
for (var i=0;i<a.length-1;i++)
{
if ((a[i+1]>=0 && a>a[i+1]) ||
(a<0 && a[i+1]>=0))
{
flip=true;
temp=a;
a=a[i+1];
a[i+1]=temp;
}
}
} while (flip);
return a;
}
// sign of number
function sgn( x )
{
if (x < 0.0) return -1;
return 1;
}
function bezierCoeffs(P0,P1,P2,P3)
{
var Z = Array();
Z[0] = -P0 + 3*P1 + -3*P2 + P3;
Z[1] = 3*P0 - 6*P1 + 3*P2;
Z[2] = -3*P0 + 3*P1;
Z[3] = P0;
return Z;
}
function warpUpperArcUntilMM( value ){
theDistnaceInPx = convertFromMMToPx( value );
var strtRulerUnits = app.preferences.rulerUnits;
var strtTypeUnits = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.PIXELS;
W = parseFloat(app.activeDocument.width);
H = parseFloat(app.activeDocument.height);
var a1 = {x:0, y:0};
var m1 = {x:W/2, y:theDistnaceInPx};
var d1 = {x:W, y:0};
resC = getCubicBezierControlPointsWithCenterAt(a1, m1, d1);
var b1 = {x:resC[0][0], y:resC[0][1]};
var c1 = {x:resC[1][0], y:resC[1][1]};
mmBz = new Bezier(a1, b1, c1, d1);
//the Correction curve::
var a2 = {x:W*(1/3), y:0};
var b2 = {x:calculateFromProc(29.8142398589065,W), y:calculateFromProc(43.3226251146384,W/2)};
var c2 = {x:calculateFromProc(20.8158404938272,W), y:calculateFromProc(81.7067695238095, W/2)};
var d2 = {x:calculateFromProc(0.00000232804233,W), y:calculateFromProc(133.333328606702, W/2)};
sb2 = getControlPolyPoints( a2.x, a2.y, 0.433778236216, b2.x, b2.y, 0.7, c2.x, c2.y, d2.x, d2.y);
mmBz2Ref = new Bezier(sb2[0], sb2[1], sb2[2], sb2[3]);
// for the intersections:::
bmmBzPx = [mmBz2Ref.a.x,mmBz2Ref.b.x,mmBz2Ref.c.x, mmBz2Ref.d.x];
bmmBzPy = [mmBz2Ref.a.y,mmBz2Ref.b.y,mmBz2Ref.c.y, mmBz2Ref.d.y];
lPx = [0, mmBz.b.x];
lPy = [mmBz.b.y, mmBz.b.y];
inters = computeIntersections(bmmBzPx,bmmBzPy,lPx,lPy);
for( var a = 0; a<inters.length; a++){
if( inters.x != -100){
// addCountAt( inters.x, inters.y);
mmBz.b = {x:inters.x, y:inters.y};
mmBz.c = {x:W - inters.x, y:inters.y};
}
}
// the vertical lines:
var al0 = {x:mmBz.b.x, y:mmBz.b.y};
var bl0 = {x:mmBz.b.x, y:mmBz.b.y};
var cl0 = {x:W*(1/3), y:H};
var dl0 = {x:W*(1/3), y:H};
var mmBzLine0 = new Bezier(al0, bl0, cl0, dl0);
var al1 = {x:mmBz.c.x, y:mmBz.c.y};
var bl1 = {x:mmBz.c.x, y:mmBz.c.y};
var cl1 = {x:W*(2/3), y:H};
var dl1 = {x:W*(2/3), y:H};
var mmBzLine1 = new Bezier(al1, bl1, cl1, dl1);
// the other 2 lines:
var a3 = {x:0,y:H*(1/3)};
var b3 = {x:mmBzLine0.mx(1/3),y:mmBzLine0.my(1/3)};
var c3 = {x:mmBzLine1.mx(1/3),y:mmBzLine1.my(1/3)};
var d3 = {x:W,y:H*(1/3)};
var mmBz1 = new Bezier(a3, b3,c3, d3);
var a4 = {x:0,y:H*(2/3)};
var b4 = {x:mmBzLine0.mx(2/3),y:mmBzLine0.my(2/3)};
var c4 = {x:mmBzLine1.mx(2/3),y:mmBzLine1.my(2/3)};
var d4 = {x:W,y:H*(2/3)};
var mmBz2 = new Bezier(a4, b4,c4, d4);
var a5 = {x:0,y:H};
var b5 = {x:W*(1/3),y:H};
var c5 = {x:W*(2/3),y:H};
var d5 = {x:W,y:H};
var mmBz3 = new Bezier(a5, b5,c5, d5);
bnds = {top:0, left:0, bottom:H, right:W};
points = [ mmBz.a, mmBz.b, mmBz.c, mmBz.d,
mmBz1.a, mmBz1.b, mmBz1.c, mmBz1.d,
mmBz2.a, mmBz2.b, mmBz2.c, mmBz2.d,
mmBz3.a, mmBz3.b, mmBz3.c, mmBz3.d
];
warpTransf(bnds, points);
app.preferences.rulerUnits = strtRulerUnits;
app.preferences.typeUnits = strtTypeUnits;
}
function calculateFromProc(val, relTo){
return (relTo*val)/100;
}
function calculateToProc(val, relTo){
return (100*val)/relTo;
}
function getCubicBezierControlPointsWithCenterAt( a, m, d ){
bx = (m.x - (1 - .75)* d.x) / .75;
by = (m.y - (1 - .75)* d.y) / .75;
cx = (m.x - (1 - .75)* a.x) / .75;
cy = (m.y - (1 - .75)* a.y) / .75;
pos = []
pos.push([bx, by]);
pos.push([cx, cy]);
return pos;
}
function convertFromMMToPx( mm ){
return (mm*(app.activeDocument.resolution/25.4));
}
function warpTransf(bounds, points){
// =======================================================
var idTrnf = charIDToTypeID( "Trnf" );
var desc259 = new ActionDescriptor();
var idFTcs = charIDToTypeID( "FTcs" );
var idQCSt = charIDToTypeID( "QCSt" );
var idQcsa = charIDToTypeID( "Qcsa" );
desc259.putEnumerated( idFTcs, idQCSt, idQcsa );
var idwarp = stringIDToTypeID( "warp" );
var desc261 = new ActionDescriptor();
var idwarpStyle = stringIDToTypeID( "warpStyle" );
var idwarpStyle = stringIDToTypeID( "warpStyle" );
var idwarpCustom = stringIDToTypeID( "warpCustom" );
desc261.putEnumerated( idwarpStyle, idwarpStyle, idwarpCustom );
var idwarpValue = stringIDToTypeID( "warpValue" );
desc261.putDouble( idwarpValue, 0.000000 );
var idwarpPerspective = stringIDToTypeID( "warpPerspective" );
desc261.putDouble( idwarpPerspective, 0.000000 );
var idwarpPerspectiveOther = stringIDToTypeID( "warpPerspectiveOther" );
desc261.putDouble( idwarpPerspectiveOther, 0.000000 );
var idwarpRotate = stringIDToTypeID( "warpRotate" );
var idOrnt = charIDToTypeID( "Ornt" );
var idHrzn = charIDToTypeID( "Hrzn" );
desc261.putEnumerated( idwarpRotate, idOrnt, idHrzn );
var idbounds = stringIDToTypeID( "bounds" );
var desc262 = new ActionDescriptor();
var idTop = charIDToTypeID( "Top " );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idTop, idPxl, bounds.top );
var idLeft = charIDToTypeID( "Left" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idLeft, idPxl, bounds.left );
var idBtom = charIDToTypeID( "Btom" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idBtom, idPxl, bounds.bottom );
var idRght = charIDToTypeID( "Rght" );
var idPxl = charIDToTypeID( "#Pxl" );
desc262.putUnitDouble( idRght, idPxl, bounds.right );
var idRctn = charIDToTypeID( "Rctn" );
desc261.putObject( idbounds, idRctn, desc262 );
var iduOrder = stringIDToTypeID( "uOrder" );
desc261.putInteger( iduOrder, 4 );
var idvOrder = stringIDToTypeID( "vOrder" );
desc261.putInteger( idvOrder, 4 );
var idcustomEnvelopeWarp = stringIDToTypeID( "customEnvelopeWarp" );
var desc263 = new ActionDescriptor();
var idmeshPoints = stringIDToTypeID( "meshPoints" );
var list81 = new ActionList();
var desc264 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc264.putUnitDouble( idHrzn, idPxl, points[0].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc264.putUnitDouble( idVrtc, idPxl, points[0].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc264 );
var desc265 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc265.putUnitDouble( idHrzn, idPxl, points[4].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc265.putUnitDouble( idVrtc, idPxl, points[4].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc265 );
var desc266 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc266.putUnitDouble( idHrzn, idPxl, points[8].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc266.putUnitDouble( idVrtc, idPxl, points[8].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc266 );
var desc267 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc267.putUnitDouble( idHrzn, idPxl, points[12].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc267.putUnitDouble( idVrtc, idPxl, points[12].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc267 );
var desc268 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc268.putUnitDouble( idHrzn, idPxl, points[1].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc268.putUnitDouble( idVrtc, idPxl, points[1].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc268 );
var desc269 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc269.putUnitDouble( idHrzn, idPxl, points[5].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc269.putUnitDouble( idVrtc, idPxl, points[5].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc269 );
var desc270 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc270.putUnitDouble( idHrzn, idPxl, points[9].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc270.putUnitDouble( idVrtc, idPxl, points[9].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc270 );
var desc271 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc271.putUnitDouble( idHrzn, idPxl, points[13].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc271.putUnitDouble( idVrtc, idPxl, points[13].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc271 );
var desc272 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc272.putUnitDouble( idHrzn, idPxl, points[2].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc272.putUnitDouble( idVrtc, idPxl, points[2].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc272 );
var desc273 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc273.putUnitDouble( idHrzn, idPxl, points[6].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc273.putUnitDouble( idVrtc, idPxl, points[6].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc273 );
var desc274 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc274.putUnitDouble( idHrzn, idPxl, points[10].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc274.putUnitDouble( idVrtc, idPxl, points[10].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc274 );
var desc275 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc275.putUnitDouble( idHrzn, idPxl, points[14].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc275.putUnitDouble( idVrtc, idPxl, points[14].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc275 );
var desc276 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc276.putUnitDouble( idHrzn, idPxl, points[3].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc276.putUnitDouble( idVrtc, idPxl, points[3].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc276 );
var desc277 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc277.putUnitDouble( idHrzn, idPxl, points[7].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc277.putUnitDouble( idVrtc, idPxl, points[7].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc277 );
var desc278 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc278.putUnitDouble( idHrzn, idPxl, points[11].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc278.putUnitDouble( idVrtc, idPxl, points[11].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc278 );
var desc279 = new ActionDescriptor();
var idHrzn = charIDToTypeID( "Hrzn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc279.putUnitDouble( idHrzn, idPxl, points[15].x );
var idVrtc = charIDToTypeID( "Vrtc" );
var idPxl = charIDToTypeID( "#Pxl" );
desc279.putUnitDouble( idVrtc, idPxl, points[15].y );
var idrationalPoint = stringIDToTypeID( "rationalPoint" );
list81.putObject( idrationalPoint, desc279 );
desc263.putList( idmeshPoints, list81 );
var idcustomEnvelopeWarp = stringIDToTypeID( "customEnvelopeWarp" );
desc261.putObject( idcustomEnvelopeWarp, idcustomEnvelopeWarp, desc263 );
var idwarp = stringIDToTypeID( "warp" );
desc259.putObject( idwarp, idwarp, desc261 );
executeAction( idTrnf, desc259, DialogModes.NO );
}
app.activeDocument.suspendHistory("bcmWarpCustomUpperArc", "warpUpperArcUntilMM( 1.8 )");
Copy link to clipboard
Copied
I have just tested both scripts and neither work for me. I checked the bounds for the height of the layer before and after running the scripts and there was no difference. I ran mine ant it did create the arc.
I also tried runing both scripts without the suspend history, every run of the scripts didn't produce any errors at all.
Very strange.
Edit:
I saved the script and watched it in Photoshop, before I was running it from ESTK. I can now see that it is doing a curve but it is doing a LOWER not upper curve, that why the bounds were returning the same height.
Copy link to clipboard
Copied
Yes, actually that's what CapablancaYEAH nedded an interior arc, from his firts post I see that he uses -1.9.
I can adjust the script to go upper as well....
Copy link to clipboard
Copied
It's me not reading it right! I must do better next time! Sorry for confusing matters.
Copy link to clipboard
Copied
Dear friends!
Thank u very much for your help !
But i must tell, that our printing machine is having pretty bad failure times now.
Instead of constantly makin 1.8mm distorion it now gives various, unpredictable, depending of document width
So i think there is no sense making script anymore (( cause it has became too complicated, unsolvable
Excuse me, friends (
Copy link to clipboard
Copied
Ok, no problem , just to let you know the scrpt I've done can receve arguments, so you can alawys change the amount of distortion.