はじめに
前回RustとWebAssemblyで電光掲示板ツール作った際に、拡大鏡ツール的なものも作ってみたいと思ったため、作成してみようと思う。🔎
(作り始めてから気が付きました、、、これ、わざわざWasm使わなくても
CSSのscaleなどを使えば簡単に実装できる!!😮
と考えながらも、とりあえず作ってしまったので記事にします💪)
前回作った電光掲示板ツールについて
プロジェクトの作成
まず、画像を取り込み、imgタグに表示する。
取り込む際に、処理しやすいサイズとアスペクト比に画像をクロップしておく。(今回は1280pxベース)
// 省略
#[wasm_bindgen]
pub fn resize_img(image_data: &[u8]) -> String {
let img = resize_image(image::load_from_memory(image_data).unwrap());
let mut buffer = Cursor::new(Vec::new());
img.write_to(&mut buffer, ImageFormat::Png).unwrap();
let base64_string = general_purpose::STANDARD.encode(buffer.get_ref());
// データURL形式で返す
format!("data:image/png;base64,{}", base64_string)
}
// 画像のアスペクト比・操作しやすいサイズに設定・調整
fn resize_image(img: DynamicImage) -> DynamicImage {
let aspect_ratio = img.width() as f32 / img.height() as f32;
let (new_width, new_height) = if aspect_ratio > 1.0 {
// 横長の画像の場合
(1280, (1280.0 / aspect_ratio) as u32)
} else {
// 縦長の画像の場合
((1280.0 * aspect_ratio) as u32, 1280)
};
// リサイズ
let resized_img = img.resize_exact(new_width, new_height, FilterType::Lanczos3);
// 1280x1280のキャンバスを作成
let mut canvas = DynamicImage::new_rgba8(1280, 1280);
// 白を背景色とする
let bkg_image= ImageBuffer::from_pixel(1280, 1280, Rgba([255, 255, 255, 255]));
image::imageops::overlay(&mut canvas, &bkg_image, 0, 0);
// リサイズ画像をキャンバスの中央に貼付
let x = (1280 - resized_img.width()) / 2;
let y = (1280 - resized_img.height()) / 2;
image::imageops::overlay(&mut canvas, &resized_img, x.into(), y.into());
canvas
}
// 省略
mousemove中にZoom処理を行う。
取り込み時Resize済みの画像と拡大鏡ツールの座標を受け取る。
imgタグが320pxで画像サイズが1280pxのため座標を4倍したものと、
16倍の拡大率を考慮してpixelを設定。
// 省略
#[wasm_bindgen]
pub fn zoom_img(str_url: String,point_x: u32,point_y: u32) -> String {
let comma_pos = str_url.find(',').unwrap();
let str_base64 :String =Some(&str_url[comma_pos + 1..]).unwrap().to_string();
let image_data = general_purpose::STANDARD.decode(str_base64).unwrap();
let img = image::load_from_memory_with_format(&image_data, ImageFormat::Png).unwrap();
let scaled_img: ImageBuffer<Rgba<u8>, Vec<u8>> = ImageBuffer::from_fn(
img.width(),img.height(),
|i, j| {
let original_x = point_x * 4 + i / 16;// zoom 16倍
let original_y = point_y * 4 + j / 16;
img.get_pixel(original_x, original_y).clone()
},
);
let mut buffer = Cursor::new(Vec::new());
scaled_img.write_to(&mut buffer, ImageFormat::Png).unwrap();
let base64_string = general_purpose::STANDARD.encode(buffer.get_ref());
// データURL形式で返す
format!("data:image/png;base64,{}", base64_string)
}
// 省略
この上記関数をJavascript側でmousemoveのeventで呼び出して、
その都度拡大表示させたら完成!🔎
今回の成果物
デモURL
デモ画像
ソース
まとめ
今回はRustで画像の拡大処理を処理してみた。📚
おそらくCSSで実装したほうが楽だと思うが、
Rustの勉強中ということもあり、
細かいことは気にせずコーディングを楽しもうと思う💪
※間違い等ありましたら、ご指摘いただけると助かります。