中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在PS中自己來繪制形體

發布時間:2022-01-10 11:50:56 來源:億速云 閱讀:173 作者:柒染 欄目:開發技術

這篇文章給大家介紹如何在PS中自己來繪制形體,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

通過編寫JSDom腳本,控制PhotoShop,最終自動進行九宮格切圖,并且將整個切圖過程輸出到文件:

如何在PS中自己來繪制形體

下面涉及的主題是PhotoShop plugin開發的基礎,主要關注如何在PS中自己來繪制形體。

要做的:

基礎繪制篇--以PhotoShop的Document為舞臺,在上面繪制文字和任意形狀

不做的:

1) 不涉及Channel操作,對位圖像素操作我們不關心
2) 不涉及PhotoShop界面編程。因為PS界面編程隨著版本變化,有好多種方式,一直在改變。
     C++方式,強大,但是難度較大,不是三言兩語說得清楚的
     As3 Flex方式,簡單易用,和PSDom交互方便,但是適合Adobe CS系列
     Html5方式,簡單應用,和PSDom交互方便,但是適合Adobe CC系列
     但不管如何,核心的PhotoShop操作是通過PSDom API公開出來的,
     這個不管版本如何變,其本身DOM是不會發生較大變化的。
     因此才更有研究的價值
     
你會發現其實開發PS插件蠻簡單的,PSDom非常強大。

PSDom的開發環境—ExtendScript ToolKit
在安裝Adobe cs/cc系列時,會自動安裝(我裝的是CS5.0)

如果在Windows下開發,請見后綴名改為.jsx
如果使用.js后綴的話,可能會由Windows Scripting Host(WSH)來執行,而不是PS 腳本解析器。防沖突!

通過這篇文章,希望能夠讓大家在PhotoShop中為所欲為!!!

讓我們來關注一下吧:

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

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

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

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

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

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

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


其中JavaScript Ref和Scripting Guide是你必須要進行查閱的參考,因為PS DOM開發網絡上的信息非常少,所以這兩篇文檔是你基本唯一的依靠

Utilities 目錄下:

scriptListener插件,用于PS Action錄制時候將錄制的步驟的js代碼記錄下來并輸出到桌面文件。 是一個非常重要的具有開發功能插件,以后會有專門文章,目前不關注。

Sample Scripts 目錄下:
雙擊運行

里面都是js演示代碼:

雙擊后跳出Yes/No Alert界面:
Yes會打開PS并運行代碼,顯示腳本運行后的效果
No會打開JS開發環境,可以進行腳本開發,修改,運行,debug等

5)常用的基礎代碼結構流程:

1、js代碼文件的開始

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

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

2、單位標尺等數據的保存與恢復:

   // 存儲當前的狀態
   var startRulerUnits = app.preferences.rulerUnits;
   var startTypeUnits = app.preferences.typeUnits;
   var startDisplayDialogs = app.displayDialogs;

  //設置新的狀態,我們使用像素來作為標尺和文檔中各個對象的計量單位
  //當然也可以設置其他計量單位,例如厘米,英寸等
  app.preferences.rulerUnits = Units.PIXELS;
  app.preferences.typeUnits = TypeUnits.PIXELS;
  app.displayDialogs = DialogModes.NO;

//之所以這么做,是因為ps的開發是基于狀態機模式的
//所有圖形化操作基本都是狀態機,opengl d3d gdi quartz2d.......

3、如果你PS打開了很多程序,希望只顯示現在正在操作的那個文檔,那么可以使用下面代碼先關閉所有文檔

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

4、使用open全局函數,打開一個PSD文件,并將該文件設置為當前活動的Document

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

5、 針對各種文檔進行相關的操作

針對文檔對象以及文檔中的各個對象進行操作的代碼是需要你來實現的!!

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

     // 恢復到修改前的狀態
     app.preferences.rulerUnits = startRulerUnits;
     app.preferences.typeUnits = startTypeUnits;
     app.displayDialogs = startDisplayDialogs;
     //狀態機恢復default狀態

6) 文本操作(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);
   }

如何在PS中自己來繪制形體
  

2、不要從現有的PSD載入,而是從無到有通過代碼創建文檔,層等

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

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

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

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

   //當設置為TEXT類型時,PS自動會創建一個TextItem對象給Layer,因此可以直接引用

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

   //這里需要注意的是,TextItem.font的數據類型是字符串,該字符串是使用了TextFont
   //對象中的postScriptName,這一點務必要注意。
   //由這里看出,前面 printAllInstalledTextFontInfo函數的作用了,你可以打印出來,查找
   //postScriptName的名稱,然后記住是用這個名稱來設置字體name和style

4、繪制文字內容為”隨風而行的PSDOM Demo”

   //設置要顯示的內容
   newTextLayer.textItem.contents = "隨風而行的PSDOM Demo";

5、設置文字的大小

   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;
   //這樣就可以顯示文字了

其他的文字相關屬性請查閱文檔

如何在PS中自己來繪制形體

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

1、先來一段示例代碼,能夠對PathItem有個比較直觀的了解
     我們編寫一個函數,用來顯示多邊形:

   function DrawPolygon() {

    //PS是狀態機,基于當前選中的狀態進行操作
    var doc = app.activeDocument;

    //獲取參數的數量,使用js可變參數
//因為多邊形參數不確定,例如三角形,三個頂點,n邊形,n個頂點
var y = arguments.length;
var i = 0;

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

        lineArray[i] = new PathPointInfo;

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

        lineArray[i].kind = PointKind.CORNERPOINT;

        //要繪制的點的坐標,來源于參數,類型為[x,y];
        //對于非曲線來說,leftDirection = rightDirection=anchor
        lineArray[i].anchor = arguments[i];
        lineArray[i].leftDirection = lineArray[i].anchor;
        lineArray[i].rightDirection = lineArray[i].anchor;
}

//到此處,所有的繪制點的信息都保存在lineArray數組中

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

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

//設置SubPathiInfo.closed為true,這樣在strokePath時候,會自動封閉整個路徑
//否則如果為false的話,那么會缺少最后一條線段,導致路徑非封閉狀態。
lineSubPathArray.closed = true;

//設置ShapeOperation為Add模式,疊加模式,前景層直接覆蓋到背景層上
//還有其他也寫操作,可以理解為布爾操作,例如前景和背景取并集,交集,差集等
lineSubPathArray.operation = ShapeOperation.SHAPEADD;

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

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

//繪制好后,將PathItem去除掉,由于已經描邊渲染了,所有所有效果都輸出到
//像素緩沖區了,因此不需要該PathItem了
//如果你需要后續進行頂點級別的操作的話,那你也可以保留著,不要remove掉
    myPathItem.remove();
}

2、測試多邊形繪制:

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

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

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

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

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

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

//修改顏色為藍色,繪制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.999×××847443],[36.9999885559082,81.999×××847443],[16.9999957084656,61.9999945163727],[16.9999957084656,33.9999973773956]);

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

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

如何在PS中自己來繪制形體

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

如何在PS中自己來繪制形體

3、PathItem對象模型:

如何在PS中自己來繪制形體

由此可見,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,而且網上也很難查到相關資料

因此只有抽取數據進行查看了解其數據的格式以及猜測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;
    //如果已經存在,彈框確認是否覆蓋重寫
    if (file.exists) {
        if(!confirm(file.fsName + " exists.\\\\rOver write?")) return;
    }
    //打開要寫的文件流,并且設置編碼為utf16格式存儲
    file.open("w"); // open as write
    file.encoding = "UTF16";
    file.write("\\\\uFEFF"); // Unicode marker
    //將anchor數據寫入文件流
    file.write("pts:");
    file.write(msg1);
    //將left Direction points數據寫入文件流
    file.write("lts:");
    file.write(msg2);
    file.write("rts:");
    file.write(msg3);
    //將right Direction points數據寫入文件流
    file.write("tps:");
    file.write(types);
    file.write("\\\\n");
    //關閉文件流,寫入完成
    file.close();
}
//將每個pathItem中的每個subPathItem中的pathPoint值輸出到文件參看具體數據
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

如何在PS中自己來繪制形體

我們將一個圓角矩形輸出到文件,并且對浮點數進行四舍五入后獲得所有數據,進行分析:

如何在PS中自己來繪制形體

1、頂點的定義是左手系,順時針方式 [0,1,2,3,4,5,6,7]
   如上圖所畫形狀。多邊形的面是有正反面之分,ps中按照左手順時針為正面。

2、線段是以Line_Strip或Line_Strip_Loop方式連接的

如何在PS中自己來繪制形體

上圖來源于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次曲線中四個頂點的含義

如何在PS中自己來繪制形體

如果要繪制上面的曲線,則頂點如下:
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個點
        //目前還沒法逆向出來,以后再研究吧!!
        return; 
    }

    var doc = app.activeDocument;
    var i = 0;
    var lineArray = [];

    //下面代碼以半徑和頂點為參數,設置錨點和定位點
    //具體算法上圖演示
    //這些算法需要有一定數學基礎的,我正想開辟一個文章集,名為
    //數學之美
    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();  
}

我們來測試一下:

// 存儲當前的狀態
var startRulerUnits = app.preferences.rulerUnits;
var startTypeUnits = app.preferences.typeUnits;
var startDisplayDialogs = app.displayDialogs;

//設置新的狀態
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
app.displayDialogs = DialogModes.NO;

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

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

//調用上面的函數
drawRoundRetange(20,20,200,200,50);

//恢復為系統初始化的狀態
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
app.displayDialogs = startDisplayDialogs;

如何在PS中自己來繪制形體

至此,我們掌控Photoshop的第一篇結束,以后有機會我們來關注如何進行PS Layer的操作,這也是非常有趣的一個話題。

如何在PS中自己來繪制形體

         上圖photoshop中的界面使用flash as3.0編寫,目前html5是最好的替代品

注: 關于參數曲線曲面,其實還是有很多數學知識的,包括前段時間發的OpenGL太陽系Demo這篇bolg,并沒有很詳細的講解代碼,因為都涉及到很多計算機圖形學的數學方法,因此隨風計劃開辟一個名為數學之美的文集,使用基于javascript /typescript的Canvas2D,WebGL來演示各種動畫效果,體驗數學之美!

關于如何在PS中自己來繪制形體就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

满洲里市| 根河市| 左权县| 五大连池市| 永兴县| 大邑县| 兴山县| 台前县| 金门县| 长治县| 彭山县| 怀远县| 龙陵县| 宝山区| 宁乡县| 怀柔区| 滨海县| 禄劝| 柘荣县| 灵台县| 扎鲁特旗| 衢州市| 卢湾区| 光泽县| 大丰市| 五华县| 莒南县| 沂水县| 海林市| 肥乡县| 平定县| 蒲城县| 社旗县| 邮箱| 成都市| 铜陵市| 白沙| 光泽县| 景谷| 无为县| 淳化县|