summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDylan <boss@tehbox.org>2026-09-16 11:51:24 +1200
committerDylan <boss@tehbox.org>2026-09-16 11:51:24 +1200
commitebc1e7030558111134d18f87af3d108f08fb9488 (patch)
tree5ab48f34d0219499d86386f994d75d8a88de2c35 /src
parent048ebdcee5d48592b6d1b669e9db0a9ba030d859 (diff)
downloadtehimage-rs-ebc1e7030558111134d18f87af3d108f08fb9488.tar.gz
tehimage-rs-ebc1e7030558111134d18f87af3d108f08fb9488.zip
feat: PNG decoding working without zlib-rsHEADmaster
Diffstat (limited to 'src')
-rw-r--r--src/png.rs47
-rw-r--r--src/zlib.rs31
2 files changed, 41 insertions, 37 deletions
diff --git a/src/png.rs b/src/png.rs
index 780bd9c..82c4df2 100644
--- a/src/png.rs
+++ b/src/png.rs
@@ -1,7 +1,6 @@
use std::{any::TypeId, collections::HashMap};
use byte_encode_derive::ByteEncode;
-use zlib_rs::{InflateConfig, decompress_slice};
use crate::{byte_encode::ByteEncode, crc::update_crc, image::{RGB, ColorType, Image, ImageBase, PixelArr}, reader::FileReader, zlib::{BitBuffer, zlib_decode}};
@@ -14,24 +13,25 @@ pub struct PNGImage
tEXt: Option<tEXt>,
}
-fn paeth_filter(a: u8, b: u8, c: u8) -> u8 {
- let p = (a as i32 + b as i32 - c as i32) as u8;
- let pa = p.abs_diff(a);
- let pb = p.abs_diff(b);
- let pc = p.abs_diff(c);
+fn paeth_filter(a: &u8, b: &u8, c: &u8) -> u8 {
+ let p = (*a as i32 + *b as i32 - *c as i32) as u8;
+ let pa = p.abs_diff(*a);
+ let pb = p.abs_diff(*b);
+ let pc = p.abs_diff(*c);
if pa <= pb && pa <= pc
{
- a
+ *a
}
else if pb <= pc
{
- b
+ *b
}
else
{
- c
+ *c
}
}
+#[derive(Debug)]
enum FilterMethod
{
None,
@@ -52,12 +52,12 @@ impl FilterMethod
_ => panic!("Filter {x} is invalid!\nOnly 5 filters exist")
}
}
- fn apply(&self, a: u8, b: u8, c: u8, x: u8) -> u8 {
+ fn apply(&self, a: &u8, b: &u8, c: &u8, x: &u8) -> u8 {
match self {
- FilterMethod::None => x,
- FilterMethod::Sub => x.wrapping_add(a),
- FilterMethod::Up => x.wrapping_add(b),
- FilterMethod::Average => x.wrapping_add((a + b)/2),
+ FilterMethod::None => *x,
+ FilterMethod::Sub => x.wrapping_add(*a),
+ FilterMethod::Up => x.wrapping_add(*b),
+ FilterMethod::Average => x.wrapping_add((*a + *b)/2),
FilterMethod::Paeth => x.wrapping_add(paeth_filter(a, b, c)),
}
}
@@ -295,12 +295,10 @@ impl<T: RGBu8> Image<T> for PNGImage
let height: u32 = IHDR.height;
println!("{bpp}, {width}, {height}");
- let compression_method: u8 = IDAT.data[0];
- let additional_flags: u8 = IDAT.data[1];
-
- let mut decoded = vec![0u8; 1920*(1080*3 + 1)]; // zlib_decode(BitBuffer::new(&IDAT.data[2..]));
- let (decompressed, rc) = decompress_slice(&mut decoded, &IDAT.data, InflateConfig::default());
- println!("{rc:?}");
+ let _compression_method: u8 = IDAT.data[0];
+ let _additional_flags: u8 = IDAT.data[1];
+
+ let decoded = zlib_decode(BitBuffer::new(&IDAT.data[2..]));
let mut pixels = PixelArr::<T>::new(width, height);
let mut rows: Vec<Vec<u8>> = Vec::new();
@@ -308,16 +306,15 @@ impl<T: RGBu8> Image<T> for PNGImage
let mut i = 0;
for y in 0..(height as usize)
{
- // println!("i: {i}");
let filter = FilterMethod::from_byte(decoded[i]);
i += 1;
let mut row: Vec<u8> = Vec::with_capacity(width as usize * 3);
for x in 0..(width as usize * 3)
{
- let a: u8 = if x < 3 { 0 } else { row[x - 3] };
- let b: u8 = if y < 1 { 0 } else { rows[y - 1][x] };
- let c: u8 = if y < 1 || x < 3 { 0 } else { rows[y - 1][x - 3] };
- let x = decoded[i];
+ let a: &u8 = if x < 3 { &0 } else { &row[x - 3] };
+ let b: &u8 = if y < 1 { &0 } else { &rows[y - 1][x] };
+ let c: &u8 = if y < 1 || x < 3 { &0 } else { &rows[y - 1][x - 3] };
+ let x = &decoded[i];
i += 1;
row.push(filter.apply(a, b, c, x));
}
diff --git a/src/zlib.rs b/src/zlib.rs
index 41816f3..f17c466 100644
--- a/src/zlib.rs
+++ b/src/zlib.rs
@@ -20,11 +20,11 @@ const DIST_EXTRA: [usize; 30] = [0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
const DYNAMIC_CODE_START: [usize; 3] = [3, 3, 11];
const DYNAMIC_CODE_EXTRA: [usize; 3] = [2, 3, 7];
-#[derive(Clone)]
+#[derive(Clone, Debug)]
struct HuffmanTree<const LENGTH: usize>
{
- pub len_counts: [u8; MAX_BITS + 1],
- pub ordered_codes: [u16; LENGTH]
+ len_counts: [u8; MAX_BITS + 1],
+ ordered_codes: [u16; LENGTH]
}
impl<const LENGTH: usize> HuffmanTree<LENGTH>
@@ -76,18 +76,20 @@ impl<const LENGTH: usize> HuffmanTree<LENGTH>
fn decode<T: Bitstream>(&self, bitstream: &mut T) -> u16
{
- let mut code: i16 = 0;
+ let mut code: u16 = 0;
let mut first: u16 = 0;
let mut index: usize = 0;
- for len in 1..MAX_BITS
+ for len in 1..(MAX_BITS + 1)
{
- code |= bitstream.next_bit() as i16;
- let count: i16 = self.len_counts[len] as i16;
- // println!("{code} {count}");
- if code - count < first as i16
+ code |= bitstream.next_bit() as u16;
+ let count: u16 = self.len_counts[len] as u16;
+ // println!("{code} {count} {len}");
+ // let a = self.len_counts;
+ // println!("{a:?}");
+ if count > code || code - count < first as u16
{
- return self.ordered_codes[index + ((code - first as i16) as usize)];
+ return self.ordered_codes[index + ((code - first) as usize)];
}
index += count as usize;
first += count as u16;
@@ -218,7 +220,7 @@ pub fn zlib_decode<T: Bitstream>(mut instream: T) -> Vec<u8>
final_chunk = instream.next_bit();
let compression_type = CompressionType::new(instream.next_bits(2) as u8);
let t = output_buffer.len();
- println!("New chunk at pos: {t}, compression type: {compression_type:?}");
+ // println!("New chunk at pos: {t}, compression type: {compression_type:?}");
if compression_type == CompressionType::Reserved
{
panic!("Reserved compression type should not be used");
@@ -300,10 +302,14 @@ pub fn zlib_decode<T: Bitstream>(mut instream: T) -> Vec<u8>
let mut dist_tree_lens = [0u8; DIST_TREE_LEN];
dist_tree_lens[0..hdist].copy_from_slice(&code_dist_tree_lens[hlit..(hlit + hdist)]);
+
+ // println!("{code_tree_lens:?}\n{dist_tree_lens:?}");
(HuffmanTree::new(code_tree_lens),
HuffmanTree::new(dist_tree_lens))
};
+
+ // println!("{code_tree:?}\n{dist_tree:?}");
let mut code = 0u16;
@@ -323,7 +329,8 @@ pub fn zlib_decode<T: Bitstream>(mut instream: T) -> Vec<u8>
let dist = DIST_START[dist_code as usize]
+ instream.next_bits(DIST_EXTRA[dist_code as usize]) as usize;
- let out_pos = output_buffer.len() - 1;
+ output_buffer.reserve(len);
+ let out_pos = output_buffer.len();
for i in 0..len
{
output_buffer.push(output_buffer[out_pos - dist + i]);