1. 程式人生 > >第25周-Photoshop-指令碼程式設計簡介

第25周-Photoshop-指令碼程式設計簡介

這個工具包在PS裡面,你可以在這個資料夾中中找到:

Mac OSX: /Applications/Utilities/Adobe Utilities CS6/ExtendScript ToolkitCS6/

Windows: C:\Program Files\Adobe\Adobe Utilities-CS6\ExtendScriptToolkit CS6(64位的Program Files(x86))

ExtendedScript Toolkit的使用者介面非常的簡單。開始寫程式碼,第一步就是要在下拉選單中選擇目標應用。如果PS已經在執行,就可以看下下拉選單旁邊的綠色連結圖示:

no-7

這個時候,你可以像這樣寫:

  1. alert("Hello Photoshop!"); 

no-9

ExtendedScript Toolkit 有一些其他的除錯程式碼的不錯特性,但是這一段程式碼就這樣就夠了。你可以通過:幫助-JavaScript Tools Guide學到更多如何使用它。

你可以使用任何文字編輯來寫程式碼,只需要儲存為.jsx格式檔案就好了。你必須在PS裡通過File-Scripts-Browse來找到並執行它。 或者是,在PS裡面開啟指令碼檔案。你也可以在指令碼的前面加上一行程式碼,這樣這個程式碼就會常在PS裡面開啟:

  1. #target photoshop 

直接儲存你的程式碼在 Photoshop/Presets/Scripts/,然後通過File-Scripts訪問它們。你也可以設定一個快捷鍵,前往 Edit-Keyboard Shortcuts,連結到 File-Script-[你的程式碼名稱],然後選擇一個你想要設定的快捷鍵。

ExtendedScript Toolkit可以在整合的開發環境下執行和除錯程式碼,同時它還有一個目標模型指示器來安裝,這是很有用的。所以我推薦使用toolkit來寫指令碼。不幸的是,Mac版本的有時候會崩潰,所以要記住這一點。

Photoshop物件模型

為了使指令碼寫起來簡單些,你需要懂得在Photoshop檔案物件模型(DOM)中事件是怎樣互相聯絡的。如果你觀察PS本身,理解起來並不困難。PS的DOM裡面最主要的物件就是應用程式。在應用程式裡面,我們有一個資料夾在PS裡面是當前開啟的(翻譯錯誤!本人認為應該糾正為:應用程式裡有photoshop當前開啟的一系列檔案)。

每一個檔案包含一些元素:例如圖層(被稱為Artlayers),圖層組(layerSets),通道,歷史記錄等等–就像一個普通的PSD檔案。

下面就是一個簡單的視覺化的PS的DOM。更詳細的包含層級的可以在”Adobe Photoshop CS6 Scripting Guide”Pdf檔案中12頁裡找到。

no-11

一個簡單的視覺化的Photoshop DOM

這裡面的每一個目標都有它自己的屬性和方法你可以編輯它。例如,在一個檔案中改變所選圖層的透明度,你就可以前往Application-Document-layer-Opacity然後選擇你的期望值。程式碼就是這樣寫:

  1. app.activeDocument.activeLayer.opacity = 50

你應該可以猜到,activeDocument和activelayer決定了當前選擇的檔案和圖層。

你可以在“Adobe Photoshop CS6 JavaScript Scripting Reference”PDF檔案中找到大部分的目標和它們的屬性和方法的說明,或者在ExtendedScript Toolkit中通過前往help-object Model Viewer.

讓我們來看看在一個真實的例子中是如何執行的。在接下來的段落中,我們將會基於一個動作寫一段我們自己的程式碼。

用程式碼來重現自我旋轉動作

幾年前的聖誕節,我有一個想法就是用動作幫助我畫一個雪花。

畫雪花

1,首先畫一支雪花的圖案。

no-13

2,複製這一支,同時旋轉一定的角度。

no14

3,重複第二步直到一個完整的圓。

no-15

手動去複製和旋轉每一個元素非常麻煩,所以我想出了一個自動的動作(an action to automate it)去完成它。演算法是這樣的:

1,複製元素。

2,使用變化工具按照你所選擇的角度去旋轉這個元素。

3,複製圖層。

4,使用“重複變換”功能。

5,重複動作4和5直到一個完整的圓。

非常不錯!但是這個動作有一個缺點:根據你在第三步設定的角度數值的演算法,你只能設定一定數量的雪花的分支。

回到當我還不是很熟悉指令碼的時候,我做了幾個版本的動作,每一種產生的雪花都是不同的分支數。

今天,我們將用你輸入分支的數值的動態指令碼來重繪這個動作,讓我們開始吧。

演算法

當你開始寫指令碼的時候,在挖掘程式碼本身之前先設定演算法是個不錯的主意。在我們的情況下,演算法將會是這樣的:

1,詢問使用者輸入分支的數目。

2,計算旋轉的角度。

3,通過第一步設定的數目來複制並旋轉圖層。

首先讓我們從把當前或選定的圖層作為變數儲存起來,為了將來使用:

  1. // Save selected layer to variable: 
  2. var originalStem = app.activeDocument.activeLayer; 

在JavaScript 中注意,你可以標記兩條雙斜線(//)做註解。註解被用來為未來相關部分的程式碼做解釋但是不影響指令碼的執行。

現在讓我們回到我們的演算法上。

1,要求使用者輸入

我們通過prompt(message,defaultvalue[,tittle])這個功能來獲取使用者的輸入資訊:。這個功能表明一個有 著”message”對話方塊和一個包含這”fefault value”的輸入框。當用戶點選“確定”,這個給你功能就回到輸入值;因此,我們需要儲存它為一個可是用的變數。

  1. // Ask user for input by showing prompt box and save inputted value to variable: 
  2. var stemsAmount = prompt("Processing \""+originalStem.name+"\"\nHow many stems do you need?", 12); 

注意我使用了“orginalStem.name”在這段資訊裡面。所以對話方塊會現實所選擇圖層的名稱。

在Mac OS X中,在資訊中的第一行是寬的,作用是標題。因此,我們主要的資訊應該在第二行。另起一行,輸入“\n”.

在Windows中,你可以在功能中指定第三種引數來設定一個標題:

  1. // Ask user for input by showing prompt box and save inputted value to variable: 
  2. var stemsAmount = prompt("How many stems do you need?", 12, "Processing "+originalStem.name); 

如果我們在PS中執行這個程式碼,將會看到這樣一個對話方塊:

no-19

當用戶點選“確定”,輸入值將會儲存到stemsAmount變數中。如果用去點選“取消”,這個功能將會返回一個無效值。這個我們後面要使用到。

2,計算旋轉的角度

為了計算旋轉的角度,我們需要通過分支的數目來分360度(一個整圓):

  1. // Calculate the rotation angle 
  2. var angle = 360 / stemsAmount; 

3,複製和旋轉

現在我們已經有了我們需要複製的分支的一切。為了這樣去做,我們將使用“for”迴圈。它可以讓我們按照我們想要的次數來反覆的執行一段程式碼。我們的迴圈將會是這樣的:

  1. for(var i = 1; i <stemsAmount; i++){ 
  2.     // This code will run "stemAmount - 1" of times 
  3. }; 

注意第一個在程式中的物件例子已經有了值為0,但是因為我們第一個圖層已經在畫布上了,我們從1開始這個迴圈。

為了輔助和旋轉我們的圖層,我們將會使用:duplicate()和rotate(angle,AnchorPosition)函式:在angle 裡面被旋轉圖層的數目通過複製的指數相乘而得。 Anchorposition決定了哪個圖層將會旋轉的點。當你在PS中使用旋轉工具的時候你可以看到這個點—它看起來是一個小小的加了十字的圓圈。在腳 本中,它僅有9個指定的值-i.e.9個位置的錨點:

no-22

在我們這個情況下,它是這個圖層按鈕的中心。BOTTOMCENTER. PS在這裡或那裡的一些功能上使用了很多其他的一些常量,你可以在”Adobe Photoshop CS6JavaScript Reference”PDF檔案中的197頁找到。因此我們的迴圈就是這個樣子:

  1. // Duplicate and rotate layers: 
  2. for(var i = 1; i <stemsAmount; i++){ 
  3.     // Duplicate original layer and save it to the variable  
  4.     var newStem = originalStem.duplicate(); 
  5.     // Rotate new layer 
  6.     newStem.rotate(angle * i, AnchorPosition.BOTTOMCENTER); 
  7. }; 

完整的程式碼就是下面這個樣子,你可以試著執行:

  1. // Save selected layer to variable: 
  2. var originalStem = app.activeDocument.activeLayer; 
  3. // Ask user for input by showing prompt box and save inputted value to variable: 
  4. var stemsAmount = prompt("Processing \""+originalStem.name+"\"\nHow many stems do you need?", 12); 
  5. // Calculate the rotation angle: 
  6. var angle = 360 / stemsAmount; 
  7. // Duplicate and rotate layers: 
  8. for(var i = 1; i <stemsAmount; i++){ 
  9.     // Duplicate original layer and save it to the variable 
  10.     var newStem = originalStem.duplicate(); 
  11.     // Rotate new layer 
  12.     newStem.rotate(angle * i, AnchorPosition.BOTTOMCENTER);  
  13. }; 

最後的潤色

我通常會試著使用指令碼來完成我的主要目的。當一切都正確的執行起來的時候,我將會開始優化程式碼。在我們這種情況下,我們需要確保使用者在提示框中輸入一個有效的數值—i.e.一個正整數,而且要大於1。

當然,為了不讓PS瘋掉,我們會限制分支的書目,我們規定,小於100.為了這麼做, 當他們提交了一個無效的數值的時候 ,我們需要使用一個“while”迴圈來告訴使用者一個錯誤的資訊。而且這個提示框將會一直存在,直到使用者輸入一個有效值或者點選“取消”按鈕。(記住如果 使用者點選取消將會提示無效值)。

新的程式碼將會是這樣的:

  1. // Save selected layer to variable: 
  2. var originalStem = app.activeDocument.activeLayer; 
  3. // Ask user for input by showing prompt box and save inputted value to variable: 
  4. var stemsAmount = prompt ("Processing \""+originalStem.name+"\"\nHow many stems do you need? (From 2 to 100)", 12); 
  5. // Check that user entered a valid number and, if invalid, show error message and ask for input again 
  6. while(isNaN(stemsAmount) || stemsAmount <= 0 || stemsAmount > 100){ 
  7.     // If user clicks "Cancel" button, then exit loop 
  8.     if(stemsAmount == null) break; 
  9.     // Show error message… 
  10.     alert("Please enter number in range from 2 to 100"); 
  11.     // …and ask for input again 
  12.     stemsAmount = prompt("Processing \""+originalStem.name+"\"\nHow many stems do you need? (From 2 to 100)", 12); 
  13. }; 
  14. // Run the copying process 
  15. if(stemsAmount != null){  
  16.     // Calculate the rotation angle 
  17.     var angle = 360 / parseInt(stemsAmount); 
  18.     // Duplicate and rotate layers: 
  19.     for(var i = 1; i <stemsAmount; i++){ 
  20.         // Duplicate original layer and save it to the variable 
  21.         var newStem = originalStem.duplicate(); 
  22.         // Rotate new layer 
  23.         newStem.rotate(angle * i, AnchorPosition.BOTTOMCENTER); 
  24.     }; 
  25. }; 

你可能注意到:我們使用了“isNaN(value)”這個功能,它返回 “true”如果 “value”不是一個數字,同時當我們計算旋轉的角度的時候,“parseInt(value)”把“value”轉換成一個整數。

接下來我們要做的事情是管理圖層,通過為它們增加一個索引來重新命名我們的圖層。同事也要確保我們不會把檔案的圖層搞亂,讓我們把我們的分支編組。

為圖層重新命名不是一個很難的事情。我們只需要使用圖層的“name”屬性,然後為它們增加一個索引數字:

  1. // Add index to new layers 
  2. newStem.name = originalStem.name + " " + (i+1); 

PS應用程式介面裡的編組被稱為“LayerSet”,我們通過“layerSets”屬性可以進入檔案的所有編組。為了給檔案增加一個新的組,我們需要稱“layerSet”方法為“add()”:

  1. // Create a group for stems 
  2. var stemsGroup = app.activeDocument.layerSets.add(); 
  3.     stemsGroup.name = originalStem.name + " ("+stemsAmount+" stems)"; 

然後,為了把一個圖層增加到組裡面,我們會使用“move(relativeobject,ElementPlacement)”函式。請注 意,“move()”函式只是把圖層移動到圖層堆,而不是移動到畫布上。(你可以用“trabslate(deltaX[,deltaY])”函式把圖層 移動到畫布上)

ElementPlacement是另外一個常量,這個常量決定我們怎樣把的圖層跟 relativeobject 關聯在一起。在我們的案例裡,我們使用ElementPlacement.INSIDE 把一個普通圖層放進一個組裡面:

  1. // Place original layer in group 
  2. originalStem.move(stemsGroup, ElementPlacement.INSIDE); 

我們使用 ElementPlacement.PLACEATEND.把每一個拷貝的新圖層放在所有圖層租的底部。結果就是我們的所有圖層都是以上升的順序排列,第一個圖層在頂部,最後一個圖層在底部:

  1. // Place new layer inside stems group 
  2. newStem.move(stemsGroup, ElementPlacement.PLACEATEND); 

最終程式碼

這就是它!RotateMe.jsx已經完成。我們的最終程式碼看起來像這樣:

[javascript] view plain copy
  1. // Save selected layer to variable:
  2. var originalStem = app.activeDocument.activeLayer;  
  3. // Ask user for input by showing prompt box and save inputted value to variable:
  4. var stemsAmount = prompt ("Processing \""+originalStem.name+"\"\nHow many stems do you need? (From 2 to 100)", 12);  
  5. // Check that user entered a valid number and, if invalid, show error message and ask for input again
  6. while(isNaN(stemsAmount) || stemsAmount <= 0 || stemsAmount > 100){  
  7.     // If user clicks "Cancel" button, then exit loop
  8.     if(stemsAmount == nullbreak;  
  9.     // Show error message…
  10.     alert("Please enter number in range from 2 to 100");  
  11.     // …and ask for input again
  12.     stemsAmount = prompt("Processing \""+originalStem.name+"\"\nHow many stems do you need? (From 2 to 100)", 12);  
  13. };  
  14. // Run the copying process
  15. if(stemsAmount != null){   
  16.     // Calculate the rotation angle
  17.     var angle = 360 / parseInt(stemsAmount);  
  18.     // Create a group for stems
  19.     var stemsGroup = app.activeDocument.layerSets.add();  
  20.         stemsGroup.name = originalStem.name + " ("+stemsAmount+" stems)";  
  21.     // Place original layer in group
  22.     originalStem.move(stemsGroup, ElementPlacement.INSIDE);  
  23.     // Duplicate and rotate layers:
  24.     for(var i = 1; i < stemsAmount; i++){  
  25.         // Duplicate original layer and save it to the variable
  26.         var newStem = originalStem.duplicate();  
  27.         // Rotate new layer
  28.         newStem.rotate(angle * i, AnchorPosition.BOTTOMCENTER);  
  29.         // Add index to new layers
  30.         newStem.name = originalStem.name + " " + (i+1);  
  31.         // Place new layer inside stems group
  32.         newStem.move(stemsGroup, ElementPlacement.PLACEATEND);  
  33.     };  
  34.     // Add index to the original layer
  35.     originalStem.name += " 1";  
  36. };  

怎麼樣,不難吧?

現在你可以把它放在這個目錄下 Photoshop/Presets/Scripts/ 然後操作 File → Scripts 執行指令碼. 不同的圖形不同的輸入值都會產生不一樣的有趣效果:

相關推薦

25-Photoshop-指令碼程式設計簡介

這個工具包在PS裡面,你可以在這個資料夾中中找到: Mac OSX: /Applications/Utilities/Adobe Utilities CS6/ExtendScript ToolkitCS6/ Windows: C:\Program Files\Adobe\Adobe Utilities

201825總結

充電器 最重要的 類加載 找工作 經濟 開發 CA 下一步 沒有 Java類加載器回顧,重點是Java類加載機制不能實現現實的需求時如何處理,重點是兩種情況沒法處理,SPI(服務提供接口),接口在調用方,可能被根加載器加載,實現方通過獨立的Jar包實現被系統加載器,那麽接口

10課--10_05_指令碼程式設計之八 指令碼完成磁碟分割槽格式化

一、until 迴圈where CONDTION;dostatementdone進入迴圈,條件滿足退出迴圈,條件不滿足until CONDTION;dostatementdone進入迴圈,條件不滿足退出迴圈,條件滿足for i in list ;dostatementdonefor ((expr1;epxr2

25天面向物件程式設計詳解之繼承

面向物件補充知識 面向物件概念 面向物件核心二字在與物件,物件就是特徵和技能的結合體,基於該思想程式設計就好比在建立一個世界,世界上的任何事物都是物件,你就好比是這個世界的上帝,這是一種基於上帝式的思維方式。 優點:擴充套件性強 缺點:程式設計的複雜度要遠遠高於面向過程 問題一:既然面向物件這麼好,我們之

6作業 #高階程式設計技術

第11章 11-1 城市和國家 編寫一個函式,它接受兩個形參:一個城市名和一個國家名。這個函式返回一個格式為City, Country 的字串,如Santiago, Chile 。將這個函式儲存在一個名為city_functions.py的模組

Nervos CKB 指令碼程式設計簡介[1]:驗證模型

CKB 指令碼程式設計簡介[1]: 驗證模型 本文作者:Xuejie 原文連結:Introduction to CKB Scrip

【在 Nervos CKB 上做開發】Nervos CKB指令碼程式設計簡介[2]:指令碼基礎

CKB指令碼程式設計簡介[2]:指令碼基礎 原文作者:Xuejie 原文連結:Introduction to CKB Script

CentOS 7 Shell指令碼程式設計七講 Bash Shell 常用內建命令簡介

開發十年,就只剩下這套架構體系了! >>>   

20172303 2018-2019-1《程式設計與資料結構》7學習總結

20172303 2018-2019-1《程式設計與資料結構》第7周學習總結 教材學習內容總結 本週在上週學習了二叉樹的基礎上,學習了一種二叉樹的特殊形式——二叉查詢樹,又叫有序二叉樹、排序二叉樹。本章學習了兩種二叉查詢樹的實現方法,以及兩種二叉查詢樹的應用。 一、概述 1.二叉查詢樹

# 20172307 2018-2019-1 《程式設計與資料結構》7學習總結

20172307 2018-2019-1 《程式設計與資料結構》第7周學習總結 教材學習內容總結 樹的分類 廣義樹:對結點所含有的孩子數目無限制的樹。 n元樹:每一結點不超過n個孩子的樹。(結點最多具有兩個孩子的樹稱為二叉樹) 樹的平衡:樹的所有葉子都位於同一層或者至少是彼此相差不超過一

201711671125 《Java程式設計7學習總結

教材學習內容總結 第六章 1.介面 使用interface來定義一個介面,介面分為介面宣告和介面體。 (1)介面宣告:interface 介面的名字 (2)介面體:包含常量的宣告(沒有變數)和抽象方法兩部分。介面體中所有的常量和抽象方法的訪問許可權都是public,而且是stat

201711671125 《Java程式設計6學習總結

教材學習內容總結 第五章 1.子類與父類 繼承是一種由已有的類建立類的機制。由繼承得到的類稱為子類,被繼承的類稱為父類。Java不支援多重繼承,即子類只有一個父類。 1.1子類 在類的宣告中,通過使用關鍵字extends來定義一個類的子類。(格式:class 子類名 extend

201711671125 《Java程式設計5學習總結

教材學習內容總結 第四章 1.構造方法與物件的建立 1.1構造方法 沒有型別,一個類中可以有若干個構造方法,但必須保證引數的個數不同,或引數個數相同,但引數列表中對應的某個引數的型別不同。 1.2建立物件 格式:類的名字 物件名字 使用new運算子和類的構造方法為宣告的物

201711671125 《Java程式設計3學習總結

教材學習內容總結 第三章 1.運算子與表示式 1.1算術運算子與算數表示式 加減運算子是一目運算子,結合方向是從左到右。 乘、除和求餘運算子*、/、%是二目運算子,結合方向是從左到右。 1.2自增、自減運算子 是單目運算子,可放在操作元之前,也可放在操作元之後,操作元必須

201771010120 蘇浪浪 面向物件程式設計(Java)10

  1、實驗目的與要求 (1) 理解泛型概念; (2) 掌握泛型類的定義與使用; (3) 掌握泛型方法的宣告與使用; (4) 掌握泛型介面的定義與實現; (5)瞭解泛型程式設計,理解其用途。 2、實驗內容和步驟 實驗1: 匯入第8章示例程式,測試程式並進行程式碼註釋。 測試程式1:

《Java程式設計6學習總結

201711671201《Java程式設計》第6周學習總結 教材學習內容總結 第5章:子類與繼承 5.1 子類與父類 繼承是一種由已有的類建立新類的機制。先定義一個共有屬性的一般類,再定義具有特殊屬性的子類。 由繼承得到的類稱為子類,被繼承的類稱為父類(超類)。 Java不支

《Java程式設計5學習總結

201711671201《Java程式設計》第5周學習總結 教材學習內容總結 第4章:類與物件 4.1 程式語言的幾個發展階段 4.1.1 面向機器語言。 4.1.2 面向過程語言。 4.1.3 面嚮物件語言 3個特性:封裝性,繼承,多型。 4.2 類 類的定義包括兩

《Java程式設計2學習總結

201711671201《Java程式設計》第2周學習總結 教材學習內容總結 第2章:基本資料型別與陣列 2.1 識別符號與關鍵字 2.1.1 識別符號 用來標識類名、變數名、方法名、型別名、陣列名及檔名的有效字元序列稱為識別符號。 識別符號由字母、下劃線、美元符號和數字組成

《Java程式設計1學習總結

201711671201《Java程式設計》第1周學習總結 教材學習內容總結 第1章:Java入門 Sun公司,爪(zhao)哇,Java虛擬機器(JVM)。  【類、物件、繼承、多型、介面】 印度尼西亞的一個重要的盛產咖啡的島嶼叫Java,中文譯名為爪哇,其寓意是為世人端

中國大學MOOC—基礎學Java語言----6程式設計題——單詞長度(5分)

import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String