背景:身在一个有实业的电商公司,设计部的妹子们总是会有做不完的商品图片,当然了,要是做点有技术含量的美化工作也罢,但是最近她们很是无聊,总是要做一些重复性的工作,就比如如题所说的,图片量产,量产什么呢?价格牌。。。这东西很没意思哎!就是给你一个模板,然后你自己把模板原来的文字图片换掉就行了,再排一下版,纯体力劳动好么!博主做过一阵子的对日外包工作,深知她们的痛苦,如果说某些对日外包的程序猿是人肉转码器的话,那么设计部的妹子们现在就成了。。算了,词就不说了,太残酷了

========================================炫炸天的分割线========================================

线索:针对背景交代的情况,BOSS给了我一个提示:PS脚本,顺着这个线索,我就进行了一系列调查,我分别做了@#¥%……&*()的努力,简而言之,photoShop自带的开发文档帮了我大忙,文档位于Adobe Photoshop CS5\Scripting\Documents\,参考了Photoshop CS5 Scripting Guide.pdf和Photoshop CS5 JavaScript Ref.pdf,当然了,自带的文档貌似还不能完全满足我的需求,我还自己下载了一个JavaScriptToolsGuide_CS5.pdf,抱着这三个文档啃了又啃,总归算是完成了这样一个量产工具。

========================================酷炸天的分割线========================================

开发思路:既然是量产工具,那么他的工作流程应该是这样的,1工具读了一个文件,文件包含了所有产品的信息,2循环抽取每一个商品的信息,生成图片并保存,3循环完毕,给出一个提示,OK,大概思路就是这样了,然后接下来就是顺着这个思路啃文档了。。。

========================================拽炸天的分割线========================================

代码如下:

 //测试版本:PhotoShop CS5 12.0.3 x32 通过
//作者:Duke
//测试完结日期:2014/08/24 priceCardGenerator() function priceCardGenerator(){ /**
* 定义统一的赋值变量
*/
var title //标题
var liwaiCode //里外编码
var priceTitle //售价标题,为了方便替换
var price //售价
var sample //价格符号
var fiveAssureFeeTitle //五包费用标题,为方便替换
var fiveAssureFee //五包费用
var seftFeeTitle //自提费用标题,为方便替换
var seftFee //自提费用
var size //尺寸
var producingArea //产地
var material //材质 /**
* 定义统一的字体配置
*/
var tipFont = "MicrosoftYaHei-Bold"
var valueFont = "MicrosoftYaHei"
var priceFont = "Century Gothic" /**
* 定义统一的颜色配置
*/
//价格的颜色
var priceColor = new SolidColor()
priceColor.rgb.red = 208
priceColor.rgb.green = 28
priceColor.rgb.blue = 119
//顶部栏的颜色
var topBarColor = new SolidColor()
topBarColor.rgb.red = 212
topBarColor.rgb.green = 0
topBarColor.rgb.blue = 102 /**
* 在此读取文件
*/
//打开logo图片
var logoImg = app.open(File("D:/priceCard/liwailogo.jpg")) //读取数据文件
var dataFile = new File("D:/priceCard/priceCardData.xml")
//后续操作设置为“读”操作
dataFile.open("r") //缓冲变量
var xmlCode = dataFile.read()
//alert(xmlCode) //空文件直接退出
if(xmlCode == ""){
alert("文件没有内容")
return
} //新建XML对象
var products = new XML(xmlCode) //产品总数
var productCount = products.product.length() //遍历
for( i = 0;i < productCount;i++){ //变量赋值
title = products.product[i].elements()[0]
liwaiCode = "里外编码:" + products.product[i].elements()[1]
priceTitle = "售价"
price = products.product[i].elements()[2]
sample = "¥"
fiveAssureFeeTitle = "五包费用"
fiveAssureFee = "¥" + products.product[i].elements()[3]
seftFeeTitle = "自提费用"
seftFee = "¥" + products.product[i].elements()[4]
size = products.product[i].elements()[5]
producingArea = products.product[i].elements()[6]
material = products.product[i].elements()[7] // 存储当前的单位长度,并设置自定义的单位
var originalUnit = preferences.rulerUnits
preferences.rulerUnits = Units.PIXELS // 声明一个文档
var docRef = app.documents.add( 886, 561 ,72.0,"tempDoc") // 顶部栏,创建选区并上色
// “选区”的填充要在定义组之前操作,否则会报出“fill方法在当前版本不可用”
docRef.selection.select([[0,0],[0,20],[886,20],[886,0]],SelectionType.EXTEND)
var selRef = docRef.selection
selRef.fill( topBarColor, ColorBlendMode.NORMAL, 100, false) // 定义一个图片组
var layerSetRef =docRef.layerSets.add()
layerSetRef.name = "图片组" //设置logo所在的文档为活动文档
app.activeDocument = logoImg
//声明logo图层
var logoLayer = logoImg.activeLayer
//复制商品图层到背景文档
var logoLayerTemp = logoLayer.duplicate(layerSetRef,
ElementPlacement.PLACEATEND)
//设置背景文档为活动文档
app.activeDocument=docRef
//logo移动至左下角
logoLayerTemp.translate(-265,225) //读取当前商品对应的二维码图片
var qrCodeImg = app.open(File(products.product[i].elements()[9]))
//设置二维码图片所在的文档为活动文档
app.activeDocument = qrCodeImg
//声明二维码图片图层
var qrCodeImgLayer = qrCodeImg.activeLayer
//复制二维码图片到背景文档
var qrCodeImgLayerTemp = qrCodeImgLayer.duplicate(layerSetRef,
ElementPlacement.PLACEATEND)
//设置背景文档为活动文档
app.activeDocument=docRef
//商品图片移动至中间偏右
qrCodeImgLayerTemp.translate(320,180)
//关闭商品图片文档
qrCodeImg.close(SaveOptions.DONOTSAVECHANGES) //读取当前价格牌的商品图片
var productImg = app.open(File(products.product[i].elements()[8]))
//设置商品图片所在的文档为活动文档
app.activeDocument = productImg
//声明商品图片图层
var productImgLayer = productImg.activeLayer
//复制商品图层到背景文档
var productImgLayerTemp = productImgLayer.duplicate(layerSetRef,
ElementPlacement.PLACEATEND)
//设置背景文档为活动文档
app.activeDocument=docRef
//商品图片移动至中间偏右
productImgLayerTemp.translate(200,-50)
//关闭商品图片文档
productImg.close(SaveOptions.DONOTSAVECHANGES) /**
*内容开始
*/
// 商品名称
var proNameLayerRef = docRef.artLayers.add()
proNameLayerRef.kind = LayerKind.TEXT
var proNameTextItemRef = proNameLayerRef.textItem
proNameTextItemRef.contents = title
proNameTextItemRef.position = Array(55, 70)
proNameTextItemRef.font = tipFont
proNameTextItemRef.size = 30 //里外编码
var liwaiCodeLayerRef = docRef.artLayers.add()
liwaiCodeLayerRef.kind = LayerKind.TEXT
var liwaiCodeTextItemRef = liwaiCodeLayerRef.textItem
liwaiCodeTextItemRef.contents = liwaiCode
liwaiCodeTextItemRef.position = Array(55, 95)
liwaiCodeTextItemRef.font = valueFont
liwaiCodeTextItemRef.size = 14 //售价标题
var liwaiCodeLayerRef = docRef.artLayers.add()
liwaiCodeLayerRef.kind = LayerKind.TEXT
var liwaiCodeTextItemRef = liwaiCodeLayerRef.textItem
liwaiCodeTextItemRef.contents = priceTitle
liwaiCodeTextItemRef.position = Array(55, 135)
liwaiCodeTextItemRef.font = tipFont
liwaiCodeTextItemRef.size = 22 //¥
var sampleLayerRef = docRef.artLayers.add()
sampleLayerRef.kind = LayerKind.TEXT
var sampleTextItemRef = sampleLayerRef.textItem
sampleTextItemRef.contents = sample
sampleTextItemRef.position = Array(50, 235)
sampleTextItemRef.font = tipFont
sampleTextItemRef.size = 40
sampleTextItemRef.color = priceColor //金额
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = price
liwaiPriceTextItemRef.position = Array(105, 235)
liwaiPriceTextItemRef.font = valueFont
liwaiPriceTextItemRef.size = 100
liwaiPriceTextItemRef.color = priceColor //五包费用
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = fiveAssureFeeTitle
liwaiPriceTextItemRef.position = Array(55, 275)
liwaiPriceTextItemRef.font = tipFont
liwaiPriceTextItemRef.size = 20 //五包费用金额
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = fiveAssureFee
liwaiPriceTextItemRef.position = Array(140, 275)
liwaiPriceTextItemRef.font = valueFont
liwaiPriceTextItemRef.size = 18
liwaiPriceTextItemRef.color = priceColor //自提费用
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = seftFeeTitle
liwaiPriceTextItemRef.position = Array(250, 275)
liwaiPriceTextItemRef.font = tipFont
liwaiPriceTextItemRef.size = 20 //自提费用金额
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = seftFee
liwaiPriceTextItemRef.position = Array(335, 275)
liwaiPriceTextItemRef.font = valueFont
liwaiPriceTextItemRef.size = 18
liwaiPriceTextItemRef.color = priceColor //规格
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = "规格:"
liwaiPriceTextItemRef.position = Array(55, 345)
liwaiPriceTextItemRef.font = tipFont
liwaiPriceTextItemRef.size = 20 //规格数值
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = size
liwaiPriceTextItemRef.position = Array(125, 345)
liwaiPriceTextItemRef.font = valueFont
liwaiPriceTextItemRef.size = 20 //产地
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = "产地:"
liwaiPriceTextItemRef.position = Array(55, 375)
liwaiPriceTextItemRef.font = tipFont
liwaiPriceTextItemRef.size = 20 //产地值
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = producingArea
liwaiPriceTextItemRef.position = Array(125, 375)
liwaiPriceTextItemRef.font = valueFont
liwaiPriceTextItemRef.size = 20 //材质
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = "材质:"
liwaiPriceTextItemRef.position = Array(55, 405)
liwaiPriceTextItemRef.font = tipFont
liwaiPriceTextItemRef.size = 20 //材质值
var liwaiPriceLayerRef = docRef.artLayers.add()
liwaiPriceLayerRef.kind = LayerKind.TEXT
liwaiPriceLayerRef.textItem.kind = TextType.PARAGRAPHTEXT
var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
liwaiPriceTextItemRef.contents = material
liwaiPriceTextItemRef.position = Array(125, 391)
liwaiPriceTextItemRef.font = valueFont
liwaiPriceTextItemRef.width = 550
liwaiPriceTextItemRef.height = 200
liwaiPriceTextItemRef.size = 20 //保存文件
new Folder("D:/priceCard/result").create ()
jpgFile = new File( "D:/priceCard/result/" + products.product[i].elements()[1] + ".jpeg" )
jpgSaveOptions = new JPEGSaveOptions()
jpgSaveOptions.embedColorProfile = true
jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE
jpgSaveOptions.matte = MatteType.NONE
jpgSaveOptions.quality = 12
app.activeDocument.saveAs(jpgFile, jpgSaveOptions, true,
Extension.LOWERCASE) //强制关闭
docRef.close(SaveOptions.DONOTSAVECHANGES) //恢复默认长度单位
app.preferences.rulerUnits = originalUnit
}
//关闭logo所在的文档
logoImg.close(SaveOptions.DONOTSAVECHANGES)
alert("生成" + productCount + "条产品信息,请在以下位置\"D:/priceCard/result/\"查看")
}

代码里的priceCardData.xml的文档格式是下面这个样子的

<products>
<product>
<!--模板文件禁止修改-->
<产品名称></产品名称>
<!--里外编码-->
<里外编码></里外编码>
<!--售价-->
<售价></售价>
<!--五包费用-->
<五包费用></五包费用>
<!--自提费用-->
<自提费用></自提费用>
<!--规格大小-->
<规格大小></规格大小>
<!--产地-->
<产地></产地>
<!--材质-->
<材质></材质>
<!--产品图片地址-->
<产品图片地址></产品图片地址>
<!--产品二维码地址-->
<产品二维码地址></产品二维码地址>
</product>
<product>
<!--模板文件禁止修改-->
<产品名称></产品名称>
<!--里外编码-->
<里外编码></里外编码>
<!--售价-->
<售价></售价>
<!--五包费用-->
<五包费用></五包费用>
<!--自提费用-->
<自提费用></自提费用>
<!--规格大小-->
<规格大小></规格大小>
<!--产地-->
<产地></产地>
<!--材质-->
<材质></材质>
<!--产品图片地址-->
<产品图片地址></产品图片地址>
<!--产品二维码地址-->
<产品二维码地址></产品二维码地址>
</product>
</products>

看完了这个文档格式,你应该会有以下的疑问:

1:博主逗比吧,XML标签怎么用中文?!

2:写两遍product节点干什么?手抖么?

哎,我知道自己挺逗的,但是这事要从开发之初说起,我最开始不是用XML来存放数据的,我本来幻想着可以使用CVS文件,或者PRN文件来存放数据源,然而都是以失败告终,因为商品的描述里什么都有可能存,一些卖萌的编辑什么都会写的。。。都怪我太年轻,用什么分割数据搞不清啊。。。

好了,回到问题1,我为什么用中文?因为,是为了避免装13,和让非技术人员看懂。为什么这么说呢,因为用Excel打开这个模板文件,Excel会把子节点当字段名来显示,就比如

<产品二维码地址></产品二维码地址>

这个节点在Excel里的标题就是“产品二维码地址”,这就是用中文的原因,方便理解。不过呢,这里提一个有趣的现象,使用中文去取节点里的内容竟然是可以的,很是让我惊喜哎

代码里可以看到,我是通过

title = products.product[i].elements()[0]

去取商品名称的值的,但是实际上

title = products.product[i].产品名称

也能取得商品名称的值,感觉帅帅哒!
不过呢,我怕出问题,还是没有用中文去取。。。

再看问题2,为什么写两遍,这个就要问Excel了,因为只写一个子节点的话,Excel里是没有表头的, 写两个才有带表头的表格,如下

产品名称 里外编码 售价 五包费用 自提费用 规格大小 产地 材质 产品图片地址 产品二维码地址
                   

好了,使用Excel填写产品信息,再保存为XMl数据文件,准备工作就算完成了,接下来就是见证奇迹的时刻了

怎么运行?在页面里运行?看着不像啊。。app是个啥?浏览器认识么。。

其实是在photoShop里运行的,将写好的脚本放置于Adobe Photoshop CS5\Presets\Scripts下,打开PS,已经打开的就重启一下PS,之后你会在PS->文件->脚本下发现放入的脚本文件,默认是支持.jsx结尾的脚本文件,记得文档里说.js结尾的文件也支持来着。点击运行之后,你就会发现,图层啊,文字啊,刷刷的生成,刷刷的关闭,自动化的感觉很好啊,代码中的图片生成速度是10s左右一张,最高画质的,还可以接受。

好了,洋洋洒洒写了这么多,一是为了记录一下自己的心得,二是希望能给那些深陷在重复性设计工作中的人们一些帮助,只要稍微懂得一些脚本知识,能看懂英文文档就可以写啦,很炫酷的。PS脚本对我来说是一个新鲜的东西,或许我写的这些小玩意早就有大神在我之前写过,而且效率更高,或许有现成的软件可以直接生成,或许我做了很多无用功,但是都没关系啦,因为有时候是不是坑,你只有跳进去再爬出来才能知道它是不是,这样以后才好绕着走。博文至此,希望技术大神,和设计大师不用过分重视,毕竟这篇小小的博文只能是一个针对初学者的小例子,就比如说我,我作为一个程序员,两天前都不知道PS可以运行脚本,而对于那些和我一样的小伙伴们,如果你们感兴趣,自己可以先去写个脚本,alert一下自己的helloworld!哈哈~

												

开博第二篇:记一个利用JavaScript,编写PS脚本,开发图片量产工具的更多相关文章

  1. JavaWeb学习总结第二篇--第一个JavaWeb程序

    JavaWeb学习总结第二篇—第一个JavaWeb程序 最近我在学院工作室学习并加入到研究生的项目中,在学长学姐的带领下,进入项目实践中,为该项目实现一个框架(用已有框架进行改写).于是我在这里记录下 ...

  2. artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口

    artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口 自适应内容 artDialog的特殊UI框架能够适应内容变化,甚至连外部程序动态插入的内容它仍然能自适应 ...

  3. LoadRunner利用ODBC编写MySql脚本

    最近做了几周的LoadRunner测试,有一些心得,记录下来,以便以后查找. LoadRunner测试数据库是模拟客户端去连接数据库服务器,因此,需要协议(或者说驱动的支持).LoadRunner本身 ...

  4. JavaScript编写Web脚本最佳实现

    最近在看JavaScript DOM 编程艺术,总结一下JavaScript编写Web脚本的规范与实现,对于实现有以下几点要求: 平稳退化:确保网页在没有JavaScript下也能正常运行 分离Jav ...

  5. Golang学习-第二篇 搭建一个简单的Go Web服务器

    序言 由于本人一直从事Web服务器端的程序开发,所以在学习Golang也想从Web这里开始学起,如果对Golang还不太清楚怎么搭建环境的朋友们可以参考我的上一篇文章 Golang的简单介绍及Wind ...

  6. LoadRunner利用ODBC编写MySql脚本(转)

    LoadRunner测试数据库是模拟客户端去连接数据库服务器,因此,需要协议(或者说驱动的支持).LoadRunner本身直接支持Oracle.SqlServer数据库,这两个数据库直接选择相应的协议 ...

  7. 第二篇,前端高性能JavaScript优化

    加载和执行 JavaScript是单线程,所以JavaScript的加载和执行是从上下文加载执行完一个继续加载执行下一个文件会阻塞页面资源的加载,所以一般情况下JavaScript文件放在body标签 ...

  8. 开博第一篇:DHT 爬虫的学习记录

    经过一段时间的研究和学习,大致了解了DHT网络的一些信息,大部分还是参会别人的相关代码,一方面主要对DHT爬虫原理感兴趣,最主要的是为了学习python,大部分是别人的东西原理还是引用别人的吧 DHT ...

  9. OpenStack学习系列-----第二篇 由一个错误看理解整个架构的重要性

    看了openstack没几天,然后就开始试着用Java调用所有的API,第一步得到Credentials的时候成功了,然后第二步,传参数使所有的server信息都列出来的时候报错404.具体描述如下( ...

随机推荐

  1. dojo.create\dojo.place\dojo.empty\dojo.destroy\dojo.body

    1.dojo.create 1.create a node; 2.set attributes on it;  3.place it in the DOM. dojo.create(/*String| ...

  2. 表设计与SQL优化

    1. 说说分区表的主要好处是什么,为什么会有这些好处. 分区功能能够将表.索引或索引组织表进一步细分为段,这些数据库对象的段叫做分区.每个分区有自己的名称,还可以选择自己的存储特性. 从数据库管理员的 ...

  3. RTUILabel+正则表达式

    RTLabel和RegexKitLite都要导入第三方库 使用Regexkitlite库进行正则表达式的解析 1.库是使用MRR,如果在ARC工程里面使用这个类,必须在project->buil ...

  4. iOS二进制和资源包的自检

    因为现在做的是企业版的APP,不能保证用户不越狱,也不能保证有些用户喜欢自己修改ipa包里的资源文件,比如更换一些资源图片.因此,我们有必要在请求报文中,增加正版应用的二进制和资源文件的标识,让服务器 ...

  5. express框架目录结构

    . ├── app.js ├── bin │   └── www ├── node_modules │   ├── body-parser │   ├── cookie-parser │   ├── ...

  6. Android系统信息

    前提:获取的都是AndroidMainfest.xml下的信息 一.PackageManager 负责管理所有已安装的App 二.ActivityInfo 封装了Mainifest中的<acti ...

  7. 淘宝api 开发_获取用户信息

    string url = "http://gw.api.taobao.com/router/rest"; "; string appsecret = "fdf7 ...

  8. SQL Server 影响dbcc checkdb的 8 种因素

    第一种: 数据库的大小. 第二种: IO系统的速度. 第三种: 当前CPU的负荷. 第四种: 当前数据库的并发修改量.因为并发修改量越大维护数据库快照的成本就越高,dbcc 的过程中要创建快照,所以. ...

  9. Linux上配置Nginx+PHP5(FastCGI)

    原为地址:http://www.laruence.com/2009/07/28/1030.html Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,以事件驱动的方式编写,所以有非常好的性能,同时 ...

  10. openwrt 新版IPV6问题

    我的版本是r45579,表现是路由认证后正确获取IPV6地址并且可以ping通外网,电脑可以获取地址但是连不上外网. 加一条转发规则就好了 先查看/etc/config/network里给电脑分配的地 ...