为什么你保存的 JPG 图片文件大得离谱?

连从 UI 培训学校刚毕业的实习生小妹都知道,一张图片的文件大小,和它的尺寸、分辨率、格式、质量、颜色内容等都有关系。如果你经常用到 PhotoShop 处理图片,基本对保存的每张图片文件大小都心里有谱。

不过,随时着我们的P图生涯越来越长,经常会碰到 PS 界三大诡异现象之一:本以为存的图片很小,结果保存出来却大得离谱!

这里举个栗子,一张 256px * 256px 且颜色简单的 jpg 图片文件能有多大?正常情况下有几百 KB 就很了不得了。但是下面左侧这张样图却有 6.23MB!不是 KB 而是 MB!肉眼可分辨的视觉效果与右侧样图却一模一样(示例文件在文末可下载)。

作为P图老司机,我有一百种方法来减小图片的文件大小,比如“存储为” PNG 格式、使用“存储为 Web 所用格式”保存、使用其它软件转存压缩等等常用方法。但只要使用“Ctrl+S 存储为” 来保存 JPG 图片,文件就会大得离谱。除此以外,还必然会伴随着另一个现象,对应的 PSD 文件也会大得离谱,上面左侧样图对应的 PSD 文件就有 7.96MB。

所以想深究一下造成文件大得离谱的原因是什么?而不是每次都绕道而行。

前面已知使用不同的保存方式,或不同的图片格式,就会导致图片大小的明显差异。初步判断是,文件过大一定是包含了一些多余数据没有被精简掉,于是继续尝试了一些常见操作,再存为 JPG 和 PNG 格式,看能不能排除定位出问题的范围,见下表。

常见的 PS 操作JPG 格式PNG 格式
Ctrl+S > PNG 格式
Ctrl+S > JPG 格式
Shift+Ctrl+S > 不同的“元数据”选项:
版权
版权和联系信息
除相机信息外的全部
全部
新建一个原尺寸空白画布,最后 Ctrl+S:
拖动复制所有图层到新画布
用菜单命令复制所有图层到新画布
所有图层转为“智能对象”,拖动复制到新画布
所有图层转为“智能对象”,用菜单命令复制到新画布
拖动复制一个图层到新画布
用菜单命令复制一个图层到新画布
一个图层转为“智能对象”,拖动复制到新画布
一个图层转为“智能对象”,用菜单命令复制到新画布

通过上面的操作与现象,大致有以下结论:

  • 不同的复制方式都会影响文件大小,所以问题与图层无关
  • JPG 和 PNG 格式都有可能变成大文件,所以问题与格式无关
  • 多余数据属于文件本身的某种元数据,会跟随某些操作被带到其它文件中
  • 存为 PNG 格式一定是小文件,是因为多余元数据会被默认精简,除非手动保留

接下来就是要看看文件中的这些多余元数据是什么了,可以使用 PhotoShop 中的“文件简介 Alt+Shift+Ctrl+I”来查看,挨着翻一遍,切换到“原始数据”标签页时,这一大堆东西什么鬼就特别显眼,没有什么语义一看就很异常冗余。

这是什么?

于是又到了求助 Google 的环节, 这是什么东西?从 Adobe 的 XMP 官方文档可以找到如下说明(第32页):

photoshop:DocumentAncestors

If the source document for a copy-and-paste or place operation has a document ID, that ID is added to this list in the destination document’s XMP.

当你进行复制粘贴、拖入、导入新文件等操作时,如果这些内容来源有文档ID,就会被记录到当前文档的 XMP 数据中,并且这些记录是不断累加的,所以特别是那些反复编辑的文档,就会慢慢累计越来越多的“文档来源”数据。

官方解释比较模糊,其它帖子也没说明白“文档ID”到底是怎么记录的,有什么用途。文件的 XMP 数据可以导出,上面示例文件就包含了11万多条的“文档来源”数据,里面又分为几种不同的标签内容,这么海量的来源数据真不知道都它在记录些什么(导出的 XMP 数据在文末可下载)。

该怎么办?

遗憾的是这些数据完全是软件自动记录,没办法禁用这种记录行为。因为 XMP 数据的开放性与可编辑性,需要想办法直接清理掉文件中的冗余数据,而不是导出图片的时候再清理,不然还会继续存在于 PSD 文件中。

当然,这么浅显的解决思路一定有大神已经实现了,利用 PhotoShop 的脚本事件功能,就能自动清理文件中的“文档来源”数据:

  • 将下面这段代码存为 .jsx 格式(也有现成的在文末可下载)
function deleteDocumentAncestorsMetadata() {
whatApp = String(app.name);
if (whatApp.search("Photoshop") > 0) {
if (!documents.length) {
alert("There are no open documents. Please open a file to run this script.")
return;
}
if (ExternalObject.AdobeXMPScript == undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
xmp.deleteProperty(XMPConst.NS_PHOTOSHOP, "DocumentAncestors");
app.activeDocument.xmpMetadata.rawData = xmp.serialize();
}
}
deleteDocumentAncestorsMetadata();
  • 在 PhotoShop 中打开“文件 > 脚本 > 脚本事件管理器”窗口,照着下图设置

这种方法的效果就是,PhotoShop 每次打开文件,都会先自动清理掉冗余的“文档来源”数据,然后你就可以开心地随意保存图片了,并且对应的 PSD 文件都不会大得离谱。如果文件依然很大,那就是它本来就应该那么大,这是UI 培训学校刚毕业的实习生小妹都知道的那些原因。

XMP 相关知识

其实这篇文章的标题也可以叫做《为什么你保存的 PSD 文件大得离谱?》,关于 PSD 文件瘦身,除了清理冗余元数据这种情况,还有下面一些偏方:

  • 清理空图层
  • 清理未使用的样式
  • 合理使用“智能对象”
  • 适量的栅格化图层
  • 保存时隐藏全部图层
  • 发送文件时先压缩打包

至于这些偏方的原理是什么,多问问身边的P图老司机吧。

文中相关的示例及脚本文件下载:百度网盘