PSD 文件转 PNG
今天主要调查了下如何读取 PSD 文件并转化为 PNG 的方法,最好是支持读取每个图层的信息,并将每个图层转化为 PNG 文件。
在本地简单的测试了一下,使用了 PSD 和 PSB 格式的文件各一个。由于时间有限,测试的样本比较少,而且测试的文件也比较小 (只有几 M )。
Java
通过 Java 程序转换主要是参考这篇博客,其中记载了三种方法。
Aspose.PSD for Java
官方文档:https://docs.aspose.com/psd/java/
- 可以将整个 PSD 转成 PNG(支持 PSB 和 PSD)
- 可以获取每个图层的位置、大小,并支持将每个图层导出为单独的 PNG 图片
- 需要付费(试用时导出的图片左上角会有一个类似水印的方框)
注意: 添加 Java Maven 依赖时要注意下版本,感觉尽量使用新版的应该兼容性会比较好。测试时先用的是文档中的版本( 20.2 ),结果各种出错,改成最新版本( 21.7 )就好了。
Aspose.PSD for Java 的包不在官方 Maven 仓库里,需要添加 <repository>
配置:
<repositories>
<repository>
<id>AsposeJavaAPI</id>
<name>Aspose Java API</name>
<url>http://repository.aspose.com/repo/</url>
</repository>
</repositories>
添加依赖:
<dependencies>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-psd</artifactId>
<version>21.7</version>
<classifier>jdk16</classifier>
</dependency>
</dependencies>
保存图层为 PNG 文件的示例:
// Load a PSD file as an image and caste it into PsdImage
PsdImage psdImage = (PsdImage) Image.load(file.getInputStream());
// Create an instance of PngOptions class
PngOptions pngOptions = new PngOptions();
pngOptions.setColorType(PngColorType.TruecolorWithAlpha);
// Loop through the list of layers
String tmpFileName = RandomUtil.randomString(10);
psdImage.save(String.format("%s.png", tmpFileName), pngOptions);
for (int i = 0; i < psdImage.getLayers().length; i++) {
// Convert and save the layer to PNG file format.
psdImage.getLayers()[i].save(String.format("%s_layer_%d.png", tmpFileName, i), pngOptions);
}
TwelveMonkeys + Thumbnailator
TwelveMonkeys: https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-psd
Thumbnailator: https://mvnrepository.com/artifact/net.coobird/thumbnailator
- 支持将整个文件转成 PNG
- 转 PSB 文件成功
- 转 PSD 文件报错
- 不支持获取单独的图层
奇怪的是转测试的 PSD 格式文件时会报错,估计还是兼容性有些问题。
添加依赖:
<!-- https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.twelvemonkeys.imageio/imageio-psd -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-psd</artifactId>
<version>3.8.3</version>
</dependency>
示例代码:
BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(new File(fileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
try {
String thumbnailFileName = String.format("twelve_monkeys_%s_%d.png", fileName, System.currentTimeMillis());
Thumbnails.of(bufferedImage)
.size(bufferedImage.getWidth(), bufferedImage.getWidth())
.toFile(new File(thumbnailFileName));
log.info("thumbnailFileName: {}", thumbnailFileName);
} catch (IOException e) {
throw new RuntimeException(e);
}
PsdReader
在这篇博客中提供了一个博客作者自己实现的 PSD 读取类(PsdReader
),是根据 PSD 的格式规范实现的。
测试结果:
- 转 PSB 文件没有报错,但是图片仅有黑色背景
- 转 PSD 文件成功
代码示例(PsdReader
类代码比较长,这里就不贴了,详见原博客):
PsdReader psdReader = new PsdReader(new File(fileName));
BufferedImage bufferedImage = psdReader.getImg();
String thumbnailFileName = String.format("psd_reader_%s_%d.png", fileName, System.currentTimeMillis());
try {
ImageIO.write(bufferedImage,"png",new File(thumbnailFileName));
} catch (IOException e) {
throw new RuntimeException(e);
}
JavaScript
JavaScript 版貌似都是基于 PSD.js 这个模块的。
PSD.js
项目仓库:https://github.com/meltingice/psd.js
这个模块支持获取各个图层的具体信息,详细介绍和用法见项目仓库(不过貌似文档并不多)。
测试结果:
- PSB 文件转换失败,只有黑色的背景
- 应该是没有获取到图层信息导致的
- PSD 文件转 PNG 成功
- 可以获取到图层的信息
安装 psd 模块
npm install psd
示例代码:
var PSD = require('psd');
var psd = PSD.fromFile("1.psb");
psd.parse();
console.log("1.psb", psd.tree().export());
// console.log(psd.tree().childrenAtPath('A/B/C')[0].export());
// You can also use promises syntax for opening and parsing
PSD.open("1.psb").then(function (psd) {
return psd.image.saveAsPng('./1-output.png');
}).then(function () {
console.log("Finished!");
});
// You can also use promises syntax for opening and parsing
PSD.open("2.psd").then(function (psd) {
console.log("2.psd", psd.tree().export());
return psd.image.saveAsPng('./2-output.png');
}).then(function () {
console.log("Finished!");
});
1.psb 文件的解析结果:
{
children: [],
document: {
width: 1747,
height: 1137,
resources: {
layerComps: [],
resolutionInfo: [Object],
guides: [Array],
slices: []
}
}
}
2.psd 文件的解析结果:
{
children: [
{
type: 'group',
visible: true,
opacity: 1,
blendingMode: 'normal',
name: 'iPhone 4',
left: 163,
right: 838,
top: 137,
bottom: 1468,
height: 1331,
width: 675,
children: [Array]
},
{
type: 'group',
visible: true,
opacity: 1,
blendingMode: 'normal',
name: 'iPhone 4 Side',
left: 902,
right: 1009,
top: 138,
bottom: 1456,
height: 1318,
width: 107,
children: [Array]
},
{
type: 'layer',
visible: false,
opacity: 1,
blendingMode: 'normal',
name: 'Background',
left: 0,
right: 1234,
top: 0,
bottom: 1600,
height: 1600,
width: 1234,
mask: {},
text: undefined,
image: {}
},
{
type: 'layer',
visible: true,
opacity: 1,
blendingMode: 'normal',
name: 'Background',
left: 0,
right: 1234,
top: 0,
bottom: 1600,
height: 1600,
width: 1234,
mask: {},
text: undefined,
image: {}
}
],
document: {
width: 1234,
height: 1600,
resources: {
layerComps: [],
resolutionInfo: [Object],
guides: [Array],
slices: []
}
}
}
Python
Python 的 PIL 图像处理库支持 PSD 文件的解析。
- 根据文档,可以导出每个图层的图片
- 试用了 Psd2Png 里生成好的 exe 文件,导出的图层文件高宽是一样的(背景透明)
参考项目:
总结
综上,付费的 Aspose.PSD for Java 表现最好,文档也比较全。免费的里面 Python 的测试结果最好,导出的 PNG 结果和 Aspose.PSD 有些区别。
因为时间有限,测试的样本也比较少,以上结论仅供参考。