Rust で BMP
阿部さんを描くまで拡張したが、未だ引数寿命の指定を求められていないので、まだ入り口にも達しない。
関数型言語は一般に型に神経質で混合演算を許さないが、Rust もその流れを汲むので FORTRAN66 以前に戻ったような趣き。王莽が周礼によって政治を行おうとするがごときか。子曰、周監於二代、郁郁乎文哉、吾從周。(八佾篇 第十四章)
郁郁乎といえば阿素湖素子。
- 作者:吾妻 ひでお
- 発売日: 2000/01/01
- メディア: 文庫
- 作者:吾妻 ひでお
- 発売日: 2000/03/01
- メディア: 文庫
- 作者:吾妻 ひでお
- 発売日: 2000/05/01
- メディア: 文庫
一般論として、rust 的な変数ロックの掛け方だと、task parallel には向いているが、Fortran でやるような超大きい配列を手分けして計算する data parallel には向いていないような感じを受ける。まぁ何とかなるだろうが、気持ち自然にはいかない気がする(よく考えていないw)。
追記:R3-4-30 配列を排他的な領域のスライスに分けることで、同時アクセス可能だそうです。ヘリはどうするのか、なんかあるんでしょうね。
実行結果
プログラム
use std::fs::File; use std::io::{Write, BufWriter}; use std::io; struct BmpFileHeader { bf_type: i16, //'BM' bf_size: i32, // file size in bytes bf_reserved1: i16, bf_reserved2: i16, bf_off_bits: i32 } struct BmpInfoHeader{ bi_size: i32, // Z'28' ! size of bmp_info_header ; 40bytes bi_width: i32, bi_height: i32, bi_planes: i16, // = 1 ! always 1 bi_bit_count: i16, bi_compression: i32, // = 0 ! 0:nocompression, 1:8bitRLE, 2:4bitRLE, 3:bitfield bi_size_image: i32, bi_x_pels_per_meter: i32, // = 3780 ! 96dpi bi_y_pels_per_meter: i32, // = 3780 ! 96dpi bi_clr_used: i32, // = 0 bi_clr_important: i32 // = 0 } trait Wr { fn wr(&self, writer: &mut BufWriter<File>) -> io::Result<()>; } impl Wr for BmpFileHeader { fn wr(&self, writer: &mut BufWriter<File>) -> io::Result<()> { writer.write_all(&self.bf_type.to_le_bytes() )?; writer.write_all(&self.bf_size.to_le_bytes() )?; writer.write_all(&self.bf_reserved1.to_le_bytes() )?; writer.write_all(&self.bf_reserved2.to_le_bytes() )?; writer.write_all(&self.bf_off_bits.to_le_bytes() )?; Ok(()) } } impl Wr for BmpInfoHeader{ fn wr(&self, writer: &mut BufWriter<File>) -> io::Result<()> { writer.write_all(&self.bi_size.to_le_bytes() )?; writer.write_all(&self.bi_width.to_le_bytes() )?; writer.write_all(&self.bi_height.to_le_bytes() )?; writer.write_all(&self.bi_planes.to_le_bytes() )?; writer.write_all(&self.bi_bit_count.to_le_bytes() )?; writer.write_all(&self.bi_compression.to_le_bytes() )?; writer.write_all(&self.bi_size_image.to_le_bytes() )?; writer.write_all(&self.bi_x_pels_per_meter.to_le_bytes() )?; writer.write_all(&self.bi_y_pels_per_meter.to_le_bytes() )?; writer.write_all(&self.bi_clr_used.to_le_bytes() )?; writer.write_all(&self.bi_clr_important.to_le_bytes() )?; Ok(()) } } #[derive(Clone, Copy)] struct Rgb { b: u8, g: u8, r: u8 } struct Bmp { width: usize, height: usize, data: Box<[Rgb]> } impl Bmp { fn point(&mut self, ix: usize, iy: usize, color: Rgb) { let nx = self.width; self.data[nx * iy + ix] = color; } fn line0(&mut self, ix0:i32, iy0:i32, ix1:i32, iy1:i32) { let nx = ix1 - ix0; let ny = iy1 - iy0; if nx.abs() < ny.abs() { let d = nx as f32 / ny as f32; for i in 0..ny.abs() { let x = ix0 as f32 + i as f32 * d * ny.signum() as f32; let ix = x.round() as usize; let iy = (iy0 + i * ny.signum()) as usize; self.point(ix, iy, Rgb{r:0, g:0, b:0}) } } else { let d = ny as f32 / nx as f32; for i in 0..nx.abs() { let y = iy0 as f32 + i as f32 * d * nx.signum() as f32; let iy = y.round() as usize; let ix = (ix0 + i * nx.signum()) as usize; self.point(ix, iy, Rgb{r:0, g:0, b:0}) } } } fn line(&mut self, x: f32, y: f32, ipen: i32) { static mut IX0: i32 = 0; static mut IY0: i32 = 0; const XN: f32 = 250.0; const YN: f32 = 180.0; const F: f32 = 4.0; let ix = (F * x + XN) as i32; let iy = (F * y + YN) as i32; unsafe { if ipen == 1 { let jx = IX0; let jy = IY0; self.line0(jx, jy, ix, iy); } IX0 = ix; IY0 = iy; } } } trait Wri { fn wri(&self, filename: &str) -> io::Result<()>; } impl Wri for Bmp { fn wri(&self, filename: &str) -> io::Result<()> { let nx = self.width as i32; let ny = self.height as i32; let bfile_header = BmpFileHeader {bf_type: 0x4d42, bf_size: 14 + 40 + 0 + (3 * nx + (ny % 4)) * ny, bf_reserved1: 0, bf_reserved2: 0, bf_off_bits: 14 + 40}; let binfo_header = BmpInfoHeader {bi_size: 0x28, bi_width: nx, bi_height: ny, bi_planes: 1, bi_bit_count: 24, bi_compression: 0, bi_size_image: (3 * nx + (ny % 4)) * ny, bi_x_pels_per_meter: 3780, bi_y_pels_per_meter: 3780, bi_clr_used: 0, bi_clr_important: 0}; let mut writer = BufWriter::new(File::create(filename)?); bfile_header.wr(&mut writer)?; binfo_header.wr(&mut writer)?; for iy in 0..ny { for ix in 0..nx { let a = self.data[(nx * iy + ix) as usize]; writer.write(&[a.b])?; writer.write(&[a.g])?; writer.write(&[a.r])?; } } println!("write {}: {} x {}", &filename, nx, ny); Ok(()) } } fn main() -> std::io::Result<()> { const NX:usize = 500; const NY:usize = 600; let data = [Rgb{r:255, g:255, b:255}; NX * NY]; let mut bmp = Bmp { width: NX, height: NY, data: Box::new(data) }; // chin chin bmp.line( 0.0, 11.0, 0); bmp.line( 0.0, 8.0, 1); bmp.line( -8.0, -26.5, 0); bmp.line(-11.0, -24.0, 1); bmp.line( 8.0, -26.5, 0); bmp.line( 11.0, -24.0, 1); bmp.line( 5.5, -26.0, 0); bmp.line( 2.0, -36.0, 1); bmp.line( -5.5, -26.0, 0); bmp.line( -2.0, -36.0, 1); bmp.line( 20.0, -18.0, 0); bmp.line( 8.5, -19.0, 1); bmp.line( 4.0, -21.5, 1); bmp.line( 0.0, -23.0, 1); bmp.line( -4.0, -21.5, 1); bmp.line( -8.5, -19.0, 1); bmp.line(-20.0, -18.0, 1); bmp.line( 12.0, -16.0, 0); bmp.line( 22.0, 14.0, 1); bmp.line(-12.0, -16.0, 0); bmp.line(-22.0, 14.0, 1); bmp.line( 53.0, -9.0, 0); bmp.line( 28.5, 1.0, 1); bmp.line( 28.5, -14.0, 0); bmp.line( 28.5, 25.0, 1); bmp.line( 28.5, 33.0, 0); bmp.line( 28.5, 76.0, 1); bmp.line( -2.5, 76.0, 1); bmp.line( -2.5, 72.0, 1); bmp.line( -0.5, 68.0, 1); bmp.line( 1.0, 66.0, 1); bmp.line( -1.5, 67.0, 1); bmp.line( -4.0, 72.0, 1); bmp.line( -4.0, 76.0, 1); bmp.line(-28.5, 76.0, 1); bmp.line(-28.5, 33.0, 1); bmp.line(-28.5, 25.0, 0); bmp.line(-28.5, -14.0, 1); bmp.line(-53.0, -9.0, 0); bmp.line(-28.5, 1.0, 1); bmp.line( 0.0, 0.0, 0); bmp.line( 6.5, 0.0, 1); bmp.line( 10.0, 3.0, 1); bmp.line( 15.0, 7.0, 1); bmp.line( 22.0, 14.0, 1); bmp.line( 28.5, 25.0, 1); bmp.line( 31.0, 26.0, 1); bmp.line( 35.0, 34.0, 1); bmp.line( 38.0, 44.0, 1); bmp.line( 38.0, 53.0, 1); bmp.line( 36.0, 55.0, 1); bmp.line( 32.0, 55.0, 1); bmp.line( 28.5, 51.0, 1); bmp.line( 0.0, 0.0, 0); bmp.line( -6.5, 0.0, 1); bmp.line(-10.0, 3.0, 1); bmp.line(-15.0, 7.0, 1); bmp.line(-22.0, 14.0, 1); bmp.line(-28.5, 25.0, 1); bmp.line(-31.0, 26.0, 1); bmp.line(-35.0, 34.0, 1); bmp.line(-38.0, 44.0, 1); bmp.line(-38.0, 53.0, 1); bmp.line(-36.0, 55.0, 1); bmp.line(-32.0, 55.0, 1); bmp.line(-28.5, 51.0, 1); bmp.line( 34.0, 55.0, 0); bmp.line( 34.0, 76.0, 1); bmp.line( 31.0, 82.0, 1); bmp.line( 26.0, 87.0, 1); bmp.line( 21.0, 91.0, 1); bmp.line( 15.0, 95.0, 1); bmp.line( 0.0, 95.0, 1); bmp.line(-34.0, 55.0, 0); bmp.line(-34.0, 76.0, 1); bmp.line(-31.0, 82.0, 1); bmp.line(-26.0, 87.0, 1); bmp.line(-21.0, 91.0, 1); bmp.line(-15.0, 95.0, 1); bmp.line( 0.0, 95.0, 1); // nose bmp.line( -5.0, 41.0, 0); bmp.line( -4.0, 40.0, 1); bmp.line( 0.0, 40.0, 1); bmp.line( 2.0, 42.0, 1); bmp.line( 3.0, 42.0, 1); bmp.line( 5.5, 37.0, 1); bmp.line( 5.0, 37.0, 1); bmp.line( 4.0, 38.5, 1); bmp.line( 0.5, 38.5, 1); bmp.line( 0.0, 37.0, 1); bmp.line( -2.0, 37.0, 1); bmp.line( -3.0, 38.5, 1); bmp.line( -7.0, 38.5, 1); bmp.line( -8.0, 37.0, 1); bmp.line( -8.5, 40.0, 1); bmp.line( -4.0, 45.0, 1); bmp.line( -4.0, 54.0, 1); bmp.line( -5.0, 55.0, 1); bmp.line( -6.0, 53.0, 0); bmp.line( -5.0, 53.0, 1); bmp.line( -5.0, 47.0, 1); bmp.line( -7.5, 46.0, 1); bmp.line( -6.0, 53.0, 1); // left eye bmp.line(-24.0, 55.0, 0); bmp.line(-22.0, 53.0, 1); bmp.line(-17.0, 54.5, 1); bmp.line( -8.0, 55.0, 1); bmp.line( -7.0, 55.5, 1); bmp.line( -8.5, 56.5, 1); bmp.line(-24.0, 55.0, 1); bmp.line( -8.0, 54.5, 0); bmp.line(-12.0, 52.5, 1); bmp.line(-23.0, 56.0, 0); bmp.line(-21.5, 57.0, 1); bmp.line(-10.0, 58.0, 1); bmp.line( -9.0, 57.0, 1); // left eyebrow bmp.line(-27.5, 56.5, 0); bmp.line(-24.0, 59.0, 1); bmp.line(-11.0, 59.5, 1); bmp.line( -7.0, 61.0, 1); bmp.line( -4.0, 65.0, 1); bmp.line( -9.0, 63.0, 1); bmp.line(-25.0, 62.0, 1); bmp.line(-27.5, 56.5, 1); // right eyebrow bmp.line( 27.5, 56.5, 0); bmp.line( 24.0, 59.0, 1); bmp.line( 11.0, 59.5, 1); bmp.line( 7.0, 61.0, 1); bmp.line( 4.0, 65.0, 1); bmp.line( 9.0, 63.0, 1); bmp.line( 25.0, 62.0, 1); bmp.line( 27.5, 56.5, 1); // right eye bmp.line( 19.0, 53.0, 0); bmp.line( 23.0, 55.0, 1); bmp.line( 16.0, 55.0, 1); bmp.line( 9.0, 56.0, 1); bmp.line( 9.5, 55.0, 1); bmp.line( 19.0, 53.0, 1); bmp.line( 9.0, 58.0, 0); bmp.line( 12.0, 58.0, 1); bmp.line( 19.0, 56.0, 1); bmp.line( 21.5, 56.0, 1); bmp.line( 0.0, 29.0, 0); bmp.line( 5.0, 29.0, 1); bmp.line( 11.0, 27.0, 1); bmp.line( 6.0, 32.0, 1); bmp.line( 0.0, 30.0, 1); bmp.line( -6.0, 32.0, 1); bmp.line(-11.0, 27.0, 1); bmp.line( -5.0, 29.0, 1); bmp.line( 0.0, 29.0, 1); bmp.line(-6.5, 21.5, 0); bmp.line(-3.5, 20.0, 1); bmp.line( 3.5, 20.0, 1); bmp.line( 6.5, 21.5, 1); bmp.line(-5.0, 21.0, 0); bmp.line( 5.0, 21.0, 1); let filename = "test.bmp"; bmp.wri(filename) }