被嫌弃的博客图像处理

11 小时前 · 昆明

· Picture by ChatGPT· Picture by ChatGPT

要在博客主题里优雅的呈现图像,是一件繁琐的事情,这货,除了类型多,特么的尺寸也多,浏览器也会对其做跨域限制,还有,像是约定好的一般,主流浏览器都不支持渲染显示 TIFF 图像,等等。

如果只是满足个人需求,倒是相对简单了,不需要操这份心,比如,发布图像前,我会在调片后一并添加水印,统一输出尺寸和体积都合适的 Jpg 格式文件,也会移除 Exif 数据。这些前期准备,自然免去了在博客主题中通过代码处理图像的操作。

但是,博客主题是要面向不同的用户,大家对图像有着因人而异的要求,那么,在制作博客主题时,势必要把各种使用习惯都考虑周到。最重要的要以「最低环境要求」为基线,降低门槛,确保博客主题即使在低配条件下也能稳定运行。比如,图像处理器 ImageMagick 相比 GD 库更为强大,但是,大多数用户的初始环境默认只用 GD 库;又比如,现代浏览器已经支持图像的一些新特性(如 loading="lazy" 等),但是,新特性或多或少对旧版浏览器不太友好,存在兼容问题;再比如,少部分用户通过对象存储可以方便的生成同一图像的不同尺寸链接,但是,更多用户是以博客的附件形式上传图像,只能生成一条原始图像链接,等等。

这也是在重制 Snapic Plus v6 的过程中,最为烧脑的部分,需要顾及可能的边界情况。现在 SP.v6 完成了对图像较为理想的处理和测试,至少达到了预期想要的:


图像链接

众所周知,图像的类型不胜枚举,在以前的 Snapic Plus 主题中,使用严格的正则匹配图像的扩展名,以此初略的判断是否是图像链接,这会出现遗漏,也会导致一些通过对象存储生成的带参数的图像链接无法被匹配,尤其是那些经过编码没有扩展名的图像链接。

SP.v6 中,使用了与 Typecho 解析 Markdown 一致的方法,修正了这一问题。


图像加载

延迟加载,可以说是显示图像必不可少的标配功能,在现代浏览器中,虽然可以使用一些原生属性实现图像的延迟加载,但是,会有局限性,比如,之前提到的 loading="lazy" 属性,在我使用的旧版 Chrome 浏览器中,就是摆设,加之尚不能自定义加载阈值,在当下,这一属性还是很鸡肋;又比如,图像的尺寸并非越大越清晰,使用 srcset 和 sizes 属性可以根据显示设备的像素比和视口宽度,来选择对应尺寸的图像源,以呈现高清晰度的图像,但是,如上所说,还得靠对象存储生成同一图像的不同尺寸链接;再比如,图像除了 img 标签外,各大搜索引擎更推荐使用 figure 包裹 img 和 figcaption 用以关联图像和描述,让搜索引擎晓得这张图像是个啥,但是,Typecho 在解析图像链接时,是硬编码为 img 格式输出,虽然也可以在后期重构格式。

SP.v6 中,使用了兼容性更好的方式实现图像的延迟加载,也基于「最低环境要求」为前提,保持传统的单一图源,毕竟不是所有用户都能使用对象存储,或许等到这些服务低至白菜价了,再给博客主题做调整。此外,也会对加载完成的图像做渐现处理,以避免突然的惊悚显示。


图像跨域

这是被反馈最多的,其实,和博客主题压根没有任何关系,这是浏览器的安全机制,限制非同源资源进行交互,不仅是图像,其他诸如音视频等文件同样会被限制。如果图像有跨域问题,在分享海报时,图像无法绘制到画布,在读取数据时,无法获取图像元数据。

SP.v6 中,对图像做了信息反馈,可以根据提示了解图像的状态,比如:是否加载完成、是否可以下载、是否存在跨域等,以方便快速排查和正确配置图像资源。


图像数据

这里特指图像的 Exif 数据,想必是每位爱好摄影的用户都会关注的。个人觉得嘛,图像 Exif 数据对于提升拍照技术,没有半毛钱帮助,毕竟大多数放出来的摄影作品,无一不后期,所有通过相机物理功能得到的效果,在 Ps/Lr 中都能够真实复刻,图像 Exif 的意义,只是显得这张图像有这么一丢丢专业,仅此而已,多的没有,如果非得肯定它的价值,顶多也就是 GPS 数据。刚好,在 SP.v6 中,我把图像 GPS 数据应用到了地图服务中,可以在 GoogleMap 和 OpenStreetMap 以及高德、腾讯、百度地图中查看拍摄位置。

处理图像的 GPS 数据,也是一个讨人嫌的过程。某些原因,国内的坐标系统会在国际的坐标系统的基础上进行加密,衍生出了国测局坐标系统,百度更是奇葩,在国测局坐标系统的基础上,又搞出了自家的二次加密坐标系统。如果把图像的 GPS 数据应用到国内的地图中,会产生严重的漂移,需要做纠偏处理。

回到正题,图像的 Exif 数据以二进制的方式存储在 jpg jpeg webp tiff 类型的文件中。在后端,可以通过 PHP 的 EXIF 扩展获取,在前端,可以通过第三方库获取,两种方式各有优缺点,需要组合运用,目前没有看到一劳永逸的方案。比如,后端 PHP 的 EXIF 扩展还无法直接读取 WebP 图像的 Exif 数据,也仅限获取少数知名厂牌设备的专属元数据(如:镜头信息);又比如,前端老牌 exif.js 库无法读取 WebP 图像的 Exif 数据,也无法读取镜头信息(自己手搓添加标签后,可以);再比如,读取图像的 Exif 数据,前后端都需要下载完整的图像资源,那么,就说到痛点了,如果把一张不经过压制的十几兆大小的图像扔进博客里,还开启了显示 Exif 数据,这等同于给服务器和浏览器做压力测试,不崩才怪。

SP.v6 中,使用前后端搭配,在适当的时机按需获取图像 Exif 数据,有效的解决了可能出现的性能问题。


图像布局

瀑布流 masonry 是当前最接近完美的展示尺寸杂乱的多张图像的布局,具有等宽不等高,全显不裁图的优势,但是,不是单单引入 masonry.js 就能自称使用了瀑布流布局。鉴于 masonry 的运作机制,和图像延迟加载一起使用时,简直是悲催二人组,会陷入依赖困境:布局需要数据,数据需要加载,加载需要布局。这就好比「先有鸡还是先有蛋」的矛盾,如果没有妥善处理,会出现布局抖动,典型的现象是:瀑布流元素满天飞,当你浏览这张图像时,冷不丁被挤出了视口,当你要点击这张图像时,又冷不丁被弹到了别处,等等。对于图像较大,或网络不畅的场景,这个现象更为突出。

SP.v6 中,沿用了 v5 版的思路,当然,也对 v5 版的这一实验性功能做了全新编写,同时,也会基于「最低环境要求」为前提,即使不使用 aspect-ratio 新特性,也能有效的解决瀑布流布局的以上通病。

另外,瀑布流元素的封面需要缩略图加持,才能让低带宽的图像也能流畅的加载。在 SP.v6 中,分离了 v5 版的生成缩略图功能,改进为使用独立的面板操控,支持设置缩略图宽度、画质,支持一次性批量处理,支持自动断点连接,等等,有效的降低了服务器处理图像的压力。当然,如果自有对象存储生成的缩略图参数,也可以自定义使用之。

在图像布局方面,SP.v6 支持任意文章选择使用轮播布局、翻屏布局、等高布局来展示图像,不再仅限于独立页使用。还可以通过内容模块,实现比图和热区功能:

比图,即在同一容器中,通过滑块对比两张图像。使用场景:调片前后图对比,建模渲染图对比,城建卫星图对比,等等。

热区,即在底层图像上标记热区,当触发某个标记点的 hover 时,显示该标记点的图像和描述。使用场景:电商可购物热点,徒步路线兴趣点,等等。

图像灯箱

个人认为,灯箱的作用在于,可以清除无关元素,让浏览者专注于图像本身。毫不夸张的说,所有图像灯箱系统都可以做到,它生来就为这事,但是,当这些灯箱系统需要在同一个灯箱中处理多图,同时又可以使用缩略图进行索引时,那就不尽相同,有的怕是一言难尽了。

在 v5 版中,经过比对、筛选多款图像灯箱系统后,选择了 MIT 开源的 PhotoSwipe 项目,自己再往里新增一些功能后,也够用,但是,后来发现(也是事先没有预料到的),当面对几十上百张为一组的组图时,这个 PhotoSwipe 会力不从心。

和 PhotoSwipe 相似,大多数灯箱系统,在展示组图时,普遍需要预知分组后的全部图像,当组图中的图像数量又很多时,会使得 DOM 节点数量庞大,影响页面渲染而变得卡顿。

SP.v6 中,针对这些状况一一作了修正,不仅替换 PhotoSwipe 改用 Glightbox 灯箱系统,也将组图中的图像,按需获取,开灯箱,则加载,关灯箱,则销毁,有效解决了 v5 版的性能问题。

和 PhotoSwipe 相似,灯箱 Glightbox 不仅 MIT 开源,也很轻量化,甚至极简到了需要爆肝来新增以下:

1. 指示器,显示当前图像序位;
2. 拍摄设备,提示当前图像有 Exif 数据,并可以看详情;
3. 缩略导览,使用缩略图,不使用原始图,避免性能开销;
4. 下载,一键保存图像,有信息反馈;
5. 滚轮翻图,使用鼠标滚轮左右翻图;
6. 等等

那么,为什么不使用 Fancybox 灯箱系统,也是不少用户建议的,我都会回复,早期的 Fancybox 是免费开源的,新版 v4+ 采用了全新的商业许可,需要付费许可使用。可想,假若哪天国内有公司代理了该项目,被法务部致函是妥妥的事,别不信,当年的某款软件已经干过这事,俗称「隔空点穴」不劳烦境外作者亲自动手。


SP.v6 当前进度 92% ...

42,大寒
1705723200
42,大寒
当摄影师,也是有风险的!
1344938520
当摄影师,也是有风险的!
3 曲奇猫的拉夫领
1547460000
曲奇猫的拉夫领
38,大雪
1575680400
38,大雪
Tascam DR-07X & Zoom H1n
1581814800
Tascam DR-07X & Zoom H1n
28 I am Old Fashioned
1630198800
I am Old Fashioned
5 41,大寒
1674187200
41,大寒