У меня был к максу скрипт который кусками рендерил. Вам он, есно не сгодится. Если найдете как в Блэндере кусками отрендерить. То потом можно в Шопе склеить куски. Вот я еще в 16 году скрипт написал, он клеит. Сам им уже не пользуюсь давно. Может вам и сгодится.
Для его корректной работы нужно что бы названия файлов/кусков имели вид:
ANYNAME_w1_h1_0000.png
ANYNAME_w1_h2_0000.png
ANYNAME_w2_h1_0000.png
ANYNAME_w1_h2_0000.png
Вот пример батча файлов для склейки картинки 2х2 куска. Обратите внимание, что нумерация начинается не с "0" а с "1"(я не профессиональный кодер). Последние четыре нуля значения не имеют(это артефакты максовского скрипта). Влюбом случае, всегда можно под себя переписать.
Вот тело скрипта:
//СБОРКА ФАЙЛА КОМПЛИТЕ
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.TypeUnits = TypeUnits.PIXELS;
app.displayDialogs = DialogModes.NO;
var
firstPartOfImage = (nameFromDialog = File.openDialog( "Пожалуйста, укажите первый файл в папке для сборки.")).toString(),
folderPath = firstPartOfImage.slice(0, firstPartOfImage.lastIndexOf("/")) + "/",
currentFolder = new Folder(folderPath),
partsOfImage = currentFolder.getFiles(),
complitePath = folderPath.replace(/MAPS\/(.+)/, "MAPS/"),
psdFile,
widthOfImage,
heightOfImage,
widthOfPart,
heightOfPart,
widthCount = -1,
heightCount = -1,
widhtInThisItration,
heightInThisItration,
fileName,
nameOfPart,
counterOfIterations = 0;
//определение кол-ва кусков по вертикали и гаризонтали
//и размера финального файла
$.writeln ( "Count Of Files: " + partsOfImage.length + " pcs.");
for each(fileName in partsOfImage)
{
fileName = fileName.toString();
fileName = fileName.slice(firstPartOfImage.lastIndexOf("/")+1);
//$.writeln ( "fileName = " + fileName + "\nIteration: " + counterOfIterations++);
if(fileName != "Thumbs.db")
{
widhtInThisItration = fileName.replace(/(.+w)/, "");
widhtInThisItration = widhtInThisItration.replace(/(_.+)/, "");
heightInThisItration = fileName.replace(/(.+h)/, "");
heightInThisItration = heightInThisItration.replace(/(_.+)/, "");
heightInThisItration = parseInt(heightInThisItration);
widhtInThisItration = parseInt(widhtInThisItration);
//$.writeln ( "widthCount = " + widthCount + " widhtInThisItration = " + widhtInThisItration);
if(widthCount < widhtInThisItration)
{
widthCount = widhtInThisItration;
};
//$.writeln ( "heightCount = " + heightCount + " heightInThisItration = " + heightInThisItration);
if(heightCount < heightInThisItration)
{
heightCount = heightInThisItration;
};
};
};
//$.writeln ( "widthCount = " + widthCount + "\nheightCount = " + heightCount);
//создание финального файла с именем "COMPLITE"
open(new File(firstPartOfImage));
widthOfPart = app.activeDocument.width;
heightOfPart = app.activeDocument.height;
widthOfImage = app.activeDocument.width * widthCount;
heightOfImage = app.activeDocument.height * heightCount;
app.activeDocument.close(SaveOptions.DONOTSAVECHAN GES);
app.documents.add(widthOfImage, heightOfImage, 72, "IMAGEBUILDER", NewDocumentMode.RGB);
//набивка финального файла кусками из папки
for each(fileName in partsOfImage)
{
nameOfPart = fileName.toString();
nameOfPart = nameOfPart.slice(nameOfPart.lastIndexOf("/")+1);
if(nameOfPart != "Thumbs.db")
{
open(new File(fileName));
app.activeDocument.flatten();
app.activeDocument.artLayers[0].isBackgroundLayer = false;
app.activeDocument.selection.selectAll();
app.activeDocument.selection.copy();
app.activeDocument.close(SaveOptions.DONOTSAVECHAN GES);
widthCount = nameOfPart.replace(/(.+w)/, "");
widthCount = widthCount.replace(/(_.+)/, "") - 1;
heightCount = nameOfPart.replace(/(.+h)/, "");
heightCount = heightCount.replace(/(_.+)/, "") - 1;
app.activeDocument.artLayers.add();
app.activeDocument.paste();
app.activeDocument.artLayers[0].name = nameOfPart;
layerPosition(nameOfPart, widthOfPart * widthCount, heightOfPart * heightCount, "LEFTUP");
if(widthCount != 0 || heightCount != 0)
{
app.activeDocument.artLayers[0].merge();
};
//break;
};
};
//склеивание и сохранение финального файла
app.activeDocument.artLayers[0].merge();
app.activeDocument.artLayers[0].isBackgroundLayer = 0;
app.activeDocument.artLayers[0].name = "IMAGEBUILDER";
psdFile = new File( complitePath + "COMPLITE.psd" );
if(!psdFile.exists)
{
app.activeDocument.saveAs(psdFile);
};
else
{
psdFile = new File( complitePath + "IMAGEBUILDER" );
app.activeDocument.saveAs(psdFile);
};
function layerPosition(layer, layerX, layerY, pointLocation){
var layerRef = app.activeDocument.artLayers.getByName(layer);
var x, y, w, x, cx, cy, A, B, moveX, moveY;
x = layerRef.bounds[0].value;
y = layerRef.bounds[1].value;
w = layerRef.bounds[2].value;
h = layerRef.bounds[3].value;
width = layerRef.bounds[2].value - x;
height = layerRef.bounds[3].value - y;
cx = (width/2) + x;
cy = (height/2) + y;
switch(pointLocation){
case "LEFTUP": {A = x; B = y} break;
case "LEFTDOWN": {A = x, B = h} break;
case "RIGHTUP": {A = w, B = y} break;
case "RIGHTDOWN": {A = w, B = h} break;
case "CENTER": {A = cx, B = cy} break;
default:{A = x; B = y} break;
};
if(layerX == "NAN"){moveX = A}; else{moveX = layerX};
if(layerY == "NAN"){moveY = B}; else{moveY = layerY};
layerRef.translate((moveX - A), (moveY - B));
//layerRef.translate((layerX - A), (layerY - B))
return layerRef;
};