From b586a33fda92fad13e5754b892b1127a7d8b24a5 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Mon, 28 Jul 2025 13:50:42 +0800 Subject: [PATCH] features(libtlg-rs): Add tlg6 decode support --- Cargo.lock | 11 +- libtlg-rs/Cargo.toml | 3 +- libtlg-rs/src/load_tlg.rs | 170 +++++++++++++- libtlg-rs/src/tvpgl.rs | 476 ++++++++++++++++++++++++++++++++++++++ libtlg-rs/src/types.rs | 8 + tlg/Cargo.toml | 2 +- 6 files changed, 664 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b18f728..63fc84a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,10 +156,17 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libtlg-rs" -version = "0.1.1" +version = "0.1.2" dependencies = [ + "lazy_static", "overf", ] @@ -246,7 +253,7 @@ dependencies = [ [[package]] name = "tlg" -version = "0.1.1" +version = "0.1.2" dependencies = [ "clap", "libtlg-rs", diff --git a/libtlg-rs/Cargo.toml b/libtlg-rs/Cargo.toml index ea3c307..5c166b0 100644 --- a/libtlg-rs/Cargo.toml +++ b/libtlg-rs/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "libtlg-rs" -version = "0.1.1" +version = "0.1.2" description = "Rust version of libtlg" edition = "2024" license = "MIT" repository = "https://github.com/lifegpc/libtlg-rs" [dependencies] +lazy_static = "1" overf = "0.1" diff --git a/libtlg-rs/src/load_tlg.rs b/libtlg-rs/src/load_tlg.rs index 36ca1bd..a2be21d 100644 --- a/libtlg-rs/src/load_tlg.rs +++ b/libtlg-rs/src/load_tlg.rs @@ -141,8 +141,174 @@ fn load_tlg5(src: &mut T) -> Result { }) } -fn load_tlg6(_src: &mut T) -> Result { - Err(TlgError::Str("TLG6 is not supported yet".to_string())) +fn load_tlg6(src: &mut T) -> Result { + let mut buf = [0u8; 4]; + src.read_exact(&mut buf)?; + let colors = buf[0]; + let color_type = match colors { + 3 => TlgColorType::Bgr24, + 4 => TlgColorType::Bgra32, + 1 => TlgColorType::Grayscale8, + _ => return Err(TlgError::UnsupportedColorType(colors)), + }; + if buf[1] != 0 { + return Err(TlgError::Str("Data flags must be 0".to_string())); + } + if buf[2] != 0 { + return Err(TlgError::Str("Color types must be 0".to_string())); + } + if buf[3] != 0 { + return Err(TlgError::Str( + "External golomb bit length table is not yet supported.".to_string(), + )); + } + let width = src.read_u32()?; + let height = src.read_u32()?; + let max_bit_length = src.read_u32()?; + let x_block_count = (width - 1) / (TLG6_W_BLOCK_SIZE as u32) + 1; + let y_block_count = (height - 1) / (TLG6_H_BLOCK_SIZE as u32) + 1; + let main_count = width / (TLG6_W_BLOCK_SIZE as u32); + let fraction = width - main_count * TLG6_W_BLOCK_SIZE as u32; + let mut bit_pool = vec![0u8; max_bit_length as usize / 8 + 5]; + let mut pixelbuf = vec![0u32; width as usize * TLG6_H_BLOCK_SIZE + 1]; + let mut filter_types = vec![0u8; x_block_count as usize * y_block_count as usize]; + let mut lzss_text = [0u8; 4096]; + let zero = if colors == 3 { 0xff_00_00_00u32 } else { 0 }; + let zeroline = vec![zero; width as usize]; + { + let mut p = 0; + let mut i = 0; + while i < 0x20u8 { + let mut j = 0; + while j < 0x10u8 { + lzss_text[p] = i; + p += 1; + lzss_text[p] = i; + p += 1; + lzss_text[p] = i; + p += 1; + lzss_text[p] = i; + p += 1; + lzss_text[p] = j; + p += 1; + lzss_text[p] = j; + p += 1; + lzss_text[p] = j; + p += 1; + lzss_text[p] = j; + p += 1; + j += 1; + } + i += 1; + } + } + { + let inbuf_size = src.read_u32()? as usize; + let mut inbuf = vec![0u8; inbuf_size]; + src.read_exact(&mut inbuf)?; + tlg5_decompress_slide(&mut filter_types, &inbuf, inbuf_size, &mut lzss_text, 0); + } + let mut prevline = zeroline; + let mut outbuf = vec![0u32; width as usize * height as usize]; + for y in (0..height).step_by(TLG6_H_BLOCK_SIZE) { + let y_lim = (y + TLG6_H_BLOCK_SIZE as u32).min(height); + let pixel_count = (y_lim - y) as usize * width as usize; + for c in 0..colors { + let mut bit_length = src.read_u32()?; + let method = (bit_length >> 30) & 3; + bit_length &= 0x3fff_ffff; + let byte_length = (bit_length + 7) / 8; + if byte_length as usize >= bit_pool.len() { + return Err(TlgError::Str( + "Bit pool is too small for the given bit length".to_string(), + )); + } + src.read_exact(&mut bit_pool[..byte_length as usize])?; + match method { + 0 => { + tlg6_decode_golomb_values( + &mut pixelbuf, + pixel_count, + &bit_pool, + c == 0 && colors != 1, + c, + )?; + } + _ => return Err(TlgError::UnsupportedCompressedMethod(method as u8)), + } + } + let ft = &filter_types[(y as usize / TLG6_H_BLOCK_SIZE) * x_block_count as usize..]; + let skip_bytes = (y_lim - y) as usize * TLG6_W_BLOCK_SIZE; + for yy in y..y_lim { + let curline = + &mut outbuf[(yy as usize * width as usize)..(yy as usize + 1) * width as usize]; + let dir = (yy & 1) ^ 1 != 0; + let oddskip = ((y_lim - yy - 1) as isize) - (yy - y) as isize; + if main_count != 0 { + let start = TLG6_W_BLOCK_SIZE.min(width as usize) * (yy - y) as usize; + tlg6_decode_line( + &prevline, + curline, + width, + 0, + main_count as usize, + ft, + skip_bytes, + &pixelbuf, + start, + zero, + oddskip, + dir, + )?; + } + if main_count != x_block_count { + let ww = TLG6_W_BLOCK_SIZE.min(fraction as usize); + let start = ww * (yy - y) as usize; + tlg6_decode_line( + &prevline, + curline, + width, + main_count as usize, + x_block_count as usize, + ft, + skip_bytes, + &pixelbuf, + start, + zero, + oddskip, + dir, + )?; + } + prevline = curline.to_vec(); + } + } + let mut data = Vec::with_capacity(outbuf.len() * colors as usize); + for p in outbuf { + let t = p.to_le_bytes(); + let b = t[0]; + let g = t[1]; + let r = t[2]; + let a = t[3]; + match color_type { + TlgColorType::Bgr24 => { + data.extend_from_slice(&[b, g, r]); + } + TlgColorType::Bgra32 => { + data.extend_from_slice(&[b, g, r, a]); + } + TlgColorType::Grayscale8 => { + data.extend_from_slice(&[b]); + } + }; + } + Ok(Tlg { + tags: Default::default(), + version: 6, + width, + height, + color: color_type, + data, + }) } fn internal_load_tlg(src: &mut T) -> Result { diff --git a/libtlg-rs/src/tvpgl.rs b/libtlg-rs/src/tvpgl.rs index 850f1f5..083f457 100644 --- a/libtlg-rs/src/tvpgl.rs +++ b/libtlg-rs/src/tvpgl.rs @@ -1,5 +1,59 @@ +use crate::*; use overf::wrapping; +const TLG6_GOLOMB_N_COUNT: usize = 4; +const TLG6_LEADING_ZERO_TABLE_BITS: usize = 12; +const TLG6_LEADING_ZERO_TABLE_SIZE: usize = 1 << TLG6_LEADING_ZERO_TABLE_BITS; +const TLG6_GOLOMB_COMPRESSED: [[u16; 9]; TLG6_GOLOMB_N_COUNT] = [ + [3, 7, 15, 27, 63, 108, 223, 448, 130], + [3, 5, 13, 24, 51, 95, 192, 384, 257], + [2, 5, 12, 21, 39, 86, 155, 320, 384], + [2, 3, 9, 18, 33, 61, 129, 258, 511], +]; +const TLG6_GLOBMB_TABLE_SIZE: usize = TLG6_GOLOMB_N_COUNT * 2 * 128; +pub const TLG6_W_BLOCK_SIZE: usize = 8; +pub const TLG6_H_BLOCK_SIZE: usize = 8; + +lazy_static::lazy_static! { + static ref TLG6_LEADING_ZERO_TABLE: [u8; TLG6_LEADING_ZERO_TABLE_SIZE] = + tlg6_init_leading_zero_table(); + static ref TLG6_GOLOMB_BIT_LENGTH_TABLE: [[i8; TLG6_GOLOMB_N_COUNT]; TLG6_GLOBMB_TABLE_SIZE] = + tlg6_init_golomb_table(); +} + +fn tlg6_init_leading_zero_table() -> [u8; TLG6_LEADING_ZERO_TABLE_SIZE] { + let mut table = [0; TLG6_LEADING_ZERO_TABLE_SIZE]; + for i in 0..TLG6_LEADING_ZERO_TABLE_SIZE { + let mut cnt = 0; + let mut j = 1; + while j != TLG6_LEADING_ZERO_TABLE_SIZE && i & j == 0 { + j <<= 1; + cnt += 1; + } + cnt += 1; + if j == TLG6_LEADING_ZERO_TABLE_SIZE { + cnt = 0; + } + table[i] = cnt as u8; + } + table +} + +fn tlg6_init_golomb_table() -> [[i8; TLG6_GOLOMB_N_COUNT]; TLG6_GLOBMB_TABLE_SIZE] { + let mut table = [[0; TLG6_GOLOMB_N_COUNT]; TLG6_GLOBMB_TABLE_SIZE]; + for n in 0..TLG6_GOLOMB_N_COUNT { + let mut a = 0; + for i in 0..9 { + for _ in 0..TLG6_GOLOMB_COMPRESSED[n][i] { + table[a][n] = i as i8; + a += 1; + } + } + debug_assert!(a == TLG6_GLOBMB_TABLE_SIZE); + } + table +} + pub fn tlg5_compose_colors3(outp: &mut [u8], upper: &[u8], buf: &[&[u8]], width: u32) { let mut outpos = 0usize; let mut upper_pos = 0usize; @@ -120,3 +174,425 @@ pub fn tlg5_decompress_slide( } r } + +pub fn tlg6_fetch_32bits(data: &[u8], loc: usize) -> Result { + if data.len() < loc + 4 { + return Err(TlgError::IndexOutOfRange); + } + Ok(u32::from_le_bytes([ + data[loc], + data[loc + 1], + data[loc + 2], + data[loc + 3], + ])) +} + +pub fn tlg6_decode_golomb_values( + pixelbuf: &mut [u32], + pixel_count: usize, + bit_pool: &[u8], + is_first: bool, + c: u8, +) -> Result<()> { + let mut n = TLG6_GOLOMB_N_COUNT - 1; + let mut a = 0; + let mut bit_pos = 1; + let mut zero = if bit_pool[0] & 1 != 0 { 0u8 } else { 1 }; + let mut index = 0; + let mut bit_pool_index = 0; + while index < pixel_count { + let mut count; + { + let mut t = tlg6_fetch_32bits(bit_pool, bit_pool_index)? >> bit_pos; + let mut b = TLG6_LEADING_ZERO_TABLE[(t as usize) & (TLG6_LEADING_ZERO_TABLE_SIZE - 1)]; + let mut bit_count = b as i32; + while b == 0 { + bit_count += TLG6_LEADING_ZERO_TABLE_BITS as i32; + bit_pos += TLG6_LEADING_ZERO_TABLE_BITS as i32; + bit_pool_index += bit_pos as usize >> 3; + bit_pos &= 7; + t = tlg6_fetch_32bits(bit_pool, bit_pool_index)? >> bit_pos; + b = TLG6_LEADING_ZERO_TABLE[(t as usize) & (TLG6_LEADING_ZERO_TABLE_SIZE - 1)]; + bit_count += b as i32; + } + bit_pos += b as i32; + bit_pool_index += bit_pos as usize >> 3; + bit_pos &= 7; + bit_count -= 1; + count = 1 << bit_count; + count += (tlg6_fetch_32bits(bit_pool, bit_pool_index)? >> bit_pos) & (count - 1); + bit_pos += bit_count; + bit_pool_index += bit_pos as usize >> 3; + bit_pos &= 7; + } + if zero != 0 { + loop { + if is_first { + pixelbuf[index] = 0; + } else { + let mut tmp = pixelbuf[index].to_le_bytes(); + tmp[c as usize] = 0; + pixelbuf[index] = u32::from_le_bytes(tmp); + } + index += 1; + count -= 1; + if count == 0 { + break; + } + } + zero ^= 1; + } else { + loop { + let k = TLG6_GOLOMB_BIT_LENGTH_TABLE[a][n]; + let mut t = tlg6_fetch_32bits(bit_pool, bit_pool_index)? >> bit_pos; + let mut bit_count; + let mut b; + let mut v; + let sign; + if t != 0 { + b = TLG6_LEADING_ZERO_TABLE[(t as usize) & (TLG6_LEADING_ZERO_TABLE_SIZE - 1)]; + bit_count = b as i32; + while b == 0 { + bit_count += TLG6_LEADING_ZERO_TABLE_BITS as i32; + bit_pos += TLG6_LEADING_ZERO_TABLE_BITS as i32; + bit_pool_index += bit_pos as usize >> 3; + bit_pos &= 7; + t = tlg6_fetch_32bits(bit_pool, bit_pool_index)? >> bit_pos; + b = TLG6_LEADING_ZERO_TABLE + [(t as usize) & (TLG6_LEADING_ZERO_TABLE_SIZE - 1)]; + bit_count += b as i32; + } + bit_count -= 1; + } else { + bit_pool_index += 5; + bit_count = if bit_pool_index == 0 { + return Err(TlgError::IndexOutOfRange); + } else { + bit_pool[bit_pool_index - 1] as i32 + }; + bit_pos = 0; + t = tlg6_fetch_32bits(bit_pool, bit_pool_index)?; + b = 0; + } + v = (bit_count << k) + ((t as i32 >> b) & ((1 << k) - 1)); + sign = (v & 1) - 1; + v >>= 1; + a += v as usize; + if is_first { + pixelbuf[index] = (wrapping!((v ^ sign) + sign + 1) as u32) & 0xFF; + } else { + let mut tmp = pixelbuf[index].to_le_bytes(); + tmp[c as usize] = wrapping!((v ^ sign) + sign + 1) as u8; + pixelbuf[index] = u32::from_le_bytes(tmp); + } + index += 1; + bit_pos += b as i32 + k as i32; + bit_pool_index += bit_pos as usize >> 3; + bit_pos &= 7; + if n == 0 { + n = TLG6_GOLOMB_N_COUNT - 1; + a >>= 1; + } else { + n -= 1; + } + count -= 1; + if count == 0 { + break; + } + } + zero ^= 1; + } + } + Ok(()) +} + +#[inline(always)] +fn make_gt_mask(a: u32, b: u32) -> u32 { + let tmp2 = !b; + let tmp = wrapping! {((a & tmp2) + (((a ^ tmp2) >> 1) & 0x7f7f7f7f) ) & 0x80808080}; + wrapping! { ((tmp >> 7) + 0x7f7f7f7f) ^ 0x7f7f7f7f } +} + +#[inline(always)] +fn packed_bytes_add(a: u32, b: u32) -> u32 { + let tmp = wrapping! {(((a & b) << 1) + ((a ^ b) & 0xfefefefe) ) & 0x01010100}; + wrapping!(a + b - tmp) +} + +#[inline(always)] +fn med2(a: u32, b: u32, c: u32) -> u32 { + let aa_gt_bb = make_gt_mask(a, b); + let a_xor_b_and_aa_gt_bb = (a ^ b) & aa_gt_bb; + let aa = a_xor_b_and_aa_gt_bb ^ a; + let bb = a_xor_b_and_aa_gt_bb ^ b; + let n = make_gt_mask(c, bb); + let nn = make_gt_mask(aa, c); + let m = !(n | nn); + wrapping! { + (n & aa) | (nn & bb) | ((bb & m) - (c & m) + (aa & m)) + } +} + +#[inline(always)] +fn med(a: u32, b: u32, c: u32, v: u32) -> u32 { + packed_bytes_add(med2(a, b, c), v) +} + +#[inline(always)] +fn avg_packed(x: u32, y: u32) -> u32 { + wrapping!(((x) & (y)) + ((((x) ^ (y)) & 0xfefefefe) >> 1)) + (((x) ^ (y)) & 0x01010101) +} + +#[inline(always)] +fn avg(a: u32, b: u32, v: u32) -> u32 { + packed_bytes_add(avg_packed(a, b), v) +} + +#[inline(always)] +fn cal_v(b: u8, g: u8, r: u8, a: u8) -> u32 { + (0xff0000 & ((r as u32) << 16)) + + (0xff00 & ((g as u32) << 8)) + + (0xff & (b as u32)) + + ((a as u32) << 24) +} + +pub fn tlg6_decode_line( + prevline: &[u32], + curline: &mut [u32], + width: u32, + start_block: usize, + block_limit: usize, + filter_types: &[u8], + skipblockbytes: usize, + inp: &[u32], + mut inp_pos: usize, + initialp: u32, + oddskip: isize, + dir: bool, +) -> Result<()> { + let mut p; + let mut up; + let step: i32; + let mut prevline_pos = 0; + let mut curline_pos = 0; + if start_block != 0 { + prevline_pos += start_block * TLG6_W_BLOCK_SIZE; + curline_pos += start_block * TLG6_W_BLOCK_SIZE; + p = curline[curline_pos - 1]; + up = prevline[prevline_pos - 1]; + } else { + p = initialp; + up = initialp; + } + inp_pos += skipblockbytes * start_block; + step = if dir { 1 } else { -1 }; + for i in start_block..block_limit { + let mut w = (width as usize - i * TLG6_W_BLOCK_SIZE).min(TLG6_W_BLOCK_SIZE); + let ww = w; + if step == -1 { + inp_pos += ww - 1; + } + if i & 1 != 0 { + inp_pos = (inp_pos as isize + oddskip as isize * ww as isize) as usize; + } + loop { + let inpt = inp[inp_pos]; + let ia = ((inpt >> 24) & 0xFF) as u8; + let ir = ((inpt >> 16) & 0xFF) as u8; + let ig = ((inpt >> 8) & 0xFF) as u8; + let ib = (inpt & 0xFF) as u8; + let u = prevline[prevline_pos]; + p = match filter_types[i] { + 0 => med(p, u, up, cal_v(ib, ig, ir, ia)), + 1 => avg(p, u, cal_v(ib, ig, ir, ia)), + 2 => med( + p, + u, + up, + cal_v(wrapping!(ib + ig), ig, wrapping!(ir + ig), ia), + ), + 3 => avg(p, u, cal_v(wrapping!(ib + ig), ig, wrapping!(ir + ig), ia)), + 4 => med( + p, + u, + up, + cal_v(ib, wrapping!(ig + ib), wrapping!(ir + ib + ig), ia), + ), + 5 => avg( + p, + u, + cal_v(ib, wrapping!(ig + ib), wrapping!(ir + ib + ig), ia), + ), + 6 => med( + p, + u, + up, + cal_v(wrapping!(ib + ir + ig), wrapping!(ig + ir), ir, ia), + ), + 7 => avg( + p, + u, + cal_v(wrapping!(ib + ir + ig), wrapping!(ig + ir), ir, ia), + ), + 8 => med( + p, + u, + up, + cal_v( + wrapping!(ib + ir), + wrapping!(ig + ib + ir), + wrapping!(ir + ib + ir + ig), + ia, + ), + ), + 9 => avg( + p, + u, + cal_v( + wrapping!(ib + ir), + wrapping!(ig + ib + ir), + wrapping!(ir + ib + ir + ig), + ia, + ), + ), + 10 => med( + p, + u, + up, + cal_v(wrapping!(ib + ir), wrapping!(ig + ib + ir), ir, ia), + ), + 11 => avg( + p, + u, + cal_v(wrapping!(ib + ir), wrapping!(ig + ib + ir), ir, ia), + ), + 12 => med(p, u, up, cal_v(wrapping!(ib + ig), ig, ir, ia)), + 13 => avg(p, u, cal_v(wrapping!(ib + ig), ig, ir, ia)), + 14 => med(p, u, up, cal_v(ib, wrapping!(ig + ib), ir, ia)), + 15 => avg(p, u, cal_v(ib, wrapping!(ig + ib), ir, ia)), + 16 => med(p, u, up, cal_v(ib, ig, wrapping!(ir + ig), ia)), + 17 => avg(p, u, cal_v(ib, ig, wrapping!(ir + ig), ia)), + 18 => med( + p, + u, + up, + cal_v( + wrapping!(ib + ig + ir + ib), + wrapping!(ig + ir + ib), + wrapping!(ir + ib), + ia, + ), + ), + 19 => avg( + p, + u, + cal_v( + wrapping!(ib + ig + ir + ib), + wrapping!(ig + ir + ib), + wrapping!(ir + ib), + ia, + ), + ), + 20 => med( + p, + u, + up, + cal_v(wrapping!(ib + ir), wrapping!(ig + ir), ir, ia), + ), + 21 => avg(p, u, cal_v(wrapping!(ib + ir), wrapping!(ig + ir), ir, ia)), + 22 => med( + p, + u, + up, + cal_v(ib, wrapping!(ig + ib), wrapping!(ir + ib), ia), + ), + 23 => avg(p, u, cal_v(ib, wrapping!(ig + ib), wrapping!(ir + ib), ia)), + 24 => med( + p, + u, + up, + cal_v(ib, wrapping!(ig + ir + ib), wrapping!(ir + ib), ia), + ), + 25 => avg( + p, + u, + cal_v(ib, wrapping!(ig + ir + ib), wrapping!(ir + ib), ia), + ), + 26 => med( + p, + u, + up, + cal_v( + wrapping!(ib + ig), + wrapping!(ig + ir + ib + ig), + wrapping!(ir + ib + ig), + ia, + ), + ), + 27 => avg( + p, + u, + cal_v( + wrapping!(ib + ig), + wrapping!(ig + ir + ib + ig), + wrapping!(ir + ib + ig), + ia, + ), + ), + 28 => med( + p, + u, + up, + cal_v( + wrapping!(ib + ig + ir), + wrapping!(ig + ir), + wrapping!(ir + ib + ig + ir), + ia, + ), + ), + 29 => avg( + p, + u, + cal_v( + wrapping!(ib + ig + ir), + wrapping!(ig + ir), + wrapping!(ir + ib + ig + ir), + ia, + ), + ), + 30 => med( + p, + u, + up, + cal_v(ib, wrapping!(ig + (ib << 1)), wrapping!(ir + (ib << 1)), ia), + ), + 31 => avg( + p, + u, + cal_v(ib, wrapping!(ig + (ib << 1)), wrapping!(ir + (ib << 1)), ia), + ), + v => { + return Err(TlgError::Str(format!("Unsupported filter type: {}", v))); + } + }; + up = u; + curline[curline_pos] = p; + curline_pos += 1; + prevline_pos += 1; + inp_pos = (inp_pos as isize + step as isize) as usize; + w -= 1; + if w == 0 { + break; + } + } + if step == 1 { + inp_pos += skipblockbytes - ww; + } else { + inp_pos += skipblockbytes + 1; + } + if i & 1 != 0 { + inp_pos = (inp_pos as isize - oddskip as isize * ww as isize) as usize; + } + } + Ok(()) +} diff --git a/libtlg-rs/src/types.rs b/libtlg-rs/src/types.rs index abd1c17..39a9ab5 100644 --- a/libtlg-rs/src/types.rs +++ b/libtlg-rs/src/types.rs @@ -37,6 +37,10 @@ pub enum TlgError { InvalidFormat, /// Unsupported color type UnsupportedColorType(u8), + /// Index out of range error + IndexOutOfRange, + /// Unsupported compressed method + UnsupportedCompressedMethod(u8), /// String type error Str(String), } @@ -47,6 +51,10 @@ impl std::fmt::Display for TlgError { TlgError::Io(e) => write!(f, "IO Error: {}", e), TlgError::InvalidFormat => write!(f, "Invalid TLG format"), TlgError::UnsupportedColorType(c) => write!(f, "Unsupported color type: {}", c), + TlgError::IndexOutOfRange => write!(f, "Index out of range"), + TlgError::UnsupportedCompressedMethod(m) => { + write!(f, "Unsupported compressed method: {}", m) + } TlgError::Str(s) => write!(f, "{}", s), } } diff --git a/tlg/Cargo.toml b/tlg/Cargo.toml index e9375db..2ff0413 100644 --- a/tlg/Cargo.toml +++ b/tlg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tlg" -version = "0.1.1" +version = "0.1.2" description = "Tools to process TLG image file." edition = "2024" license = "MIT"