ICFP 2007 Contest: https://web.archive.org/web/20090301164728/https://save-endo.cs.uu.nl/

Clean up rna2bmp a bit

Changed files
+128 -99
rna2bmp
+76 -44
rna2bmp/src/bitmap.rs
···
-
// TODO: Better wrapper here
pub const SIZE: usize = 600;
-
pub type Bitmap = [[(u8, u8, u8, u8); SIZE]; SIZE];
-
pub fn new_bitmap() -> Bitmap {
-
[[(0, 0, 0, 0); SIZE]; SIZE]
+
pub type Point = (usize, usize);
+
pub type Pixel = (u8, u8, u8, u8);
+
pub struct Bitmap {
+
data: [[Pixel; SIZE]; SIZE],
}
-
fn output_u8(vec: &mut Vec<u8>, n: u8) {
-
vec.push(n);
-
}
+
impl Bitmap {
+
pub fn new() -> Bitmap {
+
Bitmap {
+
data: [[(0, 0, 0, 0); SIZE]; SIZE],
+
}
+
}
-
fn output_u16(vec: &mut Vec<u8>, n: u16) {
-
vec.push(n as u8);
-
vec.push((n >> 8) as u8);
+
pub fn pixel_mut(&mut self, p: Point) -> &mut Pixel {
+
let (x, y) = p;
+
&mut self.data[x][y]
+
}
+
+
pub fn pixel(&self, p: Point) -> &Pixel {
+
let (x, y) = p;
+
&self.data[x][y]
+
}
+
+
pub fn to_data(&self) -> Vec<u8> {
+
let mut writer = Writer::new();
+
let row_padding = 3 - (3 * SIZE % 4);
+
writer.output_u16(0x4d42); // BM
+
writer.output_u32((0x36 + SIZE * (3 * SIZE + row_padding)) as u32); // Size
+
writer.output_u16(0x0); // Reserved
+
writer.output_u16(0x0); // Reserved
+
writer.output_u32(0x36); // Offset of pixel array
+
writer.output_u32(0x28); // Length of DIB header
+
writer.output_u32(SIZE as u32); // Width
+
writer.output_u32(SIZE as u32); // Height
+
writer.output_u16(0x1); // Color planes
+
writer.output_u16(0x18); // Bits per pixel
+
writer.output_u32(0x0); // No pixel array compression
+
writer.output_u32(0x0); // Horizontal resolution
+
writer.output_u32(0x0); // Vertical resolution
+
writer.output_u32(0x0); // Colors in the palette
+
writer.output_u32(0x0); // All colors are important
+
+
for y in (0..SIZE).rev() {
+
for x in 0..SIZE {
+
let (r, g, b, _) = self.data[x][y];
+
writer.output_u8(b);
+
writer.output_u8(g);
+
writer.output_u8(r);
+
}
+
+
for _ in 0..row_padding {
+
writer.output_u8(0);
+
}
+
}
+
+
return writer.output();
+
}
}
-
fn output_u32(vec: &mut Vec<u8>, n: u32) {
-
vec.push(n as u8);
-
vec.push((n >> 8) as u8);
-
vec.push((n >> 16) as u8);
-
vec.push((n >> 24) as u8);
+
struct Writer {
+
output: Vec<u8>,
}
-
pub fn to_data(bmp: &Bitmap) -> Vec<u8> {
-
let mut ret = Vec::new();
-
let row_padding = 3 - (3 * SIZE % 4);
-
output_u16(&mut ret, 0x4d42); // BM
-
output_u32(&mut ret, (0x36 + SIZE * (3 * SIZE + row_padding)) as u32); // Size
-
output_u16(&mut ret, 0x0); // Reserved
-
output_u16(&mut ret, 0x0); // Reserved
-
output_u32(&mut ret, 0x36); // Offset of pixel array
-
output_u32(&mut ret, 0x28); // Length of DIB header
-
output_u32(&mut ret, SIZE as u32); // Width
-
output_u32(&mut ret, SIZE as u32); // Height
-
output_u16(&mut ret, 0x1); // Color planes
-
output_u16(&mut ret, 0x18); // Bits per pixel
-
output_u32(&mut ret, 0x0); // No pixel array compression
-
output_u32(&mut ret, 0x0); // Horizontal resolution
-
output_u32(&mut ret, 0x0); // Vertical resolution
-
output_u32(&mut ret, 0x0); // Colors in the palette
-
output_u32(&mut ret, 0x0); // All colors are important
+
impl Writer {
+
fn new() -> Writer {
+
Writer { output: Vec::new() }
+
}
-
for y in (0..SIZE).rev() {
-
for x in 0..SIZE {
-
let (r, g, b, _) = bmp[x][y];
-
output_u8(&mut ret, b);
-
output_u8(&mut ret, g);
-
output_u8(&mut ret, r);
-
}
+
fn output_u8(&mut self, n: u8) {
+
self.output.push(n);
+
}
-
for _ in 0..row_padding {
-
output_u8(&mut ret, 0);
-
}
+
fn output_u16(&mut self, n: u16) {
+
self.output.push(n as u8);
+
self.output.push((n >> 8) as u8);
+
}
+
+
fn output_u32(&mut self, n: u32) {
+
self.output.push(n as u8);
+
self.output.push((n >> 8) as u8);
+
self.output.push((n >> 16) as u8);
+
self.output.push((n >> 24) as u8);
}
-
return ret;
+
fn output(self) -> Vec<u8> {
+
self.output
+
}
}
+1 -1
rna2bmp/src/main.rs
···
let mut processor = RnaProcessor::new();
processor.process_rna(rna.lines().collect());
if let Some(bmp) = processor.bitmap() {
-
if fs::write(&args[2], bitmap::to_data(bmp)).is_err() {
+
if fs::write(&args[2], bmp.to_data()).is_err() {
println!("Could not write to {}", args[2]);
}
}
+51 -54
rna2bmp/src/rna_processor.rs
···
use crate::bitmap::Bitmap;
+
use crate::bitmap::Pixel;
+
use crate::bitmap::Point;
use crate::bitmap::SIZE;
-
use crate::bitmap::new_bitmap;
use std::cmp::max;
struct Bucket {
···
pub struct RnaProcessor {
bucket: Bucket,
-
position: (usize, usize),
-
mark: (usize, usize),
-
dir: (usize, usize),
+
position: Point,
+
mark: Point,
+
dir: Point,
bitmaps: Vec<Bitmap>,
}
···
}
}
-
fn current_pixel(&self) -> (u8, u8, u8, u8) {
-
let r = if self.count_rgb == 0 {
-
0
+
fn current_pixel(&self) -> Pixel {
+
let (r, g, b) = if self.count_rgb == 0 {
+
(0, 0, 0)
} else {
-
self.total_r / self.count_rgb
-
};
-
let g = if self.count_rgb == 0 {
-
0
-
} else {
-
self.total_g / self.count_rgb
-
};
-
let b = if self.count_rgb == 0 {
-
0
-
} else {
-
self.total_b / self.count_rgb
+
(
+
self.total_r / self.count_rgb,
+
self.total_g / self.count_rgb,
+
self.total_b / self.count_rgb,
+
)
};
let a = if self.count_a == 0 {
255
···
}
}
-
fn set_pixel(&mut self, x: usize, y: usize) {
+
fn set_pixel(&mut self, p: Point) {
if let Some(b) = self.bitmaps.last_mut() {
-
b[x][y] = self.bucket.current_pixel();
+
*b.pixel_mut(p) = self.bucket.current_pixel();
}
}
···
} else if r == "PCCIFFP" {
self.mark = self.position;
} else if r == "PFFICCP" {
+
// TODO: Can I rework this to reduce casts or locals?
let x0 = self.position.0 as isize;
let y0 = self.position.1 as isize;
let x1 = self.mark.0 as isize;
···
let mut x = x0 * d + (d - c) / 2;
let mut y = x0 * d + (d - c) / 2;
for _ in 0..d {
-
self.set_pixel((x / d) as usize, (y / d) as usize);
+
self.set_pixel(((x / d) as usize, (y / d) as usize));
x += dx;
y += dy;
}
-
self.set_pixel(x1 as usize, y1 as usize);
+
self.set_pixel((x1 as usize, y1 as usize));
} else if r == "PIIPIIP" {
-
let (x, y) = self.position;
if let Some(b) = self.bitmaps.last_mut() {
-
let old = b[x][y];
+
let old = *b.pixel(self.position);
let new = self.bucket.current_pixel();
let mut to_fill = Vec::new();
to_fill.push(self.position);
-
while let Some((x, y)) = to_fill.pop() {
-
if b[x][y] == old {
-
b[x][y] = new;
+
while let Some(p) = to_fill.pop() {
+
if *b.pixel(p) == old {
+
*b.pixel_mut(p) = new;
+
+
let (x, y) = p;
if x > 0 {
to_fill.push((x - 1, y));
}
···
}
} else if r == "PCCPFFP" {
if self.bitmaps.len() < 10 {
-
self.bitmaps.push(new_bitmap());
+
self.bitmaps.push(Bitmap::new());
}
} else if r == "PFFPCCP" {
-
if self.bitmaps.len() >= 2 {
-
let bmp0 = self.bitmaps[self.bitmaps.len() - 1];
-
let mut bmp1 = self.bitmaps[self.bitmaps.len() - 2];
-
for x in 0..SIZE {
-
for y in 0..SIZE {
-
let (r0, b0, g0, a0) = bmp0[x][y];
-
let (r1, b1, g1, a1) = bmp1[x][y];
-
let r = r0 + (((r1 as usize) * (255 - a0 as usize) / 255) as u8);
-
let g = g0 + (((g1 as usize) * (255 - a0 as usize) / 255) as u8);
-
let b = b0 + (((b1 as usize) * (255 - a0 as usize) / 255) as u8);
-
let a = a0 + (((a1 as usize) * (255 - a0 as usize) / 255) as u8);
-
bmp1[x][y] = (r, g, b, a);
+
if let Some(bmp0) = self.bitmaps.pop() {
+
if let Some(mut bmp1) = self.bitmaps.pop() {
+
for x in 0..SIZE {
+
for y in 0..SIZE {
+
let (r0, b0, g0, a0) = *bmp0.pixel((x, y));
+
let (r1, b1, g1, a1) = *bmp1.pixel((x, y));
+
let r = r0 + ((r1 as usize) * (255 - a0 as usize) / 255) as u8;
+
let g = g0 + ((g1 as usize) * (255 - a0 as usize) / 255) as u8;
+
let b = b0 + ((b1 as usize) * (255 - a0 as usize) / 255) as u8;
+
let a = a0 + ((a1 as usize) * (255 - a0 as usize) / 255) as u8;
+
*bmp1.pixel_mut((x, y)) = (r, g, b, a);
+
}
}
+
self.bitmaps.push(bmp1);
}
-
self.bitmaps.pop();
}
} else if r == "PFFICCF" {
-
if self.bitmaps.len() >= 2 {
-
let bmp0 = self.bitmaps[self.bitmaps.len() - 1];
-
let mut bmp1 = self.bitmaps[self.bitmaps.len() - 2];
-
for x in 0..SIZE {
-
for y in 0..SIZE {
-
let (_, _, _, a0) = bmp0[x][y];
-
let (r1, b1, g1, a1) = bmp1[x][y];
-
let r = ((r1 as usize) * (a0 as usize) / 255) as u8;
-
let g = ((g1 as usize) * (a0 as usize) / 255) as u8;
-
let b = ((b1 as usize) * (a0 as usize) / 255) as u8;
-
let a = ((a1 as usize) * (a0 as usize) / 255) as u8;
-
bmp1[x][y] = (r, g, b, a);
+
if let Some(bmp0) = self.bitmaps.pop() {
+
if let Some(mut bmp1) = self.bitmaps.pop() {
+
for x in 0..SIZE {
+
for y in 0..SIZE {
+
let (_, _, _, a0) = *bmp0.pixel((x, y));
+
let (r1, b1, g1, a1) = *bmp1.pixel((x, y));
+
let r = ((r1 as usize) * (a0 as usize) / 255) as u8;
+
let g = ((g1 as usize) * (a0 as usize) / 255) as u8;
+
let b = ((b1 as usize) * (a0 as usize) / 255) as u8;
+
let a = ((a1 as usize) * (a0 as usize) / 255) as u8;
+
*bmp1.pixel_mut((x, y)) = (r, g, b, a);
+
}
}
+
self.bitmaps.push(bmp1);
}
-
self.bitmaps.pop();
}
}
}