PS動作、腳本實際工作中的應(yīng)用
最近在做一些無聊游戲,具體就不多說了,談實際碰到的兩個例子:
由于常常有人抱怨寫的東西看不懂,所以廢話多了點,講的內(nèi)容也比較粗淺,還望熟手見諒
一、自己的麻將牌變對家的牌
做好一副麻將牌,需要把它上下顛倒過來。

如果用垂直or水平反轉(zhuǎn),很明顯字都是反的。直接旋轉(zhuǎn)順序不符合程序要求,且透視不對,于是要一張張牌單獨處理。
由于是重復(fù)操作,且沒有什么變數(shù),于是我們采用動作處理:
做選區(qū),ctrl t旋轉(zhuǎn)180度,移動選區(qū)到下一個位置(1張牌的距離)



本來這個動作很簡單,但是實際測試發(fā)現(xiàn):
ctrl t自由變換后,移動選區(qū)會帶著圖像走,不能單純移動

想辦法解決:自由變換后,先取消選區(qū)(ctrl d),再恢復(fù)上一個選區(qū)(ctrl shift d)。這樣,在移動選區(qū),就不會帶走圖像了。
于是我們錄制動作,一遍遍的執(zhí)行,只要第一次選區(qū)準(zhǔn)確、移動準(zhǔn)確,就萬事大吉了

二、找茬游戲中腳本的應(yīng)用
項目要求:制作一大批圖片。每兩幅一組,兩幅之間有十處不同,記錄每處不同的矩形區(qū)域坐標(biāo)。
首先是制作圖片:其實就是簡單的p圖,制造一些差異。
為了方便對比觀察,避免錯漏,使用了cs3的智能對象的堆棧功能(new)。
感覺這樣比較方便比較,能在精確查看不同的同時ps圖片的內(nèi)容。
首先建立固定大小的文件,再把素材圖拉進(jìn)來,調(diào)整大小,然后ctrl e合并到底層(合并是為了確保未來的智能對象大小和圖像大小一致),ctrl j 新建一層。我們只ps 新建出來的這一層,下面不動。
因為有10處差異,所以光靠切換可視對比~比較辛苦,且容易錯漏,[差值]對比效果也差又累。
所以我們同時選中兩個圖層,右鍵-[轉(zhuǎn)換為智能對象],然后菜單-圖層-智能對象-堆棧模式-標(biāo)準(zhǔn)偏差

這時候我們就明顯看到兩層之間的差異了,
我們可以雙擊圖層面板的智能對象縮略圖,就可以展開進(jìn)入智能對象內(nèi)部,繼續(xù)編輯兩個圖層

我們在智能對象內(nèi)部編輯的時候,只要隨手ctrl s 保存一下,就可以看到原圖(黑色那張)上的差異變化了。
圖像處理完后,然后就是獲得由差異區(qū)域的坐標(biāo):程序需要把差異區(qū)域作為一個個矩形,要得到每個區(qū)域左上角和右下角的坐標(biāo)。

最開始,想把所有區(qū)域拉出選區(qū),然后通過 cs3 的新增統(tǒng)計功能獲得詳細(xì)的選區(qū)數(shù)據(jù),結(jié)果~~
非常遺憾,統(tǒng)計可以同時獲得所有選區(qū)的周長、長寬、面積甚至密度~ 就是不給出具體的每一組坐標(biāo)(如下圖所示)

于是只有改變做法,這時候想到了腳本 里面的 selection.bounds 獲得選區(qū)坐標(biāo),
遺憾的發(fā)現(xiàn),似乎腳本里面沒有獲取多個區(qū)域選取數(shù)據(jù)的方法,只能獲得總選區(qū)的左上角 右下角坐標(biāo)
也就是說10個區(qū)域當(dāng)成一個大區(qū)域來看了。~
繼續(xù)改變方案,改用圖層,每個圖層只記錄一個區(qū)域,總可以了吧~~
因為之前的經(jīng)驗,確定圖層的范圍坐標(biāo)是可以在腳本里通過 ArtLayer.bounds 獲取的。
所以接下來要做的事情就是手動建立一個個小矩形的圖層。
由于工作量巨大,不偷懶是不行的,所以錄制了一個動作

可以看到,這個動作錄制了3步:
-
新建圖層
填充選區(qū)
取消選區(qū)
有了這個動作,我只要拉出一個選區(qū),然后按一下 F12,就自動新建一個圖層,并填充好。
這樣就方便腳本獲取每層的數(shù)據(jù)了。
完成后的文件結(jié)構(gòu)如下:
在編寫腳本的時候,不能不提到的一個輔助工具就是“腳本偵聽程序” 鑒于實踐表明: 同樣顯示效果下 [另存為jpg] 比 [保存為web所用格式-jpg] 文件體積要大很多,所以最后替換了保存函數(shù)。 把saveAs,換成了exportDocument.,具體如下:
上面是10層不同位置的矩形,最底層是一個智能對象(包含兩個圖層,上面一層為修改后的,下面一層為原圖)
文件格式ok,接下來就是腳本大顯身手的地方了。
接下來我們開始編寫腳本,為了通俗,這一步主要只是談?wù)勊悸?/strong>
首先測試單個文件,腳本大致需要執(zhí)行如下步驟:
移動到最底層
向上移動一層,利用 activeLayer.bounds 記錄層范圍坐標(biāo),并把坐標(biāo)記錄下來
反復(fù)執(zhí)行第2步,直到最頂層
輸出記錄
有了以前一些腳本的經(jīng)驗,實現(xiàn)上面這個功能沒有碰到什么難度,很容易搞定。
然后就是批量處理了 ,該腳本已經(jīng)有完善的批量打開、保存處理模塊。局部Copy后稍加修改,就讓我們的腳本實現(xiàn)了如下功能:
用戶選擇待處理文件夾
獲取該文件夾下所有文件
打開一個文件,獲取并記錄所有需要的坐標(biāo),關(guān)閉不保存
重復(fù)第3步,直至處理完所有文件
輸出記錄
測試成功后,想到:既然已經(jīng)動用腳本獲取了所有坐標(biāo),索性把兩張不同的圖片也輸出保存好了。于是添加了一個保存位置選擇。
并對單個文件內(nèi)的操作作了修改:
移動到最底層
打開最底層智能對象
另存智能對象為jpg文檔(xxx_1)
隱藏智能對象里的最上層,也就是我們修改過的那層
再次另存智能對象為jpg文檔(xxx_0)
不保存關(guān)閉智能對象(回到原文檔)
向上移動一層,利用 activeLayer.bounds 記錄層范圍坐標(biāo),并把坐標(biāo)記錄下來
反復(fù)執(zhí)行第7步,直到最頂層
這樣不但記錄了坐標(biāo)數(shù)據(jù),還順便把智能對象里面的兩個層都輸出為jpg圖像了。
后來,由于第二張圖片和第一張圖片很多相同的地方,導(dǎo)致游戲文件體積較大,所以想了一個解決辦法,就是把相同的部分用黑色擋住,只保留不同的地方,這樣jpg就小很多。也許是個笨辦法吧,畢竟不太清楚別人怎么做的,這里只是給大家說說思路罷了。
于是再次修改單個文件內(nèi)的操作部分
移動到最底層
向上移動一層,利用activeLayer.bounds 記錄層范圍坐標(biāo),并把坐標(biāo)記錄下來
反復(fù)執(zhí)行第2步,直到最頂層
再次回到最底層
打開最底層智能對象
利用記錄的坐標(biāo),建立選區(qū)(增加模式),全部選區(qū)增添完后,反選
填充黑色(這時候是填充在智能對象內(nèi)部最上層上,也就是我們修改過的那層)
另存為智能對象為jpg文檔(xxx_1)
隱藏當(dāng)前圖層
再次另存智能對象為jpg文檔(xxx_0)
不保存關(guān)閉智能對象(回到原文檔)
這樣我們就給修改過的圖像增添了一個黑色部分,擋住了沒動過的地方,只留下了差異處。為了減少jpg 保存可能對邊緣造成的影響,所以黑色部分的填充范圍縮小了2像素。后來為了修改方便,索性在面板上放了一個位置,可以手動輸入縮小量。
為了程序調(diào)用方便,腳本還順便實現(xiàn)其他一些功能:
比如把文件名作些規(guī)范處理:按照數(shù)字大小排序文件(否則打開順序會是1、11、12、2、21這樣),并且把1.psd 、2.psd 之類的記錄為 0001、0002;
用簡單正則替換去掉坐標(biāo)記錄轉(zhuǎn)換為字符串后的“ px”單位等等。
為了處理時對進(jìn)度有個掌握,腳本界面上還放了進(jìn)度條。
最后,發(fā)現(xiàn)有時候不需要重新生成圖像,只需要獲取坐標(biāo)。又在界面上加了一個 “僅查詢坐標(biāo),不生成圖片”的選項。如果勾選,就會跳過保存的步驟,以節(jié)省時間。
以上的過程,最終就是如下這個腳本程序,處理我近百張圖片也就3分多的樣子,手工的話又容易出錯又慢,程序的優(yōu)勢就這樣體現(xiàn)出來了。

以后要修改、調(diào)整,只要修改psd文檔,再用腳本重新生成 就很快完成工作。兩個多小時的編寫調(diào)試還是值得的 。
#target photoshop
app.bringToFront();
res ="dialog { \
text:'找茬數(shù)據(jù)專用',\
group: Group{orientation: 'column',alignChildren:'left',\
folderO:Group{ orientation: 'row', \
b: Button {text:'待處理文件夾', properties:{name:'open'} ,helpTip:'選擇您需要處理的文件所在的文件夾'},\
s: EditText { text:'', preferredSize: [360, 20] },\
},\
folderS:Group{ orientation: 'row', \
b: Button {text:'輸出圖像至', properties:{name:'save'} ,helpTip:'選擇您處理好的文件要保存至的文件夾'},\
s: EditText { text:'', preferredSize: [360, 20] },\
},\
meng:Group{ orientation: 'row', \
c:Checkbox { text:' 啟用黑色蒙版'} ,\
s: StaticText { text:'| 蒙版收縮量(單位px):' }, \
e: EditText { text:'2', preferredSize: [20, 18]},\
},\
Quality: Group { orientation: 'row', \
c:Checkbox { text:' 僅查詢坐標(biāo),不生成圖片'} ,\
s: StaticText { text:'| 生成JPG的壓縮質(zhì)量:' }, \
d: DropDownList { alignment:'left', itemSize: [26,14] },\
}, \
gg: Group{orientation: 'column',alignChildren:'left' },\
timeline:Progressbar{bounds:[0,0,400,10] , minvalue:0,maxvalue:100}\
aa: Button { text:'START'}, \
}\
}";
var mengPoint="";
var mengColor =new SolidColor;
mengColor.rgb.red =0;
mengColor.rgb.green =0;
mengColor.rgb.blue =0;
win = new Window (res);
win.myText = win.group.gg.add("edittext",[0,0,500,300],'~~~',{multiline:true, readonly:false});
for (i=0;i<13;i ){ //初始化jpeg質(zhì)量下拉
win.group.Quality.d.add("item", i );
}
win.group.Quality.d.items[7].selected=true;
function lyFoot() { // 選中最下層
var id553 = charIDToTypeID( "slct" );
var desc88 = new ActionDescriptor();
var id554 = charIDToTypeID( "null" );
var ref95 = new ActionReference();
var id555 = charIDToTypeID( "Lyr " );
var id556 = charIDToTypeID( "Ordn" );
var id557 = charIDToTypeID( "Back" );
ref95.putEnumerated( id555, id556, id557 );
desc88.putReference( id554, ref95 );
var id558 = charIDToTypeID( "MkVs" );
desc88.putBoolean( id558, false );
executeAction( id553, desc88, DialogModes.NO );
}
function lyUp(){ //選中上一層
var id559 = charIDToTypeID( "slct" );
var desc89 = new ActionDescriptor();
var id560 = charIDToTypeID( "null" );
var ref96 = new ActionReference();
var id561 = charIDToTypeID( "Lyr " );
var id562 = charIDToTypeID( "Ordn" );
var id563 = charIDToTypeID( "Frwr" );
ref96.putEnumerated( id561, id562, id563 );
desc89.putReference( id560, ref96 );
var id564 = charIDToTypeID( "MkVs" );
desc89.putBoolean( id564, false );
executeAction( id559, desc89, DialogModes.NO );
}
function openSm() { //打開智能對象
var id216 = stringIDToTypeID( "placedLayerEditContents" );
var desc43 = new ActionDescriptor();
executeAction( id216, desc43, DialogModes.NO );
}
function lyHidden(){ //隱藏當(dāng)前圖層
var id217 = charIDToTypeID( "Hd " );
var desc44 = new ActionDescriptor();
var id218 = charIDToTypeID( "null" );
var list1 = new ActionList();
var ref24 = new ActionReference();
var id219 = charIDToTypeID( "Lyr " );
var id220 = charIDToTypeID( "Ordn" );
var id221 = charIDToTypeID( "Trgt" );
ref24.putEnumerated( id219, id220, id221 );
list1.putReference( ref24 );
desc44.putList( id218, list1 );
executeAction( id217, desc44, DialogModes.NO );
}
function sm(name) { //保存結(jié)果圖像
lyFoot();
openSm();
var smDoc=app.activeDocument;
if (win.group.meng.c.value) meng(smDoc);
var saveFolder = win.group.folderS.s.text "/";
saveOptions = new JPEGSaveOptions();
saveOptions.quality =win.group.Quality.d.selection.index;; //獲取jpg壓縮質(zhì)量
smDoc.saveAs(new File(saveFolder name "_1.jpg"),saveOptions, true,Extension.LOWERCASE);
lyHidden();
smDoc.saveAs(new File(saveFolder name "_0.jpg"),saveOptions, true,Extension.LOWERCASE);
smDoc.close(SaveOptions.DONOTSAVECHANGES);
}
function selectBounds(name,a,b,c,d) { //做選區(qū)
app.activeDocument.selection.select([[a, b],[ a, d ], [c, d], [ c, b]],SelectionType.EXTEND);
}
function meng(smDoc) { //添加蒙版
nowPoint=mengPoint.split(",");
for (var i=0;i<nowPoint.length-4;i =4){
selectBounds(smDoc,nowPoint[i],nowPoint[i 1],nowPoint[i 2],nowPoint[i 3],)
}
// ==================================擴(kuò)展n像素
var id32 = charIDToTypeID( "Expn" );
var desc5 = new ActionDescriptor();
var id33 = charIDToTypeID( "By " );
var id34 = charIDToTypeID( "#Pxl" );
desc5.putUnitDouble( id33, id34, Number(win.group.meng.e.text) );
executeAction( id32, desc5, DialogModes.NO );
// ==================================反選
var id35 = charIDToTypeID( "Invs" );
executeAction( id35, undefined, DialogModes.NO );
//
smDoc.selection.fill(mengColor); //填充蒙版色
}
// 打開文件夾的操作
var folderOpen=win.group.folderO
var folderSave=win.group.folderS
folderOpen.b.onClick = function() {
var defaultFolder = folderOpen.s.text;
var testFolder = new Folder(defaultFolder);
if (!testFolder.exists) {
defaultFolder = "~";
}
var selFolder = Folder.selectDialog("選擇待處理文件夾", defaultFolder);
if ( selFolder != null ) {
folderOpen.s.text = selFolder.fsName;
folderOpen.s.helpTip = selFolder.fsName.toString();
}
}
folderSave.b.onClick = function() {
var defaultFolder = folderSave.s.text;
var testFolder = new Folder(defaultFolder);
if (!testFolder.exists) {
defaultFolder = "~";
}
var selFolder = Folder.selectDialog("選擇要儲存至的文件夾", defaultFolder);
if ( selFolder != null ) {
folderSave.s.text = selFolder.fsName;
folderSave.s.helpTip = selFolder.fsName.toString();
}
}
win.group.aa.onClick=function(){
var myText="";
var openFolder = Folder(win.group.folderO.s.text);
var fileList = openFolder.getFiles() //獲取open文件夾下所有文件
win.group.timeline.value =0;
var k=100/fileList.length;
//調(diào)整文件順序,按數(shù)字大小排序
fileList.sort(function compare(a,b){return Number(a.name.substring(0, a.name.length-4))-Number(b.name.substring(0, b.name.length-4));})
//
for (i=0;i<fileList.length;i ){
if (fileList[i] instanceof File && fileList[i].hidden == false){ //不處理隱藏文件
var docRef =open(fileList[i]);
var nowName =docRef.name.substring(0, docRef.name.length-4);
while (nowName.length<4) {
nowName ="0" nowName;
}
myText =nowName ",";
mengPoint="";
lyFoot();
for (j=1;j<docRef.layers.length;j ){
lyUp();
myText =docRef.activeLayer.bounds ",";
mengPoint =docRef.activeLayer.bounds ",";
}
if (!win.group.Quality.c.value) sm(nowName);
docRef.close(SaveOptions.DONOTSAVECHANGES);
myText ="\r\n";
}
win.group.timeline.value =win.group.timeline.value k;
}
var re = / px/g; //要替換的“ px”
win.myText.text=myText.replace(re, "");
}
//////////////
win.center();
win.show();
這個東西就在 cs3 安裝目錄下面的“腳本指南/實用工具”里面(英文版在 Scripting Guide\Utilities\)

如果把它拷貝到“增效工具/自動”目錄下(英文版為 Plug-Ins\Automate),再重新啟動ps。你的ps就相當(dāng)于安裝了一個“竊聽器”,會把你所有的操作步驟像錄制動作一樣錄制為腳本。只要你有可記錄的動作,它就在桌面生成“ScriptingListenerJS”、“ScriptingListenerVB” 兩個文本文件。其實就是 javascript 和 vbscript 兩種規(guī)則記錄的動作。

雖然不像手工書寫的代碼易于理解和修改,但是很多直接操作的步驟都可以拷貝來用。
比如說上面的 “移動到最底層”“選中上一層”“隱藏當(dāng)前層”“打開智能對象”“擴(kuò)展n像素”“反選”等等動作就是通過腳本偵聽錄制下來 直接拷貝過來的。
再結(jié)合自己的編寫的其他邏輯語句,很容易寫出你想要的東西。
最后,希望有點編程基礎(chǔ)又有興趣的朋友,
在處理重復(fù)、量大或者經(jīng)常碰到的工作的時候,多多挖掘ps的潛力。
其實寫一個簡單的針對性腳本或者動作 并不是很難哦 ^_^
提供jsx源文件 兩個psd文檔,分本是 F14和殲10,有興趣的朋友可以試試看,注意cs3以上




function sm(name) { //保存結(jié)果圖像
lyFoot();
openSm();
var smDoc=app.activeDocument;
if (win.group.meng.c.value) meng(smDoc);
var saveFolder = win.group.folderS.s.text "/";
saveOptions = new ExportOptionsSaveForWeb();
saveOptions.format =SaveDocumentType.JPEG;
saveOptions.quality=win.group.Quality.e.text;
smDoc.exportDocument(new File(saveFolder name "_1.jpg"),ExportType.SAVEFORWEB,saveOptions);
lyHidden();
smDoc.exportDocument(new File(saveFolder name "_0.jpg"),ExportType.SAVEFORWEB,saveOptions);
smDoc.close(SaveOptions.DONOTSAVECHANGES);
}
相關(guān)文章
今天我們繼續(xù)來介紹ps基礎(chǔ)教程,這篇我們主要講橡皮擦工具組和填充工具組,這兩個工具在修圖的時候是比較常用的,下面我們就來看看基礎(chǔ)教程2025-05-01
photoshop圖層初識 ps圖層相關(guān)概念與基本操作
ps圖層是什么?簡單來說,ps軟件中的圖層就好比是一張“透明紙”,將圖像的各個部分繪制在不同的“透明紙”上,可以看到紙后的東西,而且每層紙都是獨立的,下面我們就來看2025-04-25
PS基礎(chǔ)教程之學(xué)習(xí)應(yīng)用圖層樣式的基本方法
ps零基礎(chǔ)之圖層樣式的講解,在使用ps的時候,我們經(jīng)常會在圖層上添加一些效果,這就是圖層樣式,該怎么應(yīng)用呢?詳細(xì)請看下文介紹2024-12-23
ps如何把一張長圖切成幾張小圖片? ps把長圖切成短圖的技巧
有時候,我們希望能把一張圖片均勻地分成幾張圖片,就像拼圖一般的效果,需要某一部分隨時可以拿出來使用,該怎么操作呢?詳細(xì)請看下文介紹2024-09-10
PS調(diào)整字體大小是一個非常基礎(chǔ)的操作,但也是非常實用的技能,在Photoshop中,調(diào)整字體大小的方式有多種,詳細(xì)請看下文介紹2024-02-02
ps窗口字體太小怎么調(diào) PS窗口字體大小調(diào)節(jié)技巧
但最近有用戶在使用photoshop時發(fā)現(xiàn)窗口界面的字體比較小,使用起來非常的不方便,因此有不少用戶想將其大小進(jìn)行調(diào)節(jié),具體該如何操作呢?詳細(xì)請看下文介紹2024-02-02
ps中圖層被父圖層鎖定怎么辦? 圖層被父圖層鎖定的解鎖技巧ps
ps中圖層被父圖層鎖定怎么辦?ps中圖層解鎖失敗,提示圖層被父圖層鎖定該怎么辦呢?下面我們就來看看詳細(xì)的解決辦法2023-12-19
ps描邊最大只有288怎么辦? Photoshop描邊只能調(diào)到288像素的解決辦法
ps描邊最大只有288怎么辦?ps描邊在使用的過程中,發(fā)現(xiàn)只能調(diào)到288像素,該怎么操作呢?下面我們就來看看Photoshop描邊只能調(diào)到288像素的解決辦法2023-11-30
PS工具欄中的工具有缺失怎么辦? Photoshop工具欄不全的多種解決辦法
PS工具欄中的工具有缺失怎么辦?ps工具欄中有很多工具,但是發(fā)現(xiàn)有些工具不見了,該怎么辦呢?下面我們就來看看Photoshop工具欄不全的多種解決辦法2023-11-30
Photoshop2024怎么下載安裝? ps2024安裝圖文教程
Photoshop2024怎么下載安裝?ps2024發(fā)布以后,很多朋友想要嘗試信工鞥,該怎么下載安裝呢?下面我們就來看看ps2024安裝圖文教程2023-11-30




