Cómo fusionar capas para exportar por lotes y optimizar para web

Lo que estoy tratando de hacer:

  1. Exportación por lotes
  2. Optimizar para web (Jpeg)

Mi estructura de capas:

Capa1 --- Logotipo
Capa2 --- Capa de ajuste (Brillo y Control)
Carpeta-A
~~ Capa3 -- imagen
~~ Capa4 -- imagen
~~ Capa5 -- imagen
~~ ..... (más capas)
Carpeta- B
~~ Capa6 -- imagen
~~ Capa7 -- imagen
~~ Capa8 -- imagen
~~ ..... (más capas)

Quiero exportar por lotes las capas de imagen a archivos individuales y optimizar cada imagen para la web. Pensé que podía exportar capas a archivos individuales y usar la acción automática por lotes para optimizar para la web.

Lo uso Export layers as PNGpero no fusiona la capa del logotipo con la capa de la imagen. Necesito que el logo aparezca en cada capa de imagen. ¿Hay una manera de lograr esto?

Creo que hice un script que hace lo que quieres... o al menos casi ( Imagen ): Exportar documento para cada capa dentro del grupo seleccionado. jsx : lo único es que solo admite una carpeta de origen a la vez.
Hola @Joonas, ¡Gracias! Solo para asegurarme de que entiendo cómo funciona, fusionará la capa del logotipo + la capa de imagen 1 = combine-jpeg-1, la capa del logotipo + la capa de imagen 2 = combine-jpeg-2, la capa del logotipo + la capa de imagen 3 = combine-jpeg3. .... etc
Creo que vas. Dependiendo de cómo lo mires, realmente no fusiona nada. Simplemente guarda el documento completo para cada capa dentro del grupo seleccionado. Comienza ocultando cada capa dentro del grupo seleccionado, luego, una por una, selecciona cada capa a su vez, hace que la capa sea visible y guarda el documento. Entonces, básicamente, todo lo que está fuera del grupo seleccionado aparece en cada imagen que guarda el script.
@Joonas ¡Funciona de maravilla! ¡Gracias! ¿Puedes dar esto como respuesta?
Hola @Joonas, ¿hay alguna manera de ajustar la configuración de optimización? Veo que la imagen está optimizada pero la resolución es un poco baja para mis necesidades.
Si cambias esta línea para decir= 12

Respuestas (1)

Hice un script que hace casi exactamente eso (en términos de resultado final... Realmente no fusiona nada). La cuestión es que solo admite una carpeta de origen a la vez.

Exporte el documento para cada capa dentro del grupo seleccionado.jsx .

ingrese la descripción de la imagen aquí

La forma en que funciona:

  1. Primero oculta todas las capas en el primer nivel de la carpeta seleccionada
  2. Luego recorre cada una de esas capas realizando estas acciones en cada capa:
    1. Muestra la capa actual (que también puede ser un grupo)
    2. Guarda el documento
    3. Oculta la capa actual

Entonces, cualquier cosa fuera del grupo seleccionado es visible en cada imagen de salida.

// Name: Export document for each layer inside selected group.jsx
// Formerly: Export Layers Inside Selected Group.jsx

// Description: Photoshop script that saves the whole document for each top level layer inside the selected group.
// Image example: https://user-images.githubusercontent.com/1164476/49152494-aef8af00-f31b-11e8-80ff-d774e3103eae.png

// https://gist.github.com/joonaspaakko/013a223e94ba0fb9a2a0

#target photoshop

try {
  var doc = app.activeDocument;
    var n = 0;
    var duplicates = {};
}
catch (e) {
  alert( 'Open a document first...' );
}

function processLayers( options) {
    
    var group       = doc.activeLayer;
    var groupLength = group.layers.length;
    
    var visibleArray = [];
    
    // HIDE ALL LAYERS
    for ( var i = 0; i < groupLength; i++ ) {
        visibleArray.push( group.layers[i].visible );
        group.layers[i].visible = false;
    }
    
    // START SAVING
    options.docName = doc.name.split('.')[0]; // Assumes filename contains only one period before the extion.
    for ( var i = 0; i < groupLength; i++ ) {
        
        var layer = group.layers[ i ];
        
        options.layerName = layer.name;
        options.layerIndex = i+1;
        
        layer.visible = true;
        save.file( options );
        layer.visible = false;
        
    }
    
    // RESTORE VISIBILITY
    for ( var i = 0; i < groupLength; i++ ) {
        group.layers[i].visible = visibleArray[i];
    }
    
    doc.activeLayer = group;

    alert('Done!'); // There's no error check so who am I to say if the files were saved, but at least the script is done...
    
}

var save = {
    file: function( options ) {
        
        var saveOptions = {};
        
        for ( var i=0; i < options.fileFormats.length; i++ ) {
            
            var fileformat = options.fileFormats[i];
            var destinationFolder = options.destination + "/" + fileformat.toUpperCase();
            
            makeFolder( destinationFolder ); // If it doesn't exist already...
            
            var filename = '';
            filename += options.prefix;
            filename += options.useLayerName ? options.layerName : options.custonName;
            filename += options.suffix;
            
            // IF FILENAME CONTAINS A DOLLAR SIGN
            if ( filename.match(/\$/) !== null ) {
                filename =  filename.replace('$',options.layerIndex);
            }
            // IF FILENAME DOESN'T HAVE THE DOLLAR SIGN AND A
            // DUPLICATE FILENAME IS FOUND, ADD A NUMBER ANYWAYS.
            else {
                
                if ( typeof duplicates[ fileformat ] == 'undefined' ) {
                    duplicates[ fileformat ] = {};
                }
                
                var duplicateNumber = '';
                if ( typeof duplicates[ fileformat ][ filename ] === 'object' ) {
                    duplicateNumber = ' ' + duplicates[ fileformat ][ filename ].length;
                    duplicates[ fileformat ][ filename ].push( filename );
                }
                else {
                    duplicates[ fileformat ][ filename ] = [ filename ];
                }
                
                filename += duplicateNumber;
            }
            
            doc.saveAs( File( destinationFolder + "/" + filename ), save[ fileformat ](), true );
            
        }
        
    },
    psd: function() {
        
        var psd_saveOpts = new PhotoshopSaveOptions();
        
        psd_saveOpts.layers            = true;
        psd_saveOpts.embedColorProfile = true;
        psd_saveOpts.annotations       = true;
        psd_saveOpts.alphaChannels     = true;
        
        return psd_saveOpts;
        
    },
    pdf: function() {
        
        var presetName = '[High Quality Print]';
        
        var pdf_SaveOpts = new PDFSaveOptions();
        
        pdf_SaveOpts.pDFPreset = presetName;
        
        return pdf_SaveOpts;
        
    },
    jpeg: function() {
        
        var jpg_SaveOpts = new JPEGSaveOptions();
        
        jpg_SaveOpts.matte   = MatteType.WHITE;
        jpg_SaveOpts.quality = 10;
        jpg_SaveOpts.formatOptions.STANDARDBASELINE;
        
        return jpg_SaveOpts;
        
    },
    png: function() {
        
        var png_SaveOpts = new PNGSaveOptions();
        
        png_SaveOpts.compression = 9;
        png_SaveOpts.interlaced = false;
        
        return png_SaveOpts;
        
    },
    tiff: function() {
        
        var tiff_SaveOpts = new TiffSaveOptions();
        
        tiff_SaveOpts.alphaChannels      = true;
        tiff_SaveOpts.annotations        = true;
        tiff_SaveOpts.imageCompression   = TIFFEncoding.JPEG;
        tiff_SaveOpts.interleaveChannels = true;
        tiff_SaveOpts.jpegQuality        = 10;
        tiff_SaveOpts.layers             = true;
        tiff_SaveOpts.layerCompression   = LayerCompression.ZIP;
        tiff_SaveOpts.transparency       = true;
        
        return tiff_SaveOpts;
        
    }
};

function makeFolder( path ) {
  var newFolder = Folder( path );
  if( !newFolder.exists ) newFolder.create();
}

if ( app.documents.length > 0 ) {
  if ( app.activeDocument.activeLayer.layers ) {
        init();
  }
  else {
    alert( "Error: \nSelect a parent group of the layers you want to export.")
  }
}

function init() {
    
    /*
    Code for Import https://scriptui.joonas.me — (Triple click to select):
    {"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"text":"Export document for each layer inside selected group.jsx","preferredSize":[0,0],"margins":16,"orientation":"column","spacing":10,"alignChildren":["center","top"]}},"item-1":{"id":1,"type":"Checkbox","parentId":6,"style":{"text":"PSD","preferredSize":[0,0],"alignment":null}},"item-2":{"id":2,"type":"Checkbox","parentId":6,"style":{"text":"TIFF","preferredSize":[0,0],"alignment":null}},"item-3":{"id":3,"type":"Checkbox","parentId":6,"style":{"text":"JPEG","preferredSize":[0,0],"alignment":null,"checked":true}},"item-4":{"id":4,"type":"Checkbox","parentId":6,"style":{"text":"PNG","preferredSize":[0,0],"alignment":null}},"item-5":{"id":5,"type":"Checkbox","parentId":6,"style":{"text":"PDF","preferredSize":[0,0],"alignment":null}},"item-6":{"id":6,"type":"Panel","parentId":9,"style":{"text":"","preferredSize":[0,0],"margins":10,"orientation":"row","spacing":10,"alignChildren":["center","top"],"alignment":null}},"item-7":{"id":7,"type":"Panel","parentId":9,"style":{"text":"","preferredSize":[0,0],"margins":10,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-8":{"id":8,"type":"EditText","parentId":14,"style":{"text":"","preferredSize":[90,0],"alignment":null}},"item-9":{"id":9,"type":"Group","parentId":0,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["fill","top"],"alignment":null}},"item-10":{"id":10,"type":"Group","parentId":0,"style":{"preferredSize":[0,0],"margins":[15,0,10,0],"orientation":"row","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-11":{"id":11,"type":"Button","parentId":10,"style":{"text":"Save","justify":"center","preferredSize":[0,0],"alignment":null}},"item-12":{"id":12,"type":"Button","parentId":10,"style":{"text":"Cancel","justify":"center","preferredSize":[0,0],"alignment":null}},"item-13":{"id":13,"type":"StaticText","parentId":14,"style":{"text":"Prefix:","justify":"left","preferredSize":[0,0],"alignment":null}},"item-14":{"id":14,"type":"Group","parentId":22,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-15":{"id":15,"type":"Checkbox","parentId":7,"style":{"text":"Use layer name","preferredSize":[0,0],"alignment":null,"checked":false}},"item-16":{"id":16,"type":"Group","parentId":22,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-17":{"id":17,"type":"StaticText","parentId":16,"style":{"text":"Custom name:","justify":"left","preferredSize":[0,0],"alignment":null}},"item-18":{"id":18,"type":"EditText","parentId":16,"style":{"text":"File Name ","preferredSize":[160,0],"alignment":null}},"item-19":{"id":19,"type":"Group","parentId":22,"style":{"preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","top"],"alignment":null}},"item-20":{"id":20,"type":"StaticText","parentId":19,"style":{"text":"Suffix:","justify":"left","preferredSize":[0,0],"alignment":null}},"item-21":{"id":21,"type":"EditText","parentId":19,"style":{"text":"","preferredSize":[90,0],"alignment":null}},"item-22":{"id":22,"type":"Group","parentId":7,"style":{"preferredSize":[0,0],"margins":0,"orientation":"row","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-23":{"id":23,"type":"Divider","parentId":7,"style":false},"item-24":{"id":24,"type":"StaticText","parentId":7,"style":{"text":"Dollar symbol ($) is replaced with incremental numbers","justify":"left","preferredSize":[0,0],"alignment":"center"}}},"order":[0,9,7,15,23,22,14,13,8,16,17,18,19,20,21,24,6,3,4,1,5,2,10,12,11],"activeId":10}
    */

    // DIALOG
    // ======
    var dialog = new Window("dialog");
        dialog.text = "Export document for each layer inside selected group.jsx";
        dialog.orientation = "column";
        dialog.alignChildren = ["center","top"];
        dialog.spacing = 10;
        dialog.margins = 16;

    // GROUP1
    // ======
    var group1 = dialog.add("group");
        group1.orientation = "column";
        group1.alignChildren = ["fill","top"];
        group1.spacing = 10;
        group1.margins = 0;

    // PANEL1
    // ======
    var panel1 = group1.add("panel");
        panel1.orientation = "column";
        panel1.alignChildren = ["left","top"];
        panel1.spacing = 10;
        panel1.margins = 10;

    var checkbox1 = panel1.add("checkbox");
        checkbox1.text = "Use layer name";

    var divider1 = panel1.add("panel");
        divider1.alignment = "fill";

    // GROUP2
    // ======
    var group2 = panel1.add("group");
        group2.orientation = "row";
        group2.alignChildren = ["left","center"];
        group2.spacing = 10;
        group2.margins = 0;

    // GROUP3
    // ======
    var group3 = group2.add("group");
        group3.orientation = "column";
        group3.alignChildren = ["left","top"];
        group3.spacing = 10;
        group3.margins = 0;

    var statictext1 = group3.add("statictext");
        statictext1.text = "Prefix:";

    var edittext1 = group3.add("edittext");
        edittext1.minimumSize.width = 90;

    // GROUP4
    // ======
    var group4 = group2.add("group");
        group4.orientation = "column";
        group4.alignChildren = ["left","top"];
        group4.spacing = 10;
        group4.margins = 0;

    var statictext2 = group4.add("statictext");
        statictext2.text = "Custom name:";

    var edittext2 = group4.add("edittext");
        edittext2.text = "File Name ";
        edittext2.minimumSize.width = 160;

    // GROUP5
    // ======
    var group5 = group2.add("group");
        group5.orientation = "column";
        group5.alignChildren = ["left","top"];
        group5.spacing = 10;
        group5.margins = 0;

    var statictext3 = group5.add("statictext");
        statictext3.text = "Suffix:";

    var edittext3 = group5.add("edittext");
        edittext3.minimumSize.width = 90;

    // PANEL1
    // ======
    var statictext4 = panel1.add("statictext");
        statictext4.text = "Dollar symbol ($) is replaced with incremental numbers";
        statictext4.alignment = ["center","top"];

    // PANEL2
    // ======
    var panel2 = group1.add("panel");
        panel2.orientation = "row";
        panel2.alignChildren = ["center","top"];
        panel2.spacing = 10;
        panel2.margins = 10;

    var checkbox2 = panel2.add("checkbox");
        checkbox2.text = "JPEG";
        checkbox2.value = true;

    var checkbox3 = panel2.add("checkbox");
        checkbox3.text = "PNG";

    var checkbox4 = panel2.add("checkbox");
        checkbox4.text = "PSD";

    var checkbox5 = panel2.add("checkbox");
        checkbox5.text = "PDF";

    var checkbox6 = panel2.add("checkbox");
        checkbox6.text = "TIFF";

    // GROUP6
    // ======
    var group6 = dialog.add("group");
        group6.orientation = "row";
        group6.alignChildren = ["left","top"];
        group6.spacing = 10;
        group6.margins = [0,15,0,10];

    var button1 = group6.add("button", undefined, undefined, {name:"cancel"});
        button1.text = "Cancel";
        button1.justify = "center";

    var button2 = group6.add("button", undefined, undefined, {name:"ok"});
        button2.text = "Save";
        button2.justify = "center";
  
    
    // DIALOG CUSTOMIZATION
    var filename = edittext2;
    filename.text = app.activeDocument.name.split()[0]; // Assumes filename contains only one period before the extion.
    filename.active = true;
    
  var useLayerName = checkbox1;
  useLayerName.onClick = function() {
    var check = this.value;
    var customName = edittext2;
    if ( check ) customName.enabled = !check;
    else customName.enabled = !check;
  };
  
  var cancelBtn = button1;
  cancelBtn.onClick = function() {
        dialog.close();
  };
  
  var saveBtn = button2;
  saveBtn.onClick = function() {
        n = ++n;
        if ( n === 1 ) {
            
        var formatsArray = [];
        var formats = panel2.children;
        for (var i = 0; i < formats.length; i++) {
                var format = formats[i];
                if ( format.value ) {
                    formatsArray.push( format.text.toLowerCase() );
                }
        }
            
            var path = '';
            try { path = doc.path; } catch(e) {}
            
        var options = {
          useLayerName: useLayerName.value,
          fileFormats: formatsArray,
          prefix: edittext1.text,
          custonName: edittext2.text,
          suffix: edittext3.text,
                destination: Folder.selectDialog( 'Select destination folder...', path )
        };
        
        dialog.close();
        
            if ( options.destination ) {
                processLayers( options );
            }
            
        }
  };
    
    dialog.show();
    
}
Tengo otra secuencia de comandos que es para reemplazar por lotes el contenido en un PSD de maqueta, pero esto podría usarse para lograr el mismo resultado final... si cada una de las capas dentro del grupo se ha guardado como archivos: Reemplazo de objeto inteligente de maqueta por lotes . jsx Photoshop script + solo puede cambiar el tamaño de las imágenes usando fito fill. — Aquí hay un ejemplo específico para este tipo de escenario: github.com/joonaspaakko/…
Publicó accidentalmente la misma URL dos veces. Esta es la página del script github.com/joonaspaakko/… (aunque también dejé un enlace en esa página de ejemplo)