Skip to main content
Participating Frequently
February 25, 2018
Answered

Stretch image in one dimension

  • February 25, 2018
  • 2 replies
  • 6584 views

Hi, I need to create a slice of an image and then stretch it either horizontally or vertically by a few millimetres. This would be the same as holding down the Command or Control key while dragging on a handle. Any help would be much appreciated.

Stuart

This topic has been closed for replies.
Correct answer Peter Kahrel

Just set the horizontalScale of the image's container (a rectangle).

P.

2 replies

Marc Autret
Legend
March 3, 2018

Hi all,

Not sure I clearly understood the goal, but it was really exciting to play with the idea.

Here is a first try, and first draft of my AutoFeedSlug script.

function nonZero(/*num*/x,  e)

//----------------------------------------------------------

// EPSILON-aware nonzero test.

{

    e = Math.pow(2,-51);

    return ( 0 > x ? -x : x ) > e;

};

function autoFeedSlug(/*?Image[0]*/img,  pge,rec,side,dpg,snap,edge,a,i,t,s,o)

//----------------------------------------------------------

// Given an Image that should extend up to the slug but has not enough material,

// try to feed the missing area by fitting and rescaling a slice of the picture.

// [REM] The code autodetects the edge of interest, provided the image presents any

// border close to a page edge. (Also, make sure the container has no stroke.)

{

    // Settings and constants.

    // ---

    const SNAP = .05;            // 5% of the lowest page dim.

    const FIT_FACTOR = 2;        // Should be 2 (IMHO) to optimize the joint.

    const PGE=0, REC=1, IMG=2;   // Simple enum.

    // ---

    const CS_SPREAD = +CoordinateSpaces.SPREAD_COORDINATES;

    const BB_GEO = +BoundingBoxLimits.GEOMETRIC_PATH_BOUNDS;

    const RM_MULT = +ResizeMethods.MULTIPLYING_CURRENT_DIMENSIONS_BY;

    const RC_KEEP = +ResizeConstraints.KEEP_CURRENT_VALUE;

    const PS_LEFT = +PageSideOptions.LEFT_HAND;

    const PS_RIGHT = +PageSideOptions.RIGHT_HAND;

    // Checkpoints.

    // ---

    if( FIT_FACTOR <= 1 )

    {

        alert("The FIT_FACTOR setting must be greater than 1.");

    }

    while( (!img) || (1!=img.length) || !((img=img[0]) instanceof Image) )

    {

        if( img.hasOwnProperty('images') && (img=img.images).length && ((img=img[0]) instanceof Image) ) break;

        alert("Select an Image.");

        return;

    }

    if( !(pge=img.properties.parentPage) )

    {

        alert("The Image must be on a page.");

        return;

    }

    if( !((rec=img.parent) instanceof Rectangle) || (0 < rec.properties.strokeWeight) )

    {

        alert("The Image must belong to a rectangular box having no stroke.");

        return;

    }

    // Metrics.

    // => `a` :: [ pageTLBR, recTLBR, imgTLBR ]

    // ---

    for( a=[pge,rec,img], i=PGE ; i <= IMG ; ++i )

    {

        t = a.transformValuesOf(CS_SPREAD)[0].matrixValues;

        if( nonZero(t[0]*t[1]) || nonZero(t[2]*t[3]) )

        {

            alert("No weird rotation should be applied to the "+a.constructor.name+".");

            return;

        }

        a = (t=a.properties[i===PGE?'bounds':'geometricBounds']);

        a.width = t[3]-t[1];

        a.height = t[2]-t[0];

    }

    // Page side.

    // => `side` :: -1_left  |  0_single  |  +1_right

    // ---

    side = +(0 < pge.documentOffset && pge.side);

    side = (side==PS_RIGHT)-(side==PS_LEFT);

    // Bleed.

    // => `dpg` :: [-top,-left, +bot,+right]

    // ---

    t = resolve(pge.toSpecifier().replace(/\/\/.+/,''));

    if( !(t instanceof Document) ) throw "Unable to find the parent document."

    t = t.documentPreferences.properties;

    dpg = t.documentBleedUniformSize ?

        ( (t=t.documentBleedTopOffset), [-t,-t,t,t] ) :

        [

            -t.documentBleedTopOffset,

            -t.documentBleedInsideOrLeftOffset,

            t.documentBleedBottomOffset,

            t.documentBleedOutsideOrRightOffset

        ];

    // Identify the most relevant edge.

    // => edge :: { 0:TLBR-index, dist:num }, -BLEED < dist < SNAP

    // ---

    snap = SNAP*Math.min(a[PGE].width, a[PGE].height);

    for( (edge=[i=-1]).dist=1/0 ; ++i < 4 ; )

    {

        // i :: 0_top ; 1_left ; 2_bot ; 3_right

        // Calculate the algebraic distance.

        // ---

        s = 2 > i ? 1 : -1;

        t = s*(Math[0<s?'max':'min'](a[REC],a[IMG])-a[PGE]);

        // Skip this edge if its distance to page > snap zone.

        // ---

        if( t > snap ) continue;

       

        // Skip this edge if it already reaches the bleed.

        // ---

        if( t <= s*dpg ) continue;

        // Skip this edge if it regards the spine.

        // ---

        if( side && side==2-i ) continue;

        t < edge.dist && (edge[0]=i,edge.dist=t);

    }

   

    if( 0 > (i=edge[0]) )

    {

        alert("Unable to find the relevant edge. Make sure the image is in the snap zone.");

        return;

    }

   

    // ---

    // Process.

    // ---

   

    // First, duplicate the rec applying the proper shift.

    // ---

    edge[0] = edge.dist*(2 > i ? -1 : 1) + dpg;

    edge[(1&i)?'push':'unshift'](0);

    t = rec.duplicate(void 0,edge);

   

    // Make sure autofit is off.

    // ---

    t.hasOwnProperty('frameFittingOptions') && t.clearFrameFittingOptions();

   

    // Adjust the geometric bounds.

    // ---

    o = t.geometricBounds;

    o = a[PGE]+dpg;

    o[2^i] = o-FIT_FACTOR*edge[1-(1&i)];

    t.geometricBounds = o;

   

    // Resize the inner image to fit.

    // ---

    img = t.images[0].getElements()[0];

   

    // Ok this step is a bit hacky, but basically

    // we want an anchor point in the form [u,v].

    // i==0  -->  [u,v]==[.5,0]  i.e center-TOP

    // i==1  -->  [u,v]==[0,.5]  i.e LEFT-center

    // i==2  -->  [u,v]==[.5,1]  i.e center-BOTTOM

    // i==3  -->  [u,v]==[1,.5]  i.e RIGHT-center

    // ---

    // It is important to resolve the location of

    // of that anchor relative to the container `t`,

    // not relative to the image bounding box, for

    // the image area may exceed the area of its

    // container! We must use the correct origin

    // in the resize transformation.

    // ---

    (ap=[.5])[(1&i)?'unshift':'push'](+(i>1));

    ap = t.resolve([ap,BB_GEO,CS_SPREAD],CS_SPREAD)[0];

    // Why do I use `resize()`? Because I'm not definitely

    // sure that 90 or 180 angles and/or reflections

    // applied to either the frame or the image couldn't

    // make fail naive methods. Resizing is reliable.

    // ---

    (a=[RC_KEEP])[(1&i)?'unshift':'push'](FIT_FACTOR);

    img.resize(

        CS_SPREAD,        // In-spread bounding box of the Image.

        [ap,CS_SPREAD],   // Origin as computed above (in the spread space)

        RM_MULT,          // Multiply the size by FIT_FACTOR...

        a);               // ...along the desired dimension.

    app.select(null);

};

app.doScript("autoFeedSlug(app.properties.selection)",

    ScriptLanguage.JAVASCRIPT,void 0,UndoModes.ENTIRE_SCRIPT,"AutoFeedSlug");

And here is a quick demo (not sure the link works):

AutoFeedSlug - YouTube

Best,

Marc

Marc Autret
Legend
March 3, 2018

As you have noted I constantly confuse the words 'bleed' and 'slug.'

So FeedBleed would probably be a better name for that script…

Marc Autret
Legend
March 25, 2018

Ah yes. Of course that will be a valid option.

Only the user may decide on showing parts of an image, not an automation per se…

Thanks,
Uwe


So I made a more advanced script.

New name: FillBleed. Supports CS4/CS5/CS6/CC and provides localization in EN (default), FR, DE, ES.

Here is how the UI of version 1.03 beta look like:

Download and test: http://indiscripts.com/blog/public/scripts/FillBleed.jsx

Note: This script is entirely based on IdExtenso's BasicScript module:

IdExtenso/$$.BasicScript.jsxlib at master · indiscripts/IdExtenso · GitHub

This was a perfect example for testing a real-world application of all its features :-)

@+

Marc

Peter Kahrel
Community Expert
Peter KahrelCommunity ExpertCorrect answer
Community Expert
February 26, 2018

Just set the horizontalScale of the image's container (a rectangle).

P.

stuarth64Author
Participating Frequently
February 26, 2018

Thank you Peter.

stuarth64Author
Participating Frequently
March 3, 2018

Hi Peter,

I finally got round to trying this but it's not the solution I need. What I'm trying to do is create missing bleed by duplicating a thin slice of the image, just in from each edge and then have the script replicate the action of dragging the centre outer handle out by a couple of millimetres while holding down the Command key.

I would really appreciate any help you or anyone else can offer.