Skip to main content
Participant
January 11, 2023
Question

Mirroring wrap.

  • January 11, 2023
  • 3 replies
  • 1049 views

Hi,

 

Is there any script or way to do warp mirroring without mirroring the mirrored image or smart object?

And is there any way to copy warp from a smart object to another smart object?

This topic has been closed for replies.

3 replies

c.pfaffenbichler
Community Expert
Community Expert
January 13, 2023

For Smart Objects one could create a New Smart Object Via Copy, then flip the instance and flip the content in the Smart Object. 

Or to maintain one Smart Object use Layer Comps in the Smart Object. 

 

@jazz-y , did you already include custom grids in your code? 

Legend
January 13, 2023

I haven't tested it, but it looks like it does 🙂

 

c.pfaffenbichler
Community Expert
Community Expert
January 13, 2023

A good surprise! 

Legend
January 12, 2023

Copying warp transformation properties from smart object is possible:

 

var apl = new AM('application'),
    doc = new AM('document'),
    lr = new AM('layer'),
    s2t = stringIDToTypeID;
if (apl.getProperty('numberOfDocuments')) {
    var len = doc.getProperty('numberOfLayers'),
        smartObjects = [],
        warpStyles = [];
    for (var i = 1; i <= len; i++) {
        if (lr.getProperty('layerKind', i, true) == 5) {
            var id = lr.getProperty('layerID', i, true),
                title = lr.getProperty('name', i, true);
            if (lr.hasProperty('smartObjectMore', i, true)) {
                var so = lr.getProperty('smartObjectMore', i, true).value,
                    warp = null,
                    quiltWarp = null;
                if (so.hasKey(s2t('warp'))) warp = so.getObjectValue(s2t('warp'))
                if (so.hasKey(s2t('quiltWarp'))) quiltWarp = so.getObjectValue(s2t('quiltWarp'))
                if (warp || quiltWarp) warpStyles.push({ id: id, name: title, quiltWarp: quiltWarp, warp: warp })
            }
            smartObjects.push({ id: id, name: title })
        }
    }
    if (smartObjects.length && warpStyles.length) dialog(smartObjects.reverse(), warpStyles.reverse());
}
function dialog(s, w) {
    var d = new Window("dialog {text: 'Copy quilt warp style'}"),
        stFrom = d.add("statictext {text: 'From:'}"),
        dlFrom = d.add("dropdownlist {preferredSize: [200, -1]}"),
        stTo = d.add("statictext {text: 'To:'}"),
        lbTo = d.add("listbox", [0, 0, 200, 150], undefined, { multiselect: true }),
        grBn = d.add("group"),
        ok = grBn.add("button", undefined, 'ok', { name: "ok" }),
        cancel = grBn.add("button", undefined, 'Cancel', { name: "cancel" });
    dlFrom.onChange = function () {
        var warpId = w[dlFrom.selection.index].id;
        for (var i = 0; i < s.length; i++) {
            lbTo.items[i].selected = false
            if (s[i].id != warpId) lbTo.items[i].selected = true
        }
    }
    ok.onClick = function () {
        d.close()
        for (var i = 0; i < lbTo.selection.length; i++) {
            lr.selectLayerByIDList([s[lbTo.selection[i].index].id])
            lr.copyWarp(w[dlFrom.selection.index])
        }
    }
    d.onShow = function () {
        var activeLayerID = lr.getProperty('layerID');
        for (var i = 0; i < w.length; i++) dlFrom.add('item', w[i].name)
        for (var i = 0; i < s.length; i++) lbTo.add('item', s[i].name)
        for (var i = 0; i < w.length; i++) {
            if (w[i].id == activeLayerID) {
                dlFrom.selection = i
                break;
            }
        }
        if (!dlFrom.selection) dlFrom.selection = 0
    }
    d.show();
}
function AM(target) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    target = target ? s2t(target) : null;
    this.getProperty = function (property, 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'), s2t('targetEnum'));
        return getDescValue(executeActionGet(r), property)
    }
    this.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        try { return executeActionGet(r).hasKey(property) } catch (e) { return false }
    }
    this.descToObject = function (d, o) {
        o = o ? o : {}
        for (var i = 0; i < d.count; i++) {
            var k = d.getKey(i)
            o[t2s(k)] = getDescValue(d, k)
        }
        return o
    }
    this.selectLayerByIDList = function (IDList) {
        var ref = new ActionReference()
        for (var i = 0; i < IDList.length; i++) {
            ref.putIdentifier(s2t("layer"), IDList[i])
        }
        var desc = new ActionDescriptor()
        desc.putReference(s2t("target"), ref)
        desc.putBoolean(s2t("makeVisible"), false)
        executeAction(s2t("select"), desc, DialogModes.NO)
    }
    this.copyWarp = function (from) {
        (transform = new ActionDescriptor()).putEnumerated(s2t("freeTransformCenterState"), s2t("quadCenterState"), s2t("QCSAverage"));
        (offset = new ActionDescriptor()).putUnitDouble(s2t("horizontal"), s2t("distanceUnit"), 0);
        offset.putUnitDouble(s2t("vertical"), s2t("distanceUnit"), 0);
        transform.putObject(s2t("offset"), s2t("offset"), offset);

        if (from.quiltWarp) {
            (quiltWarp = new ActionDescriptor()).putEnumerated(k = s2t("warpStyle"), s2t("warpStyle"), from.quiltWarp.getEnumerationValue(k));
            quiltWarp.putDouble(k = s2t("warpValue"), from.quiltWarp.getDouble(k));
            quiltWarp.putDouble(k = s2t("warpPerspective"), from.quiltWarp.getDouble(k));
            quiltWarp.putDouble(k = s2t("warpPerspectiveOther"), from.quiltWarp.getDouble(k));
            quiltWarp.putEnumerated(k = s2t("warpRotate"), s2t("orientation"), from.quiltWarp.getEnumerationValue(k));
            var bounds = from.quiltWarp.getObjectValue(s2t('bounds')),
                floatRect = new ActionDescriptor();
            floatRect.putDouble(k = s2t("top"), bounds.getDouble(k));
            floatRect.putDouble(k = s2t("left"), bounds.getDouble(k));
            floatRect.putDouble(k = s2t("bottom"), bounds.getDouble(k));
            floatRect.putDouble(k = s2t("right"), bounds.getDouble(k));
            quiltWarp.putObject(s2t("bounds"), s2t("classFloatRect"), floatRect);
            quiltWarp.putInteger(k = s2t("uOrder"), from.quiltWarp.getInteger(k));
            quiltWarp.putInteger(k = s2t("vOrder"), from.quiltWarp.getInteger(k));
            quiltWarp.putInteger(k = s2t("deformNumRows"), from.quiltWarp.getInteger(k));
            quiltWarp.putInteger(k = s2t("deformNumCols"), from.quiltWarp.getInteger(k))
            var evelopeWarp = new ActionDescriptor(),
                warp = from.quiltWarp.getObjectValue(s2t('customEnvelopeWarp')),
                sliceX = warp.getList(s2t('quiltSliceX')),
                sliceY = warp.getList(s2t('quiltSliceY'));
            var slicesX = new ActionList();
            for (var i = 0; i < sliceX.count; i++) {
                var floatUnit = new ActionDescriptor();
                floatUnit.putUnitDouble(k = s2t("quiltSliceX"), s2t("pixelsUnit"), sliceX.getObjectValue(i).getUnitDoubleValue(k));
                slicesX.putObject(s2t("floatUnit"), floatUnit);
            }
            var slicesY = new ActionList();
            for (var i = 0; i < sliceY.count; i++) {
                var floatUnit = new ActionDescriptor();
                floatUnit.putUnitDouble(k = s2t("quiltSliceY"), s2t("pixelsUnit"), sliceY.getObjectValue(i).getUnitDoubleValue(k));
                slicesY.putObject(s2t("floatUnit"), floatUnit);
            }
            evelopeWarp.putList(s2t("quiltSliceX"), slicesX);
            evelopeWarp.putList(s2t("quiltSliceY"), slicesY);
            var mesh = warp.getList(s2t('meshPoints')),
                meshPoints = new ActionList(); // 
            for (var i = 0; i < mesh.count; i++) {
                var rationalPoint = new ActionDescriptor();
                rationalPoint.putUnitDouble(k = s2t("horizontal"), s2t("pixelsUnit"), mesh.getObjectValue(i).getUnitDoubleValue(k));
                rationalPoint.putUnitDouble(k = s2t("vertical"), s2t("pixelsUnit"), mesh.getObjectValue(i).getUnitDoubleValue(k));
                meshPoints.putObject(s2t("floatUnit"), rationalPoint);
            }
            evelopeWarp.putList(s2t("meshPoints"), meshPoints);
            quiltWarp.putObject(s2t("customEnvelopeWarp"), s2t("customEnvelopeWarp"), evelopeWarp);
            transform.putObject(s2t("quiltWarp"), s2t("quiltWarp"), quiltWarp);
        }

        if (from.warp) {
            var warp = new ActionDescriptor();
            warp.putEnumerated(k = s2t("warpStyle"), k, from.warp.getEnumerationValue(k));
            warp.putDouble(k = s2t("warpValue"), from.warp.getDouble(k));
            warp.putDouble(k = s2t("warpPerspective"), from.warp.getDouble(k));
            warp.putDouble(k = s2t("warpPerspectiveOther"), from.warp.getDouble(k));
            warp.putEnumerated(k = s2t("warpRotate"), s2t("orientation"), from.warp.getEnumerationValue(k));
            var bounds = from.warp.getObjectValue(s2t('bounds')),
                floatWarpRect = new ActionDescriptor();
            floatWarpRect.putDouble(k = s2t("top"), bounds.getDouble(k));
            floatWarpRect.putDouble(k = s2t("left"), bounds.getDouble(k));
            floatWarpRect.putDouble(k = s2t("bottom"), bounds.getDouble(k));
            floatWarpRect.putDouble(k = s2t("right"), bounds.getDouble(k));
            warp.putObject(s2t("bounds"), s2t("classFloatRect"), floatWarpRect);
            warp.putInteger(k = s2t("uOrder"), from.warp.getInteger(k));
            warp.putInteger(k = s2t("vOrder"), from.warp.getInteger(k));

            if (from.warp.hasKey(s2t('customEnvelopeWarp'))) {
                var mesh = from.warp.getObjectValue(s2t('customEnvelopeWarp')).getList(s2t('meshPoints')),
                    meshPoints = new ActionList(); // 
                for (var i = 0; i < mesh.count; i++) {
                    var rationalPoint = new ActionDescriptor();
                    rationalPoint.putUnitDouble(k = s2t("horizontal"), s2t("pixelsUnit"), mesh.getObjectValue(i).getUnitDoubleValue(k));
                    rationalPoint.putUnitDouble(k = s2t("vertical"), s2t("pixelsUnit"), mesh.getObjectValue(i).getUnitDoubleValue(k));
                    meshPoints.putObject(s2t("floatUnit"), rationalPoint);
                }
                var mesh = new ActionDescriptor();
                mesh.putList(s2t("meshPoints"), meshPoints);
                warp.putObject(s2t("customEnvelopeWarp"), s2t("customEnvelopeWarp"), mesh);
            }
            transform.putObject(s2t("warp"), s2t("warp"), warp);
        }

        executeAction(s2t("transform"), transform, 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;
        };
    }
}

 

(sometimes this does not work correctly, perhaps due to the initial transformation properties of objects)

 

var apl = new AM('application'),
    doc = new AM('document'),
    lr = new AM('layer'),
    s2t = stringIDToTypeID;
if (apl.getProperty('numberOfDocuments')) {
    var len = doc.getProperty('numberOfLayers'),
        smartObjects = [],
        warpStyles = [];
    for (var i = 1; i <= len; i++) {
        if (lr.getProperty('layerKind', i, true) == 5) {
            var id = lr.getProperty('layerID', i, true),
                title = lr.getProperty('name', i, true);
            if (lr.hasProperty('smartObjectMore', i, true)) {
                var so = lr.getProperty('smartObjectMore', i, true).value
                if (so.hasKey(s2t('quiltWarp'))) {
                    warpStyles.push({ id: id, name: title, quiltWarp: so.getObjectValue(s2t('quiltWarp')), warp: so.getObjectValue(s2t('warp')) })
                }
            }
            smartObjects.push({ id: id, name: title })
        }
    }
    if (smartObjects.length && warpStyles.length) dialog(smartObjects.reverse(), warpStyles.reverse());
}
function dialog(s, w) {
    var d = new Window("dialog {text: 'Copy quilt warp style'}"),
        stFrom = d.add("statictext {text: 'From:'}"),
        dlFrom = d.add("dropdownlist {preferredSize: [200, -1]}"),
        stTo = d.add("statictext {text: 'To:'}"),
        lbTo = d.add("listbox", [0, 0, 200, 150], undefined, { multiselect: true }),
        grBn = d.add("group"),
        ok = grBn.add("button", undefined, 'ok', { name: "ok" }),
        cancel = grBn.add("button", undefined, 'Cancel', { name: "cancel" });
    dlFrom.onChange = function () {
        var warpId = w[dlFrom.selection.index].id;
        for (var i = 0; i < s.length; i++) {
            lbTo.items[i].selected = false
            if (s[i].id != warpId) lbTo.items[i].selected = true
        }
    }
    ok.onClick = function () {
        d.close()
        for (var i = 0; i < lbTo.selection.length; i++) {
            lr.selectLayerByIDList([s[lbTo.selection[i].index].id])
            lr.copyWarp(w[dlFrom.selection.index], s[i])
        }
    }
    d.onShow = function () {
        var activeLayerID = lr.getProperty('layerID');
        for (var i = 0; i < w.length; i++) dlFrom.add('item', w[i].name)
        for (var i = 0; i < s.length; i++) lbTo.add('item', s[i].name)
        for (var i = 0; i < w.length; i++) {
            if (w[i].id == activeLayerID) {
                dlFrom.selection = i
                break;
            }
        }
        if (!dlFrom.selection) dlFrom.selection = 0
    }
    d.show();
}
function AM(target) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    target = target ? s2t(target) : null;
    this.getProperty = function (property, 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'), s2t('targetEnum'));
        return getDescValue(executeActionGet(r), property)
    }
    this.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), s2t('targetEnum'));
        try { return executeActionGet(r).hasKey(property) } catch (e) { return false }
    }
    this.descToObject = function (d, o) {
        o = o ? o : {}
        for (var i = 0; i < d.count; i++) {
            var k = d.getKey(i)
            o[t2s(k)] = getDescValue(d, k)
        }
        return o
    }
    this.selectLayerByIDList = function (IDList) {
        var ref = new ActionReference()
        for (var i = 0; i < IDList.length; i++) {
            ref.putIdentifier(s2t("layer"), IDList[i])
        }
        var desc = new ActionDescriptor()
        desc.putReference(s2t("target"), ref)
        desc.putBoolean(s2t("makeVisible"), false)
        executeAction(s2t("select"), desc, DialogModes.NO)
    }
    this.copyWarp = function (from, to) {
        (transform = new ActionDescriptor()).putEnumerated(s2t("freeTransformCenterState"), s2t("quadCenterState"), s2t("QCSAverage"));
        (offset = new ActionDescriptor()).putUnitDouble(s2t("horizontal"), s2t("distanceUnit"), 0);
        offset.putUnitDouble(s2t("vertical"), s2t("distanceUnit"), 0);
        transform.putObject(s2t("offset"), s2t("offset"), offset);
        (customEnvelopeWarp = new ActionDescriptor()).putEnumerated(k = s2t("warpStyle"), s2t("warpStyle"), from.quiltWarp.getEnumerationValue(k));
        customEnvelopeWarp.putDouble(k = s2t("warpValue"), from.quiltWarp.getDouble(k));
        customEnvelopeWarp.putDouble(k = s2t("warpPerspective"), from.quiltWarp.getDouble(k));
        customEnvelopeWarp.putDouble(k = s2t("warpPerspectiveOther"), from.quiltWarp.getDouble(k));
        customEnvelopeWarp.putEnumerated(k = s2t("warpRotate"), s2t("orientation"), from.quiltWarp.getEnumerationValue(k));
        var bounds = from.quiltWarp.getObjectValue(s2t('bounds')),
            floatRect = new ActionDescriptor();
        floatRect.putDouble(k = s2t("top"), bounds.getDouble(k));
        floatRect.putDouble(k = s2t("left"), bounds.getDouble(k));
        floatRect.putDouble(k = s2t("bottom"), bounds.getDouble(k));
        floatRect.putDouble(k = s2t("right"), bounds.getDouble(k));
        customEnvelopeWarp.putObject(s2t("bounds"), s2t("classFloatRect"), floatRect);
        customEnvelopeWarp.putInteger(k = s2t("uOrder"), from.quiltWarp.getInteger(k));
        customEnvelopeWarp.putInteger(k = s2t("vOrder"), from.quiltWarp.getInteger(k));
        customEnvelopeWarp.putInteger(k = s2t("deformNumRows"), from.quiltWarp.getInteger(k));
        customEnvelopeWarp.putInteger(k = s2t("deformNumCols"), from.quiltWarp.getInteger(k))
        var evelopeWarp = new ActionDescriptor(),
            warp = from.quiltWarp.getObjectValue(s2t('customEnvelopeWarp')),
            sliceX = warp.getList(s2t('quiltSliceX')),
            sliceY = warp.getList(s2t('quiltSliceY'));
        var slicesX = new ActionList();
        for (var i = 0; i < sliceX.count; i++) {
            var floatUnit = new ActionDescriptor();
            floatUnit.putUnitDouble(k = s2t("quiltSliceX"), s2t("pixelsUnit"), sliceX.getObjectValue(i).getUnitDoubleValue(k));
            slicesX.putObject(s2t("floatUnit"), floatUnit);
        }
        var slicesY = new ActionList();
        for (var i = 0; i < sliceY.count; i++) {
            var floatUnit = new ActionDescriptor();
            floatUnit.putUnitDouble(k = s2t("quiltSliceY"), s2t("pixelsUnit"), sliceY.getObjectValue(i).getUnitDoubleValue(k));
            slicesY.putObject(s2t("floatUnit"), floatUnit);
        }
        evelopeWarp.putList(s2t("quiltSliceX"), slicesX);
        evelopeWarp.putList(s2t("quiltSliceY"), slicesY);
        var mesh = warp.getList(s2t('meshPoints')),
            meshPoints = new ActionList(); // 
        for (var i = 0; i < mesh.count; i++) {
            var rationalPoint = new ActionDescriptor();
            rationalPoint.putUnitDouble(k = s2t("horizontal"), s2t("pixelsUnit"), mesh.getObjectValue(i).getUnitDoubleValue(k));
            rationalPoint.putUnitDouble(k = s2t("vertical"), s2t("pixelsUnit"), mesh.getObjectValue(i).getUnitDoubleValue(k));
            meshPoints.putObject(s2t("floatUnit"), rationalPoint);
        }
        evelopeWarp.putList(s2t("meshPoints"), meshPoints);
        customEnvelopeWarp.putObject(s2t("customEnvelopeWarp"), s2t("customEnvelopeWarp"), evelopeWarp);
        transform.putObject(s2t("quiltWarp"), s2t("quiltWarp"), customEnvelopeWarp);
        var warp = new ActionDescriptor();
        warp.putEnumerated(k = s2t("warpStyle"), k, from.warp.getEnumerationValue(k));
        warp.putDouble(k = s2t("warpValue"), from.warp.getDouble(k));
        warp.putDouble(k = s2t("warpPerspective"), from.warp.getDouble(k));
        warp.putDouble(k = s2t("warpPerspectiveOther"), from.warp.getDouble(k));
        warp.putEnumerated(k = s2t("warpRotate"), s2t("orientation"), from.warp.getEnumerationValue(k));
        var bounds = from.warp.getObjectValue(s2t('bounds')),
            floatWarpRect = new ActionDescriptor();
        floatWarpRect.putDouble(k = s2t("top"), bounds.getDouble(k));
        floatWarpRect.putDouble(k = s2t("left"), bounds.getDouble(k));
        floatWarpRect.putDouble(k = s2t("bottom"), bounds.getDouble(k));
        floatWarpRect.putDouble(k = s2t("right"), bounds.getDouble(k));
        warp.putObject(s2t("bounds"), s2t("classFloatRect"), floatWarpRect);
        warp.putInteger(k = s2t("uOrder"), from.warp.getInteger(k));
        warp.putInteger(k = s2t("vOrder"), from.warp.getInteger(k));
        transform.putObject(s2t("warp"), s2t("warp"), warp);
        executeAction(s2t("transform"), transform, 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;
        };
    }
}

 

In principle, you can recalculate the coordinates of all points and make a mirror image in any direction, but I'm not ready to spend time on this.

lxvmAuthor
Participant
January 12, 2023

Yes, that's exactly what I meant. You understood me very well. Super! The only thing missing is mirroring.

Is there a chance to talk to you outside this forum? Could you prepare such a script for a fee?

Legend
January 12, 2023

We help you in this community completely free of charge.

 

The idea of recalculating coordinates for reflection is still just an idea. There are problems that are very difficult to solve. I'll keep that in mind, but I'm not sure if I can find the time to do it.

Kevin Stohlmeyer
Community Expert
Community Expert
January 11, 2023

This is a known issue with the current build. Go to Preferences > Technology Previews and check (activate) Older GPU mode (pre 2016).

https://community.adobe.com/t5/photoshop-ecosystem-bugs/p-perspective-warp-upside-down/idc-p/13452447/page/3#M71912