Rustで画像をネガポジ変換
Rustの勉強を兼ねて、画像を読み込んでネガポジ変換するコードを書いてみました。 全然Rustらしさが無いですが、小さなことからコツコツと。
なお、今回はimageとうクレートを利用しました。
[dependencies]
image = "*"
実はネガポジ変換だけであれば、このクレートを使って画像を読み込んだ後、invert()
というメソッドを叩いたら実現できてしまいます。
が、今回は勉強のために自分で各ピクセルの色情報(RGBa)を取得して弄りたかったので、その部分のみ自分で実装しました。
extern crate image;
use image::GenericImageView;
use image::GenericImage;
use image::DynamicImage;
use image::Rgba;
fn main() {
let input = "/home/koji/Desktop/test.jpg";
let output = "/home/koji/Desktop/test_inverted.jpg";
let mut img: DynamicImage = image::open(input).unwrap();
// 実は標準でメソッドが用意されている。これで反転できるよ
// img.invert();
invert(&mut img);
img.save(output).unwrap();
}
fn invert(img: &mut DynamicImage) {
let (width, height) = img.dimensions();
for y in 0..height {
for x in 0..width {
// 1pixelの情報を取得
let mut pixel: Rgba<u8> = img.get_pixel(x, y);
// RgbaはPixelトレイトを実装している。dataというプロパティでpixelの情報を取れる。
// dataプロパティは、上記の型パラメタの通りu8型の配列になる。
let red = pixel.data[0];
let green = pixel.data[1];
let blue = pixel.data[2];
let alpha = pixel.data[3];
// 手動で各色情報をネガポジ計算
// 単純に各色のビットを反転するのみ。
let new_color = [255-red, 255-green, 255-blue, alpha];
let pixel: Rgba<u8> = Rgba(new_color);
// put_pixel自体は、GenericImage(trait)で定義されて、DynamicImage(enum)で実装されている。
// https://docs.rs/image/0.20.0/src/image/dynimage.rs.html#588
// つまり、img変数の型であるDynamicImgeはちゃんとput_pixel()を持っている。
// なので以下のimg.put_pixel()は普通に動くと思っちゃったけど、実はコンパイルエラーになる。
// Rustではtrait自体を名前空間に置いておかないとその定義(trait)が確認できなくてコンパイルエラーになるらしい。
// つまり、このコードに、
// use image::GenericImage
// を追加しないと以下はコンパイルエラーになってしまう。
// Javaのinterfaceのつもりでtraitを使っていたのでココで混乱してしまった。。。
img.put_pixel(x, y, pixel);
}
};
}
これで完了です。あとはcargo run
すれば
が
のようにちゃんとネガポジ変換されて保存されました。
画像のR/W、各ピクセル情報の取得自体はimageを用いましたが、そのピクセル情報自体を弄る部分は自分で実装できました。 これで画像自体を色々な方法でRustから弄る基礎が分かったので色々試していこうと思います。
公開日:2018/09/28