0
0

はじめに

前回RustとWebAssemblyで電光掲示板ツール作った際に、拡大鏡ツール的なものも作ってみたいと思ったため、作成してみようと思う。🔎

(作り始めてから気が付きました、、、これ、わざわざWasm使わなくても

CSSのscaleなどを使えば簡単に実装できる!!😮

と考えながらも、とりあえず作ってしまったので記事にします💪)

前回作った電光掲示板ツールについて

プロジェクトの作成

まず、画像を取り込み、imgタグに表示する。

取り込む際に、処理しやすいサイズとアスペクト比に画像をクロップしておく。(今回は1280pxベース)

lib.rs
// 省略

#[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を設定。

lib.rs
// 省略

#[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とWebAssemblyで拡大鏡ツール作ってみた_001.jpg

RustとWebAssemblyで拡大鏡ツール作ってみた_002.jpg

ソース

まとめ

今回はRustで画像の拡大処理を処理してみた。📚

おそらくCSSで実装したほうが楽だと思うが、

Rustの勉強中ということもあり、

細かいことは気にせずコーディングを楽しもうと思う💪

※間違い等ありましたら、ご指摘いただけると助かります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0