CORDEA blog

Android application engineer

【Rust】imageproc で任意の位置に text を描画する際の注意点

imageproc に限らず、rusttype で font の layout を使用する際には概ね同じ問題に当たりそうなんですが、
そこまで調べてないので imageproc に限った話として紹介します。

今回はテキストの描画位置をちょうど真ん中にすることを考えてみます。
なお、ここで紹介している描画部分のコードは GitHub にあります。

github.com


まず、imageproc の draw_text_mut で任意の文字を描画してみます。

draw_text_mut(&mut image, Rgba([0u8, 0u8, 0u8, 255u8]), 0, 0, scale, &font, "rustpythonclojureC#");


f:id:CORDEA:20190616145632p:plain

中央にする場合、テキストの正確な width と height が必要になります。
これは font.layout で取得できるので、取得して各文字の min.x, min.y, max.x, max.y をもとに周りを囲ってみます。

f:id:CORDEA:20190616151012p:plain

見れば分かる通り、例えば max.x - min.x で文字ごとの width は取れるものの、
文字間の padding (kerning 処理?) は考慮されないため、ここを考慮して width を計算する必要があります。
また、height に関しては一文字目の max.y - min.y だけを見た場合、'r' の高さしか考慮されないため、
min.y の一番小さい文字 ('h' など) - max.y の一番大きい文字 ('p' など) を取得して高さを計算する必要があります。
高さに関してはどこを baseline と置くかで計算方法も変わってくるでしょう。

このあたりが 1 つ目の注意したほうが良さそうな点です。

以上を踏まえて、文字列全体の width と height を計算し、周りを囲ってみます。

f:id:CORDEA:20190616152046p:plain

これで正確な width, height が取得できました。
ただ、ここから中央揃えにするために (image.width / 2) - (width / 2) などとして x, y を計算して描画すると微妙にずれることに気がつくはずです。
というかそもそも画像でも margin が入っていますよね...

これが 2 つめの注意点で、描画する際に x, y に margin が入るため、描画する際にここを考慮する必要があります。

実際にこの margin がどの程度かですが
x に関しては一番はじめの文字の min.x を見れば良いです。
y に関しては、min.y が一番小さい文字の min.y を見れば良さそうです (ex. 'h')。

以上を踏まえて、x, y を margin 分左と上にずらすことで、ちょうど真ん中に描画することが出来ます。

f:id:CORDEA:20190616152910p:plain