Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
1

Creating duplicate images for multi-packs on Online Marketplaces within Photoshop

Community Beginner ,
Nov 09, 2021 Nov 09, 2021

Hi all, 

 

I have quite an intermediate understanding of Photoshop, but can't figure out an action or method for quickly creating duplicates of a product within a canvas to then be uploaded to online marketplaces, for example, I have the potential to sell products in multi-packs, there are quite a few sellers online that sell this way and they also create duplicate images of the product for these multi-pack variation ads.

 

Please see below for an example of multi-pack images that are used for the main image of the advertisements online. 

 

s-l1600s-l1600s-l1600s-l1600

 

As you can see, all of these seem to be created in photoshop using some form of action to quickly do this in bulk - does anyone have specific knowledge as to how to recreate this process quickly? 

 

Many thanks.

TOPICS
Actions and scripting , Windows
15.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Jan 02, 2022 Jan 02, 2022

*EDIT – 8th April 2022: I have updated the code to a 1.4 version. Version 1.3 was updated to work with vector layer content. Version 1.2 includes the optional ability to call the Fit Image script or the Image Size command. Simply remove the // double slash comments. If enabled, these options will bring up a second dialog after script completion.

 

 

@JJMack  - thank you for the feedback.

 

No, it was not designed to resize for web, all it does is create N amount of horizontal and vertical copies

...
Translate
Community Expert , Oct 29, 2022 Oct 29, 2022

@defaultc46l0h0jo9o1 

 

The following “Multi Pack Generator" script offers the following features:

 

  • Trims the input image to the upper left & lower right pixel colour
  • Creates six different PNG output files in a user-adjustable array for 1, 2, 3, 4, 6, and 12 pack combinations. PNG versions are saved to the same location as the input image. If the input image has not been previously saved, you will be prompted to select an output location.
  • Output is 1000px square with white background
  • The scrip
...
Translate
Adobe
Community Expert ,
Oct 29, 2022 Oct 29, 2022

@defaultc46l0h0jo9o1 

 

The following “Multi Pack Generator" script offers the following features:

 

  • Trims the input image to the upper left & lower right pixel colour
  • Creates six different PNG output files in a user-adjustable array for 1, 2, 3, 4, 6, and 12 pack combinations. PNG versions are saved to the same location as the input image. If the input image has not been previously saved, you will be prompted to select an output location.
  • Output is 1000px square with white background
  • The script can be recorded into an Action, then used via File > Automate > Batch to bulk process an input folder of multiple images.

 

/*
Multi Pack Generator.jsx
v1.0 - Stephen Marsh, 30th October 2022
https://community.adobe.com/t5/photoshop-ecosystem-discussions/creating-duplicate-images-for-multi-packs-on-online-marketplaces-within-photoshop/td-p/12511723
*/

#target photoshop

if (app.documents.length) {

	var savedRuler = app.preferences.rulerUnits;
	app.preferences.rulerUnits = Units.PIXELS;

	var doc = activeDocument;
	var docName = activeDocument.name.replace(/\.[^\.]+$/, '');

	// Prepare for step and repeat
	trim(true, true, true, true, "topLeftPixelColor");
	trim(true, true, true, true, "bottomRightPixelColor");
	layerFromBackground(docName);

	var docWidth = activeDocument.width.value;
	var docHeight = activeDocument.height.value;

	try {
		// Use the previously saved directory path
		var docPath = activeDocument.path;
	} catch (e) {
		// If unsaved, prompt for the save path
		var docPath = Folder.selectDialog('Unsaved file, select the save directory:');
	}

	////////// 1 pack //////////
	arrayGenerator(1, 1);
	var saveFile = new File(docPath + '/' + docName + '_1-pack.png');
	saveAsPNG(saveFile, 9);
	executeAction(stringIDToTypeID("revert"), undefined, DialogModes.NO);
	trim(true, true, true, true, "topLeftPixelColor");
	trim(true, true, true, true, "bottomRightPixelColor");
	layerFromBackground(docName);
	////////////////////////////

	////////// 2 pack //////////
	arrayGenerator(2, 1);
	var saveFile = new File(docPath + '/' + docName + '_2-pack.png');
	saveAsPNG(saveFile, 9);
	executeAction(stringIDToTypeID("revert"), undefined, DialogModes.NO);
	trim(true, true, true, true, "topLeftPixelColor");
	trim(true, true, true, true, "bottomRightPixelColor");
	layerFromBackground(docName);
	////////////////////////////

	////////// 3 pack //////////
	arrayGenerator(3, 1);
	var saveFile = new File(docPath + '/' + docName + '_3-pack.png');
	saveAsPNG(saveFile, 9);
	executeAction(stringIDToTypeID("revert"), undefined, DialogModes.NO);
	trim(true, true, true, true, "topLeftPixelColor");
	trim(true, true, true, true, "bottomRightPixelColor");
	layerFromBackground(docName);
	////////////////////////////

	////////// 4 pack //////////
	arrayGenerator(2, 2);
	var saveFile = new File(docPath + '/' + docName + '_4-pack.png');
	saveAsPNG(saveFile, 9);
	executeAction(stringIDToTypeID("revert"), undefined, DialogModes.NO);
	trim(true, true, true, true, "topLeftPixelColor");
	trim(true, true, true, true, "bottomRightPixelColor");
	layerFromBackground(docName);
	////////////////////////////

	////////// 6 pack //////////
	arrayGenerator(3, 2);
	var saveFile = new File(docPath + '/' + docName + '_6-pack.png');
	saveAsPNG(saveFile, 9);
	executeAction(stringIDToTypeID("revert"), undefined, DialogModes.NO);
	trim(true, true, true, true, "topLeftPixelColor");
	trim(true, true, true, true, "bottomRightPixelColor");
	layerFromBackground(docName);
	////////////////////////////

	////////// 12 pack //////////
	arrayGenerator(4, 3);
	var saveFile = new File(docPath + '/' + docName + '_12-pack.png');
	saveAsPNG(saveFile, 9);
	executeAction(stringIDToTypeID("revert"), undefined, DialogModes.NO);
	////////////////////////////

	app.preferences.rulerUnits = savedRuler;

} else {
	alert("A document must be open to use this script!");
}


/* Functions */

function fitImage(fWidth, fHeight) {
	if (doc.height > doc.width) {
		doc.resizeImage(null, UnitValue(fHeight, "px"), null, ResampleMethod.BICUBIC);
	} else {
		doc.resizeImage(UnitValue(fWidth, "px"), null, null, ResampleMethod.BICUBIC);
	}
}

function layerFromBackground(layerName) {
	if (activeDocument.activeLayer.isBackgroundLayer && activeDocument.layers.length === 1) {
		function s2t(s) {
			return app.stringIDToTypeID(s);
		}
		var descriptor = new ActionDescriptor();
		var descriptor2 = new ActionDescriptor();
		var reference = new ActionReference();
		reference.putProperty(s2t("layer"), s2t("background"));
		descriptor.putReference(s2t("null"), reference);
		descriptor2.putString(s2t("name"), layerName);
		descriptor2.putUnitDouble(s2t("opacity"), s2t("percentUnit"), 100);
		descriptor2.putEnumerated(s2t("mode"), s2t("blendMode"), s2t("normal"));
		descriptor.putObject(s2t("to"), s2t("layer"), descriptor2);
		executeAction(s2t("set"), descriptor, DialogModes.NO);
	}
}

function trim(top, bottom, left, right, refPoint) {
	var s2t = function (s) {
		return app.stringIDToTypeID(s);
	};
	var descriptor = new ActionDescriptor();
	descriptor.putEnumerated(s2t("trimBasedOn"), s2t("trimBasedOn"), s2t(refPoint));
	descriptor.putBoolean(s2t("top"), top);
	descriptor.putBoolean(s2t("bottom"), bottom);
	descriptor.putBoolean(s2t("left"), left);
	descriptor.putBoolean(s2t("right"), right);
	executeAction(s2t("trim"), descriptor, DialogModes.NO);
}

function saveAsPNG(saveFile, quality) {
	pngOpts = new PNGSaveOptions();
	pngOpts.compression = quality; //0-9
	pngOpts.interlaced = false;
	activeDocument.saveAs(File(saveFile), pngOpts, true);
}

//////////

function arrayGenerator(paramX, paramY) {

	var copiesX = paramX - 1;
	var copiesY = paramY - 1;

	// Convert to % for relative canvas resize
	var newCanvasX = copiesX * 100;
	var newCanvasY = copiesY * 100;

	// Relative % canvas resize
	relativeCanvasSizePercent(true, newCanvasX, newCanvasY);

	// Select all layers and group (hack to support multi-layered docs)
	layerFromBackground(docName);
	app.runMenuItem(stringIDToTypeID('selectAllLayers'));
	app.runMenuItem(stringIDToTypeID('groupLayersEvent'));
	doc.activeLayer.name = "Original Layers";

	// Step & repeat X
	for (var i = 0; i < copiesX; i++) {
		copyToLayer();
		movePX(docWidth, 0);
	}

	// Select all layers
	app.runMenuItem(stringIDToTypeID('selectAllLayers'));

	// Step & repeat Y
	for (var i = 0; i < copiesY; i++) {
		copyToLayer();
		movePX(0, docHeight);
	}

	// Select all layers and group
	app.runMenuItem(stringIDToTypeID('selectAllLayers'));
	app.runMenuItem(stringIDToTypeID('groupLayersEvent'));
	doc.activeLayer.name = "Step & Repeat";

	// Extract original layers from step & repeat set
	moveOriginalLayersSet();
	deleteLayerSet();


	/* Helper functions for the array generator */

	function moveOriginalLayersSet() {
		var s2t = function (s) {
			return app.stringIDToTypeID(s);
		};
		var descriptor = new ActionDescriptor();
		var list = new ActionList();
		var reference = new ActionReference();
		var reference2 = new ActionReference();
		reference.putName(s2t("layer"), "Original Layers");
		descriptor.putReference(s2t("null"), reference);
		reference2.putIndex(s2t("layer"), 0);
		descriptor.putReference(s2t("to"), reference2);
		descriptor.putBoolean(s2t("adjustment"), false);
		descriptor.putInteger(s2t("version"), 5);
		list.putInteger(3);
		descriptor.putList(s2t("layerID"), list);
		executeAction(s2t("move"), descriptor, DialogModes.NO);
	}

	function deleteLayerSet() {
		var s2t = function (s) {
			return app.stringIDToTypeID(s);
		};
		var descriptor = new ActionDescriptor();
		var reference = new ActionReference();
		reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
		descriptor.putReference(s2t("null"), reference);
		descriptor.putBoolean(s2t("deleteContained"), false); // delete set contents
		executeAction(s2t("delete"), descriptor, DialogModes.NO);
	}

	function movePX(horizontal, vertical) {
		var s2t = function (s) {
			return app.stringIDToTypeID(s);
		};
		var descriptor = new ActionDescriptor();
		var descriptor2 = new ActionDescriptor();
		var reference = new ActionReference();
		reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
		descriptor.putReference(s2t("null"), reference);
		descriptor2.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), horizontal);
		descriptor2.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), vertical);
		descriptor.putObject(s2t("to"), s2t("offset"), descriptor2);
		executeAction(s2t("move"), descriptor, DialogModes.NO);
	}

	function copyToLayer() {
		var s2t = function (s) {
			return app.stringIDToTypeID(s);
		};
		executeAction(s2t("copyToLayer"), undefined, DialogModes.NO);
	}

	function relativeCanvasSizePercent(relative, width, height) {
		var s2t = function (s) {
			return app.stringIDToTypeID(s);
		};
		var descriptor = new ActionDescriptor();
		descriptor.putBoolean(s2t("relative"), relative);
		descriptor.putUnitDouble(s2t("width"), s2t("percentUnit"), width);
		descriptor.putUnitDouble(s2t("height"), s2t("percentUnit"), height);
		descriptor.putEnumerated(s2t("horizontal"), s2t("horizontalLocation"), s2t("left"));
		descriptor.putEnumerated(s2t("vertical"), s2t("verticalLocation"), s2t("top"));
		executeAction(s2t("canvasSize"), descriptor, DialogModes.NO);
	}

	fitImage(950, 950); // pixel value
	doc.resizeCanvas(1000, 1000, AnchorPosition.MIDDLECENTER); // pixel value
	activeDocument.flatten();
}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines