20 个版本 (6 个破坏性更新)

0.7.0 2023 年 6 月 17 日
0.6.0 2023 年 6 月 1 日
0.5.2 2023 年 5 月 31 日
0.4.4 2023 年 5 月 29 日
0.1.7 2021 年 11 月 27 日

#244 in 多媒体

Download history 11/week @ 2024-03-09 2/week @ 2024-03-16 3/week @ 2024-03-30 1/week @ 2024-04-06

每月下载量 2,178

自定义许可

4.5MB
4.5K SLoC

Rust 4K SLoC // 0.0% comments AsciiDoc 591 SLoC Shell 1 SLoC

包含 (WOFF 字体, 59KB) impact.woff2, (WOFF 字体, 59KB) assets/fonts/impact.woff2

胶原蛋白 — 拼贴生成器

collagen

胶原蛋白 — 由“拼贴”和“生成”组成(因为胶原蛋白是连接你身体的蛋白质;s/protein/tool/;s/body/images/) — 是一个程序,它接受一个包含 JSON 清单文件的文件夹作为输入,该文件描述了任意数量的 SVG 元素的布局(例如 <rect><line><g> 等),图像文件(JPEG、PNG 等),其他 SVG 和其他胶原蛋白文件夹,并输出一个包含任何外部资源的单个 SVG 文件。也就是说,它将 SVG 及其提供的资源的文本描述转换为一个可移植的 SVG 文件。

除了将清单直接映射到 SVG,胶原蛋白还支持一些功能,使作者创建图形更加方便,例如变量分配和 SVG 属性的插值,用于在字符串中评估数学表达式的 LISP 类语言,条件生成元素的“if”标签,以及生成元素序列的“for-each”标签。例如,以下清单将创建一个彩虹旋风。

collagen.json

{
    "$schema": "https://rben01.github.io/collagen/schemas/schema.json",
    "vars": {
        "width": 100,
        "height": "{width}",
        "n-spokes": 16,
        "cx": "{(/ width 2)}",
        "cy": "{(/ height 2)}",
        "spoke-length": "{(* width 0.75)}"
    },
    "attrs": {
        "viewBox": "0 0 {width} {height}"
    },
    "children": [
        {
            "for_each": {
                "variable": "i",
                "in": { "start": 0, "end": "{n-spokes}" }
            },
            "do": {
                "tag": "line",
                "vars": {
                    "theta": "{(* (/ i n-spokes) (pi))}",
                    "dx": "{(* (/ spoke-length 2) (cos theta))}",
                    "dy": "{(* (/ spoke-length 2) (sin theta))}"
                },
                "attrs": {
                    "x1": "{(+ cx dx)}",
                    "x2": "{(- cx dx)}",
                    "y1": "{(+ cy dy)}",
                    "y2": "{(- cy dy)}",
                    "stroke": "hsl({(* (/ i n-spokes) 360)}, 100%, 50%)"
                }
            }
        }
    ]
}

A rainbow pinwheel

原理

创建和编辑图片很困难。大部分困难是由于图像编辑程序缺乏程序化设施。我必须声明,我并没有使用市场上所有的图形编辑程序。但我尝试过的那些都存在不足。Collagen旨在以下方面填补这一空白:

  1. 纯文本是可移植的,并且可以轻松编辑。当通过编辑文本文件来编辑图片时,唯一的门槛是了解JSON,了解Collagen使用的模式,以及了解SVG元素目录。此外,包含文本文件和一些图片的文件夹很容易共享:只需将其压缩并发送即可。最后,Collagen是非破坏性的;最终图片中使用的所有资产都以其原始形式直接位于该文件夹中。

  2. 虽然大多数图像编辑程序支持“参考线”和“吸附”功能,允许图形元素相对于彼此精确定位,但没有任何“粘合剂”可以无限期地保持元素在一起;移动一个通常不会移动另一个。例如,从一个矩形的特定角落指向固定点的箭头无法使其尾部始终位于那个角落,同时使头部静止。变量通过让作者使用相同的变量(组)来指定矩形的角落和箭头头的位置,从而解决这个问题。更普遍地说,变量支持在不需要编辑多个硬编码值的情况下保持多个值同步的问题。

  3. 图像编辑程序输出单个图像文件,该文件是众所周知的一种图像类型(JPEG、PNG等)。不同的图像格式针对不同的图像数据类型进行了优化,并且当用于存储它们未优化的图像数据时会崩溃。

    1. 例如,JPEG针对具有平滑变化的渐变图像进行了优化(这通常意味着由物理相机拍摄的图片)。因此,当JPEG用于存储几何形状或文本时,会产生令人不快的压缩伪影。下面是一张文本的PNG图像,以及将其转换为JPEG后的相同PNG。JPEG已被放大,以便更容易地看到压缩伪影。

      “Collagen”一词的PNG格式截图

      A screenshot of the word “Collagen” in PNG format

      “Collagen”一词的JPG格式截图,已放大

      A screenshot of the word “Collagen” in JPG format zoomed

    2. 另一方面,PNG针对具有长串少数不同颜色的图像进行了优化,需要巨大的文件大小来存储JPEG优化的数据类型。尽管显示的是完全相同的图像(来源),下面所示的PNG文件比JPEG大6.6倍。

      重量为407KB的JPEG

      A bunch of cherries

      重量为2.7MB的PNG

      A bunch of cherries

    3. JPEG和PNG都是光栅格式,这意味着它们对应于像素的矩形网格。给定的光栅图像具有固定的分辨率(以每英寸像素数表示,例如),这大致是图像中存在的细节量。当你足够放大光栅图像时,你将能够看到组成图像的各个像素。与此同时,矢量图形存储几何对象,例如线条、矩形、椭圆,甚至文本,这些对象没有分辨率可言——你可以无限放大它们,它们始终会保持平滑、像素完美的外观。没有Collagen,如果你想在JPEG上添加一些文本,你只能将文本光栅化,将无限平滑的形状转换为像素网格,从而丢失矢量图形固有的精度。

    Collagen通过允许JPEG、PNG和任何其他浏览器支持的图像与SVG文件中的每个其他图像和矢量图形元素共存,从而解决这个问题,既不会损失质量,也不会增加文件大小,这是使用错误图像格式时出现的问题。(Collagen通过简单地使用base64编码源图像并将它们直接嵌入SVG来实现这一点。)

  4. 手动创建多个相似的元素既麻烦,而且保持它们同步甚至更糟糕。胶原蛋白提供了一个for_each标签来以编程方式创建任意数量的元素,并且子元素可以使用循环变量来控制它们的行为。我们在上面提到的风车中看到了这一点,它使用了循环变量i来设置每个辐条的角和颜色。本身for循环也可以访问在文件开头设置的n-spokes变量,这回到了第2点:变量使事情变得简单。

  5. 为什么是SVG?为什么不选择其他输出图像格式呢?

    • SVG确实可以存储矢量图形和不同类型的位图。

    • SVG具有广泛的兼容性,因为几乎每个浏览器都支持它。

    • SVG只是具有一些属性的节点树,因此它们很容易实现。

    • SVG是用XML编写的,它是纯文本,并且很容易编辑。

上述功能使胶原蛋白适合作为“程序员的图像编辑器”。每个人都喜欢迷因,包括程序员,让我们使用胶原蛋白来制作一个。

collagen.json

{
    "$schema": "https://rben01.github.io/collagen/schemas/schema.json",
    "vars": { "width": 800 },
    "attrs": { "viewBox": "0 0 {width} 650" },
    "children": [
        {
            "tag": "defs",
            "children": [
                {
                    "tag": "style",
                    "text": "@import url(\"https://my-fonts.pages.dev/Impact/impact.css\");",
                    "should_escape_text": false
                }
            ]
        },
        {
            "image_path": "./drake-small.jpg",
            "attrs": {
                "width": "{width}"
            }
        },
        {
            "vars": {
                "x": 550,
                "dy": 50
            },
            "tag": "text",
            "attrs": {
                "font-family": "Impact",
                "font-size": 50,
                "color": "black",
                "text-anchor": "middle",
                "vertical-align": "top",
                "x": "{x}",
                "y": 420
            },
            "children": [
                {
                    "for_each": [
                        { "variable": "i", "in": { "start": 0, "end": 4 } },
                        {
                            "variable": "line",
                            "in": [
                                "Using SVG-based text,",
                                "which is infinitely",
                                "zoomable and has",
                                "no artifacts"
                            ]
                        }
                    ],
                    "do": {
                        "tag": "tspan",
                        "text": "{line}",
                        "attrs": { "x": "{x}", "dy": "{(if (= i 0) 0 dy)}" }
                    }
                }
            ]
        }
    ]
}

A Drake meme. Top panel

使用胶原蛋白

快速入门

使用以下命令安装胶原蛋白:cargo install collagen。这将安装可执行文件clgn

安装后,如果您在路径path/to/collagen/manifest.json处有一个清单文件,您可以运行以下命令

clgn -i path/to/collagen -o output-file.svg

要持续监控输入文件夹并在任何更改时重新运行,您可以在监视模式下运行Collagen

clgn -i path/to/collagen -o output-file.svg --watch

在监视模式下,每次path/to/collagen中的文件被修改时,Collagen都会尝试重新生成输出文件,并打印一个通用的成功消息或记录遇到的具体错误,具体情况而定。监视模式永远不会自行终止。与其他大多数终端命令一样,您可以使用终止它。

此文档包含一些示例,可以作为创建清单的良好起点。更多示例作为测试案例在tests/examples中可用。

定义

Collagen 此项目的名称。
clgn 将转换成SVG的可执行文件。
骨架 这是一个文件夹,它是clgn的输入。它必须包含一个collagen.json文件和由collagen.json指定的任何资产。例如,如果骨架my_skeleton’s `collagen.json包含{ "image_path": "path/to/image" },则my_skeleton/path/to/image必须存在。
清单 位于骨架顶级目录中的collagen.json文件。

详细描述

Collagen的输入是一个文件夹,至少包含一个名为collagen.json清单文件。这样的文件夹被称为一个骨架。清单文件基本上是SVG(它本身是XML)的JSON版本,提供了一些方便的功能,例如循环和通过路径包含图像。例如,如果没有Collagen,为了在SVG中嵌入您的图像,您必须手动将其进行base64编码并构造该图像标签,其样子可能如下所示:

<image href="data:image/png;base64,iVBORw0KGgoAAAA...(many, many bytes omitted)..."></image>

相比之下,在Collagen清单中包含一个图像就像以下JSON对象作为根标签的子节点一样简单:

{ "image_path": "path/to/image" }

Collagen处理图像的base64编码并为您构造具有正确属性的<image>标签。

基本模式

为了从JSON生成SVG,Collagen必须知道如何将表示标签的对象转换为实际的SVG标签,包括执行任何附加工作(如base64编码图像)。Collagen通过包含的键简单地通过对象类型来识别它反序列化的对象。例如,存在"for_each"属性告诉Collagen这个标签是一个for循环标签,而"image_path"属性告诉Collagen这个标签是一个包含关联图像文件的<image>标签。为了避免歧义,一个对象包含意外的键是错误的。

对于用户:将"$schema": "https://rben01.github.io/collagen/schemas/schema.json"添加到清单的最高层对象中,以获得验证和建议。对于开发者:标签在docs.rs/collagen中列出。

常见问题解答

  1. 这与模板语言(如Liquid)有何不同?

    模板语言通常由两个组件组成:模板库,它负责渲染模板,以及模板语言,它通常类似于HTML,增加了控制流和插值等功能。库负责将模板文件和一些外部数据结合起来,生成输出文件。但是您不能(通常)直接在模板文件中写入数据,这不太方便,并且与您使用Collagen创建的图像的复杂性相比,需要单独写入数据可能会带来很大的开销。此外,实际上驱动模板库可能需要在该库的语言中编写一些代码,并在语言的运行时中运行它。

    相比之下,Collagen 允许您直接在清单中包含数据(例如循环的列表),并通过单个可执行文件运行,没有运行时。它还允许您将图像写入单个文件(collagen.json),而不是两个(模板文件和创建输出的“真实代码”)。此外,Collagen 本身没有需要学习的语法;您只需编写 JSON。如果您参考 Collagen 的 JSON 模式,编写 Collagen 清单就变得非常简单方便。

  2. Collagen 如何处理跨多个平台的路径?

    一般来说,文件系统路径不一定是有效的 UTF-8 字符串。此外,Windows 和 *nix 系统使用不同的路径分隔符。那么 Collagen 如何以跨平台的方式处理磁盘上的文件路径呢?Collagen 消耗的所有路径都必须是使用正斜杠(/)作为路径分隔符的有效 UTF-8 字符串。在解析路径之前,正斜杠被替换为系统路径分隔符。因此,在 \*nix 系统上,path/to/image 保持不变,但在 Windows 上变为 path\to\image。这意味着为了便携性,路径组件不应包含任何系统的路径分隔符,即使它在编写骨架的系统上是合法的。例如,以反斜杠 \ 结尾的文件名在 Linux 上是合法的,但在 Windows 上解码时会出现问题。一般来说,如果您将文件和文件夹名称限制为使用单词字符、连字符、空白字符和有限的标点符号,那么应该没问题。

    当然,您也受系统路径名固有限制的限制。例如,虽然 CON 在 Linux 上是有效的文件名,但在 Windows 上是禁止的。Collagen 不会努力为其可能使用的系统执行文件名验证;确保骨架可以在目标设备上解码是骨架作者的职责。

依赖项

~13–23MB
~322K SLoC