completed bitmap loader
parent
b41525006e
commit
8c6543030c
11
src/main.rs
11
src/main.rs
|
@ -71,7 +71,16 @@ fn process_wad(b: &[u8]) -> ResultS<()>
|
|||
|
||||
fn process_shp(b: &[u8]) -> ResultS<()>
|
||||
{
|
||||
shp::testfn_replaceme(b)
|
||||
for (i, cl) in shp::testfn_replaceme(b)?.iter().enumerate() {
|
||||
if let Some(cl) = &cl.0 {
|
||||
shp::testfn_dump_bitmaps(cl, i)?;
|
||||
}
|
||||
if let Some(cl) = &cl.1 {
|
||||
shp::testfn_dump_bitmaps(cl, i + 100)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> ResultS<()>
|
||||
|
|
|
@ -19,93 +19,94 @@ fn color(b: &[u8]) -> ResultS<(usize, ColorShp)>
|
|||
Ok((i, ColorShp::Opaque{r, g, b, l}))
|
||||
}
|
||||
|
||||
fn clut_collection(b: &[u8],
|
||||
clu_num: usize,
|
||||
clr_num: usize)
|
||||
-> ResultS<Vec<Vec<ColorShp>>>
|
||||
fn tab_coll(b: &[u8],
|
||||
tab_num: usize,
|
||||
clr_num: usize)
|
||||
-> ResultS<Vec<Vec<ColorShp>>>
|
||||
{
|
||||
let mut tables = vec![vec![ColorShp::Translucent; clr_num]; clu_num];
|
||||
let mut p = 0;
|
||||
let mut tabs = vec![vec![ColorShp::Translucent; clr_num]; tab_num];
|
||||
let mut p = 0;
|
||||
|
||||
for i in 0..clu_num {
|
||||
let clut = &mut tables[i];
|
||||
for i in 0..tab_num {
|
||||
let clut = &mut tabs[i];
|
||||
|
||||
for j in 0..clr_num {
|
||||
for _ in 0..clr_num {
|
||||
let (i, cr) = color(c_data(b, p..)?)?;
|
||||
|
||||
if i >= clr_num {
|
||||
bail!("invalid index");
|
||||
}
|
||||
|
||||
clut[i] = cr;
|
||||
*ok!(clut.get_mut(i), "invalid index")? = cr;
|
||||
p += 8;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(tables)
|
||||
Ok(tabs)
|
||||
}
|
||||
|
||||
fn bitmap<'a>(b: &[u8], clut: &'a [ColorShp]) -> ResultS<ImageShp<'a>>
|
||||
fn bitmap(b: &[u8]) -> ResultS<Bitmap>
|
||||
{
|
||||
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 compr = c_u16b(b, 4)? == u16::max_value();
|
||||
let flags = c_u16b(b, 6)?;
|
||||
let depth = c_u16b(b, 8)?;
|
||||
let flags = ok!(BmpFlags::from_bits(flags), "bad BmpFlags")?;
|
||||
let alpha = flags.contains(BmpFlags::Transparent);
|
||||
let cmajr = flags.contains(BmpFlags::ColumnMajor);
|
||||
|
||||
if depth != 8 {
|
||||
bail!("invalid bit depth (should always be 8)");
|
||||
}
|
||||
|
||||
if flags.contains(BmpFlags::ColumnMajor) {
|
||||
bail!("column major format not supported");
|
||||
}
|
||||
let mut bmp = Bitmap::new(width, height, alpha, cmajr);
|
||||
let mut p = 30 + if cmajr {4 * width} else {4 * height};
|
||||
|
||||
if pitch == u16::max_value() as usize {
|
||||
bail!("compressed shape bitmap not supported");
|
||||
}
|
||||
let scanlines = if cmajr {width} else {height};
|
||||
let pitch = if cmajr {height} else {width};
|
||||
|
||||
let mut im = ImageShp::new(width, height, clut, alpha);
|
||||
let mut p = 30 + if flags.contains(BmpFlags::ColumnMajor) {
|
||||
4 * width
|
||||
} else {
|
||||
4 * height
|
||||
};
|
||||
if compr {
|
||||
// compressed scanlines (transparency RLE)
|
||||
for _ in 0..scanlines {
|
||||
let fst = c_u16b(b, p)? as usize;
|
||||
let lst = c_u16b(b, p + 2)? as usize;
|
||||
|
||||
for _ in 0..height {
|
||||
for _ in 0..width {
|
||||
im.cr.push(b[p]);
|
||||
p += 1;
|
||||
if lst < fst || fst > pitch || lst > pitch {
|
||||
bail!("invalid compressed scanline");
|
||||
}
|
||||
|
||||
p += 4;
|
||||
|
||||
for _ in 0..fst {
|
||||
bmp.cr.push(0);
|
||||
}
|
||||
|
||||
let end = lst - fst;
|
||||
bmp.cr.extend_from_slice(c_data(b, p..p + end)?);
|
||||
|
||||
for _ in lst..pitch {
|
||||
bmp.cr.push(0);
|
||||
}
|
||||
|
||||
p += end;
|
||||
}
|
||||
} else {
|
||||
// simple copy
|
||||
bmp.cr.extend_from_slice(c_data(b, p..p + width * height)?);
|
||||
}
|
||||
|
||||
Ok(im)
|
||||
Ok(bmp)
|
||||
}
|
||||
|
||||
fn bitmap_collection<'a>(b: &[u8],
|
||||
bmp_ofs: usize,
|
||||
bmp_num: usize,
|
||||
clut: &'a [ColorShp])
|
||||
-> ResultS<Vec<ImageShp<'a>>>
|
||||
fn bmp_coll(b: &[u8], bmp_ofs: usize, bmp_num: usize) -> ResultS<Vec<Bitmap>>
|
||||
{
|
||||
let mut bitmaps = Vec::with_capacity(bmp_num);
|
||||
let mut p = bmp_ofs;
|
||||
let mut bmps = 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{}.tga", ofs))?;
|
||||
let mut out = io::BufWriter::new(out);
|
||||
write_tga(&mut out, &bmp)?;
|
||||
|
||||
bmps.push(bitmap(c_data(b, ofs..)?)?);
|
||||
p += 4;
|
||||
}
|
||||
|
||||
Ok(bitmaps)
|
||||
Ok(bmps)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -183,8 +184,8 @@ fn collection(b: &[u8]) -> ResultS<Collection>
|
|||
let cl_type = c_u16b(b, 2)?;
|
||||
// flags = c_u16b(b, 4)?;
|
||||
let clr_num = c_u16b(b, 6)? as usize;
|
||||
let clu_num = c_u16b(b, 8)? as usize;
|
||||
let clu_ofs = c_u32b(b, 10)? as usize;
|
||||
let tab_num = c_u16b(b, 8)? as usize;
|
||||
let tab_ofs = c_u32b(b, 10)? as usize;
|
||||
let seq_num = c_u16b(b, 14)? as usize;
|
||||
let seq_ofs = c_u32b(b, 16)? as usize;
|
||||
let frm_num = c_u16b(b, 20)? as usize;
|
||||
|
@ -192,65 +193,73 @@ fn collection(b: &[u8]) -> ResultS<Collection>
|
|||
let bmp_num = c_u16b(b, 26)? as usize;
|
||||
let bmp_ofs = c_u32b(b, 28)? as usize;
|
||||
// xform = c_i16b(b, 30)?;
|
||||
let size = c_u32b(b, 32)? as usize;
|
||||
// size = c_u32b(b, 32)? as usize;
|
||||
let cl_type = CollectionType::from_repr(cl_type)?;
|
||||
|
||||
if version != 3 {
|
||||
bail!("invalid collection version number");
|
||||
bail!("invalid collection definition");
|
||||
}
|
||||
|
||||
/*
|
||||
for i in 0..frm_num {
|
||||
let p = c_u32b(b, frm_ofs + 4 * i)? as usize;
|
||||
frame(c_data(b, p..)?)?;
|
||||
}
|
||||
let tabs = tab_coll(c_data(b, tab_ofs..)?, tab_num, clr_num)?;
|
||||
let bmps = bmp_coll(b, bmp_ofs, bmp_num)?;
|
||||
// frms = frm_coll(c_data(b, frm_ofs..)?, frm_num)?;
|
||||
// seqs = seq_coll(c_data(b, seq_ofs..)?, seq_num)?;
|
||||
|
||||
for i in 0..seq_num {
|
||||
let p = c_u32b(b, seq_ofs + 4 * i)? as usize;
|
||||
sequence(c_data(b, p..)?)?;
|
||||
}
|
||||
*/
|
||||
|
||||
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()})
|
||||
Ok(Collection{tabs, bmps /*, frms, seqs*/})
|
||||
}
|
||||
|
||||
pub fn testfn_replaceme(b: &[u8]) -> ResultS<()>
|
||||
pub fn testfn_dump_bitmaps(c: &Collection, i: usize) -> ResultS<()>
|
||||
{
|
||||
for i in 0..32 {
|
||||
let p = 32 * i;
|
||||
// status = c_u16b(b, p + 0)?;
|
||||
// flags = c_u16b(b, p + 2)?;
|
||||
let offset_lo = c_u32b(b, p + 4)? as usize;
|
||||
let length_lo = c_u32b(b, p + 8)? as usize;
|
||||
let offset_hi = c_u32b(b, p + 12)? as usize;
|
||||
let length_hi = c_u32b(b, p + 16)? as usize;
|
||||
use std::{fs, io};
|
||||
|
||||
let collections =
|
||||
(if offset_lo != u32::max_value() as usize {
|
||||
Some(collection(c_data(b, offset_lo..offset_lo + length_lo)?)?)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
if offset_hi != u32::max_value() as usize {
|
||||
Some(collection(c_data(b, offset_hi..offset_hi + length_hi)?)?)
|
||||
} else {
|
||||
None
|
||||
});
|
||||
|
||||
dbg!(collections);
|
||||
// TODO: output with all CLUTs too
|
||||
for (j, bmp) in c.bmps.iter().enumerate() {
|
||||
let out = fs::File::create(&format!("out/shape{}_{}.tga", i, j))?;
|
||||
let mut out = io::BufWriter::new(out);
|
||||
write_tga(&mut out, &ImageShp{bmp: bmp.clone(), clut: &c.tabs[0]})?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl ImageShp<'_>
|
||||
pub fn testfn_replaceme(b: &[u8]) -> ResultS<Vec<CollectionDef>>
|
||||
{
|
||||
fn new(w: usize, h: usize, clut: &[ColorShp], alpha: bool) -> ImageShp
|
||||
let mut cl = Vec::with_capacity(32);
|
||||
let mut p = 0;
|
||||
|
||||
for _ in 0..32 {
|
||||
// status = c_u16b(b, p + 0)?;
|
||||
// flags = c_u16b(b, p + 2)?;
|
||||
let lo_ofs = c_u32b(b, p + 4)? as usize;
|
||||
let lo_len = c_u32b(b, p + 8)? as usize;
|
||||
let hi_ofs = c_u32b(b, p + 12)? as usize;
|
||||
let hi_len = c_u32b(b, p + 16)? as usize;
|
||||
|
||||
let c_lo = if lo_ofs != u32::max_value() as usize {
|
||||
Some(collection(c_data(b, lo_ofs..lo_ofs + lo_len)?)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let c_hi = if hi_ofs != u32::max_value() as usize {
|
||||
Some(collection(c_data(b, hi_ofs..hi_ofs + hi_len)?)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
cl.push((c_lo, c_hi));
|
||||
|
||||
p += 32;
|
||||
}
|
||||
|
||||
Ok(cl)
|
||||
}
|
||||
|
||||
impl Bitmap
|
||||
{
|
||||
fn new(w: usize, h: usize, alpha: bool, cmajr: bool) -> Self
|
||||
{
|
||||
ImageShp{w, h, clut, alpha, cr: Vec::with_capacity(w * h)}
|
||||
Self{w, h, alpha, cmajr, cr: Vec::with_capacity(w * h)}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,16 +267,20 @@ impl Image for ImageShp<'_>
|
|||
{
|
||||
type Output = ColorShp;
|
||||
|
||||
fn w(&self) -> usize {self.w}
|
||||
fn h(&self) -> usize {self.h}
|
||||
fn w(&self) -> usize {self.bmp.w}
|
||||
fn h(&self) -> usize {self.bmp.h}
|
||||
|
||||
fn index(&self, x: usize, y: usize) -> &Self::Output
|
||||
{
|
||||
static TRANSLUCENT_COLOR: ColorShp = ColorShp::Translucent;
|
||||
|
||||
let cr = self.cr[x + y * self.w] as usize;
|
||||
let cr = if self.bmp.cmajr {
|
||||
self.bmp.cr[y + x * self.bmp.h] as usize
|
||||
} else {
|
||||
self.bmp.cr[x + y * self.bmp.w] as usize
|
||||
};
|
||||
|
||||
if self.alpha && cr == 0 {
|
||||
if self.bmp.alpha && cr == 0 {
|
||||
&TRANSLUCENT_COLOR
|
||||
} else {
|
||||
self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR)
|
||||
|
@ -311,7 +324,7 @@ impl Color for ColorShp
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum ColorShp
|
||||
pub enum ColorShp
|
||||
{
|
||||
Translucent,
|
||||
Opaque
|
||||
|
@ -323,24 +336,32 @@ enum ColorShp
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ImageShp<'a>
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Bitmap
|
||||
{
|
||||
w: usize,
|
||||
h: usize,
|
||||
cr: Vec<u8>,
|
||||
alpha: bool,
|
||||
clut: &'a [ColorShp],
|
||||
cmajr: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Collection<'a>
|
||||
pub struct ImageShp<'a>
|
||||
{
|
||||
clr_num: usize,
|
||||
tables: Vec<Vec<ColorShp>>,
|
||||
bitmaps: Vec<ImageShp<'a>>,
|
||||
bmp: Bitmap,
|
||||
clut: &'a [ColorShp],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Collection
|
||||
{
|
||||
pub tabs: Vec<Vec<ColorShp>>,
|
||||
pub bmps: Vec<Bitmap>,
|
||||
}
|
||||
|
||||
pub type CollectionDef = (Option<Collection>, Option<Collection>);
|
||||
|
||||
bitflags! {
|
||||
pub struct BmpFlags: u16
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue