Copy link to clipboard
Copied
Hi,
I have a group of layers arranged as shown below.
I need help shuffling these layers so that the rectangles change their positions to get rearranged.
So that image of a 4x8 grid structure was just an example, just as the fill layers were just examples of photos?
Does that layout grid structure stay the same then? It is just the 22 photos that are placed into the grid that need to be randomised and the grid layout is static?
I'm thinking of two possible options that don't require custom scripting:
1) Photohshop "Variables" (AKA Data Driven Graphics):
https://helpx.adobe.com/au/photoshop/using/creating-data-driven-graphics.html
Where you
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I need the rectangles in the canvas to get shuffled (Change their positions randomly).
Copy link to clipboard
Copied
Would changing their colour randomly be an acceptable alternative?
Copy link to clipboard
Copied
No, the colors here help me explain what I mean.
In my situation, they are photos of people.
Copy link to clipboard
Copied
That is a bit advanced for me, there are others here who can help though, good luck!
P.S. Have you searched the forum for similar requests?
Copy link to clipboard
Copied
Yeah, I searched a lot and tried a lot of scripts... but nothing worked.
Copy link to clipboard
Copied
Will there always be 32 photos to be randomly sorted in this particular grid layout? More, less?
Copy link to clipboard
Copied
They are 22 photos.
Copy link to clipboard
Copied
So that image of a 4x8 grid structure was just an example, just as the fill layers were just examples of photos?
Does that layout grid structure stay the same then? It is just the 22 photos that are placed into the grid that need to be randomised and the grid layout is static?
I'm thinking of two possible options that don't require custom scripting:
1) Photohshop "Variables" (AKA Data Driven Graphics):
https://helpx.adobe.com/au/photoshop/using/creating-data-driven-graphics.html
Where you would use pixel replacement to swap out the images. Using the RAND formula to randomise the order of the images in the spreadsheet so that they populate randomly in Photoshop.
2) Using one of the late JJMack scripts for creating a Montage:
Either alpha channel based or smart object based, where you would use image names that randomly sort, say by adding a random number prefix to each filename:
https://github.com/MarshySwamp/JJMack-Archive
https://github.com/MarshySwamp/JJMack-Archive/blob/main/PhotoCollageToolkit.zip
Copy link to clipboard
Copied
Exactly!
Copy link to clipboard
Copied
Thank's a lot!
Copy link to clipboard
Copied
I was interested in this topic, so, despite the presence of a working solution, I still decided to make a script:
#target photoshop
activeDocument.suspendHistory('Shuffle layers', 'shuffleLayers()');
function shuffleLayers() {
var doc = new AM('document'),
lr = new AM('layer');
if (!doc.hasProperty('selection')) {
var selectedLayers = doc.getProperty('targetLayersIDs'),
layers = [];
for (var i = 0; i < selectedLayers.count; i++) {
var id = selectedLayers.getReference(i).getIdentifier(),
bounds = lr.descToObject(lr.getProperty('bounds', id).value);
layers.push({ id: id, center: { x: bounds.left + (bounds.right - bounds.left) / 2, y: bounds.top + (bounds.bottom - bounds.top) / 2 } });
}
}
do {
var source = layers.shift(),
len = layers.length;
if (!len) break;
var target = layers.splice((Math.random() * (len - 1)) | 0, 1).shift();
lr.selectLayers([source.id])
lr.move(source, target, false)
lr.selectLayers([target.id])
lr.move(target, source, true)
if (layers.length == 1) layers.push(target);
} while (true)
var layers = [];
for (var i = 0; i < selectedLayers.count; i++) layers.push(selectedLayers.getReference(i).getIdentifier());
lr.selectLayers(layers)
}
function AM(target, order) {
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'), order ? s2t(order) : 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'), order ? s2t(order) : s2t('targetEnum'));
return executeActionGet(r).hasKey(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.selectLayers = function (list) {
var r = new ActionReference();
do { r.putIdentifier(s2t('layer'), list.shift()) } while (list.length);
(d = new ActionDescriptor()).putReference(s2t('null'), r);
executeAction(s2t('select'), d, DialogModes.NO);
}
this.move = function (source, target, updateCenter) {
(r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putReference(s2t('null'), r);
(d1 = new ActionDescriptor()).putUnitDouble(s2t('horizontal'), s2t('pixelsUnit'), target.center.x - source.center.x);
d1.putUnitDouble(s2t('vertical'), s2t('pixelsUnit'), target.center.y - source.center.y);
d.putObject(s2t('to'), s2t('offset'), d1);
executeAction(s2t('move'), d, DialogModes.NO);
if (updateCenter) {
source.center.x += target.center.x - source.center.x
source.center.y += target.center.y - source.center.y
}
}
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;
};
}
}