什么?Figma 的 fig 文件格式居然被破解出来了

大家好,我是前端西瓜哥。

上周图形编辑器交流群里有人问,对于 Figma 导出的 fig 文件,该如何解析其格式,拿到可读数据。

经过群友的一番讨论,这个问题最后算是解决了。

fig 文件

导出 Figma 的设计文件,我们会得到一个 fig 文件。

fig 是一种二进制的格式。

它没有使用 XML 或是 JSON 的格式,而是选择使用了 Figma 自己实现的特殊编码工具进行了序列化编码,并做了封装,最后得到一个二进制文件。

二进制相比明文格式(JSON 和 XML),优点有:

  1. 体积更小,因为数据更紧凑;

  2. 解析速度快,像是 JSON 这种,要逐个字符解析然后构建 AST,考虑转义、空格等特殊情况,对于大文件,解析效率很差;

  3. 高保真,比如一些类型明文格式其实是不好表达的,需要多做一层转换(比如 Float32Array 类型,要保存为字符串就要转为普通数组);

  4. 安全性。因为编码规则是应用自己实现的,此外方便做加密(比如异或加密)。编码和解码的规则我们是无法知道的,除非它主动公布出来,否则只能尝试去做逆向。

先用 Figma 随便画几个基本图形。

在这里插入图片描述

然后导出 fig 文件,拿到了一个名为 fig-file.fig 的文件。

在这里插入图片描述

先用 vscode 打开看看。

不是文本文件,应该就是二进制文件了。

在这里插入图片描述

不管怎样,强行用文本格式打开。

在这里插入图片描述

PK 打头,应该就是 ZIP 格式文件头的标识。

顺便再查看一下这个文件的二进制内容,看到开头这个 50 4B 03 04,说明确确实实是个 ZIP 文件。

在这里插入图片描述

基本上很多应用的导出文件都选择 ZIP 格式,然后再把后缀名改成自己定义的,比如 fig、xmind。

使用 ZIP 格式有以下好处:

  1. 进行了文件压缩,体积更小,并且是单文件;

  2. 保留了目录结构;

  3. 跨平台,基本所有主流操作系统都支持 ZIP。虽然用户一般来说并不会手动解压它,但用户安装的应用程序能直接使用操作系统的底层 API 去解压,有助于减少应用程序包体积;

解压一下。

unzip fig-file.fig

解压内容

解压后的内容为:

.
├── canvas.fig
├── fig-file.fig # 这个是压缩源文件
├── images
│   └── 0b15125516ae308a2d819f2970e851c0402949d2
├── meta.json
└── thumbnail.png

需要注意的是,解压出来的内容,并没有一个根文件夹存放这些内容。

但如果你用可视化界面去解压,通常会解压出一个文件夹,这个文件夹和压缩包同名。

这个其实是操作系统的额外操作,目的是防止解压出大量文件和当前文件夹的其他文件混在一起了,可能还会有文件同名的问题。

canvas.fig 是真正的 Figma 数据内容,记录图形树中图形的关系,以及图形的属性。

images 文件夹,存放的是图片,给里面的文件加上 .png 后缀可查看图片。

meta.json 是一些图纸的基本信息,比如导出的客户端使用的背景色,文件名等。

thumbnail.png 是预览图图片,如果你装了 figma 桌面端,则在会从 fig 提取出这个图片给文件预览器预览。

在这里插入图片描述

等下,不对,canvas.fig?怎么又是 fig 文件,这是在玩套娃?

经识别,也是个二进制文件,但它的文件格式却是。。。fig-kiwi

在这里插入图片描述

Kiwi

这个叫做 Kiwi 的特殊格式被 Figma 的前 CTO,Evan Wallace 开源了。

https://github.com/evanw/kiwi

Kiwi 是一种基于 Schecha 的二进制格式,用于高效地对树形数据结构进行编码。

它受到 Google 的 Protoclol Buffer 格式的启发,但更简单,编码更紧凑,且对自定义字段有更好的支持。

Kiwi 库提供了工具,能够解析二进制文件转换为编程语言中的对象,目前支持 JavaScript (TypeScript)、C++、Rust、Skew。

但要提供一个 Schecha,来进行类型的映射。

好在这个 Schecha 有保存在 fig 文件里的。

canvas.fig 文件

实际上这个 canvas.fig 文件并不是 Kiwi,它是一个复合产物。

首先开头的 fig-kiwi 字符串是一个注释,表示它是一个 fig 文件(毕竟前面也看到了,fig 文件可能也是 ZIP),并使用了 kiwi 进行编码。

文件里有 Kiwi 的二进制数据部分,也有 Schecha 部分,需要把它们提取出来。

这里要做 切片 了。

有个开源项目 Figma-To-JSON 成功解析了 fig,我们看看它怎么做的。

看了下,貌似是切在 50 89 这个地方,切好几刀,得到一些切片。我们需要前两个切片。

第一个切片是 Schecha,第二个是 Kiwi 数据。

每个切片都是 ZIP 压缩的,需要先给它们解压,然后再做 Kiwi 解码。

import { ByteBuffer, compileSchema, decodeBinarySchema } from "kiwi-schema"

export const figToJson = (fileBuffer: Buffer | ArrayBuffer): object => {
  // 提取 fig 文件的 schema 和 kiwi 格式数据
  const [schemaByte, dataByte] = figToBinaryParts(fileBuffer)

  const schemaBB = new ByteBuffer(schemaByte)
  const schema = decodeBinarySchema(schemaBB)
  const dataBB = new ByteBuffer(dataByte)
  const schemaHelper = compileSchema(schema)

  // 这个 json 对象就是最终结果了
  const json = schemaHelper[`decodeMessage`](dataBB)
  return convertBlobsToBase64(json)
}

流程总结一下,大致如下:

在这里插入图片描述

Figma-To-JSON

上面都是在说解码 fig 文件的过程。

如果你只是想要得到 fig 的结构,对过程不感兴趣,可以直接用一个名为 Figma-To-JSON 的开源项目去解析。

https://github.com/yagudaev/figma-to-json

下面是转换结果,是一个一维数组,风格类似 quill 的 delta。

每个节点保存有父节点的 id,可以关联构建出一棵图形树。

在这里插入图片描述

拿到 fig 数据格式有什么好处呢?

首先如果你开发自己的图形编辑器,或者直接就是 Figma 的竞品,你是要设计数据结构的,那 fig 数据格式就有很好的参考价值。

然后就是做二次开发,写一些工具做一些离线的批处理操作,比如提取 fig 的一些文本数据转换为 excal 之类的奇怪操作。

这样你就不用联网打开 Figma 网站,使用插件去进行这些操作。

Figma 官方的看法

Figma 的 fig 格式算是半公开的,在网上找找能找到不少蛛丝马迹。因为 Figma 还是比较开放的,使用的 Kiwi 编码格式也公开了。

但 Figma 不会主动提供在客户端转换 fig 的方式(但可以使用开发者 API 请求服务端数据),因为这 和它所希望的生态稳定相悖

如果 Figma 主动提供 fig 的内部格式出来,那它就要对这个格式负责,且 Figma 在开发新的功能时,fig 文件在未来发展中结构大概率会有破坏性改变的。

当然如果你想和 Photopea 一样,尝试去解析它转换成的结构,那也是可以的,但你自己要对这个数据结构负责。

结尾

我是前端西瓜哥,欢迎关注我,学习更多图形编辑器知识。

如果你想加图形编辑器交流群,加我微信 frstars,我拉你进群。


相关阅读,

Figma 是如何做协同编辑的?

图形编辑器开发:是否要像 Figma 一样上 wasm

SVGEdit:老牌开源 SVG 编辑器是如何架构的?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/255092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能优化算法应用:基于人工电场算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于人工电场算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于人工电场算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工电场算法4.实验参数设定5.算法结果6.…

产品调研——AI平台

本文主要记录了对腾讯云-TIONE平台、华为云-ModelArt等主流AI平台的产品调研。 交互式建模 简单点说就是提供了带训练资源的云IDE,使用形态包括Notebook、VsCode等。 腾讯云-TI平台 TI平台将tensorflow、pytorch、spark环境等均集成到一个Notebook容器中&#xf…

深入理解强化学习——马尔可夫决策过程:价值迭代-[价值迭代算法]

分类目录:《深入理解强化学习》总目录 文章《深入理解强化学习——马尔可夫决策过程:价值迭代-[最优性原理]》和文章《深入理解强化学习——马尔可夫决策过程:价值迭代-[确认性价值迭代]》介绍了价值迭代的基础知识,本文将介绍价值…

AX7A200教程(9): ov5640摄像头输出显示720p视频

一,功能框图 ov5640摄像头视频通过ddr3缓存后,最后使用hdmi接口进行输出显示 二,摄像头硬件说明 2.1,像头硬件管脚 如下图所示,一共18个管脚 2.2,摄像头电源初始化时序 因这个ov5640摄像头是买的老摄像…

制造企业MES管理系统可以和AI结合应用吗

在当今的数字化时代,人工智能AI和MES生产管理系统的结合将成为制造企业发展的重要趋势。这种结合可以为制造企业带来许多优势,如提高生产效率、降低成本、优化资源利用等。本文将探讨MES管理系统和AI的结合以及它们在制造企业中的应用,并分析…

【JavaWeb学习笔记】11 - WEB工程路径专题

一、工程路径问题 1.引入该问题 通过这几个去访问很麻烦 二、工程路径解决方案 1.相对路径 1.说明:使用相对路径来解决,一 个非常重要的规则:页面所有的相对路径,在默认情况下,都会参考当前浏览器地址栏的路径http:/ /ip:port/工程名/来进…

BM61 矩阵最长递增路径

题目 矩阵最长递增路径 给定一个 n 行 m 列矩阵 matrix ,矩阵内所有数均为非负整数。 你需要在矩阵中找到一条最长路径,使这条路径上的元素是递增的。并输出这条最长路径的长度。 这个路径必须满足以下条件: 1. 对于每个单元格,你…

【基于APB总线的DES实现】

基于APB总线的DES实现 本文内容摘要APB介绍仿真结果整体仿真写入数据DES加密部分DES加密读出密文 整体代码 本文内容摘要 本文是设计一个可兼容APB总线的DES加密协处理器,用来将DES加密模块与APB总线进行对接,使总线发送来的数据可以正常写入并进行加密后…

十四、YARN核心架构

1、目标 (1)掌握YARN的运行角色和角色之间的关系 (2)理解使用容器做资源分配和隔离 2、核心架构 (1)和HDFS架构的对比 HDFS架构: YARN架构:(主从模式) &…

分类预测 | Matlab实现AOA-SVM算术优化支持向量机的数据分类预测【23年新算法】

分类预测 | Matlab实现AOA-SVM算术优化支持向量机的数据分类预测【23年新算法】 目录 分类预测 | Matlab实现AOA-SVM算术优化支持向量机的数据分类预测【23年新算法】分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现AOA-SVM算术优化支持向量机的数据分类预测…

Note3---初阶二叉树~~

目录​​​​​​​ 前言🍄 1.树概念及结构☎️ 1.1 树的概念🎄 1.2 树的相关概念🦜 1.2.1 部分概念的加深理解🐾 1.2.2 树与非树🪴 1.3 树的表示🎋 1.4 树在实际中的运用(表示文件系统…

Leetcode—11.盛最多水的容器【中等】

2023每日刷题&#xff08;六十三&#xff09; Leetcode—11.盛最多水的容器 实现代码 #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) int maxArea(int* height, int heightSize) {int left 0, right heightSize - 1;int m…

屏幕超时休眠-Android13

屏幕超时休眠-Android13 1、设置界面1.2 属性值1.2.1 默认值1.2.2 最小值限制 1.3 属性值疑问 Settings.System.SCREEN_OFF_TIMEOUT 2、超时灭屏2.1 锁定屏幕的超时2.2 屏幕灭屏的超时 3、永不休眠* 关键日志 1、设置界面 packages/apps/Settings/src/com/android/settings/dis…

八.创建和管理表

目录 1. 基础知识1.1 一条数据存储的过程1.2 标识符命名规则1.3 MySQL中的数据类型 2. 创建和管理数据库2.2 使用数据库2.3 修改数据库 3. 创建表3.1 创建方式13.2 创建方式23.4 查看数据表结构 4. 修改表4.1 追加一个列4.2 修改一个列4.3 重命名一个列4.4 删除一个列 5. 重命名…

【Docker五】使用Harbor搭建Docker私有仓库

目录 一、harbor概述 1、harbor概念&#xff1a; 2、harbor的特性 3、harbor的组件&#xff1a; 二、harbor实验&#xff1a; 1、搭建harbor 2、远程主机使用docker-harbor&#xff1a; 3、镜像同步&#xff1a; 一、harbor概述 1、harbor概念&#xff1a; harbor&…

计网01 计算机网络基础

一、计算机网络基本概念 1、什么是计算机网络 网络&#xff1a;由两台或多台计算机通过网络设备串联&#xff08;网络设备通过传输介质串联&#xff09;而形成的网络网络设备&#xff1a;计算机、路由交换、防火墙、上网行为管理等传输介质&#xff1a;双绞线&#xff08;网线…

Eclipse 一直提示 loading descriptor for 的解决方法

启动eclipse之后&#xff0c;进行相关操作时&#xff0c;弹出界面&#xff0c;提示&#xff1a;loading descriptor for xxx 解决方法&#xff1a; 在Eclipse左侧的Project Explorer 最右上角有一个小钮,鼠标移上去时提示"View Menu". 你点一下,在弹出的上下文菜单中…

JAVA主流日志框架梳理学习及使用

前言&#xff1a;目前市面上有挺多JAVA的日志框架&#xff0c;比如JUL(JDK自带的日志框架),Log4j,Logback,Log4j2等&#xff0c;有人可能有疑问说还有slf4j&#xff0c;不过slf4j不是一种日志框架的具体实现&#xff0c;而是一种日志门面&#xff08;日志门面可以理解为是一种统…

Java基于SpringBoot的二次元商城网站系统

简介 二次元商城网站的使用是更为便捷的&#xff0c;互联网的普及在这个社会是非常成功的&#xff0c;小到个人的交际交流&#xff0c;大到公司企业员工的交流&#xff0c;都已经离不开科技&#xff0c;所以&#xff0c;在这么成熟的平台上&#xff0c;各种类型的网站也就应运…

【数据结构复习之路】图(严蔚敏版)两万余字超详细讲解

专栏&#xff1a;数据结构复习之路 复习完上面四章【线性表】【栈和队列】【串】【数组和广义表】【树和二叉树】&#xff0c;我们接着复习 图&#xff0c;这篇文章我写的非常详细且通俗易懂&#xff0c;看完保证会带给你不一样的收获。如果对你有帮助&#xff0c;看在我这么辛…