Exportación por lotes de capas de Photoshop a archivos PNG individuales

Soy desarrollador web y soy competente en Fireworks, pero no tanto en Photoshop.

Acabo de recibir un archivo PSD en capas para convertirlo en una página web. ¿Alguien puede decirme la forma más fácil de exportar todas las capas a archivos png individuales?

Hay muchas capas y hacer esto manualmente parece incorrecto.

He visto esto , pero parece que debería haber una funcionalidad nativa para esto en PS.

Tengo acceso a Photoshop CS4. Cualquier sugerencia apreciada.

¿Hay alguna forma de evitar que los .pngs se conviertan en modo de índice? Los necesito RGB. Probablemente podría crear una gota para él, pero no sabía si había una manera más fácil... Gracias por el consejo, ¡es genial!
El convertcomando gratuito de Imagemagick podría usarse para esto (puede carecer de una cobertura completa de las funciones de psd).

Respuestas (4)

Método 1: el script incorporado de Adobe

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

ingrese la descripción de la imagen aquí

Aquí hay algunas preguntas relacionadas...

Exportación de capas individuales en Photoshop, manteniendo sus tamaños

Exportar capas a archivos exporta solo 4 archivos png de 100 capas


Método 2: Guión personalizado

Pasé un tiempo y escribí mi propio archivo de script para automatizar este proceso. Este proceso es mucho más rápido que el script incorporado mencionado anteriormente.

¡Obtenga el script ahora en Github!

Información Adicional

Ejecuté este script en un archivo de 100 capas y 450 MB en menos de 60 segundos. Ejecutar el script integrado en el mismo archivo me lleva unos 30 minutos.

Al probar con grupos de capas anidadas, descubrí que mi secuencia de comandos se ejecuta en unos 90 segundos, mientras que la secuencia de comandos integrada tarda unos 27 minutos (y en realidad la exporta mal).

Tenga en cuenta que estos resultados variarán según la complejidad de los archivos, así como el hardware de su computadora y la versión de Photoshop. Datos adicionales de rendimiento .

Esta secuencia de comandos (en los últimos años) ha obtenido varias mejoras de varios colaboradores. Si tiene algún problema con el script. Puede presentar problemas con el script aquí .

Lea el archivo Léame para obtener información adicional adicional.

Descargo de responsabilidad: este script no está asociado con Adobe de ninguna manera. Use el script bajo su propio riesgo: siempre haga una copia de seguridad de su PSD antes de usarlo. No soy responsable de ningún dato dañado o perdido.

@Lucian: si está utilizando Photoshop CC , puede hacer esto de lo contrario, presente un problema en Github . ¡Gracias!
Johannes ha creado un guión increíble para esta pregunta y debería merecer legítimamente un voto a favor varias veces, pero no busque apoyo para esto en los comentarios. Si tiene un problema con esto, busque una solución a través del repositorio para que puedan ser rastreados en consecuencia.
Informes de 2018. Esta herramienta está, ahora, bajoFile -> Export -> Layers to Files...
En caso de que alguien más se confunda, este es un script de Photoshop y, por lo tanto, requiere Photoshop. Pensé que iba a ser un script de shell. :)
@Hanna estos son ÉPICOS!! ¡Buen trabajo y gracias!
Tal vez tengo una buena idea, agréguela al menú de exportación. Mucho más fácil de llegar a la secuencia de comandos
Me ahorró horas de trabajo, gracias :).

He actualizado la solución de Johannes de hace un año con muchas mejoras. Significativamente:

  • Los grupos de capas ahora se manejan correctamente para que todas las capas se escriban.
  • Los nombres de los archivos se incrementan automáticamente para evitar colisiones (esto sucede cuando más de una capa tiene el mismo nombre).
  • Se aumenta el rendimiento. El script puede guardar 500 capas simples en unos minutos.

Además de esto, el código ha sido limpiado. Por ejemplo, las variables globales se han integrado en una sola matriz.

Tenga en cuenta que el mensaje emergente inicial solo le indicará el número de capas de nivel superior . Esto es para evitar la degradación del rendimiento. Realmente no puedo imaginar un caso en el que no sepa nada sobre el archivo con el que está tratando, por lo que esto no debería ser un gran compromiso.

Coge el guión aquí . Gracias al autor anterior por abrir el camino.

Realmente bien hecho en el mantenimiento de este guión. Funcionó extremadamente bien exportando algunas correcciones de lapso de tiempo en miles de capas :)

EL CRÉDITO VA A JOHANNES POR CONTRIBUIR CON EL ARCHIVO. ¡MUCHAS GRACIAS!

Agregué una función que me ayudó a revisar mi archivo de capa 2448 en aproximadamente 3 horas.

Aquí está el enlace al archivo modificado Descargar aquí

Actualicé el script para usar el BackgroundLayer principal del documento. Para que cada jpg que exporte se compile con él.

Sería genial si alguien agregara etiquetas a las capas para convertirlas en capas maestras en lugar de la capa de fondo predeterminada ;-)

guión completo:

    // 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();
Si realiza una verificación de capa recursiva, sabrá que la primera es un fondo si realiza una verificación de nombre. ¿Idea tal vez?