一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

?? 詳解一鍵生成邀請海報工具 | Rust 與 WebAssembly

 新用戶0118F7lQ 2021-03-25

背景:用 Rust 與 WebAssembly 為 Rust China Conf 做了一個快速生成海報的工具,在線體驗。

記得點擊閱讀原文,查看文章文中的資源。


以下為正文,Enjoy!??

在辦各種技術(shù)大會的時候,主辦方都會給參與者制作帶有個人名字的邀請海報,以顯示對參會者的重視,同時也希望達到最大范圍的傳播。

邀請海報一般的工作流:

  • 設(shè)計確定好海報樣式;
  • 運營提供給設(shè)計名字;
  • 設(shè)計根據(jù)名字一張一張輸出海報;
  • 運營再把海報一張一張發(fā)給參與者;

如果我們只有兩位數(shù)的參與者,那使用這個工作流工作是沒有問題的。但是當我們面向的是 300 人規(guī)模的 Rust China Conf 的時候,這個工作流的工作量就過于大了些,需要更多人力支持。再加上雖然 Rust 社區(qū)中的開發(fā)者無法到現(xiàn)場參與大會,依然也想轉(zhuǎn)發(fā) Rust 大會海報,為 Rust China Conf 打 Call。

在這種情況下,統(tǒng)計人名,再讓設(shè)計志愿者一張一張輸出海報,并把海報發(fā)給指定的人,對只有個位數(shù)的 Rust China Conf 組委會來說,基本上是不可能完整完成的任務(wù)。

不就是改改參數(shù)嗎???

那要怎么辦呢?既然是辦 Rust China Conf,首先想到的還是要用 Rust 解決。當然,Rust 與 WebAssembly 的集合很適合圖片處理這種計算密集型函數(shù)。

我們這家創(chuàng)業(yè)公司(Second  State)在成立的時候,就堅定地認為用 Rust 與 Wasm 做 serverless 是云計算的未來。所以很自然地就想到我們之前用 Rust 函數(shù)寫的的 watermark demo。為什么不把水印變成名字/昵稱,這樣就可以讓開發(fā)者自己在網(wǎng)頁上輸入名字,然后就能生成一張專屬邀請海報。使用 Serverless 的好處是只需為所使用的資源付費,成本也能 Cover 住。

使用 Second State Functions 給出的例子,需要解決的是

  • 找到一個中英文通用的字體,沒有任何版權(quán)問題
  • 重新計算 watermark 在海報上的位置,居中放置
  • watermark 的顏色與大小
#[wasm_bindgen]
pub fn watermark (img_buf: &[u8]) -> Vec<u8> {
    // 讀取輸入的圖片
    let mut img = image::load_from_memory(img_buf).unwrap();
    let (w,h) = img.dimensions();
    let scale = Scale {
      x: w as f32 /10.0,
      y: h as f32 /10.0,
    };

    // 準備 watermark 的字體
    let font = Vec::from(include_bytes!('DejaVuSans.ttf') as &[u8]);
    let font = Font::try_from_vec(font).unwrap();

    // 在輸入的圖片畫出 watermark
    drawing::draw_text_mut(&mut img, image::Rgba([255u8, 255u8, 255u8, 255u8]), 0 (h/10),h/2, scale, &font, 'Hello Second State');

    // 編寫并返回已經(jīng)加好水印的照片
    let mut buf = vec![];
    img.write_to(&mut buf, image::ImageOutputFormat::Png).unwrap();
    return buf;
}

let font = Vec::from(include_bytes!('DejaVuSans.ttf') as &[u8]);  在這里替換字體,用 PingFang Bold.ttf  替換原來的字體。

PingFang Bold.ttf 支持中英文,也與 Rust China Conf 的主 kv 字體一致,是個完美的選擇。

Rgba([255u8, 255u8, 255u8, 255u8]), 0 (h/10),h/2, 在這里調(diào)整顏色的 RGB 值與位置,RGB 值也就是水印的顏色。根據(jù)海報的背景最終選定白色。再接下來就是通過調(diào)整 0 (h/10),h/2, 調(diào)整字體的位置了。

經(jīng)過幾次調(diào)試后,終于找到了基本上是居中的位置。雖然還有一點小瑕疵,但是看起來還不錯,可以用了。效果如下圖:

original.png

改參數(shù)也是要技巧的 ??

但是很快又有一個問題出現(xiàn),中英文長度不一樣。如果輸入的名字是 Second State Functions,英文字符過長,而且文字不是居中的,甚至超出了圖片的安全區(qū)域。

?? ?? ??

簡單地調(diào)整位置參數(shù)的做法并不能很好解決這個問題。尤其現(xiàn)在是多元化環(huán)境,大家的昵稱五花八門,無法判斷輸入文字的大小、也無法判斷是否輸入的是中文,還是中英混雜。

我們需要再多寫點 Rust,來確保輸入的文字,無論長短,無論中英文,都能夠居中顯示,這樣才能達到為任何人生成定制海報的目的。

之前提到的代碼已經(jīng)告訴了我們?nèi)绾卧趫D片上添加文字,并輸出新的圖片。那我們再知道文字畫到圖片上的尺寸,就能實現(xiàn)文字的居中顯示啦。

那么如何獲取到這個尺寸呢?

我們的解決思路是,輸入文字后,函數(shù)會先按照基準字號把文字畫到一張純白的圖片上,然后根據(jù)文字在這張圖片的表現(xiàn)自動調(diào)整文字大小,從而保證文字一直居中并且大小合適。

const MAX_WIDTH : u32 = 349;
const MAX_HEIGHT : u32 = 80;
const MAX_FONT_SIZE : f32 = 125.0;
const FAR_LEFT : u32 = 200;
const FAR_TOP : u32 = 590;

lib.rs  先確定了輸入文字的寬度與高度、基準字號、文字的左上角位置,這里可以理解成先規(guī)定了一個安全區(qū)域。

當我們輸入文字 Second State Functions 之后,lib.rs 里的 watermark 函數(shù)的write_to_crop 函數(shù)先把文字按基準字號,即上文已經(jīng)確定好的 MAX_FONT_SIZE ,畫到 crop.png 上。crop.png 就是我們上文提到的純白的圖片。

pub fn watermark (watermark_text: &str) -> Vec<u8> {
    let width = write_to_crop(watermark_text);

    let mut left = FAR_LEFT;
    let mut top = FAR_TOP;
    let mut font_size = MAX_FONT_SIZE;

接下來, imagecrop.rs 里定義的結(jié)構(gòu)對象計算出白色背景上黑色文字所占據(jù)的寬度,這也就是水印畫到圖片上的基準寬度。

使用基準字號,Second State Functions 的位置明顯過寬了,那就來調(diào)整字號,

lib.rs 里的 watermark 函數(shù)根據(jù) imagecrop 里計算出的基準寬度,以及海報上允許放置文字的最大尺寸和相對位置,計算出能讓文字居中顯示的位置和字號。

if width < MAX_WIDTH {
      left = FAR_LEFT   (MAX_WIDTH - width) / 2;
    } else {
      font_size = (MAX_WIDTH as f32) / (width as f32) * MAX_FONT_SIZE;
      top = FAR_TOP   ((1.0 - (MAX_WIDTH as f32) / (width as f32)) * (MAX_HEIGHT as f32)) as u32;
    }

得出字號以及讓文字能夠居中顯示的位置后,剩下的工作就和前面提到的在圖片上添加文字完全一樣了。

當完成了 Rust 程序以后,就可以編譯成 wasm 文件,并將其部署到 Second State Functions 上提供給外界使用。這一步是通過 ajax 的方式實現(xiàn)了這個服務(wù)。這樣,任何拿到鏈接的人,都可以輸入自己的名字,生成一張定制的個人打 Call 海報。

better.png

生成適合自己的海報,解放雙手 ??

首先是 fork 這個 github repo,然后就可以肆意更改了。

字體使用 ttf 格式。我測試的時候,otf 格式的字體不能工作,如果有哪位大神知道原因,歡迎指出。更改字體在 lib.rs 里。

template.png 是模板海報,你可以替換成自己的海報。如果你的海報寬度與我們的海報寬度一樣,且名字的位置也一樣,那么就不用調(diào)整任何參數(shù)了。

如果你的海報與我們的模板不一致,那你需要在 lib.rs  修改下面這些參數(shù):

//文字安全區(qū)域的最大寬度
const MAX_WIDTH : u32 = 349;
//文字安全區(qū)域的最大高度
const MAX_HEIGHT : u32 = 80;
//最大允許字號
const MAX_FONT_SIZE : f32 = 125.0;
//文字安全區(qū)域相對圖片左上角的偏移量
const FAR_LEFT : u32 = 200;
const FAR_TOP : u32 = 590;

改完參數(shù)之后,按照 github 上的 Readme 部署函數(shù),測試出最佳位置。

為了方便測試,我們在 src 文件夾添加了 main.rs 文件。

最后使用 ajax 部署成一個網(wǎng)頁,這樣就可以方便地把生成海報應(yīng)用分享給相關(guān)的人使用,解放雙手!

 $.ajax({
      url: 'https://rpc.ssvm.:8081/api/run/149/watermark/bytes',
      type: 'post',
      data : $('#input')[0].files[0],
      contentType: 'application/octet-stream',
      processData: false,
      xhrFields:{
        responseType: 'blob'
      },
      success: function (data) {
        const img_url = URL.createObjectURL(data);
        $('#wm_img').prop('src', img_url);
      }
  });

這或許也可以稱為 Low Code Rust。Happy Coding!??

Reference ?? 

  • Mixing Text and Binary Data in Call Arguments
  • 源碼
  • 執(zhí)行 Rust 函數(shù)的 WebAssembly 虛擬機 SSVM

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    亚洲av日韩一区二区三区四区| 亚洲欧美中文日韩综合| 又色又爽又黄的三级视频| 午夜精品麻豆视频91| 成人区人妻精品一区二区三区 | 中文字幕亚洲视频一区二区| 日韩av欧美中文字幕| 人妻熟女欲求不满一区二区| 91欧美视频在线观看免费| 日韩精品视频免费观看| 99免费人成看国产片| 在线欧洲免费无线码二区免费| 四十女人口红哪个色好看| 国产一区欧美午夜福利| 欧美中文日韩一区久久| 国内精品偷拍视频久久| 欧美欧美日韩综合一区| 久久99午夜福利视频| 日本精品视频一二三区| 国产午夜福利不卡片在线观看| 婷婷色香五月综合激激情| 老鸭窝精彩从这里蔓延| 亚洲精品有码中文字幕在线观看| 亚洲欧美日韩在线中文字幕| 亚洲综合色婷婷七月丁香| 日本东京热加勒比一区二区| 中文精品人妻一区二区| 国产不卡最新在线视频| 日本高清中文精品在线不卡| 日韩中文无线码在线视频| 亚洲国产性生活高潮免费视频| 亚洲精品偷拍视频免费观看| 男女午夜福利院在线观看| 亚洲国产精品久久精品成人| 精品人妻少妇二区三区| 中文字幕一区二区熟女| 日本不卡片一区二区三区| 精品人妻一区二区四区| 小草少妇视频免费看视频| 内射精子视频欧美一区二区| 亚洲一区二区亚洲日本|