140

I am a web dev and competent in Fireworks, but not so much in Photoshop.

I have just received a layered PSD file to turn into a web page. Can anyone tell me the easiest way to export all layers to individual png files?

There are lots of layers and doing this manually seems wrong.

I have seen this but it does seem there should be native functionality for this in PS.

I have access to Photoshop CS4. Any pointers appreciated.

2
  • Is there any way to avoid having the .pngs turned into Index mode? I need them RGB. I could probably just create a droplet for it, but didn't know if there were an easier way... Thanks for the tip though, this is great!
    – user2995
    Nov 25, 2011 at 23:17
  • The free convertcommand from Imagemagick could be used for this (it may lack complete psd features coverage).
    – Uriel
    Dec 14, 2015 at 21:52

4 Answers 4

171

Method 1: The Built-In Script from Adobe

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

enter image description here

Here are some related questions...

Exporting individual layers in Photoshop, keeping their sizes

Export Layers to Files exports only 4 png files from 100 layers


Method 2: Custom Script

I spent some time and wrote my own script file to automate this process. This process is much faster than the built-in script mentioned above.

Get the script now on Github!

Additional Information

I ran this script on a 100 layer, 450MB file in under 60 seconds. Running the built-in script on the same file takes me about 30 minutes.

When testing with nest layer groups, I found that my script runs in about 90 seconds whereas the built-in script takes about 27 minutes (and actually exports it wrong).

Please note that these results will vary depending on the complexities of the files as well as the hardware on your computer and the version of Photoshop. Additional performance data.

This script has (over the past few years) gotten various improvements from various contributors. If you run into any issues with the script. You can files issues with the script here.

Please read through the read-me for any additional, additional information.

Disclaimer: This script is not associated with Adobe in any way. Please use script at your own risk -- always make a back-up of your PSD before using. I am not responsible for any damaged or lost data.

7
  • 1
    @Lucian -- if you are using Photoshop CC you can just do this otherwise, file an issue on Github. Thanks!
    – Hanna
    Dec 2, 2016 at 2:03
  • Johannes has made an awesome script for this question and should rightfully deserve an upvote several times but please do not seek support for this in the comments. If you have an issue with this please seek a solution through the repo so they can be tracked accordingly.
    – user9447
    Dec 20, 2016 at 23:38
  • 1
    Reporting from 2018. This tool is, now, under File -> Export -> Layers to Files...
    – akinuri
    Jan 17, 2018 at 7:57
  • In case anyone else gets confused, this is a Photoshop script and therefore required Photoshop. I thought it was going to be a shell script. :)
    – Chris Rae
    Jun 12, 2018 at 17:21
  • 2
    @Hanna these are EPIC!! Nice work and thank you! Feb 19, 2019 at 11:23
21

I have updated Johannes' solution of a year ago with many improvements. Significantly:

  • Layer groups are now properly handled so that all layers get written.
  • File names are auto-incremented to prevent collisions (this happens when more than one layer has the same name).
  • Performance is increased. The script can save 500 simple layers in a few minutes.

Besides this, the code has been cleaned up. For example, global variables have been integrated into a single array.

Note that the initial popup message will only tell you the number of top level layers. This is to avoid performance degradation. I can't really imagine a case where you don't know anything about the file you are dealing with, so this should not be much of a compromise.

Grab the script here. Thanks to the previous author for leading the way.

1
  • Really well done on maintaining this script. It worked extremely well exporting some time lapsing corrections on thousands of layers :)
    – iwasrobbed
    Oct 8, 2014 at 17:48
8

CREDIT GOES TO JOHANNES FOR CONTRIBUTING THE FILE. THANK YOU SO MUCH!

I have added a function that helped me go through my 2448 layer file in about 3 hours.

Here is the link to the modified file Download Here

0
7

I updated the script to use the core BackgroundLayer of the doc. So that each jpg that exports is compiled with it.

Would be great if someone added tagging to layers to make them Master layers instead of the default BackgroundLayer ;-)

full script:

    // 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();
1
  • If you do recursive layer checking, then you know the first is a background if you do a name check. Idea perhaps? Mar 24, 2020 at 16:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.