From 2969fa94521a684868fc77adbc8cf325f1b8a381 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Wed, 27 Nov 2024 02:00:22 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7(icu=5Flib):=20Refactor=20RLE=20enc?= =?UTF-8?q?oding=20and=20update=20LVGL=20handling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactored the RLE encoding logic in `rle.rs` to improve clarity and efficiency. Updated the `lvgl.rs` module to support compression methods, including RLE, and adjusted the `Flags` enum to `HeaderFlag` for better flag management. Signed-off-by: Benign X <1341398182@qq.com> --- icu_lib/src/endecoder/lvgl/lvgl.rs | 38 ++++++++++++++++++++++++++---- icu_lib/src/endecoder/lvgl/mod.rs | 29 ++++++++++++++--------- icu_lib/src/endecoder/utils/rle.rs | 15 +++++------- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/icu_lib/src/endecoder/lvgl/lvgl.rs b/icu_lib/src/endecoder/lvgl/lvgl.rs index a6ca7e4..f7dcbc0 100644 --- a/icu_lib/src/endecoder/lvgl/lvgl.rs +++ b/icu_lib/src/endecoder/lvgl/lvgl.rs @@ -1,6 +1,7 @@ use crate::endecoder::lvgl::color_converter::{rgba8888_from, rgba8888_to}; use crate::endecoder::lvgl::{ - Flags, ImageCompressedHeader, ImageDescriptor, ImageHeader, LVGLVersion, LVGL, + has_flag, with_flag, Compress, Flags, HeaderFlag, ImageCompressedHeader, ImageDescriptor, + ImageHeader, LVGLVersion, LVGL, }; use crate::endecoder::{EnDecoder, ImageInfo}; use crate::midata::MiData; @@ -36,7 +37,7 @@ impl EnDecoder for LVGL { imageops::dither(&mut img_data, &cmap); } - let img_data = rgba8888_to( + let mut img_data = rgba8888_to( img_data.as_mut(), color_format, img.width(), @@ -45,13 +46,42 @@ impl EnDecoder for LVGL { encoder_params.dither, ); + let mut flags = Flags::from(0u16); + + match encoder_params.compress { + Compress::NONE => {} + Compress::RLE => { + use super::super::utils::rle::RleCoder; + let blk_size = ((color_format.get_bpp() + 7) >> 3) as usize; + let rle_coder = RleCoder::new(blk_size).unwrap(); + let mut data = match rle_coder.encode(&img_data) { + Ok(data) => data, + Err(err) => { + log::error!("RLE encoding failed: {:?}", err); + return vec![]; + } + }; + + let image_compressed_header = ImageCompressedHeader::new() + .with_method(encoder_params.compress) + .with_compressed_size(data.len() as u32) + .with_decompressed_size(img_data.len() as u32); + let mut ich_vec = image_compressed_header.into_bytes().to_vec(); + ich_vec.append(&mut data); + + img_data = ich_vec; + flags = with_flag(flags, HeaderFlag::COMPRESSED); + } + _ => {} + } + let mut buf = Cursor::new(Vec::new()); buf.write_all( &ImageDescriptor::new( ImageHeader::new( encoder_params.lvgl_version, color_format, - Flags::NONE, + flags, img.width() as u16, img.height() as u16, stride as u16, @@ -129,7 +159,7 @@ impl EnDecoder for LVGL { } // Deal Flag has Compressed - if header.flags().has_flag(Flags::COMPRESSED) { + if has_flag(header.flags(), HeaderFlag::COMPRESSED) { let data = &data[header.header_size()..]; let compressed_header = ImageCompressedHeader::from_bytes([ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], diff --git a/icu_lib/src/endecoder/lvgl/mod.rs b/icu_lib/src/endecoder/lvgl/mod.rs index 68af7a9..449cc10 100644 --- a/icu_lib/src/endecoder/lvgl/mod.rs +++ b/icu_lib/src/endecoder/lvgl/mod.rs @@ -58,7 +58,7 @@ pub struct LVGL {} #[bits = 16] #[derive(Copy, Clone, Debug)] #[repr(u16)] -pub enum Flags { +pub enum HeaderFlag { NONE = 0, PREMULTIPLIED = 1 << 0, MODIFIABLE = 1 << 1, @@ -75,6 +75,8 @@ pub enum Flags { USER8 = 0x0800, } +type Flags = u16; + #[derive(BitfieldSpecifier)] #[bits = 4] #[derive(Copy, Clone, PartialEq, Debug, Default)] @@ -137,10 +139,12 @@ pub enum ImageHeader { V9(ImageHeaderV9), } -impl Flags { - pub fn has_flag(&self, flag: Flags) -> bool { - *self as u8 & flag as u8 != 0 - } +pub fn has_flag(flags: Flags, flag: HeaderFlag) -> bool { + flags & flag as u16 != 0 +} + +pub fn with_flag(flags: Flags, flag: HeaderFlag) -> Flags { + flags | flag as u16 } impl ImageHeader { @@ -207,8 +211,8 @@ impl ImageHeader { pub fn flags(&self) -> Flags { match self { - ImageHeader::Unknown => Flags::NONE, - ImageHeader::V8(_) => Flags::NONE, + ImageHeader::Unknown => 0, + ImageHeader::V8(_) => 0, ImageHeader::V9(header) => header.flags(), } } @@ -329,7 +333,7 @@ impl ImageDescriptor { _ => 0, }; - if header.flags().has_flag(Flags::COMPRESSED) { + if has_flag(header.flags(), HeaderFlag::COMPRESSED) { log::trace!("Dealing Compressed image"); let compressed_header = ImageCompressedHeader::from_bytes([ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], @@ -338,11 +342,14 @@ impl ImageDescriptor { let method = compressed_header.method(); match method { Compress::RLE => { + let blk_size = ((header.cf().get_bpp() + 7) >> 3) as usize; use super::utils::rle::RleCoder; - let rle_coder = RleCoder::new(1).unwrap(); - if compressed_header.decompressed_size() != data_size { + let rle_coder = RleCoder::new(blk_size).unwrap(); + if compressed_header.compressed_size() != data_size - 12 { log::error!( - "Compressed data size mismatch, but still try to decode" + "Compressed data size mismatch, but still try to decode. current: {} expected {}", + compressed_header.compressed_size(), + data_size ); } let decoded = rle_coder diff --git a/icu_lib/src/endecoder/utils/rle.rs b/icu_lib/src/endecoder/utils/rle.rs index 2672cbb..749d2c8 100644 --- a/icu_lib/src/endecoder/utils/rle.rs +++ b/icu_lib/src/endecoder/utils/rle.rs @@ -39,21 +39,18 @@ impl RleCoder { .count() .min(127); - if repeat_count > 1 { + if repeat_count == 0 { + break; + } + + if repeat_count >= 16 { // Run-length mode result.push(repeat_count as u8); result.extend_from_slice(block); i += repeat_count; } else { // Direct copy mode - let literal_end = blocks[i..] - .iter() - .take(127) - .take_while(|&&x| { - let next_pos = i + 1; - next_pos >= blocks.len() || x != blocks[next_pos] - }) - .count(); + let literal_end = blocks[i..].iter().take(127).count(); result.push(0x80 | (literal_end as u8)); blocks[i..i + literal_end]