写点什么

前端“秀肌肉”,云端 Photoshop 亮相

作者 | Addy Osmani

  • 2023-10-30
    北京
  • 本文字数:4172 字

    阅读完需:约 14 分钟

前端“秀肌肉”,云端 Photoshop 亮相

WebAssembly + Emscripten, Web 组件 + Lit, Service Workers + Workbox,以及全新 Web API 在此汇聚。Chrome 和 Adobe 正在携手打造新的图像编辑体验。


为 Photoshop 桌面应用程序开发 Web(photoshop.adobe.com)版,标志着将高度复杂和图形密集型软件引入浏览器的一个巨大里程碑。它的诞生离不开 Adobe 工程师们的多年努力,以及同 Chrome 等浏览器供应商的携手合作与 Web 技术本身的持续发展。



Photoshop Web 版中包含一系列高级功能,例如生成填充等


在本次案例研究中,我们将一同了解现已公布的高级 Web 功能、已经实现的性能优化以及未来有望落地的更多可能性。感兴趣的朋友还可参考《Photoshop 的 Web 之旅》(https://web.dev/ps-on-the-web/)一文了解更多细节信息。


发展愿景:让 Photoshop 登陆浏览器


几十年来,Photoshop 一直是图像编辑和图形设计领域的黄金标准,一直在 Windows 和 macOS 平台上为创意人士提供助力。但随着将其从桌面平台上解放出来,一个充满机遇的新世界也由此敞开了大门。


Web 的优势,在于无处不在、顺畅灵活的访问方式。用户只需打开浏览器即可着手编辑和协作,无需任何安装步骤。工作内容还可跨设备实现无缝衔接。


通过链接形式共享工作流程。Photoshop 文档可以通过 URL 访问,而不再隐藏于文件系统之内。如此一来,创作者可以轻松将链接发送给其他协作伙伴。


轻松实现跨平台操作。作为运行时,Web 抽象掉了底层操作系统,使得 Photoshop 能够覆盖用户手中的多种不同平台。


但实现这个愿景也面临着巨大的技术挑战,工程师们需要重新思考 Photoshop 这样强大的应用程序要如何在 Web 上运行、起效。


全新 Web 功能,释放 Photoshop 潜力


近年来,新的 Web 平台功能不断涌现。依托各种标准化和实施成果,Photoshop 级的应用程序终于具备了登陆 Web 端的可能性。Adobe 工程师也在项目中创新性地使用了几大关键下一代 API。


使用 Origin 私有文件系统,实现高性能本地文件访问


Photoshop 在操作中需要读取和写入大量 PSD 文件,这就要求其必须高效访问本地文件系统。新的 Origin 私有文件系统 API(OPFS)就提供一套指定特定数据源的快速虚拟文件系统。


const opfsRoot = await navigator.storage.getDirectory();
复制代码


OPFS 能够快速创建、读取、写入和删除文件。例如:


// Create fileconst file = await opfsRoot.getFileHandle('image.psd', {create: true});// Get read/write handleconst handle = await file.createSyncAccessHandle();// Write contents handle.write(buffer);// Read contentshandle.read(buffer);// Delete fileawait file.remove();
复制代码


对于绝对速度最快的同步操作,Web Workers 能够使用 FileSystemSyncAccessHandle。


这种本地高性能文件系统,让 Photoshop 具备了在浏览器端严格处理文件工作流程的能力。


释放 WebAssembly 的力量


WebAssembly 的任务,是使用 JavaScript 重新创建 Photoshop 计算密集型图形处理体系的重要前提。Adobe 使用 Emscripten 编译器将其现有 C/C++ 代码库移植成了 WebAseembly 模块。


其中,WebAssembly 的以下重要功能发挥了关键作用:


  • Threads —Photoshop 使用工作线程以并行方式处理任务,例如处理图像图块:

  • SIMD — SIMD 矢量指令用于加速像素操作与过滤。

  • 异常处理 — C++ 异常在 Photoshop 代码库中得到广泛应用。

  • 流实例化 — Photoshop 的 80 MB+ WASM 模块离不开流式编译的支持。

  • 调试 — Chrome 的 WebAssembly 调试支持在 DevTools 中发挥着重要作用。

  • 运用 P3 宽色域


P3 那宽广的色域足以令 sRGB 色谱相形见绌,但长期以来,后者一直是 Web 端上的唯一选择。



如今,Photoshop 使用新的 color() 函数与 Canvas API 将 P3 充分运用起来,带来了更加准确的色彩表现。


color: color(display-p3 1 0.5 0)
复制代码


Web 组件让 UI 更加灵活


Photoshop 属于 Adobe 整体 Creative Cloud 生态系统中的组成部分。使用基于 Lit 构建的标准化 Web 组件策略,即可实现跨应用程序的 UI 一致性。



Photoshop 的 UI 元素来自 Adobe 的 Spectrum Web 组件库,Adobe 设计系统中的各种实现均来自该库。


Spectrum Web 组件具备以下特性:


  • 默认可及性——开发时即考虑到各现有及新兴浏览器规范,并可支持辅助服务选项。

  • 轻量化——使用 LitElement 以将运行开销控制在最低。

  • 基于标准——基于 Web 组件标准(例如自定义元素与 Shaodw DOM)进行构建。

  • 框架中立性——依托于浏览器的支持,可匹配任意框架。


此外,整个 Photoshop 应用均使用基于 Lit 的 Web 组件构建而成。Lit 的模板和虚拟 DOM diffing 可实现高效 UI 更新。Web 组件封装更可以在必要时轻松集成来自其他团队的 React 代码。


总体而言,Web 组件的浏览器原生自定义元素与 Lit 的性能优势相结合,共同为 Adobe 提供了构建 Photoshop 复杂 UI 所需要的灵活性,同时保持其拥有良好的运行效率。


优化 Photoshop 在浏览器中的性能表现


虽然有各项 Web 新功能作为实现基础,但像 Photoshop 这样的资源密集型桌面应用程序仍需要大量的性能跟踪与优化调整,才能转化为一流的线上使用体验。



在 Photoshop Web 应用进行初始加载时,会对长任务进行拆分


使用 Service Workers 缓存资产与代码


Service Workers 允许 Web 应用在本地缓存其资产、代码和其他资源,以便在初次访问之后加快加载速度。尽管尚不完全支持离线运行,但 Photoshop 已经依托 Service Workers 来缓存其 WebAssembly 模块、脚本及其他资源。



在 Chrome DevTools Application 面板 > 缓存存储处,可查看 Photoshop Web 版已经预缓存的各种资源类型。在这里,我们可以看到其代码被拆分成多个 JavaScript 块进行本地缓存,这样就能在后续加载时获得极快的加载速度。


这套缓存机制对于加载性能产生了巨大影响。在首次访问之后,后续加载往往非常快(以 M1 Macbook 平台为例):



Adobe 还使用 Workbox 库,轻松将 Service Worker 缓存集成至整个构建过程当中。


V8 引擎对缓存资源进行优化


当从 Service Worker 缓存处返回资源时,V8 引擎会采取以下优化策略:


  • 在 install 期间缓存的资源,会被立即编译并进行代码缓存,从而实现更快、更一致的性能表现。

  • 在 fetch 期间通过 Cache API 缓存的资源,在第二次加载时将获得缓存优化,速度高于常规缓存。

  • V8 会根据缓存检测资源的重要度,并更主动地进行编译。


这些优化策略能够覆盖 Photoshop 中的大量缓存 Wasm 模块。



Photoshop Web 版在后续加载中能够更快显示关键视图,这在一定程度上归功于 V8 的代码缓存机制。


大型 WebAssembly 模块的流式处理与缓存


Photoshop 的代码库需要多个大型 WebAssembly 模块,有些大小已经超过 80 MB。V8 和 Chrome 能够支持流式编译,因此可以高效处理这些大体量模块。


此外,在首次从 Serivce Worker 处请求 WebAssembly 模块时,V8 会生成优化版本并将其存入缓存,这种方式对于 Photoshop 这类大体量应用至关重要。


通过多线程实现图形并行操作


Photoshop 中的很多核心图像处理操作(例如转换像素)可以通过跨线程并行处理来大幅加快速度。WebAssembly 的多线程支持可以利用多核设备的算力优势,快速执行各类计算密集型图形任务。


如此一来,Photoshop 就能以与桌面版相同的多线程方法高效执行 WebAssembly 当中的关键图像功能。


调试 WebAssembly 以做进一步优化


强大的 WebAssembly 调试支持,对于诊断和修复开发过程中的性能瓶颈至关重要。


Chrome DevTool 能够分析 WASM 代码、设置断点并检查各种变量,由此体现 JavaScript 自身的可调试性优势:



将设备上的机器学习功能与 TensorFlow.js 相集成


Web 版 Photoshop 的最新版本,还包含基于 TensorFlow.js 的 AI 驱动功能。将云端模型转为本地设备运行,有助于改善隐私、延迟和成本。


TensorFlow.js 是谷歌发布的一套开源机器学习库,主要面向希望在浏览器中运行客户端的 JS 开发人员。其具备成熟的 Web 机器学习选项,以及全面的 WebGL 及 WebAssembly 后端操作程序支持。未来随着 Web 新标准的持续发展,用户还可选择在浏览器中使用 WebGPU 后端以获得更佳性能。


Select Subject(选择对象)功能,可使用机器学习自动提取图像中的主要前景对象,从而大大加快复杂取像的执行速度。



以这张夕阳插图为例,我想将画面改为夜间。这时我们可以使用“选择对象”加 AI 提示来提取相应区域进行修改。



Photoshop 能够根据我的 AI 提示词生成更新后的插图。



还可添加更多视觉效果。


其中的 AI 模型已经由 TensorFlow 转换为 TensorFlow.js,因此可实现本地运行:


// Load Select Subject modelconst model = await tf.loadGraphModel('select_subject.json');// Run inference on image tensor const {mask, background} = model.execute(imgTensor);// Refine selection from mask
复制代码


Adobe 还与谷歌合作为 Emscripten 开发了代理 API,希望借此解决 Photoshop 中 WebAssembly 代码与 TensforFlow.js 之间的同步问题,并由此实现了框架间的无缝集成。


“由于谷歌团队通过各种受支持的后端(WebGL、WASM、Web GPU)提高了 TensorFlow.js 的硬件执行性能,模型性能实现了 30% 至 200% 的提升(模型体量越大,性能收益越高),并在浏览器端实现了近实时性能。”


关键模型也进行了优化,重点关注 Conv2D 等重视性能的操作类型。Photoshop 还可根据性能需求,选择在本地设备还是云端运行模型。


关于更多详细信息,请参阅 TensorFlow.js Photoshop 说明文章:


https://blog.tensorflow.org/2023/03/how-adobe-used-web-ml-with-tensorflowjs-to-enhance-photoshop-for-web.html。


Web 版 Photoshop 的未来规划


Photoshop Web 版的发布代表着一个巨大的里程碑,同时也是通往无穷可能性与全新世界的第一步。


Photoshop 将继续在 Web 端不断开拓,随着浏览器供应商对标准和性能的增强而逐步提升,并陆续发布更多功能选项。Photoshop Web 版仅仅只是开始,Adobe 后续计划在 Web 上积极构建完整的 Creative Cloud 套件,立足浏览器解锁更多更为复杂的设计类应用。


Adobe 还将与浏览器工程师们密切合作,共同推进标准和性能的提升,协力将 Web 打造成真正的独立平台,为各类雄心勃勃的用例提供支持。更多激动人心的时刻,就在前方!


原文链接:


https://medium.com/@addyosmani/photoshop-is-now-on-the-web-38d70954365a


相关阅读:


WebAssembly 的核心语言特性与未来发展

Photoshop 崩溃怎么办无法打开 Photoshop

Java 极客眼中的 WebAssembly

Photoshop 2023 如何切换语言?

2023-10-30 09:473778

评论

发布
暂无评论
发现更多内容

APP专项测试 —— 弱网测试

行者AI

测试

Serverless 是一种思想状态

Serverless Devs

Java Serverless 运维 云原生 后端

都 2021 年了,Serverless 能取代微服务吗?

Serverless Devs

Serverless 微服务 运维 云原生 后端

高性能MySQL

田维常

MySQL

如何阅读别人的源码

熊斌

学习 Code Review 源码阅读 七日更

SpacePX挖矿系统APP开发|SpacePX挖矿软件开发

系统开发

区块链数字货币多币种钱包开发案例

软件测试的方法

测试人生路

软件测试

架构师训练营第 1 期 - 第 11 周 - 命题作业

wgl

极客大学架构师训练营

灵魂一问:数据库连接池到底该怎么配?

Gopher指北

MySQL Go 语言

LeetCode题解:42. 接雨水,暴力法,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

阿里P8整理出Nginx笔记:Nginx应用与运维实战核心篇

996小迁

Java nginx 架构 面试

打开数“智”化之门,一字之差带来的思考

京东科技开发者

DevOps IoT 新基建 智能

应对游戏业务的四大“崩溃”场景有妙招,安全畅玩不是梦!

华为云开发者联盟

游戏 场景 崩溃

用 JavaScript 实现寻路算法 —— 编程训练

三钻

Java 算法 大前端 七日更 寻路算法

滴滴Java后台3面题目:网络+内存溢出+各种锁+高性能+消息队列

Java架构之路

Java 程序员 架构 面试 编程语言

社区一体化综合平台搭建,智慧平安小区建设解决方案

t13823115967

智慧城市 智慧平安社区平台建设

滴滴内部框架手册:Spring5+SpringMVC3+MyBatis3.X

Java架构追梦

Java spring 架构 mybatis springmvc

ECS实践案例丨逻辑卷的创建和扩容操作指导

华为云开发者联盟

数据库 数据 服务

顶会两篇论文连发,华为云医疗AI低调中崭露头角

华为云开发者联盟

人工智能 医疗 华为云

判空使用isEmpty()方法真的可行吗?

田维常

Java

你不好奇 Linux 网络发包过程吗?

小林coding

Linux 操作系统 网络

编写令人愉悦的API接口(二)

Geek_42915f

Java APi设计 接口规范

波场智能合约系统开发技术方案丨智能合约DAPP系统开发源码

程序员必看的Redis6.0多线程性能测试结果及分析 你看懂了嘛?

比伯

Java 编程 架构 面试

执法监督信息化建设,公安情报指挥一体化合成作战系统开发

t13823115967

智慧公安

传统数仓如何转型大数据

数据社

大数据 数据仓库 七日更

大神带你一睹为快!阿里技术官亲自码了“2000页的Spring全家桶笔记”真牛逼!

比伯

Java 编程 程序员 架构 计算机

架构师训练营第 1 期 第 13 周作业

李循律

极客大学架构师训练营

用 JavaScript 实现一个 TicTacToe 游戏 —— 编程训练

三钻

Java 算法 大前端 游戏开发 七日更

从中心到边缘,IoT正变为互联网之上的一张大网

华为云开发者联盟

物联网 IoT 网络

前端“秀肌肉”,云端 Photoshop 亮相_工程化_InfoQ精选文章