讓我們用JS和PSDom來掌控Photoshop吧!-繪制篇

本系列文章涉及的主題是PhotoShop plugin開發(fā)淆两。

要做的:

由兩篇文章組成:

基礎(chǔ)繪制篇--以PhotoShop的Document為舞臺断箫,在上面繪制文字和任意形狀
圖層操作篇--PS最強(qiáng)大的是圖層操作,通過操作圖層秋冰,我們可以完成各種想做的事情仲义,最經(jīng)典的就是用于UI自動切圖.

有了這些PSDom概念后,你會發(fā)現(xiàn)其實開發(fā)PS插件蠻簡單的,PSDom非常強(qiáng)大埃撵。

不做的:

1) 不涉及Channel操作赵颅,對位圖像素操作我們不關(guān)心
2) 不涉及PhotoShop界面編程。因為PS界面編程隨著版本變化暂刘,有好多種方式饺谬,一直在改變。
     C++方式谣拣,強(qiáng)大募寨,但是難度較大,不是三言兩語說得清楚的
     As3 Flex方式森缠,簡單易用拔鹰,和PSDom交互方便,但是適合Adobe CS系列
     Html5方式贵涵,簡單應(yīng)用列肢,和PSDom交互方便,但是適合Adobe CC系列
     但不管如何宾茂,核心的PhotoShop操作是通過PSDom API公開出來的瓷马,
     這個不管版本如何變,其本身DOM是不會發(fā)生較大變化的跨晴。
     因此才更有研究的價值

PSDom的開發(fā)環(huán)境--ExtendScript ToolKit
在安裝Adobe cs/cc系列時欧聘,會自動安裝(我裝的是CS5.0)

jsxIde.jpg

如果在Windows下開發(fā),請見后綴名改為.jsx
如果使用.js后綴的話坟奥,可能會由Windows Scripting Host(WSH)來執(zhí)行树瞭,而不是CS 腳本解析器。防沖突爱谁!

通過這兩篇文章晒喷,希望能夠讓大家在PhotoShop中為所欲為!7玫小凉敲!

讓我們來關(guān)注第一篇吧:

1)PS DOM(文檔對象模型)用來操縱PS中的各個對象,可以使用AppleScript(mac專用),VBScript(windows專用),以及JavaScript(跨平臺寺旺,本文檔僅使用js代碼來演示).

2)PS DOM中關(guān)鍵類圖(豎線表示包含關(guān)系爷抓,且第三層開始的所有類都是所屬于Document):

psdom類結(jié)構(gòu)圖.png

3)與繪制相關(guān)的對象:
二維繪制可以歸類為三個繪制范疇:

1、位圖/圖像操作:
PS Dom通過Application.Document.Channel(通道)對象進(jìn)行某個通道的數(shù)據(jù)操作(例如你可以分別對位圖的四個通道R G B A 進(jìn)行操作)阻塑,這不是本文所關(guān)注的蓝撇。

2、文本繪制:
PS Dom通過使用Application.Document.ArtLayer.TextItem進(jìn)行文本的顯示和相關(guān)操作陈莽。
由上面的尋址關(guān)系可以看到TextItem文本對象是被附加到PS中的一個Layer上的渤昌。

3虽抄、矢量繪制:
PS Dom 通過使用:
Application.Document.PathItem
Application.Document.PathItem.SubPathItem Application.Document.PathItem.SubPathItem.PathPoint
這三個類來進(jìn)行相關(guān)操作的(實際上還有其他一些輔助類,具體我們在后面了解)
由上面的尋址關(guān)系可以看到PathItem路徑對象是并沒有像TextItem一樣是被附加到PS中的一個Layer上的独柑,而是獨立于layer對象的迈窟。

4)JS運行調(diào)試環(huán)境和API參考文檔:
安裝好PhostShop CS5或更高的版本后,在你的PS安裝目錄下可以看到如下目錄:

psdom開發(fā)文檔.png

其中JavaScript Ref和Scripting Guide是你必須要進(jìn)行查閱的參考忌栅,因為PS DOM開發(fā)網(wǎng)絡(luò)上的信息非常少车酣,所以這兩篇文檔是你基本唯一的依靠

Utilities 目錄下:

scriptListener.png

scriptListener插件,用于PS Action錄制時候?qū)浿频牟襟E的js代碼記錄下來并輸出到桌面文件索绪。 是一個非常重要的具有開發(fā)功能插件湖员,以后會有專門文章,目前不關(guān)注瑞驱。

Sample Scripts 目錄下:
雙擊運行

psdomSample.png

里面都是js演示代碼:

雙擊后跳出Yes/No Alert界面:
Yes會打開PS并運行代碼破衔,顯示腳本運行后的效果
No會打開JS開發(fā)環(huán)境,可以進(jìn)行腳本開發(fā)钱烟,修改,運行嫡丙,debug等

5)常用的基礎(chǔ)代碼結(jié)構(gòu)流程:

1拴袭、js代碼文件的開始

   //每個JS文件的開始部分,這些代碼基本可以說是固定的
   // 如果有 #target photoshop曙博,就直接打開Ps運行js腳本
   //如果沒有拥刻,則打開ps的腳本編輯器而不是直接在ps中運行
   #target photoshop

   // in case we double clicked the file
   app.bringToFront();

2、單位標(biāo)尺等數(shù)據(jù)的保存與恢復(fù):

   // 存儲當(dāng)前的狀態(tài)
   var startRulerUnits = app.preferences.rulerUnits;
   var startTypeUnits = app.preferences.typeUnits;
   var startDisplayDialogs = app.displayDialogs;

  //設(shè)置新的狀態(tài)父泳,我們使用像素來作為標(biāo)尺和文檔中各個對象的計量單位
  //當(dāng)然也可以設(shè)置其他計量單位般哼,例如厘米,英寸等
  app.preferences.rulerUnits = Units.PIXELS;
  app.preferences.typeUnits = TypeUnits.PIXELS;
  app.displayDialogs = DialogModes.NO;

//之所以這么做惠窄,是因為ps的開發(fā)是基于狀態(tài)機(jī)模式的
//所有圖形化操作基本都是狀態(tài)機(jī)蒸眠,opengl d3d gdi quartz2d.......

3、如果你PS打開了很多程序杆融,希望只顯示現(xiàn)在正在操作的那個文檔楞卡,那么可以使用下面代碼先關(guān)閉所有文檔

    // 關(guān)閉所有打開的文檔
    while (app.documents.length != 0) 
    {
       app.activeDocument.close();
    }

4、使用open全局函數(shù)脾歇,打開一個PSD文件蒋腮,并將該文件設(shè)置為當(dāng)前活動的Document

     var  doc = open(File(app.path + "/示例/mytest.psd"));
     app.activeDocument = buttonDoc;

5、 針對各種文檔進(jìn)行相關(guān)的操作

針對文檔對象以及文檔中的各個對象進(jìn)行操作的代碼是需要你來實現(xiàn)的E焊鳌池摧!

6、操作完文檔后激况,需要恢復(fù)到原來的狀態(tài)(恢復(fù)到開始時記錄下來的狀態(tài)值)

     // 恢復(fù)到修改前的狀態(tài)
     app.preferences.rulerUnits = startRulerUnits;
     app.preferences.typeUnits = startTypeUnits;
     app.displayDialogs = startDisplayDialogs;
     //狀態(tài)機(jī)恢復(fù)default狀態(tài)
  1. 文本操作(TextItem)
    需求描述:
    1作彤、打印出ps所有的Font對象的信息膘魄,目的是為了了解TextFont對象主要屬性: Family|name|postScriptName|style
   function printAllInstalledTextFontInfo()
   {
     var allFonts = [];
     
     for(var i = 0; i < app.fonts.length; i++)
     {
         var str = "{"+app.fonts[i].family+"|"+app.fonts[i].name+"|"
                 +app.fonts[i].postScriptName+"|"+app.fonts[i].style+"}";

         allFonts.push (str);
     }
          
     alert(allFonts);
   }
psdomFonts.png

2、不要從現(xiàn)有的PSD載入宦棺,而是從無到有通過代碼創(chuàng)建文檔瓣距,層等

   //創(chuàng)建一個Document對象
   var docRef = app.documents.add(400, 300, 72);

   //創(chuàng)建一個ArtLayer對象
   var newTextLayer = docRef.artLayers.add();

   //注意:一個文本對象必須要依附于一個Layer對象,并且Layer的kind必須是TEXT類型
   newTextLayer.kind = LayerKind.TEXT;

3代咸、使用微軟雅黑并blod字體樣式

  //當(dāng)設(shè)置為TEXT類型時蹈丸,PS自動會創(chuàng)建一個TextItem對象給Layer,因此可以直接引用

newTextLayer.textItem.font = "MicrosoftYaHeiUI-Blod";

  //這里需要注意的是呐芥,TextItem.font的數(shù)據(jù)類型是字符串逻杖,該字符串是使用了TextFont
  //對象中的postScriptName,這一點務(wù)必要注意。
  //由這里看出思瘟,前面 printAllInstalledTextFontInfo函數(shù)的作用了荸百,你可以打印出來,查找
  //postScriptName的名稱滨攻,然后記住是用這個名稱來設(shè)置字體name和style

4够话、繪制文字內(nèi)容為"隨風(fēng)而行的PSDOM Demo"

 //設(shè)置要顯示的內(nèi)容
 newTextLayer.textItem.contents = "隨風(fēng)而行的PSDOM Demo";

5、設(shè)置文字的大小

   newTextLayer.textItem.size = 36;

6光绕、文字顏色為紅色(SolidColor對象)

   var textColor = new SolidColor;

   textColor.rgb.red = 255;
   textColor.rgb.green = 0;
   textColor.rgb.blue = 0;

   newTextLayer.textItem.color = textColor;
   //這樣就可以顯示文字了

其他的文字相關(guān)屬性請查閱文檔

psdomText.png

7)路徑操作(PathItem)---核心操作

1女嘲、先來一段示例代碼,能夠?qū)athItem有個比較直觀的了解
我們編寫一個函數(shù)诞帐,用來顯示多邊形:

function DrawPolygon() {

 //PS是狀態(tài)機(jī)欣尼,基于當(dāng)前選中的狀態(tài)進(jìn)行操作
var doc = app.activeDocument;

//獲取參數(shù)的數(shù)量,使用js可變參數(shù)
//因為多邊形參數(shù)不確定停蕉,例如三角形愕鼓,三個頂點,n邊形慧起,n個頂點
var y = arguments.length;
var i = 0;

 var lineArray = []; 
for (i = 0; i < y; i++) {
 //創(chuàng)建一個PathPointInfo對象
 //里面包含繪制點的相關(guān)信息

     lineArray[i] = new PathPointInfo;

     //多邊形是凸包菇晃,沒有任何曲線段表示,因此每個點都是CORNERPOINT類型
     //如果是曲線的話蚓挤,那么每個點的類似是SMOOTHPOINT

     lineArray[i].kind = PointKind.CORNERPOINT;

     //要繪制的點的坐標(biāo)谋旦,來源于參數(shù),類型為[x,y];
     //對于非曲線來說屈尼,leftDirection = rightDirection=anchor
     lineArray[i].anchor = arguments[i];
     lineArray[i].leftDirection = lineArray[i].anchor;
     lineArray[i].rightDirection = lineArray[i].anchor;
}

//到此處册着,所有的繪制點的信息都保存在lineArray數(shù)組中

 //創(chuàng)建一個SubPathInfo對象
var lineSubPathArray = new SubPathInfo();

//SubPathiInfo.entireSubPath指向了要繪制的頂點數(shù)據(jù)數(shù)組
 lineSubPathArray.entireSubPath = lineArray;

//設(shè)置SubPathiInfo.closed為true,這樣在strokePath時候,會自動封閉整個路徑
//否則如果為false的話脾歧,那么會缺少最后一條線段甲捏,導(dǎo)致路徑非封閉狀態(tài)。
lineSubPathArray.closed = true;

//設(shè)置ShapeOperation為Add模式鞭执,疊加模式司顿,前景層直接覆蓋到背景層上
//還有其他也寫操作芒粹,可以理解為布爾操作,例如前景和背景取并集大溜,交集化漆,差集等
lineSubPathArray.operation = ShapeOperation.SHAPEADD;

//創(chuàng)建一個PathItem對象,使用的是doc.pathItems.add方法
//注意钦奋,我們會發(fā)現(xiàn)是doc而不像TextItem是屬于層對象的座云。
var myPathItem = doc.pathItems.add("myPath" , [lineSubPathArray]);

//調(diào)用PathItem的描邊函數(shù)
//矢量圖形繪制可以分為邊的繪制以及封閉形體的填充兩種操作
//strokePath用來進(jìn)行邊的繪制
//fillPath則用來進(jìn)行填充內(nèi)容
myPathItem.strokePath(ToolType.PENCIL);

//繪制好后,將PathItem去除掉付材,由于已經(jīng)描邊渲染了朦拖,所有所有效果都輸出到
//像素緩沖區(qū)了,因此不需要該PathItem了
//如果你需要后續(xù)進(jìn)行頂點級別的操作的話厌衔,那你也可以保留著璧帝,不要remove掉
 myPathItem.remove();
}

2、測試多邊形繪制:

//從兩個點生成4個繪制點富寿,繪制Rect
function DrawRect(left,top,right,bottom)
{
    DrawPolygon( [left,top], [right,top], [right,bottom], [left,bottom] );
}

//由于strokePath時使用的顏色是基于當(dāng)前的前景色的
//注意睬隶,如果是填充封閉路徑fillPath的話,則使用指定顏色作為參數(shù)页徐,但是描邊是基于前
//景色的操作
//為了防止干擾理疙,因此先記錄下當(dāng)前的前景色
var   saveColor = app.foregroundColor;

//生成一個紅色的SolidColor對象
var newColor = new SolidColor;
newColor.rgb.red = 255;
newColor.rgb.green = 0;
newColor.rgb.blue = 0;

//設(shè)置前景色為紅色,并繪制三角形
app.foregroundColor = newColor; 
DrawPolygon([250,10],[350,10],[250,100]);

//修改顏色為綠色
newColor.rgb.red = 0;
newColor.rgb.green = 255;
newColor.rgb.blue = 0;

//設(shè)置前景色為綠色泞坦,并繪制四邊形
app.foregroundColor = newColor; 
DrawRect(10,100,100,200);

//修改顏色為藍(lán)色,繪制8角形
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 255;
app.foregroundColor = newColor;
DrawPolygon([36.9999885559082,13.9999985694885],[165.99999666214,13.9999985694885],[185.999989509583,33.9999973773956],[185.999989509583,61.9999945163727],[165.99999666214,81.9999992847443],[36.9999885559082,81.9999992847443],[16.9999957084656,61.9999945163727],[16.9999957084656,33.9999973773956]);

//完成后砖顷,將前景色恢復(fù)到以前記錄下來的顏色
app.foregroundColor = saveColor;

在PhotoShop顯示的結(jié)果如下:(我們使用Brush進(jìn)行繪制贰锁,如果線條的話,可以使用Pencil)

psdomPaint.png

如果使用填充模式,在PhotoShop中獲得的效果:

psdomFill.png

3滤蝠、PathItem對象模型:

psdom_objmodel.png

由此可見豌熄,PathItem對象的讀寫是使用不同的類來表示的,切記!物咳!

4锣险、貝塞爾曲線曲面研究:
pathItem中的PathPoint有三個很重要的屬性

pathPoint.anchor[x,y]          The X and Y coordinates of the anchor point of the curve

pathPoint.leftDirection[a,b]   The location of the left-direction endpoint (’in’position). 

pathPoint.rightDirection[e,f]  The location of the right-direction endpoint (’out’position).

For paths that are straight segments (not curved), the coordinates of all three points are the same.
如果是直線的話,leftDirection = rightDirection = anchor

但是如果是曲線的話览闰,文檔中的解釋是
For curved segements, the the coordinates are different. The difference between the anchor point and the left or right direction points determines the arc of the curve. You use the left direction point to bend the curve "outward" or make it convex; you use the right direction point to bend the curve "inward" or make it concave.
這些描述非常抽象芯肤,而且ps dom文檔只演示了非曲線曲面的demo,對于曲線曲面并沒有demo压鉴,而且網(wǎng)上也很難查到相關(guān)資料

因此只有抽取數(shù)據(jù)進(jìn)行查看了解其數(shù)據(jù)的格式以及猜測strokePath是如何繪制的

為了研究strokePath是如何繪制曲線的崖咨,必須先要取得矢量對象中所有曲線的點,看看是如何組成的油吭,所以先將矢量對象所有的點輸出到文件击蹲,以利于查看:

function saveFile(msg1,msg2,msg3,types)
{
    //彈出saveFile對話框署拟,save類型為txt文件
    var file = File.saveDialog("Saving TXT file.", "TXT Files: *.txt");
    if ( file == null ) return;
    //如果已經(jīng)存在,彈框確認(rèn)是否覆蓋重寫
    if (file.exists) {
        if(!confirm(file.fsName + " exists.\\\\rOver write?")) return;
    }
    //打開要寫的文件流歌豺,并且設(shè)置編碼為utf16格式存儲
    file.open("w"); // open as write
    file.encoding = "UTF16";
    file.write("\\\\uFEFF"); // Unicode marker
    //將anchor數(shù)據(jù)寫入文件流
    file.write("pts:");
    file.write(msg1);
    //將left Direction points數(shù)據(jù)寫入文件流
    file.write("lts:");
    file.write(msg2);
    file.write("rts:");
    file.write(msg3);
    //將right Direction points數(shù)據(jù)寫入文件流
    file.write("tps:");
    file.write(types);
    file.write("\\\\n");
    //關(guān)閉文件流推穷,寫入完成
    file.close();
}
//將每個pathItem中的每個subPathItem中的pathPoint值輸出到文件參看具體數(shù)據(jù)
for(var i = 0;  i < buttonDoc.pathItems.length; i++)
{   
        var subItems = buttonDoc.pathItems[i].subPathItems;
       
        for(var j = 0; j < subItems.length; j++)
        {
             var subItem = subItems[j];
             var  pathPoints = subItem.pathPoints;
             var  pts = [];
             var  lefts = [];
             var  rights = [];
             var  types = []
           
             for(var k = 0; k < pathPoints.length; k++)
             {
                 pts.push(pathPoints[k].anchor);
                 lefts.push(pathPoints[k].leftDirection);
                 rights.push(pathPoints[k].rightDirection);
                 types.push(pathPoints[k].kind);
             }
        
           saveFile(pts,lefts,rights,types);
        }
}

上面代碼運行后會在桌面生成一個文件,例如叫PathItem.txt
psdomPathItem.png

我們將一個圓角矩形輸出到文件类咧,并且對浮點數(shù)進(jìn)行四舍五入后獲得所有數(shù)據(jù)馒铃,進(jìn)行分析:

psdomPathItemAnalysis.png
1、頂點的定義是左手系轮听,順時針方式 [0骗露,1,2血巍,3萧锉,4,5述寡,6柿隙,7]
   如上圖所畫形狀。多邊形的面是有正反面之分,ps中按照左手順時針為正面鲫凶。

2禀崖、線段是以Line_Strip或Line_Strip_Loop方式連接的
opengl紅寶書之線段類型.png

上圖來源于opengl的圖元類型中的線圖源類型
ps使用的是:

Line_Strip(如果SubPathItem.closed = false)
Line_Strip_loop(如果SubPathItem.closed = true).

備注,OpenGL的頂點定義是右手系逆時針螟炫。而psdom中和d3d一樣使用左手系表示

Line_Strip            n個頂點確定n-1條線段   n >= 2
Line_Strip_Loop       n個頂點確定n條線段波附,最后一條線段首位相連 n>=2

3、PathItem貝塞爾3次曲線中四個頂點的含義
psdomPathItemSample.png
如果要繪制上面的曲線昼钻,則頂點如下:
pathPoint0.anchor = p0;
pathPoint0.leftDirection = p0;
pathPoint0.rightDirection = r0;

pathPoint1.anchor = p1;
pathPoint1.leftDirection = l1;
pathPoint1.rightDirection = r1;

pathPoint1.anchor = p2;
pathPoint1.leftDirection = l2;
pathPoint1.rightDirection = p0;

具體還是來看一個完整的繪制圓角矩形的例子吧

function DrawRoundRetange(left,top,right,bottom,radius)
{
    if(radius <= 0.01)
    {
        DrawRetangle(left,top,right,bottom);
        return;
    }

    if(radius>=(Math.min(right-left, bottom-top))/2.0)
    {
        alert("半徑太大");
        //如何處理掸屡,要研究
        //PS中、一般的情況下然评,是8個點
        //但是在半徑太大或者其他一些情況下仅财,貌似用6個點
        //目前還沒法逆向出來,以后再研究吧M胩省盏求!
        return; 
    }
     
    var doc = app.activeDocument;
    var i = 0;
    var lineArray = [];
   
    //下面代碼以半徑和頂點為參數(shù),設(shè)置錨點和定位點
    //具體算法上圖演示
    //這些算法需要有一定數(shù)學(xué)基礎(chǔ)的亿眠,我正想開辟一個文章集碎罚,名為
    //數(shù)學(xué)之美
    lineArray[0] = new PathPointInfo;
    lineArray[0].kind = PointKind.SMOOTHPOINT;
    lineArray[0].anchor = [left+radius,top];
    lineArray[0].leftDirection =lineArray[0].anchor;
    lineArray[0].rightDirection = [left,top];
   
    lineArray[1] = new PathPointInfo;
    lineArray[1].kind = PointKind.SMOOTHPOINT;
    lineArray[1].anchor = [right-radius,top];
    lineArray[1].leftDirection = [right,top];
    lineArray[1].rightDirection = lineArray[1].anchor;
    
    lineArray[2] = new PathPointInfo;
    lineArray[2].kind = PointKind.SMOOTHPOINT;
    lineArray[2].anchor = [right,top+radius];
    lineArray[2].leftDirection =  lineArray[2].anchor;;
    lineArray[2].rightDirection = [right,top];
    
    lineArray[3] = new PathPointInfo;
    lineArray[3].kind = PointKind.SMOOTHPOINT;
    lineArray[3].anchor = [right,bottom-radius];
    lineArray[3].leftDirection = [right,bottom];
    lineArray[3].rightDirection = lineArray[3].anchor;
 
    lineArray[4] = new PathPointInfo;
    lineArray[4].kind = PointKind.SMOOTHPOINT;
    lineArray[4].anchor = [right -radius,bottom];
    lineArray[4].leftDirection = lineArray[4].anchor;
    lineArray[4].rightDirection =[right,bottom];

    lineArray[5] = new PathPointInfo;
    lineArray[5].kind = PointKind.SMOOTHPOINT;
    lineArray[5].anchor = [left+radius,bottom];
    lineArray[5].leftDirection = [left,bottom];
    lineArray[5].rightDirection = lineArray[5].anchor;
    
    lineArray[6] = new PathPointInfo;
    lineArray[6].kind = PointKind.SMOOTHPOINT;
    lineArray[6].anchor = [left,bottom-radius];
    lineArray[6].leftDirection = lineArray[6].anchor;
    lineArray[6].rightDirection = [left,bottom];
   
    lineArray[7] = new PathPointInfo;
    lineArray[7].kind = PointKind.SMOOTHPOINT;
    lineArray[7].anchor = [left,top+radius];
    lineArray[7].leftDirection = [left,top];
    lineArray[7].rightDirection = lineArray[7].anchor;
    
    var lineSubPathArray = new SubPathInfo();
    lineSubPathArray.closed = true;
    lineSubPathArray.operation = ShapeOperation.SHAPEADD;
    lineSubPathArray.entireSubPath = lineArray;
    
var myPathItem = doc.pathItems.add("myRoundedRetangle" , 
                 [lineSubPathArray]);
    myPathItem.strokePath(ToolType.PENCIL);
    //myPathItem.fillPath ();
    myPathItem.remove();  
}

我們來測試一下:

// 存儲當(dāng)前的狀態(tài)
var startRulerUnits = app.preferences.rulerUnits;
var startTypeUnits = app.preferences.typeUnits;
var startDisplayDialogs = app.displayDialogs;

//設(shè)置新的狀態(tài)
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
app.displayDialogs = DialogModes.NO;

// 關(guān)閉所有打開的文檔
while (app.documents.length != 0) {
    app.activeDocument.close();
}

//創(chuàng)建一個新的500*500大小 dpi=72的文檔對象,名稱為PathItemTest
//并且設(shè)定為當(dāng)前對象
var doc = app.documents.add(500,500,72, "PathItemTest");
app.activeDocument = doc;

//調(diào)用上面的函數(shù)
drawRoundRetange(20,20,200,200,50);

//恢復(fù)為系統(tǒng)初始化的狀態(tài)
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
app.displayDialogs = startDisplayDialogs;
psdomRunResult.png

至此纳像,我們掌控Photoshop的第一篇結(jié)束魂莫,下一篇我們來關(guān)注如何進(jìn)行PS Layer的操作,這也是非常有趣的一個話題爹耗。

注: 關(guān)于參數(shù)曲線曲面耙考,其實還是有很多數(shù)學(xué)知識的谜喊,包括前段時間發(fā)的OpenGL太陽系Demo這篇bolg,并沒有很詳細(xì)的講解代碼倦始,因為都涉及到很多計算機(jī)圖形學(xué)的數(shù)學(xué)方法斗遏,因此隨風(fēng)計劃開辟一個名為數(shù)學(xué)之美的文集,使用基于javascript /typescript的Canvas2D,WebGL來演示各種動畫效果鞋邑,體驗數(shù)學(xué)之美之強(qiáng)大!

演示代碼將在第二篇層操作發(fā)布時候一起提交到github诵次,到時可以進(jìn)行下載。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枚碗,一起剝皮案震驚了整個濱河市逾一,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肮雨,老刑警劉巖遵堵,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怨规,居然都是意外死亡陌宿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門波丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來壳坪,“玉大人,你說我怎么就攤上這事掰烟∷” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵纫骑,是天一觀的道長蝎亚。 經(jīng)常有香客問我,道長惧磺,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任捻撑,我火速辦了婚禮磨隘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘顾患。我一直安慰自己番捂,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布江解。 她就那樣靜靜地躺著设预,像睡著了一般。 火紅的嫁衣襯著肌膚如雪犁河。 梳的紋絲不亂的頭發(fā)上鳖枕,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天魄梯,我揣著相機(jī)與錄音,去河邊找鬼宾符。 笑死酿秸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的魏烫。 我是一名探鬼主播辣苏,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哄褒!你這毒婦竟也來了稀蟋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤呐赡,失蹤者是張志新(化名)和其女友劉穎退客,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體罚舱,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡井辜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了管闷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粥脚。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖包个,靈堂內(nèi)的尸體忽然破棺而出刷允,到底是詐尸還是另有隱情,我是刑警寧澤碧囊,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布树灶,位于F島的核電站,受9級特大地震影響糯而,放射性物質(zhì)發(fā)生泄漏天通。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一熄驼、第九天 我趴在偏房一處隱蔽的房頂上張望像寒。 院中可真熱鬧,春花似錦瓜贾、人聲如沸诺祸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筷笨。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胃夏,已是汗流浹背轴或。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留构订,地道東北人侮叮。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像悼瘾,于是被迫代替她去往敵國和親囊榜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,527評論 25 707
  • Swift版本點擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 25,293評論 7 249
  • 廢話不多說,直接切入正題。 那一年此蜈,我初二,他初三挤渐。我們從小認(rèn)識,是青梅竹馬双絮,我們也確實很要好浴麻,但是因為一...
    crh橙子閱讀 253評論 0 0
  • 小菲想定居廈門软免。 她說廈門和大理對于她意義非凡。 她說喜洲的花園美宿值得一去焚挠。 她說那是個悲傷的故事膏萧。 她發(fā)給我一...
    二喜的深夜食堂閱讀 1,096評論 14 25
  • 有個病人抑郁了很長時間,總是悶悶不樂的蝌衔,藥物治療后好轉(zhuǎn)了榛泛,她說:感覺吃了藥很爽,人很精神胚委⌒看到病人慢慢好轉(zhuǎn)叉信,我也覺...
    bud_and_bun閱讀 83評論 0 0