斗图不用怕!用 serverless 随时创建你的表情包

meme economy(表情包经济)显然是下一件大事!这是互联网注意力经济的自然延伸,Elon Musk也沉迷于此。据估计,meme economy 已经价值 2.5亿美元了。

The meme economy is where FOMO meets YOLO. — Felix Salmon from AXIOS

现在谁的手机还没存几个表情包 meme 呢?

然而,找到合适的 meme 需要时间。程序员之间的调侃对常规创作者来说还是比较偏僻。那程序员自己做一个允许任何人自定义 meme 并生成新 meme 的 web 应用程序怎么样?这就是Meme as a service 😎。

这样,妈妈再也不用担心我斗图输了!开干!

在这里插入图片描述

为什么要用 serverless

作为开发者,创建一个在图片上添加文本标题的 Web 应用程序可能并不困难。但是,“meme as a service”还有一些其他要求。

  • 图像处理任务通常需要大量计算,并且需要高性能。
  • meme 这种场景要么使用的人数很少,要么可能会迅速普及。换句话说,meme as a service 需要具有可伸缩性,而开发者只需为实际使用付费。

上述问题的解决方案如下。首先,我们要使用高性能的现代编程语言来编写图像和文本操作函数。因此我们选择了 Rust,Rust 提供了本机性能,同时又具有内存安全性。

接下来,使用公共云中的 serverless 函数可以最好地解决可伸缩性要求。serverless 函数在没有人使用的时候是免费的,并且可以迅速扩展到数百万个用户。

虽然可以将从 Rust 编译的本机程序作为 serverless 函数运行,但更好的方法是在 WebAssembly 虚拟机中作为 serverless 函数运行 Rust 程序。 WebAssembly 虚拟机充当本机应用程序与 serverless 主机环境之间的兼容层和安全沙箱。由于 WebAssembly 虚拟机已经经过预先配置,可以在公有云的 serverless 运行时的各种老旧的操作系统和容器映像中运行,因此它使 Rust 程序更具可移植性。此外,WebAssembly 使 Rust 程序可以轻松安全地访问以 C / C ++编写的软件库。一个示例是从 Rust 访问旧版操作系统中的Tensorflow 库

快速开始

在这篇文章里,我会使用GitHub 上的模板函数 tencent-meme-scf 来在腾讯云上部署 Rust meme-as-a-service。这个模板基于开源的 Serverless Framework。Rust 程序编译成 Wasm 字节码并运行在 SSVM 上。SSVM 已经为基于云的运行环境进行了优化。

在这个例子

首先,你需要安装 Serverless Framework ,并在腾讯云上创建一个账号。腾讯云会提供免费的额度给开发者使用。接下来是 fork 或 clone 我们提供的模板函数,然后转到 tencent-meme-scf。

$ git clone https://github.com/second-state/tencent-meme-scf
$ cd tencent-meme-scf

使用 Serverless Framework 部署云函数、用于函数服务的 API 网关、让用户使用函数服务的静态 HTML 页面。 .env 文件里配置了要将函数部署到腾讯云。 只需按照屏幕上的说明,登录腾讯云并部署。

$ sls deploy
... ...
	region:  ap-hongkong
    website: https://sls-website-ap-hongkong-3wxv81e-1302315972.cos-website.ap-hongkong.myqcloud.com
60s › tencent-meme-scf › "deploy" ran for 2 apps successfully.

在浏览器加载 website URL,来看看你的 meme-as-a-service! 你可以自定义 meme 图片上的每个标题/水印的文本、大小和位置。

表情包生成原理解析

这个应用程序的总体结构是一个典型的 JAMStack 应用程序。用于图像处理的后端逻辑被部署为 serverless 函数,并且可以通过API 使用。前端用户界面是静态 HTML 和 JavaScript 网页。前端通过 JavaScript Ajax 调用与后端 API 进行交互。

main.rs 是为 meme 图片添加文字的后端 serverless 函数,是用 Rust 编写的。它先读取文本/水印的字体文件和背景图像文件。

然后,Rust 函数读取用户在 HTML 网页中输入的文本、位置和大小。输入为 JSON 文本形式, serde_json 库将 JSON 文本解析为 Rust 结构的数组。

_watermark() 函数将每个水印添加到图像。_watermark() 函数输出最终的图像并对其进行 base64 编码。serverless 运行时的 API 网关将 base64 编码的图像返回给调用JavaScript,以显示在网页上。

const FONT_FILE : &[u8] = include_bytes!("PingFang-Bold.ttf") as &[u8];
const TEMPLATE_BUF : &[u8] = include_bytes!("bg.png") as &[u8];

fn main() {
  let mut buffer = String::new();
  io::stdin().read_to_string(&mut buffer).expect("Error reading from STDIN");
  let obj: FaasInput = serde_json::from_str(&buffer).unwrap();

  let mut img = image::load_from_memory(TEMPLATE_BUF).unwrap();

  let memes: Vec<Watermark> = serde_json::from_str(&(obj.body)).unwrap();
  for m in memes {
    _watermark(m, &mut img);
  }

  let mut buf = vec![];
  img.write_to(&mut buf, image::ImageOutputFormat::Png).unwrap();
  println!("{}", base64::encode_config(buf, base64::STANDARD));
}

= _watermark() 函数在图像上添加了一条水印文本,这里用了标准的 Rust 图像处理库(Crate)来处理 meme 图像。

fn _watermark(w: Watermark, img: &mut image::DynamicImage) {
  let font_size = w.font_size;

  let font = Vec::from(FONT_FILE);
  let font = Font::try_from_vec(font).unwrap();

  let scale = Scale {
    x: font_size + 1.0,
    y: font_size + 1.0,
  };
  drawing::draw_text_mut(img, image::Rgba([0, 0, 0, 255u8]), w.left - 2, w.top - 2, scale, &font, &w.text);

  let scale = Scale {
    x: font_size,
    y: font_size,
  };
  drawing::draw_text_mut(img, image::Rgba([255u8, 255u8, 255u8, 255u8]), w.left, w.top, scale, &font, &w.text);
}

前端 JavaScript 从 HTML 表单中获取用户输入的文本、位置和字体大小,将输入数据以 JSON 提交到云函数,然后显示返回的base64 图像。

var memes = [];
memes[0] = {};
memes[0].text = $('#red-girl-says').val();
memes[0].left = parseInt($('#red-girl-left').val());
memes[0].top = parseInt($('#red-girl-top').val());
memes[0].font_size = parseInt($('#red-girl-font').val());
... ...

$.ajax({
  url: window.env.API_URL,
  type: "post",
  data : JSON.stringify(memes),
  dataType: "text",
  success: function (data) {
    const img_url = "data:image/png;base64," + data;
    $('#wm_img').prop('src', img_url);
  },
  error: function(jqXHR, exception){
    console.log("Error Status: " + jqXHR.statusText);
  }
`});`

创建你的 meme

你可以使用源代码模板来创建你自己的 meme-as-a-service。 你可以更改 meme 背景图像,并更改用于添加文本水印的 UI。 因此,请首先确保已安装 Rust 编译器和 ssvmup 构建工具。

更改 Rust 代码和 HTML 文件来适配你自己的 meme 文件。将 Rust 代码编译成 WebAssembly,并把结果复制到 scf/ 文件夹

$ ssvmup build --enable-aot
$ cp pkg/scf.so scf/

运行 Serverless Framework 命令,部署函数。

$ sls deploy
... ...
	region:  ap-hongkong
    website: https://sls-website-ap-hongkong-3wxv81e-1302315972.cos-website.ap-hongkong.myqcloud.com
60s › tencent-meme-scf › "deploy" ran for 2 apps successfully.

接下来

你可以用 JAMStack 应用和 serverless 函数做很多事情。例如,为TensorFlow 推理创建 serverless 函数,将图像识别和图片识别集成到 web 应用中。

创建你自己的 meme 图片,并提交 PR 给我们,填写这份问卷我们将为你送上一份精美礼品!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值