週末 rust ゴミメモ帳
flang が、最初の威勢のよさとは裏腹になかなか進まないので、WebAssembly 吐き出すのに rust でもいじってみるかと数時間w 文法は並列プログラミングのデータレースの類を避けようとしていると思えば、分からなくもない?
Fortran の bmp 出力プログラムを移植しようとしましたが、バイナリでバイト以外の変数を出す方法がよく分からないです。I/O がそもそも難しいし、構造体の二次元配列が簡単に作れないし等々で一応四角がかけたところで、本殿に入る前に投げ出し。
出力
$ ./bmp write test.bmp: 200 x 200
Fortran (移植元)
module m_bmp use, intrinsic :: iso_fortran_env implicit none type :: t_bmp_file_header sequence integer(int16) :: bfType = transfer('BM', 0_int16) ! BitMap integer(int32) :: bfSize ! file size in bytes integer(int16) :: bfReserved1 = 0 ! always 0 integer(int16) :: bfReserved2 = 0 ! always 0 integer(int32) :: bfOffBits end type t_bmp_file_header ! type :: t_bmp_info_header sequence integer(int32) :: biSize = Z'28' ! size of bmp_info_header ; 40bytes integer(int32) :: biWidth integer(int32) :: biHeight integer(int16) :: biPlanes = 1 ! always 1 integer(int16) :: biBitCount integer(int32) :: biCompression = 0 ! 0:nocompression, 1:8bitRLE, 2:4bitRLE, 3:bitfield integer(int32) :: biSizeImage integer(int32) :: biXPelsPerMeter = 3780 ! 96dpi integer(int32) :: biYPelsPerMeter = 3780 ! 96dpi integer(int32) :: biClrUsed = 0 integer(int32) :: biClrImportant = 0 end type t_bmp_info_header ! type :: t_rgb sequence integer(int8) :: ib, ig, ir end type t_rgb contains subroutine wr(bmp) type(t_rgb), intent(in) :: bmp(:, :) type(t_bmp_file_header) :: bmp_file_header type(t_bmp_info_header) :: bmp_info_header integer :: nx, ny nx = size(bmp, 1) ny = size(bmp, 2) bmp_file_header%bfSize = 14 + 40 + 0 + nx * ny * 3 bmp_file_header%bfOffBits = 14 + 40 bmp_info_header%biWidth = nx bmp_info_header%biHeight = ny bmp_info_header%biBitCount = 24 bmp_info_header%biSizeImage = nx * ny * 3 open(9, file = 'mandel.bmp', form = 'binary', status = 'unknown') write(9) bmp_file_header, bmp_info_header, bmp close(9) end subroutine wr end module m_bmp program test use :: m_bmp implicit none integer, parameter :: nx = 200, ny = 200 type(t_rgb) :: bmp(nx, ny) bmp = t_rgb(255, 255, 0) call wr(bmp) end program test
Rust
まるで分からん。
第三版
structure の配列: stackoverflow.com
use std::fs::File; use std::io::{Write, BufWriter}; //use std::io::prelude::*; 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<()> { let mut b2: [u8;2] = self.bf_type.to_le_bytes(); writer.write_all(&b2)?; let mut b4: [u8;4] = self.bf_size.to_le_bytes(); writer.write_all(&b4)?; b2 = self.bf_reserved1.to_le_bytes(); writer.write_all(&b2)?; b2 = self.bf_reserved2.to_le_bytes(); writer.write_all(&b2)?; b4 = self.bf_off_bits.to_le_bytes(); writer.write_all(&b4)?; Ok(()) } } impl Wr for BmpInfoHeader{ fn wr(&self, writer: &mut BufWriter<File>) -> io::Result<()> { let mut b4: [u8;4] = self.bi_size.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_width.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_height.to_le_bytes(); writer.write_all(&b4)?; let mut b2: [u8;2] = self.bi_planes.to_le_bytes(); writer.write_all(&b2)?; b2 = self.bi_bit_count.to_le_bytes(); writer.write_all(&b2)?; b4 = self.bi_compression.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_size_image.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_x_pels_per_meter.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_y_pels_per_meter.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_clr_used.to_le_bytes(); writer.write_all(&b4)?; b4 = self.bi_clr_important.to_le_bytes(); writer.write_all(&b4)?; Ok(()) } } #[derive(Clone, Copy)] struct Rgb { b: u8, g: u8, r: u8 } struct Bmp { width: usize, height: usize, data: Box<[Rgb]> } 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 p = nx * iy + ix; let a = self.data[p 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 = 200; const NY:usize = 200; let data = [Rgb{r:0, g:255, b:255}; NX * NY]; let bmp = Bmp { width: NX, height: NY, data: Box::new(data) }; let filename = "test.bmp"; bmp.wri(filename) }
第二版
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 } struct Rgb { b: u8, g: u8, r: u8 } impl BmpFileHeader { fn wr(writer: &mut BufWriter<File>, bfile_header: &BmpFileHeader) -> io::Result<()> { let mut b2: [u8;2] = bfile_header.bf_type.to_le_bytes(); writer.write_all(&b2)?; let mut b4: [u8;4] = bfile_header.bf_size.to_le_bytes(); writer.write_all(&b4)?; b2 = bfile_header.bf_reserved1.to_le_bytes(); writer.write_all(&b2)?; b2 = bfile_header.bf_reserved2.to_le_bytes(); writer.write_all(&b2)?; b4 = bfile_header.bf_off_bits.to_le_bytes(); writer.write_all(&b4)?; Ok(()) } } impl BmpInfoHeader{ fn wr(writer: &mut BufWriter<File>, binfo_header: &BmpInfoHeader) -> io::Result<()> { let mut b4: [u8;4] = binfo_header.bi_size.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_width.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_height.to_le_bytes(); writer.write_all(&b4)?; let mut b2: [u8;2] = binfo_header.bi_planes.to_le_bytes(); writer.write_all(&b2)?; b2 = binfo_header.bi_bit_count.to_le_bytes(); writer.write_all(&b2)?; b4 = binfo_header.bi_compression.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_size_image.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_x_pels_per_meter.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_y_pels_per_meter.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_clr_used.to_le_bytes(); writer.write_all(&b4)?; b4 = binfo_header.bi_clr_important.to_le_bytes(); writer.write_all(&b4)?; Ok(()) } } fn main() -> std::io::Result<()> { let nx = 200; let ny = 200; 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 filename = "test.bmp"; let mut writer = BufWriter::new(File::create(filename)?); BmpFileHeader::wr(&mut writer, &bfile_header)?; BmpInfoHeader::wr(&mut writer, &binfo_header)?; let a = Rgb{b: 255, g: 255, r: 0}; for _iy in 0..ny { for _ix in 0..nx { writer.write(&[a.b])?; writer.write(&[a.g])?; writer.write(&[a.r])?; } } println!("write {}: {} x {}", &filename, nx, ny); Ok(()) }
初版
use std::fs::File; use std::io::{Write, BufWriter}; 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 } struct Rgb { b: u8, g: u8, r: u8 } impl BmpFileHeader { fn new(bf_type: i16, bf_size: i32, bf_reserved1: i16, bf_reserved2: i16, bf_off_bits: i32) -> BmpFileHeader{ BmpFileHeader {bf_type: bf_type, bf_size: bf_size, bf_reserved1: bf_reserved1, bf_reserved2: bf_reserved2, bf_off_bits: bf_off_bits} } } impl BmpInfoHeader{ fn new(bi_size: i32, bi_width: i32, bi_height: i32, bi_planes: i16, bi_bit_count: i16, bi_compression: i32, bi_size_image: i32, bi_x_pels_per_meter: i32, bi_y_pels_per_meter: i32, bi_clr_used: i32, bi_clr_important: i32) -> BmpInfoHeader { BmpInfoHeader { bi_size: bi_size, bi_width: bi_width, bi_height: bi_height, bi_planes: bi_planes, bi_bit_count: bi_bit_count, bi_compression: bi_compression, bi_size_image: bi_size_image, bi_x_pels_per_meter: bi_x_pels_per_meter, bi_y_pels_per_meter: bi_y_pels_per_meter, bi_clr_used: bi_clr_used, bi_clr_important: bi_clr_important } } } fn main() -> std::io::Result<()> { let nx = 200; let ny = 200; let bfile_header = BmpFileHeader::new(0x4d42, 14 + 40 + 0 + (3 * nx + (ny % 4)) * ny, 0, 0, 14 + 40); let binfo_header = BmpInfoHeader::new(0x28, nx, ny, 1, 24, 0, (3 * nx + (ny % 4)) * ny, 3780, 3780, 0, 0); let a = Rgb{b: 255, g: 255, r: 0}; println!("write test.bmp: {} x {}", nx, ny); let mut writer = BufWriter::new(File::create("test.bmp")?); let b: [u8;2] = bfile_header.bf_type.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = bfile_header.bf_size.to_le_bytes(); writer.write_all(&b)?; let b: [u8;2] = bfile_header.bf_reserved1.to_le_bytes(); writer.write_all(&b)?; let b: [u8;2] = bfile_header.bf_reserved2.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = bfile_header.bf_off_bits.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_size.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_width.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_height.to_le_bytes(); writer.write_all(&b)?; let b: [u8;2] = binfo_header.bi_planes.to_le_bytes(); writer.write_all(&b)?; let b: [u8;2] = binfo_header.bi_bit_count.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_compression.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_size_image.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_x_pels_per_meter.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_y_pels_per_meter.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_clr_used.to_le_bytes(); writer.write_all(&b)?; let b: [u8;4] = binfo_header.bi_clr_important.to_le_bytes(); writer.write_all(&b)?; for _iy in 0..ny { for _ix in 0..nx { writer.write(&[a.b])?; writer.write(&[a.g])?; writer.write(&[a.r])?; } } Ok(()) }

プログラミング言語Rust 公式ガイド (アスキードワンゴ)
- 作者:Steve Klabnik,Carol Nichols,尾崎 亮太
- 発売日: 2019/07/05
- メディア: Kindle版