Silent Reverie

Creating memories with the awesome stuff I've learnt.

使用Photoshop: 将整图一分为九

| Comments

引子

前些天一同事在做拼图游戏。设计师提供了很多素材图片给他,这些图片都是整张整张的,他需要将这些图片切图成九宫格(3 x 3)、十六宫格(4 x 4)、二十五宫格(5 x 5)等。如果单张单张地进行计算然后裁切肯定不现实,那样实在效率低下,然后他问我有没快捷方法可以帮助他。

思路一(动作)

我们切图一般都在photoshop中完成。以往我遇到这种大量的重复性工作时,我绝对不会坐以待毙,我会想方设法,不达目的绝不罢休。通常面对这种问题时,我首先想到的就是生成一个action(动作),然后利用它批量完成。

action(动作)的大致思路是将各宫格图片分散到不同的图层中,然后便可以通过菜单命令File | Scripts | Export Layers to Files…将图层一一导出为文件,具体如下:

  • 计算一张图片的三等分宽高,生成并保存选区
  • 将选区定位在图片左上角,然后通过菜单命令Layer | New | Layer via Cut(Copy)将该区域隔离到新的图层
  • 重新载入选区,移位选区至新的位置,执行第二步同样命令
  • 重复执行第三步,直到图片九等分分散在不同图层

但是,生成这样的动作不仅麻烦,而且也不甚高效,原因如下:

  • 需要为九宫格(3 x 3)、十六宫格(4 x 4)、二十五宫格(5 x 5)不同规格生成不同的动作
  • 其他原因忘了~^~…

于是这种思路只成为了一种念想,一闪即过。

思路二(切片工具)

然后有考虑利用Divide Slice…(划分切图)及Slices from Guides(辅助线自动生成切片)功能——一种传统古老的切图方式。然后通过菜单命令File | Save for Web…将各切片导出为图片。这种方式可行是可行,但事实是提供的图片不是很理想,宫格中有1个像素的透明gutter(间隙)。如果不考虑gutter(间隙)的话,九宫格切图只需四条均分辅助线,否则需要八条,这样就会导出很多垃圾图片——1像素宽或(和)1像素高的图。这样效果不是很理想(自许准理想主义者),于是这种方法也不了了之了。

事实是,这种方法确实可行,考虑四条均分辅助线生成切片,最后可以生成个action(动作)对这些图片做最后的sanitization(“消毒处理”),傻眼了当时…

思路三(脚本)

最后,不得不实施Last Resort(破釜沉舟之计)。我想到了脚本语言(事实是,原来我调侃同事用写段Java代码生成图片…^-^),photoshop自带的脚本功能(支持JavaScriptVBScriptAppleScript三种脚本语言)做这类事可谓游刃有余,一段简短的代码就可以干净利落地解决它,代码如下:

划分切图脚本 (divide_slice.js) 下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#target photoshop

if (app.preferences.rulerUnits !== Units.PIXELS) {
  // 采用像素单位进行计算
  app.preferences.rulerUnits = Units.PIXELS;
}

// 当前文档引用
var docRef = app.activeDocument;

// 文档宽度
var docWidth = docRef.width;
// 文档高度
var docHeight = docRef.height;

// 细分次数(默认 3 x 3,即九宫格切分)
var divides = 3;

// 宫格间隙(默认无间隙)
var gutter = 0;

// 每宫格宽度
var slotWidth = Math.floor(docWidth / divides);
// 每宫格高度
var slotHeight = Math.floor(docHeight / divides);

// 保存当前图层(即整图)引用
var layerRef = docRef.activeLayer;

var x, y;

// 遍历行
for (y = docWidth; y > 0; y -= slotHeight) {
  // 遍历列
  for (x = docHeight; x > 0; x -= slotWidth) {
    // 重置当前图片为原图层(即整图)
    docRef.activeLayer = layerRef;

    // 从右往左、从下往上设置选区
    docRef.selection.select([
      [x - slotWidth, y - slotHeight], // 左
      [x, y - slotHeight],  // 上
      [x, y], // 右
      [x - slotWidth, y] // 下
    ], SelectionType.REPLACE, 0, false);

    // layer via copy ^-^
    docRef.selection.copy();
    docRef.artLayers.add();
    docRef.paste();

    // 水平轴向间隙偏移
    x -= gutter;
  }
  // 垂直轴向间隙偏移
  y -= gutter;
}

// 删除原图层(即整图)
layerRef.remove();

用法很简单,只需下载这段脚本到本地,打开需要切分的图片,然后执行菜单命令File | Scripts | Browse…,在打开的弹出框中找到该脚本,双击执行即可。 r 如果要处理的图片很多的话,配合动作使用即可实现批处理。

参考书目

  1. Photoshop CS6 Scripting Guide
  2. Photoshop CS6 JavaScript Ref

Comments