| 订阅 | 在线投稿
分享
 
 
 

谈Photoshop动作、脚本实际工作中的应用

来源:互联网网民  宽屏版  评论
2008-06-01 06:46:39

最近在做一些无聊游戏,具体就不多说了,谈实际碰到的两个例子:

由于常常有人抱怨写的东西看不懂,所以废话多了点,讲的内容也比较粗浅,还望熟手见谅

一、自己的麻将牌变对家的牌

做好一副麻将牌,需要把它上下颠倒过来。

谈Photoshop动作、脚本实际工作中的应用

如果用垂直or水平反转,很明显字都是反的。直接旋转顺序不符合程序要求,且透视不对,于是要一张张牌单独处理。

由于是重复操作,且没有什么变数,于是我们采用动作处理:

做选区,ctrl+t旋转180度,移动选区到下一个位置(1张牌的距离)

谈Photoshop动作、脚本实际工作中的应用

谈Photoshop动作、脚本实际工作中的应用

谈Photoshop动作、脚本实际工作中的应用

本来这个动作很简单,但是实际测试发现:

ctrl+t自由变换后,移动选区会带着图像走,不能单纯移动

谈Photoshop动作、脚本实际工作中的应用

想办法解决:自由变换后,先取消选区(ctrl+d),再恢复上一个选区(ctrl+shift+d)。这样,在移动选区,就不会带走图像了。

于是我们录制动作,一遍遍的执行,只要第一次选区准确、移动准确,就万事大吉了

谈Photoshop动作、脚本实际工作中的应用

二、找茬游戏中脚本的应用

项目要求:制作一大批图片。每两幅一组,两幅之间有十处不同,记录每处不同的矩形区域坐标。

首先是制作图片:其实就是简单的p图,制造一些差异。

为了方便对比观察,避免错漏,使用了cs3的智能对象的堆栈功能(new)。

感觉这样比较方便比较,能在精确查看不同的同时ps图片的内容。

首先建立固定大小的文件,再把素材图拉进来,调整大小,然后ctrl+e合并到底层(合并是为了确保未来的智能对象大小和图像大小一致),ctrl+j 新建一层。我们只ps 新建出来的这一层,下面不动。

因为有10处差异,所以光靠切换可视对比~比较辛苦,且容易错漏,[差值]对比效果也差又累。

所以我们同时选中两个图层,右键-[转换为智能对象],然后菜单-图层-智能对象-堆栈模式-标准偏差

谈Photoshop动作、脚本实际工作中的应用

这时候我们就明显看到两层之间的差异了,

我们可以双击图层面板的智能对象缩略图,就可以展开进入智能对象内部,继续编辑两个图层

谈Photoshop动作、脚本实际工作中的应用

我们在智能对象内部编辑的时候,只要随手ctrl+s 保存一下,就可以看到原图(黑色那张)上的差异变化了。

图像处理完后,然后就是获得由差异区域的坐标:程序需要把差异区域作为一个个矩形,要得到每个区域左上角和右下角的坐标。

谈Photoshop动作、脚本实际工作中的应用

最开始,想把所有区域拉出选区,然后通过 cs3 的新增统计功能获得详细的选区数据,结果~~

非常遗憾,统计可以同时获得所有选区的周长、长宽、面积甚至密度~ 就是不给出具体的每一组坐标(如下图所示)

谈Photoshop动作、脚本实际工作中的应用

于是只有改变做法,这时候想到了脚本 里面的 selection.bounds 获得选区坐标,

遗憾的发现,似乎脚本里面没有获取多个区域选取数据的方法,只能获得总选区的左上角+右下角坐标

也就是说10个区域当成一个大区域来看了。~

继续改变方案,改用图层,每个图层只记录一个区域,总可以了吧~~

因为之前的经验,确定图层的范围坐标是可以在脚本里通过 ArtLayer.bounds 获取的。

所以接下来要做的事情就是手动建立一个个小矩形的图层。

由于工作量巨大,不偷懒是不行的,所以录制了一个动作

谈Photoshop动作、脚本实际工作中的应用

可以看到,这个动作录制了3步:

新建图层

填充选区

取消选区

而且这个动作设置了快捷键 F12 (双击动作名称,就可以设置快捷键)

有了这个动作,我只要拉出一个选区,然后按一下 F12,就自动新建一个图层,并填充好。

这样就方便脚本获取每层的数据了。

完成后的文件结构如下:

谈Photoshop动作、脚本实际工作中的应用

上面是10层不同位置的矩形,最底层是一个智能对象(包含两个图层,上面一层为修改后的,下面一层为原图)

文件格式ok,接下来就是脚本大显身手的地方了。

接下来我们开始编写脚本,为了通俗,这一步主要只是谈谈思路

首先测试单个文件,脚本大致需要执行如下步骤:

移动到最底层

向上移动一层,利用 activeLayer.bounds 记录层范围坐标,并把坐标记录下来

反复执行第2步,直到最顶层

输出记录

有了以前一些脚本的经验,实现上面这个功能没有碰到什么难度,很容易搞定。

然后就是批量处理了 ,该脚本已经有完善的批量打开、保存处理模块。局部Copy后稍加修改,就让我们的脚本实现了如下功能:

用户选择待处理文件夹

获取该文件夹下所有文件

打开一个文件,获取并记录所有需要的坐标,关闭不保存

重复第3步,直至处理完所有文件

输出记录

测试成功后,想到:既然已经动用脚本获取了所有坐标,索性把两张不同的图片也输出保存好了。于是添加了一个保存位置选择。

并对单个文件内的操作作了修改:

移动到最底层

打开最底层智能对象

另存智能对象为jpg文档(xxx_1)

隐藏智能对象里的最上层,也就是我们修改过的那层

再次另存智能对象为jpg文档(xxx_0)

不保存关闭智能对象(回到原文档)

向上移动一层,利用 activeLayer.bounds 记录层范围坐标,并把坐标记录下来

反复执行第7步,直到最顶层

这样不但记录了坐标数据,还顺便把智能对象里面的两个层都输出为jpg图像了。

后来,由于第二张图片和第一张图片很多相同的地方,导致游戏文件体积较大,所以想了一个解决办法,就是把相同的部分用黑色挡住,只保留不同的地方,这样jpg就小很多。也许是个笨办法吧,毕竟不太清楚别人怎么做的,这里只是给大家说说思路罢了。

于是再次修改单个文件内的操作部分

移动到最底层

向上移动一层,利用activeLayer.bounds 记录层范围坐标,并把坐标记录下来

反复执行第2步,直到最顶层

再次回到最底层

打开最底层智能对象

利用记录的坐标,建立选区(增加模式),全部选区增添完后,反选

填充黑色(这时候是填充在智能对象内部最上层上,也就是我们修改过的那层)

另存为智能对象为jpg文档(xxx_1)

隐藏当前图层

再次另存智能对象为jpg文档(xxx_0)

不保存关闭智能对象(回到原文档)

这样我们就给修改过的图像增添了一个黑色部分,挡住了没动过的地方,只留下了差异处。为了减少jpg 保存可能对边缘造成的影响,所以黑色部分的填充范围缩小了2像素。后来为了修改方便,索性在面板上放了一个位置,可以手动输入缩小量。

为了程序调用方便,脚本还顺便实现其他一些功能:

比如把文件名作些规范处理:按照数字大小排序文件(否则打开顺序会是1、11、12、2、21这样),并且把1.psd 、2.psd 之类的记录为 0001、0002;

用简单正则替换去掉坐标记录转换为字符串后的“ px”单位等等。

为了处理时对进度有个掌握,脚本界面上还放了进度条。

最后,发现有时候不需要重新生成图像,只需要获取坐标。又在界面上加了一个 “仅查询坐标,不生成图片”的选项。如果勾选,就会跳过保存的步骤,以节省时间。

以上的过程,最终就是如下这个脚本程序,处理我近百张图片也就3分多的样子,手工的话又容易出错又慢,程序的优势就这样体现出来了。

谈Photoshop动作、脚本实际工作中的应用

以后要修改、调整,只要修改psd文档,再用脚本重新生成 就很快完成工作。两个多小时的编写调试还是值得的 。

#target photoshop

app.bringToFront();

res ="dialog { \

text:'找茬数据专用',\

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:' 仅查询坐标,不生成图片'} ,\

s: StaticText { text:'| 生成JPG的压缩质量:' }, \

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质量下拉

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(){ //隐藏当前图层

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) { //保存结果图像

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压缩质量

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) { //做选区

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],)

}

// ==================================扩展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;

//调整文件顺序,按数字大小排序

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\)

谈Photoshop动作、脚本实际工作中的应用

如果把它拷贝到“增效工具/自动”目录下(英文版为 Plug-Ins\Automate),再重新启动ps。你的ps就相当于安装了一个“窃听器”,会把你所有的操作步骤像录制动作一样录制为脚本。只要你有可记录的动作,它就在桌面生成“ScriptingListenerJS”、“ScriptingListenerVB” 两个文本文件。其实就是 javascript 和 vbscript 两种规则记录的动作。

谈Photoshop动作、脚本实际工作中的应用

虽然不像手工书写的代码易于理解和修改,但是很多直接操作的步骤都可以拷贝来用。

比如说上面的 “移动到最底层”“选中上一层”“隐藏当前层”“打开智能对象”“扩展n像素”“反选”等等动作就是通过脚本侦听录制下来 直接拷贝过来的。

再结合自己的编写的其他逻辑语句,很容易写出你想要的东西。

最后,希望有点编程基础又有兴趣的朋友,

在处理重复、量大或者经常碰到的工作的时候,多多挖掘ps的潜力。

其实写一个简单的针对性脚本或者动作 并不是很难哦 ^_^

提供jsx源文件+两个psd文档,分本是 F14和歼10,有兴趣的朋友可以试试看,注意cs3以上

谈Photoshop动作、脚本实际工作中的应用

谈Photoshop动作、脚本实际工作中的应用

谈Photoshop动作、脚本实际工作中的应用

谈Photoshop动作、脚本实际工作中的应用

鉴于实践表明:

同样显示效果下 [另存为jpg] 比 [保存为web所用格式-jpg]文件体积要大很多,所以最后替换了保存函数。 把saveAs,换成了exportDocument.,具体如下:

function sm(name) { //保存结果图像

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);

}

 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
  最近在做一些无聊游戏,具体就不多说了,谈实际碰到的两个例子:   由于常常有人抱怨写的东西看不懂,所以废话多了点,讲的内容也比较粗浅,还望熟手见谅   一、自己的麻将牌变对家的牌   做好一副麻将牌,需要把它上下颠倒过来。 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771028.gif[/img][/url]   如果用垂直or水平反转,很明显字都是反的。直接旋转顺序不符合程序要求,且透视不对,于是要一张张牌单独处理。   由于是重复操作,且没有什么变数,于是我们采用动作处理:   做选区,ctrl+t旋转180度,移动选区到下一个位置(1张牌的距离) [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771115.gif[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771179.gif[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771255.gif[/img][/url]   本来这个动作很简单,但是实际测试发现:   ctrl+t自由变换后,移动选区会带着图像走,不能单纯移动 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771320.gif[/img][/url]   想办法解决:自由变换后,先取消选区(ctrl+d),再恢复上一个选区(ctrl+shift+d)。这样,在移动选区,就不会带走图像了。   于是我们录制动作,一遍遍的执行,只要第一次选区准确、移动准确,就万事大吉了 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771463.gif[/img][/url] 二、找茬游戏中脚本的应用 项目要求:制作一大批图片。每两幅一组,两幅之间有十处不同,记录每处不同的矩形区域坐标。 首先是制作图片:其实就是简单的p图,制造一些差异。 为了方便对比观察,避免错漏,使用了cs3的智能对象的堆栈功能(new)。 感觉这样比较方便比较,能在精确查看不同的同时ps图片的内容。 首先建立固定大小的文件,再把素材图拉进来,调整大小,然后ctrl+e合并到底层(合并是为了确保未来的智能对象大小和图像大小一致),ctrl+j 新建一层。我们只ps 新建出来的这一层,下面不动。 因为有10处差异,所以光靠切换可视对比~比较辛苦,且容易错漏,[差值]对比效果也差又累。 所以我们同时选中两个图层,右键-[转换为智能对象],然后菜单-图层-智能对象-堆栈模式-标准偏差 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771545.gif[/img][/url] 这时候我们就明显看到两层之间的差异了, 我们可以双击图层面板的智能对象缩略图,就可以展开进入智能对象内部,继续编辑两个图层 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771682.gif[/img][/url] 我们在智能对象内部编辑的时候,只要随手ctrl+s 保存一下,就可以看到原图(黑色那张)上的差异变化了。 图像处理完后,然后就是获得由差异区域的坐标:程序需要把差异区域作为一个个矩形,要得到每个区域左上角和右下角的坐标。 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771871.gif[/img][/url] 最开始,想把所有区域拉出选区,然后通过 cs3 的新增统计功能获得详细的选区数据,结果~~ 非常遗憾,统计可以同时获得所有选区的周长、长宽、面积甚至密度~ 就是不给出具体的每一组坐标(如下图所示) [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412771889.gif[/img][/url] 于是只有改变做法,这时候想到了脚本 里面的 selection.bounds 获得选区坐标, 遗憾的发现,似乎脚本里面没有获取多个区域选取数据的方法,只能获得总选区的左上角+右下角坐标 也就是说10个区域当成一个大区域来看了。~ 继续改变方案,改用图层,每个图层只记录一个区域,总可以了吧~~ 因为之前的经验,确定图层的范围坐标是可以在脚本里通过 ArtLayer.bounds 获取的。 所以接下来要做的事情就是手动建立一个个小矩形的图层。 由于工作量巨大,不偷懒是不行的,所以录制了一个动作 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772082.gif[/img][/url] 可以看到,这个动作录制了3步: 新建图层 填充选区 取消选区 而且这个动作设置了快捷键 F12 (双击动作名称,就可以设置快捷键) 有了这个动作,我只要拉出一个选区,然后按一下 F12,就自动新建一个图层,并填充好。 这样就方便脚本获取每层的数据了。 完成后的文件结构如下: [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772098.gif[/img][/url] 上面是10层不同位置的矩形,最底层是一个智能对象(包含两个图层,上面一层为修改后的,下面一层为原图) 文件格式ok,接下来就是脚本大显身手的地方了。 接下来我们开始编写脚本,为了通俗,这一步主要只是谈谈思路 首先测试单个文件,脚本大致需要执行如下步骤: 移动到最底层 向上移动一层,利用 activeLayer.bounds 记录层范围坐标,并把坐标记录下来 反复执行第2步,直到最顶层 输出记录 有了以前一些脚本的经验,实现上面这个功能没有碰到什么难度,很容易搞定。 然后就是批量处理了 ,该脚本已经有完善的批量打开、保存处理模块。局部Copy后稍加修改,就让我们的脚本实现了如下功能: 用户选择待处理文件夹 获取该文件夹下所有文件 打开一个文件,获取并记录所有需要的坐标,关闭不保存 重复第3步,直至处理完所有文件 输出记录 测试成功后,想到:既然已经动用脚本获取了所有坐标,索性把两张不同的图片也输出保存好了。于是添加了一个保存位置选择。 并对单个文件内的操作作了修改: 移动到最底层 打开最底层智能对象 另存智能对象为jpg文档(xxx_1) 隐藏智能对象里的最上层,也就是我们修改过的那层 再次另存智能对象为jpg文档(xxx_0) 不保存关闭智能对象(回到原文档) 向上移动一层,利用 activeLayer.bounds 记录层范围坐标,并把坐标记录下来 反复执行第7步,直到最顶层 这样不但记录了坐标数据,还顺便把智能对象里面的两个层都输出为jpg图像了。 后来,由于第二张图片和第一张图片很多相同的地方,导致游戏文件体积较大,所以想了一个解决办法,就是把相同的部分用黑色挡住,只保留不同的地方,这样jpg就小很多。也许是个笨办法吧,毕竟不太清楚别人怎么做的,这里只是给大家说说思路罢了。 于是再次修改单个文件内的操作部分 移动到最底层 向上移动一层,利用activeLayer.bounds 记录层范围坐标,并把坐标记录下来 反复执行第2步,直到最顶层 再次回到最底层 打开最底层智能对象 利用记录的坐标,建立选区(增加模式),全部选区增添完后,反选 填充黑色(这时候是填充在智能对象内部最上层上,也就是我们修改过的那层) 另存为智能对象为jpg文档(xxx_1) 隐藏当前图层 再次另存智能对象为jpg文档(xxx_0) 不保存关闭智能对象(回到原文档) 这样我们就给修改过的图像增添了一个黑色部分,挡住了没动过的地方,只留下了差异处。为了减少jpg 保存可能对边缘造成的影响,所以黑色部分的填充范围缩小了2像素。后来为了修改方便,索性在面板上放了一个位置,可以手动输入缩小量。 为了程序调用方便,脚本还顺便实现其他一些功能: 比如把文件名作些规范处理:按照数字大小排序文件(否则打开顺序会是1、11、12、2、21这样),并且把1.psd 、2.psd 之类的记录为 0001、0002; 用简单正则替换去掉坐标记录转换为字符串后的“ px”单位等等。 为了处理时对进度有个掌握,脚本界面上还放了进度条。 最后,发现有时候不需要重新生成图像,只需要获取坐标。又在界面上加了一个 “仅查询坐标,不生成图片”的选项。如果勾选,就会跳过保存的步骤,以节省时间。 以上的过程,最终就是如下这个脚本程序,处理我近百张图片也就3分多的样子,手工的话又容易出错又慢,程序的优势就这样体现出来了。 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772170.gif[/img][/url] 以后要修改、调整,只要修改psd文档,再用脚本重新生成 就很快完成工作。两个多小时的编写调试还是值得的 。 #target photoshop app.bringToFront(); res ="dialog { \ text:'找茬数据专用',\ 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:' 仅查询坐标,不生成图片'} ,\ s: StaticText { text:'| 生成JPG的压缩质量:' }, \ 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质量下拉 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(){ //隐藏当前图层 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) { //保存结果图像 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压缩质量 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) { //做选区 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],) } // ==================================扩展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; //调整文件顺序,按数字大小排序 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\) [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772409.gif[/img][/url] 如果把它拷贝到“增效工具/自动”目录下(英文版为 Plug-Ins\Automate),再重新启动ps。你的ps就相当于安装了一个“窃听器”,会把你所有的操作步骤像录制动作一样录制为脚本。只要你有可记录的动作,它就在桌面生成“ScriptingListenerJS”、“ScriptingListenerVB” 两个文本文件。其实就是 javascript 和 vbscript 两种规则记录的动作。 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772465.gif[/img][/url] 虽然不像手工书写的代码易于理解和修改,但是很多直接操作的步骤都可以拷贝来用。 比如说上面的 “移动到最底层”“选中上一层”“隐藏当前层”“打开智能对象”“扩展n像素”“反选”等等动作就是通过脚本侦听录制下来 直接拷贝过来的。 再结合自己的编写的其他逻辑语句,很容易写出你想要的东西。 最后,希望有点编程基础又有兴趣的朋友, 在处理重复、量大或者经常碰到的工作的时候,多多挖掘ps的潜力。 其实写一个简单的针对性脚本或者动作 并不是很难哦 ^_^ 提供jsx源文件+两个psd文档,分本是 F14和歼10,有兴趣的朋友可以试试看,注意cs3以上 [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772618.jpg[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412772897.jpg[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412773184.jpg[/img][/url] [url=http://www.wangchao.net.cn/bbsdetail_1788580.html][img]http://image.wangchao.net.cn/it/1323412773368.jpg[/img][/url] 鉴于实践表明: 同样显示效果下 [另存为jpg] 比 [保存为web所用格式-jpg] 文件体积要大很多,所以最后替换了保存函数。 把saveAs,换成了exportDocument.,具体如下: function sm(name) { //保存结果图像 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); }
󰈣󰈤
 
 
 
>>返回首页<<
 
 热帖排行
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有