diff --git a/src/marathon/shp.rs b/src/marathon/shp.rs index b7430fa..bc01809 100644 --- a/src/marathon/shp.rs +++ b/src/marathon/shp.rs @@ -20,8 +20,8 @@ fn color(b: &[u8]) -> ResultS<(usize, ColorShp)> } fn clut_collection(b: &[u8], - clr_num: usize, - clu_num: usize) + clu_num: usize, + clr_num: usize) -> ResultS>> { let mut tables = vec![vec![ColorShp::Translucent; clr_num]; clu_num]; @@ -45,6 +45,70 @@ fn clut_collection(b: &[u8], Ok(tables) } +fn bitmap<'a>(b: &[u8], clut: &'a [ColorShp]) -> ResultS> +{ + let width = c_u16b(b, 0)? as usize; + let height = c_u16b(b, 2)? as usize; + let pitch = c_u16b(b, 4)? as usize; + let flags = c_u16b(b, 6)?; + let bpp = c_u16b(b, 8)?; + let flags = ok!(BmpFlags::from_bits(flags), "bad BmpFlags")?; + let alpha = flags.contains(BmpFlags::Transparent); + + if bpp != 8 { + bail!("invalid bit depth (should always be 8)"); + } + + if flags.contains(BmpFlags::ColumnMajor) { + bail!("column major format not supported"); + } + + if pitch == u16::max_value() as usize { + bail!("compressed shape bitmap not supported"); + } + + let mut im = ImageShp::new(width, height, clut, alpha); + // let mut p = 30 + if flags.contains(BmpFlags::ColumnMajor) { + // 4 * width + // } else { + // 4 * height + // }; + let mut p = 30 + 4 * height; + + for _ in 0..height { + for _ in 0..width { + im.cr.push(b[p]); + p += 1; + } + } + + Ok(im) +} + +fn bitmap_collection<'a>(b: &[u8], + bmp_ofs: usize, + bmp_num: usize, + clut: &'a [ColorShp]) + -> ResultS>> +{ + let mut bitmaps = Vec::with_capacity(bmp_num); + let mut p = bmp_ofs; + + for _ in 0..bmp_num { + let ofs = c_u32b(b, p)? as usize; + let bmp = bitmap(c_data(b, ofs..)?, clut)?; + + use std::{fs, io}; + let out = fs::File::create(&format!("out/shape{}.ppm", ofs))?; + let mut out = io::BufWriter::new(out); + write_ppm(&mut out, &bmp)?; + + p += 4; + } + + Ok(bitmaps) +} + /* fn frame(b: &[u8]) -> ResultS<()> { @@ -148,7 +212,8 @@ fn collection(b: &[u8]) -> ResultS } */ - let tables = clut_collection(&b[clu_ofs..], clr_num, clu_num)?; + let tables = clut_collection(&b[clu_ofs..], clu_num, clr_num)?; + let bitmaps = bitmap_collection(b, bmp_ofs, bmp_num, &tables[0])?; Ok(Collection{clr_num, tables, bitmaps: Vec::new()}) } @@ -182,6 +247,14 @@ pub fn testfn_replaceme(b: &[u8]) -> ResultS<()> Ok(()) } +impl ImageShp<'_> +{ + fn new(w: usize, h: usize, clut: &[ColorShp], alpha: bool) -> ImageShp + { + ImageShp{w, h, clut, alpha, cr: Vec::with_capacity(w * h)} + } +} + impl Image for ImageShp<'_> { type Output = ColorShp; @@ -189,46 +262,51 @@ impl Image for ImageShp<'_> fn w(&self) -> usize {self.w} fn h(&self) -> usize {self.h} - fn cr_at(&self, x: usize, y: usize) -> Option<&ColorShp> + fn cr_at(&self, x: usize, y: usize) -> &Self::Output { - self.clut.get(*self.cr.get(x + y * self.w)? as usize) + static TRANSLUCENT_COLOR: ColorShp = ColorShp::Translucent; + + let cr = self.cr[x + y * self.w] as usize; + + if self.alpha && cr == 0 { + &TRANSLUCENT_COLOR + } else { + self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR) + } } } impl Color for ColorShp { - type Comp = u16; - const MAX: u32 = u16::max_value() as u32; - fn r(&self) -> u16 { - match self { - &ColorShp::Translucent => 0, - &ColorShp::Opaque{r, ..} => r, + match *self { + ColorShp::Translucent => 0, + ColorShp::Opaque{r, ..} => r, } } fn g(&self) -> u16 { - match self { - &ColorShp::Translucent => 0, - &ColorShp::Opaque{g, ..} => g, + match *self { + ColorShp::Translucent => 0, + ColorShp::Opaque{g, ..} => g, } } fn b(&self) -> u16 { - match self { - &ColorShp::Translucent => 0, - &ColorShp::Opaque{b, ..} => b, + match *self { + ColorShp::Translucent => 0, + ColorShp::Opaque{b, ..} => b, } } fn a(&self) -> u16 { - match self { - &ColorShp::Translucent => 0, - &ColorShp::Opaque{..} => 255, + match *self { + ColorShp::Translucent => 0, + ColorShp::Opaque{..} => u16::max_value(), } } } @@ -249,10 +327,11 @@ enum ColorShp #[derive(Debug)] struct ImageShp<'a> { - w: usize, - h: usize, - cr: Vec, - clut: &'a [ColorShp], + w: usize, + h: usize, + cr: Vec, + alpha: bool, + clut: &'a [ColorShp], } #[derive(Debug)] @@ -263,6 +342,14 @@ struct Collection<'a> bitmaps: Vec>, } +bitflags! { + pub struct BmpFlags: u16 + { + const ColumnMajor = 0x80_00; + const Transparent = 0x40_00; + } +} + bitflags! { pub struct FrameFlags: u16 {