• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
4

New Feature Request - Layers to PDF

Community Beginner ,
Sep 29, 2023 Sep 29, 2023

Copy link to clipboard

Copied

Hi there,

 

I think there should be a simple way to create a PDF based on the Layers within the file...

 

This would be different than creating multiple files as would happen when doing the "Layers to Files" option because instead of creating several files, only one would be made that contains all of the layers within the project... Another way to describe it would be to convert each layer to a page within a single PDF document...

 

The best solution I"ve found thus far is to use Layer Comps, but this tool is not designed for what I'm suggesting...

 

Obviously there should be a separate window that opens when trying to do this operation and it would allow for a couple of different variables to be selected for or against...

 

Each Layer should be visible in the Window and would be checked on or off depending on if the user wishes for it to be included in the PDF. There should also be an option to do a "Quick Export" that would create a smaller PDF file with less quality.. (much like right-clicking on a layer and clicking "Quick Export as PNG."

 

That's all I have for now, but this would be very useful and would help to make things run a bit faster and with less overall clicking required to acheive the same result. It certainly deserves to have its own dedicated button within the dropdown menu...

Idea No status
TOPICS
Actions and scripting , Windows

Views

372

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
6 Comments
Community Beginner ,
Sep 30, 2023 Sep 30, 2023

Copy link to clipboard

Copied

In addition to this there would also be a way to Rearrange the order in which the Layers/Pages of the PDF would get displayed along with a Thumbnail of each of the Layers as well to see what content they have on them - all within the separate window/interface for the Layers to PDF selection...

Votes

Translate

Translate

Report

Report
Community Expert ,
Oct 06, 2024 Oct 06, 2024

Copy link to clipboard

Copied

Until Adobe possibly implements such an idea, I hope that the following script will help. Although not 100% of what has been requested, I'm happy with it so far.

 

v1.0 Features:

  • Works on a single open (target) doc and also with no docs open (manually select the target doc). If multiple docs are open, you will be prompted to close all open docs without saving or to manually save and close all open docs.
  • Optional Prefix and Suffix, separated by _ underscore characters.
  • Choice of 4 JPEG compression levels or lossless ZIP compression.
  • All supported root/top-level layers will be processed, including layer groups and the Background layer. Not intended for docs containing artboards.
  • Option to skip invisible layers.
  • Option to reverse the layer to page order.
  • Option to overwrite an existing PDF file of the same name or rename to avoid overwriting.

v1.1 Features:

  • Added a checkbox to include or exclude layer content extending past the canvas
  • Fixed the display of URI-encoded word spaces (special thanks to @Lumigraphics)

Export Layers to Multi-page PDF.png

 

/*

Export Layers to Multipage PDF scriptUI GUI.jsx
v1.1 - 8th October 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-ideas/new-feature-request-layers-to-pdf/idi-p/14122836

v1.0 Features (7th October 2024):
* Works on a single open (target) doc and also with no docs open (manually select
  the target doc). If multiple docs are open, you will be prompted to close all
  open docs without saving or to manually save and close all open docs.
* Optional Prefix and Suffix, separated by _ underscore characters.
* Choice of 4 JPEG compression levels or lossless ZIP compression.
* All supported root/top-level layers will be processed, including layer groups and
  the Background layer. Not intended for docs containing artboards.
* Option to skip invisible layers.
* Option to reverse the layer to page order.
* Option to overwrite or rename to avoid overwriting an existing file.

v1.1 Features (8th October 2024):
* Added a checkbox to include or exclude layer content extending past the canvas
* Fixed the display of URI-encoded word spaces (special thanks to @Lumigraphics)

*/

#target photoshop

    (function () {

        var inputFilePath = "";

        // Check for open documents
        if (app.documents.length === 1 && app.activeDocument.saved) {
            try {
                app.activeDocument.path;
                // If there's only one saved document open, use it as input and close it
                inputFilePath = app.activeDocument.fullName.fsName;
                app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
            } catch (e) {
                alert("The document has never been saved! Save and re-run the script...");
                return; // Exit the script
            }

        } else if (app.documents.length > 0) {
            var response = confirm("There are currently unsaved or multiple documents open. " +
                "This script requires all documents to be closed before running. " +
                "Would you like to close all open documents now? " +
                "(Any unsaved changes will be lost)", true);
            if (response) {
                while (app.documents.length) {
                    app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                }
            } else {
                alert("Please review, save and close all open documents before running this script.");
                return; // Exit the script
            }
        }

        // Create the main dialog window
        var dlg = new Window("dialog", "Export Layers to Multipage PDF (v1.1)");
        dlg.orientation = "column";
        dlg.alignChildren = ["fill", "top"];
        dlg.spacing = 10;
        dlg.margins = 16;

        // Main group to contain all elements except OK and Cancel buttons
        var mainGroup = dlg.add("panel", undefined, "");
        mainGroup.orientation = "column";
        mainGroup.alignChildren = ["fill", "top"];
        mainGroup.spacing = 10;
        mainGroup.margins = 10;

        // File selection group
        var fileGroup = mainGroup.add("group");
        fileGroup.orientation = "row";
        fileGroup.alignChildren = ["left", "center"];
        fileGroup.spacing = 10;

        var fileButton = fileGroup.add("button", undefined, "Select Input File");
        var fileText = fileGroup.add("statictext", undefined, inputFilePath || "No file selected", { truncate: "middle" });
        fileText.preferredSize.width = 350;
        fileButton.helpTip = "Select a multi-layer document";

        // Output folder selection group
        var folderGroup = mainGroup.add("group");
        folderGroup.orientation = "row";
        folderGroup.alignChildren = ["left", "center"];
        folderGroup.spacing = 10;

        var folderButton = folderGroup.add("button", undefined, "Select Output Folder");
        var folderText = folderGroup.add("statictext", undefined, inputFilePath ? (new File(inputFilePath)).parent.fsName : "No folder selected", { truncate: "middle" });
        folderText.preferredSize.width = 350;

        // Output filename group
        var filenameGroup = mainGroup.add("group");
        filenameGroup.orientation = "row";
        filenameGroup.alignChildren = ["left", "center"];
        filenameGroup.spacing = 10;

        filenameGroup.add("statictext", undefined, "Prefix:");
        var prefixText = filenameGroup.add("edittext", undefined, "");
        prefixText.preferredSize.width = 100;
        filenameGroup.add("statictext", undefined, "_");
        filenameGroup.add("statictext", undefined, "Name:");
        var baseNameText = filenameGroup.add("edittext", undefined, inputFilePath ? decodeURI((new File(inputFilePath)).name.replace(/\.[^\.]+$/, '')) : "");
        baseNameText.preferredSize.width = 200;
        filenameGroup.add("statictext", undefined, "_");
        filenameGroup.add("statictext", undefined, "Suffix:");
        var suffixText = filenameGroup.add("edittext", undefined, "");
        suffixText.preferredSize.width = 100;
        filenameGroup.add("statictext", undefined, ".pdf");

        // Compression type dropdown
        var compressionGroup = mainGroup.add("group");
        compressionGroup.orientation = "row";
        compressionGroup.alignChildren = ["left", "center"];
        compressionGroup.spacing = 10;

        compressionGroup.add("statictext", undefined, "PDF Compression:");
        var compressionDropdown = compressionGroup.add("dropdownlist", undefined, [
            "JPEG Maximum Image Quality",
            "JPEG High Image Quality",
            "JPEG Medium Image Quality",
            "JPEG Low Image Quality",
            "ZIP (Lossless Compression)"
        ]);
        compressionDropdown.selection = 1;

        // Remove invisible layers checkbox
        var invisibleLayersGroup = mainGroup.add("group");
        invisibleLayersGroup.orientation = "row";
        invisibleLayersGroup.alignChildren = ["left", "center"];
        invisibleLayersGroup.spacing = 10;

        var removeInvisibleLayersCheckbox = invisibleLayersGroup.add("checkbox", undefined, "Skip Invisible Layers");
        removeInvisibleLayersCheckbox.value = true;

        // Reverse layer order checkbox
        var reverseLayerOrderGroup = mainGroup.add("group");
        reverseLayerOrderGroup.orientation = "row";
        reverseLayerOrderGroup.alignChildren = ["left", "center"];
        reverseLayerOrderGroup.spacing = 10;

        var reverseLayerOrderCheckbox = reverseLayerOrderGroup.add("checkbox", undefined, "Reverse Layer to Page Order");
        reverseLayerOrderCheckbox.value = false;

        // Reveal All checkbox
        var revealAllGroup = mainGroup.add("group");
        revealAllGroup.orientation = "row";
        revealAllGroup.alignChildren = ["left", "center"];
        revealAllGroup.spacing = 10;

        var revealAllCheckbox = revealAllGroup.add("checkbox", undefined, "Reveal All Oversized Layer Content");
        revealAllCheckbox.value = false;

        // Buttons group
        var buttonGroup = dlg.add("group");
        buttonGroup.orientation = "row";
        buttonGroup.alignChildren = ["right", "center"];
        buttonGroup.spacing = 10;

        var cancelButton = buttonGroup.add("button", undefined, "Cancel");
        var okButton = buttonGroup.add("button", undefined, "OK");

        // Event handlers
        fileButton.onClick = function () {
            var file = File.openDialog("Select the layered file:");
            ///// Special thanks to @Lumigraphics on the tip to use a variable from the file object for use in the GUI!
            var theFile = file;
            /////
            if (theFile) {
                fileText.text = theFile.fsName;
                // Auto-populate the output folder with the parent directory of the input file
                folderText.text = theFile.parent.fsName;
                // Auto-populate the base name field (regex remove the path and extension)
                baseNameText.text = theFile.fsName.replace(/^.+\//, '').replace(/\.[^\.]+$/, '');
            }
        };

        folderButton.onClick = function () {
            var folder = Folder.selectDialog("Select the output folder:", new Folder(folderText.text));
            if (folder) {
                folderText.text = folder.fsName;
            }
        };

        cancelButton.onClick = function () {
            dlg.close();
        };

        okButton.onClick = function () {
            if (fileText.text === "No file selected") {
                alert("Please select an input file first.");
                return;
            }
            if (folderText.text === "No folder selected") {
                alert("Please select an output folder first.");
                return;
            }
            if (baseNameText.text === "") {
                alert("Please enter a base name for the output file.");
                return;
            }

            // Create the output file name
            var outputFileName = "";
            if (prefixText.text !== "") {
                outputFileName += prefixText.text + "_";
            }
            outputFileName += baseNameText.text;
            if (suffixText.text !== "") {
                outputFileName += "_" + suffixText.text;
            }
            outputFileName += ".pdf";

            // Check if the file already exists
            var outputFile = new File(folderText.text + '/' + outputFileName);
            if (outputFile.exists) {
                var overwriteConfirm = confirm("The file '" + outputFileName + "' already exists. Do you want to overwrite it?", false);
                if (!overwriteConfirm) {
                    alert("Export cancelled. Please choose a different file name.");
                    return; // Stay in the dialog
                }
            }

            dlg.close();
            processFile(fileText.text, folderText.text, compressionDropdown.selection.index, prefixText.text, baseNameText.text, suffixText.text, removeInvisibleLayersCheckbox.value, reverseLayerOrderCheckbox.value, revealAllCheckbox.value);
        };

        dlg.show();

        function processFile(filePath, outputFolderPath, compressionType, prefix, baseName, suffix, removeInvisibleLayers, reverseLayerOrder, revealAll) {
            // Open the selected file
            var selectFile = new File(filePath);
            open(selectFile);

            // Document variables
            var originalDoc = app.activeDocument;
            var outputFolder = new Folder(outputFolderPath);

            // Hide the Photoshop panels
            app.togglePalettes();

            // Script running notification window
            var working = new Window("palette");
            working.preferredSize = [300, 80];
            working.add("statictext");
            working.t = working.add("statictext");
            working.add("statictext");
            working.display = function (message) {
                this.t.text = message || "Script running, please wait...";
                this.show();
                app.refresh();
            };
            working.display();

            // Duplicate the original doc
            var tempDoc = originalDoc.duplicate(baseName, false);
            app.activeDocument = tempDoc;

            // Store the active layer (which might not be the Background layer)
            var activeLayer = app.activeDocument.activeLayer;
            var activeLayerVisibility = activeLayer.visible; // Store visibility of the active layer
            // Access the back-most layer (Background layer)
            var backgroundLayer = app.activeDocument.layers[app.activeDocument.layers.length - 1];
            // Store the Background layer's visibility
            var backgroundVisibility = backgroundLayer.visible;
            // Check if it's a Background layer
            if (backgroundLayer.isBackgroundLayer) {
                // Convert the Background layer to a standard layer
                backgroundLayer.isBackgroundLayer = false;
                // Reset the Background layer name
                backgroundLayer.name = 'Background';
                // Restore the original visibility of the Background layer
                backgroundLayer.visible = backgroundVisibility;
            }
            // Restore the visibility of the previously active layer
            activeLayer.visible = activeLayerVisibility;

            // Close the original doc without saving
            originalDoc.close(SaveOptions.DONOTSAVECHANGES);

            // Remove invisible layers if the checkbox is checked
            if (removeInvisibleLayers) {
                removeInvisibleLayersFunc(tempDoc);
            }

            // Loop over each root/top-level layer and dupe to a new doc
            var startIndex = reverseLayerOrder ? 0 : tempDoc.layers.length - 1;
            var endIndex = reverseLayerOrder ? tempDoc.layers.length : -1;
            var step = reverseLayerOrder ? 1 : -1;

            for (var i = startIndex; i !== endIndex; i += step) {
                var currentLayer = tempDoc.layers[i];
                if (!currentLayer.isBackgroundLayer) {
                    // Select the current layer
                    tempDoc.activeLayer = currentLayer;
                    // Dupe the layer to a new doc
                    dupeLayerToNewDoc();
                    // Reveal all oversized layer content if the checkbox is checked
                    if (revealAll) {
                        executeAction(stringIDToTypeID("revealAll"), new ActionDescriptor(), DialogModes.NO);
                    }
                    // Return to the temp doc
                    app.activeDocument = tempDoc;
                }
            }

            // Close the temp doc without saving
            tempDoc.close(SaveOptions.DONOTSAVECHANGES);

            // Create the output file name
            var outputFileName = "";
            if (prefix !== "") {
                outputFileName += prefix + "_";
            }
            outputFileName += baseName;
            if (suffix !== "") {
                outputFileName += "_" + suffix;
            }
            outputFileName += ".pdf";

            // Action Manager code - PDF options
            var d = new ActionDescriptor();
            var list = new ActionList();
            for (var a = 0; a < app.documents.length; a++) list.putString(app.documents[a].name);
            d.putList(stringIDToTypeID("filesList"), list);
            d.putPath(stringIDToTypeID("to"), new File(outputFolder + '/' + outputFileName));
            d.putBoolean(stringIDToTypeID("presentation"), false); // true = presentation | false = multi-page
            var d1 = new ActionDescriptor();
            d1.putBoolean(stringIDToTypeID("pdfPreserveEditing"), false);
            d1.putBoolean(stringIDToTypeID("pdfViewAfterSave"), false);
            var idpdfCompressionType = stringIDToTypeID("pdfCompressionType");
            // Set compression type based on user selection
            switch (compressionType) {
                case 0: d1.putInteger(idpdfCompressionType, 7); break; // JPEG Maximum Image Quality
                case 1: d1.putInteger(idpdfCompressionType, 8); break; // JPEG High Image Quality
                case 2: d1.putInteger(idpdfCompressionType, 9); break; // JPEG Medium Image Quality
                case 3: d1.putInteger(idpdfCompressionType, 10); break; // JPEG Low Image Quality
                case 4: d1.putInteger(idpdfCompressionType, 65540); break; // ZIP (Lossless Compression)
            }
            var idpdfDownSample = stringIDToTypeID("pdfDownSample");
            var idnone = stringIDToTypeID("none");
            d1.putEnumerated(idpdfDownSample, idpdfDownSample, idnone);
            d.putObject(stringIDToTypeID("as"), stringIDToTypeID("photoshopPDFFormat"), d1);
            executeAction(stringIDToTypeID("PDFExport"), d, DialogModes.NO);

            // Close all open docs without saving
            while (app.documents.length) {
                app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
            }

            // Ensure Photoshop has focus before closing the running script notification window
            app.bringToFront();
            working.close();

            // End of script notifications
            app.beep();
            alert('Script completed!' + '\r' + 'File saved to:' + '\r' + decodeURI(outputFolder) + '/' + decodeURI(outputFileName));

            // Restore the Photoshop panels
            app.togglePalettes();
        }

        function removeInvisibleLayersFunc(doc) {
            for (var i = doc.layers.length - 1; i >= 0; i--) {
                var layer = doc.layers[i];
                if (!layer.visible) {
                    layer.remove();
                }
            }
        }

        function dupeLayerToNewDoc() {
            function s2t(s) {
                return app.stringIDToTypeID(s);
            }
            var descriptor = new ActionDescriptor();
            var reference = new ActionReference();
            var reference2 = new ActionReference();
            reference.putClass(s2t("document"));
            descriptor.putReference(s2t("null"), reference);
            descriptor.putString(s2t("name"), app.activeDocument.activeLayer.name);
            reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
            descriptor.putReference(s2t("using"), reference2);
            executeAction(s2t("make"), descriptor, DialogModes.NO);
        }

    })();

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

Votes

Translate

Translate

Report

Report
New Here ,
Dec 08, 2024 Dec 08, 2024

Copy link to clipboard

Copied

This has helped a lot, thank you! Has already saved me a ton of time!

Is there a way to make it work on all open PSD files without the need to close them first? (I understand that the script first opens the layers as separate files, but still, just in case you have anything else). Very useful anyways!

Have a good day and thanks a lot!

Votes

Translate

Translate

Report

Report
Community Expert ,
Dec 08, 2024 Dec 08, 2024

Copy link to clipboard

Copied

@Cleont 

 

There are multiple challenges with your request, however, I'll give it some thought in my spare time.

Votes

Translate

Translate

Report

Report
New Here ,
Dec 08, 2024 Dec 08, 2024

Copy link to clipboard

Copied

@Stephen Marsh 

Thank you again!

In the meantime, I will try appending a "combine files in a folder to a single PDF" to an existing (standard) Photoshop script "export layers as (separate) [jpeg's] to a folder" (would be complex with my knowledge, but still).

Votes

Translate

Translate

Report

Report
Community Expert ,
Dec 08, 2024 Dec 08, 2024

Copy link to clipboard

Copied

LATEST

@Cleont 

 

Yes, first running File > Export > Layers to Files from each PSD and then using File > Automate > PDF presentation would be a good place to start if you need to do this for multiple documents.

 

 

Votes

Translate

Translate

Report

Report