Пакетный экспорт слоев Photoshop в отдельные файлы PNG

Я веб-разработчик и разбираюсь в Fireworks, но не в Photoshop.

Я только что получил многослойный PSD-файл, который нужно превратить в веб-страницу. Может ли кто-нибудь сказать мне самый простой способ экспортировать все слои в отдельные файлы png?

Слоев много, и делать это вручную кажется неправильным.

Я видел это , но кажется, что в PS для этого должна быть встроенная функциональность.

У меня есть доступ к Photoshop CS4. Любые указатели приветствуются.

Есть ли способ избежать превращения .png в индексный режим? Мне нужны RGB. Вероятно, я мог бы просто создать для него каплю, но не знал, есть ли более простой способ... Спасибо за совет, это здорово!
Для этого можно использовать бесплатную convertкоманду от Imagemagick (в ней может отсутствовать полный охват функций psd).

Ответы (4)

Способ 1: встроенный скрипт от Adobe

File >> Scripts >> Export layers to files...

введите описание изображения здесь

Вот несколько сопутствующих вопросов...

Экспорт отдельных слоев в Photoshop с сохранением их размеров

Экспорт слоев в файлы экспортирует только 4 файла png из 100 слоев.


Способ 2: Пользовательский скрипт

Я потратил некоторое время и написал свой собственный файл сценария для автоматизации этого процесса. Этот процесс намного быстрее, чем встроенный скрипт, упомянутый выше.

Загрузите скрипт прямо сейчас на Github!

Дополнительная информация

Я запустил этот скрипт на 100-слойном файле размером 450 МБ менее чем за 60 секунд. Запуск встроенного скрипта на том же файле занимает у меня около 30 минут.

При тестировании с группами вложенных слоев я обнаружил, что мой скрипт выполняется примерно за 90 секунд, тогда как встроенный скрипт занимает около 27 минут (и на самом деле экспортирует его неправильно).

Обратите внимание, что эти результаты будут различаться в зависимости от сложности файлов, а также аппаратного обеспечения вашего компьютера и версии Photoshop. Дополнительные данные о производительности .

Этот сценарий (за последние несколько лет) получил различные улучшения от разных участников. Если у вас возникнут проблемы со скриптом. Вы можете задать вопросы со скриптом здесь .

Пожалуйста, прочтите read-me для получения любой дополнительной информации.

Отказ от ответственности: этот скрипт никак не связан с Adobe. Пожалуйста, используйте скрипт на свой страх и риск — всегда делайте резервную копию вашего PSD перед использованием. Я не несу ответственности за любые поврежденные или потерянные данные.

@Lucian - если вы используете Photoshop CC , вы можете просто сделать это , в противном случае отправьте сообщение о проблеме на Github . Спасибо!
Йоханнес сделал отличный сценарий для этого вопроса и должен по праву заслужить одобрение несколько раз, но, пожалуйста, не ищите поддержки в комментариях. Если у вас есть проблема с этим, ищите решение через репозиторий, чтобы их можно было отслеживать соответствующим образом.
Отчет за 2018 год. Сейчас этот инструментFile -> Export -> Layers to Files...
На случай, если кто-то еще запутается, это сценарий Photoshop, поэтому требуется Photoshop. Я думал, что это будет сценарий оболочки. :)
@ Ханна, это ЭПИЧЕСКИ!! Хорошая работа и спасибо!
У меня есть, пожалуй, хорошая идея, добавить его в меню экспорта. Гораздо проще добраться до сценария
Сэкономил мне часы работы, спасибо :).

Я обновил решение Йоханнеса год назад со многими улучшениями. Существенно:

  • Группы слоев теперь обрабатываются правильно, так что все слои записываются.
  • Имена файлов автоматически увеличиваются для предотвращения коллизий (это происходит, когда несколько слоев имеют одно и то же имя).
  • Производительность увеличена. Скрипт может сохранить 500 простых слоев за несколько минут.

Кроме того, код был очищен. Например, глобальные переменные были объединены в один массив.

Обратите внимание, что в начальном всплывающем сообщении будет указано только количество слоев верхнего уровня . Это делается для того, чтобы избежать снижения производительности. Я не могу себе представить случай, когда вы ничего не знаете о файле, с которым имеете дело, так что это не должно быть большим компромиссом.

Возьмите скрипт здесь . Спасибо предыдущему автору за наводку.

Действительно молодец, поддерживая этот скрипт. Он работал очень хорошо, экспортируя временные исправления на тысячи слоев :)

ЗАЧЕТ ИДЕТ ИОАННУ ЗА ПРЕДОСТАВЛЕНИЕ ФАЙЛА. БОЛЬШОЕ СПАСИБО!

Я добавил функцию, которая помогла мне просмотреть файл слоя 2448 примерно за 3 часа.

Вот ссылка на модифицированный файл Скачать здесь

Я обновил скрипт, чтобы использовать основной BackgroundLayer документа. Так что каждый экспортируемый jpg компилируется с ним.

Было бы здорово, если бы кто-то добавил теги к слоям, чтобы сделать их главными слоями вместо фонового слоя по умолчанию ;-)

полный скрипт:

    // NAME: 
//  SaveLayers

// DESCRIPTION: 
//  Saves each layer in the active document to a PNG or JPG file named after the layer. 
//  These files will be created in the current document folder (same as working PSD).

// REQUIRES: 
//  Adobe Photoshop CS2 or higher

//Most current version always available at: https://github.com/jwa107/Photoshop-Export-Layers-as-Images

// enable double-clicking from Finder/Explorer (CS2 and higher)
#target photoshop
app.bringToFront();

function main() {
    // two quick checks
    if(!okDocument()) {
        alert("Document must be saved and be a layered PSD.");
        return; 
    }

    var len = activeDocument.layers.length;
    var ok = confirm("Note: All layers will be saved in same directory as your PSD.\nThis document contains " + len + " top level layers.\nBe aware that large numbers of layers may take some time!\nContinue?");
    if(!ok) return

    // user preferences
    prefs = new Object();
    prefs.fileType = "";
    prefs.fileQuality = 12;
    prefs.filePath = app.activeDocument.path;
    prefs.count = 0;

    //instantiate dialogue
    Dialog();
    hideLayers(activeDocument);
    saveLayers(activeDocument);
    toggleVisibility(activeDocument);
    alert("Saved " + prefs.count + " files.");
}

function hideLayers(ref) {
    var len = ref.layers.length;
    for (var i = 0; i < len; i++) {
        var layer = ref.layers[i];
        if (layer.typename == 'LayerSet') hideLayers(layer);
        else layer.visible = false;
    }
}

function toggleVisibility(ref) {
    var len = ref.layers.length;
    for (var i = 0; i < len; i++) { 
        layer = ref.layers[i];
        layer.visible = !layer.visible;
    }
}

function saveLayers(ref) {
    var len = ref.layers.length;
    // rename layers top to bottom
    for (var i = 0; i < len; i++) {
        var layer = ref.layers[i];
        if (layer.typename == 'LayerSet') {
            // recurse if current layer is a group
            hideLayers(layer);
            saveLayers(layer);
        } else {
            // otherwise make sure the layer is visible and save it
            layer.visible = true;

    // NEW MASTER BACKGROUND LAYER -- comment this line if u dont want to see that layer compiled in the jpgs
       activeDocument.backgroundLayer.visible = true;

    saveImage(layer.name);

     layer.visible = false;
        }
    }
}

function saveImage(layerName) {
    var fileName = layerName.replace(/[\\\*\/\?:"\|<> ]/g,''); 
    if(fileName.length ==0) fileName = "autoname";
    var handle = getUniqueName(prefs.filePath + "/" + fileName);
    prefs.count++;

    if(prefs.fileType=="PNG" && prefs.fileQuality=="8") {
        SavePNG8(handle); 
    } else if (prefs.fileType=="PNG" && prefs.fileQuality=="24") {
        SavePNG24(handle);
    } else {
        SaveJPEG(handle); 
    }
}

function getUniqueName(fileroot) { 
    // form a full file name
    // if the file name exists, a numeric suffix will be added to disambiguate

    var filename = fileroot;
    for (var i=1; i<100; i++) {
        var handle = File(filename + "." + prefs.fileType); 
        if(handle.exists) {
            filename = fileroot + "-" + padder(i, 3);
        } else {
            return handle; 
        }
    }
} 

function padder(input, padLength) {
    // pad the input with zeroes up to indicated length
    var result = (new Array(padLength + 1 - input.toString().length)).join('0') + input;
    return result;
}

function SavePNG8(saveFile) { 
    exportOptionsSaveForWeb = new ExportOptionsSaveForWeb();
    exportOptionsSaveForWeb.format = SaveDocumentType.PNG
    exportOptionsSaveForWeb.dither = Dither.NONE;



    activeDocument.exportDocument( saveFile, ExportType.SAVEFORWEB, exportOptionsSaveForWeb );
} 

function SavePNG24(saveFile) { 
    pngSaveOptions = new PNGSaveOptions(); 
    activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE); 
} 

function SaveJPEG(saveFile) { 
    jpegSaveOptions = new JPEGSaveOptions(); 
    jpegSaveOptions.quality = prefs.fileQuality;
   activeDocument.saveAs(saveFile, jpegSaveOptions, true, Extension.LOWERCASE); 
} 

function Dialog() {
    // build dialogue
    var dlg = new Window ('dialog', 'Select Type'); 
    dlg.saver = dlg.add("dropdownlist", undefined, ""); 
    dlg.quality = dlg.add("dropdownlist", undefined, "");
    dlg.pngtype = dlg.add("dropdownlist", undefined, "");


    // file type
    var saveOpt = [];
    saveOpt[0] = "PNG"; 
    saveOpt[1] = "JPG"; 
    for (var i=0, len=saveOpt.length; i<len; i++) {
        dlg.saver.add ("item", "Save as " + saveOpt[i]);
    }; 

    // trigger function
    dlg.saver.onChange = function() {
        prefs.fileType = saveOpt[parseInt(this.selection)]; 
        // decide whether to show JPG or PNG options
        if(prefs.fileType==saveOpt[1]){
            dlg.quality.show();
            dlg.pngtype.hide();
        } else {
            dlg.quality.hide();
            dlg.pngtype.show();
        }
    }; 

    // jpg quality
    var qualityOpt = [];
    for(var i=12; i>=1; i--) {
        qualityOpt[i] = i;
        dlg.quality.add ('item', "" + i);
    }; 

    // png type
    var pngtypeOpt = [];
    pngtypeOpt[0]=8;
    pngtypeOpt[1]=24;
    dlg.pngtype.add ('item', ""+ 8 );
    dlg.pngtype.add ('item', "" + 24);

    // trigger functions
    dlg.quality.onChange = function() {
        prefs.fileQuality = qualityOpt[12-parseInt(this.selection)];
    };
    dlg.pngtype.onChange = function() {
       prefs.fileQuality = pngtypeOpt[parseInt(this.selection)]; 
    };

    // remainder of UI
    var uiButtonRun = "Continue"; 

    dlg.btnRun = dlg.add("button", undefined, uiButtonRun ); 
    dlg.btnRun.onClick = function() {   
        this.parent.close(0); 
    }; 

    dlg.orientation = 'column'; 

    dlg.saver.selection = dlg.saver.items[0] ;
    dlg.quality.selection = dlg.quality.items[0] ;
    dlg.center(); 
    dlg.show();
}

function okDocument() {
     // check that we have a valid document

    if (!documents.length) return false;

    var thisDoc = app.activeDocument; 
    var fileExt = decodeURI(thisDoc.name).replace(/^.*\./,''); 
    return fileExt.toLowerCase() == 'psd'
}

function wrapper() {
    function showError(err) {
        alert(err + ': on line ' + err.line, 'Script Error', true);
    }

    try {
        // suspend history for CS3 or higher
        if (parseInt(version, 10) >= 10) {
            activeDocument.suspendHistory('Save Layers', 'main()');
        } else {
            main();
        }
    } catch(e) {
        // report errors unless the user cancelled
        if (e.number != 8007) showError(e);
    }
}

wrapper();
Если вы выполняете рекурсивную проверку слоев, то вы знаете, что первым является фон, если вы выполняете проверку имени. Возможно идея?