Photoshop 레이어를 개별 PNG 파일로 일괄 내보내기


130

저는 웹 개발자이며 Fireworks에서는 유능하지만 Photoshop에서는 그리 많지 않습니다.

방금 웹 페이지로 전환하기 위해 계층화 된 PSD 파일을 받았습니다. 누구든지 모든 레이어를 개별 png 파일로 내보내는 가장 쉬운 방법을 말해 줄 수 있습니까?

많은 레이어가 있으며 수동으로 수행하는 것은 잘못된 것 같습니다.

나는 이것을 보았지만 PS에는 이것에 대한 기본 기능이 있어야하는 것 같습니다.

Photoshop CS4에 액세스 할 수 있습니다. 모든 의견을 부탁드립니다.


.png를 색인 모드로 전환하지 않는 방법이 있습니까? RGB가 필요합니다. 아마 물방울을 만들 수는 있지만 더 쉬운 방법이 있는지는 몰랐습니다 ...하지만 팁 주셔서 감사합니다.

convertImagemagick 의 무료 명령을 사용할 수 있습니다 (완전한 psd 기능 적용 범위가 부족할 수 있음).
Uriel

답변:


158

방법 1 : Adobe의 내장 스크립트

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

여기에 이미지 설명을 입력하십시오

몇 가지 관련 질문이 있습니다 ...

크기를 유지하면서 Photoshop에서 개별 레이어 내보내기

레이어를 파일로 내보내기 100 개의 레이어에서 4 개의 PNG 파일 만 내 보냅니다.


방법 2 : 사용자 지정 스크립트

이 과정을 자동화하기 위해 시간을 보냈으며 자체 스크립트 파일을 작성했습니다. 이 프로세스는 위에서 언급 한 내장 스크립트보다 훨씬 빠릅니다.

지금 Github에서 스크립트를 받으십시오!

추가 정보

이 스크립트를 60 초 이내에 100MB, 450MB 파일에서 실행했습니다. 동일한 파일에서 내장 스크립트를 실행하면 약 30 분이 걸립니다.

중첩 계층 그룹으로 테스트 할 때 내 스크립트가 약 90 초 동안 실행되는 반면 내장 스크립트는 약 27 분이 소요되며 실제로는이를 내보내는 것으로 나타났습니다.

이러한 결과는 파일의 복잡성, 컴퓨터의 하드웨어 및 Photoshop 버전에 따라 달라질 수 있습니다. 추가 성능 데이터 .

이 스크립트는 (지난 몇 년 동안) 다양한 기고자들 로부터 다양한 개선을 받았습니다 . 스크립트에 문제가있는 경우 여기서 스크립트로 문제를 제기 할 수 있습니다 .

추가 정보 는 read-me 를 참조하십시오.

면책 조항 :이 스크립트는 어떤 식 으로든 Adobe와 관련이 없습니다. 스크립트는 사용자의 책임하에 사용하십시오. 사용하기 전에 항상 PSD를 백업하십시오. 손상되거나 손실 된 데이터에 대해서는 책임을지지 않습니다.


1
@Lucian - 당신이 포토샵 CC를 사용하는 경우 당신은 그냥이 작업을 수행 할 수 있습니다 그렇지 않으면, Github에서에 문제를 제기 . 감사!
Hanna

Johannes는이 질문에 대한 훌륭한 대본을 만들었으며 정당한 의견을 여러 번 올릴 자격이 있지만 의견에서이를지지하지 마십시오. 이와 관련하여 문제가있는 경우 리포지토리를 통해 솔루션을 찾으면 그에 따라 추적 할 수 있습니다.
DᴀʀᴛʜVᴀᴅᴇʀ

이 도구는 현재File -> Export -> Layers to Files...
akinuri

다른 사람이 혼란 스러울 경우 이것은 Photoshop 스크립트이므로 Photoshop이 필요합니다. 나는 그것이 쉘 스크립트가 될 것이라고 생각했다. :)
Chris Rae

1
@ 하나님 EPIC입니다! 수고하셨습니다. 감사합니다!
Chris Emerson

18

1 년 전 Johannes의 솔루션을 여러 가지로 개선했습니다. 크게 :

  • 모든 레이어가 작성되도록 레이어 그룹이 올바르게 처리됩니다.
  • 충돌을 방지하기 위해 파일 이름이 자동으로 증가합니다 (두 개 이상의 레이어가 동일한 이름을 가진 경우 발생 함).
  • 성능이 향상됩니다. 이 스크립트는 몇 분 안에 500 개의 간단한 레이어를 저장할 수 있습니다.

이 외에도 코드가 정리되었습니다. 예를 들어, 전역 변수는 단일 배열로 통합되었습니다.

초기 팝업 메시지는 최상위 레이어 수만 알려줍니다 . 이것은 성능 저하를 피하기위한 것입니다. 처리중인 파일에 대해 아무것도 모르는 경우를 상상할 수 없으므로 타협하지 않아야합니다.

여기서 스크립트를 가져옵니다 . 길을 인도 한 이전의 저자에게 감사합니다.


이 스크립트를 유지 관리하는 것이 정말 좋습니다. 그것은 :) 층의 수천 수정 빠져들지 시간이 수출 매우 잘 작동
iwasrobbed

7

파일을 배포하기 위해 크레딧이 요하네스로갑니다. 정말 고맙습니다!

약 3 시간 내에 2448 레이어 파일을 통과하는 데 도움이되는 기능을 추가했습니다.

수정 된 파일에 대한 링크는 다음과 같습니다. 여기 다운로드


6

문서의 핵심 BackgroundLayer를 사용하도록 스크립트를 업데이트했습니다. 익스포트 한 각 jpg가 컴파일됩니다.

누군가가 기본 BackgroundLayer 대신 마스터 레이어를 만들기 위해 레이어에 태그를 추가하면 좋을 것입니다 ;-)

전체 스크립트 :

    // 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();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.