mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-07-08 01:31:53 +08:00
Use better method to encode crx image
This commit is contained in:
@@ -427,115 +427,69 @@ impl CrxImage {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_row0(
|
fn encode_row0(dst: &mut Vec<u8>, src: &[u8], width: u16, pixel_size: u8, y: u16) {
|
||||||
dst: &mut Vec<u8>,
|
|
||||||
mut dst_p: usize,
|
|
||||||
src: &[u8],
|
|
||||||
width: u16,
|
|
||||||
pixel_size: u8,
|
|
||||||
y: u16,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let pixel_size = pixel_size as usize;
|
let pixel_size = pixel_size as usize;
|
||||||
let mut src_p = y as usize * width as usize * pixel_size;
|
let mut src_p = y as usize * width as usize * pixel_size;
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p];
|
dst.push(src[src_p]);
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
}
|
}
|
||||||
for _ in 1..width {
|
for _ in 1..width {
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p].wrapping_sub(src[src_p - pixel_size]);
|
dst.push(src[src_p].wrapping_sub(src[src_p - pixel_size]));
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(dst_p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_row1(
|
fn encode_row1(dst: &mut Vec<u8>, src: &[u8], width: u16, pixel_size: u8, y: u16) {
|
||||||
dst: &mut Vec<u8>,
|
|
||||||
mut dst_p: usize,
|
|
||||||
src: &[u8],
|
|
||||||
width: u16,
|
|
||||||
pixel_size: u8,
|
|
||||||
y: u16,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let pixel_size = pixel_size as usize;
|
let pixel_size = pixel_size as usize;
|
||||||
let mut src_p = y as usize * width as usize * pixel_size;
|
let mut src_p = y as usize * width as usize * pixel_size;
|
||||||
let mut prev_row_p = (y as usize - 1) * width as usize * pixel_size;
|
let mut prev_row_p = (y as usize - 1) * width as usize * pixel_size;
|
||||||
for _ in 0..width {
|
for _ in 0..width {
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p].wrapping_sub(src[prev_row_p]);
|
dst.push(src[src_p].wrapping_sub(src[prev_row_p]));
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
prev_row_p += 1;
|
prev_row_p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(dst_p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_row2(
|
fn encode_row2(dst: &mut Vec<u8>, src: &[u8], width: u16, pixel_size: u8, y: u16) {
|
||||||
dst: &mut Vec<u8>,
|
|
||||||
mut dst_p: usize,
|
|
||||||
src: &[u8],
|
|
||||||
width: u16,
|
|
||||||
pixel_size: u8,
|
|
||||||
y: u16,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let pixel_size = pixel_size as usize;
|
let pixel_size = pixel_size as usize;
|
||||||
let mut src_p = y as usize * width as usize * pixel_size;
|
let mut src_p = y as usize * width as usize * pixel_size;
|
||||||
let mut prev_row_p = (y as usize - 1) * width as usize * pixel_size;
|
let mut prev_row_p = (y as usize - 1) * width as usize * pixel_size;
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p];
|
dst.push(src[src_p]);
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
}
|
}
|
||||||
for _ in 1..width {
|
for _ in 1..width {
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p].wrapping_sub(src[prev_row_p]);
|
dst.push(src[src_p].wrapping_sub(src[prev_row_p]));
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
prev_row_p += 1;
|
prev_row_p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(dst_p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_row3(
|
fn encode_row3(dst: &mut Vec<u8>, src: &[u8], width: u16, pixel_size: u8, y: u16) {
|
||||||
dst: &mut Vec<u8>,
|
|
||||||
mut dst_p: usize,
|
|
||||||
src: &[u8],
|
|
||||||
width: u16,
|
|
||||||
pixel_size: u8,
|
|
||||||
y: u16,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let pixel_size = pixel_size as usize;
|
let pixel_size = pixel_size as usize;
|
||||||
let mut src_p = y as usize * width as usize * pixel_size;
|
let mut src_p = y as usize * width as usize * pixel_size;
|
||||||
let mut prev_row_p = (y as usize - 1) * width as usize * pixel_size + pixel_size;
|
let mut prev_row_p = (y as usize - 1) * width as usize * pixel_size + pixel_size;
|
||||||
for _ in 0..width - 1 {
|
for _ in 0..width - 1 {
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p].wrapping_sub(src[prev_row_p]);
|
dst.push(src[src_p].wrapping_sub(src[prev_row_p]));
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
prev_row_p += 1;
|
prev_row_p += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _ in 0..pixel_size {
|
for _ in 0..pixel_size {
|
||||||
dst[dst_p] = src[src_p];
|
dst.push(src[src_p]);
|
||||||
dst_p += 1;
|
|
||||||
src_p += 1;
|
src_p += 1;
|
||||||
}
|
}
|
||||||
Ok(dst_p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_row4(
|
fn encode_row4(dst: &mut Vec<u8>, src: &[u8], width: u16, pixel_size: u8, y: u16) {
|
||||||
dst: &mut Vec<u8>,
|
|
||||||
mut dst_p: usize,
|
|
||||||
src: &[u8],
|
|
||||||
width: u16,
|
|
||||||
pixel_size: u8,
|
|
||||||
y: u16,
|
|
||||||
) -> Result<usize> {
|
|
||||||
let pixel_size = pixel_size as usize;
|
let pixel_size = pixel_size as usize;
|
||||||
let src_p = y as usize * width as usize * pixel_size;
|
let src_p = y as usize * width as usize * pixel_size;
|
||||||
for offset in 0..pixel_size {
|
for offset in 0..pixel_size {
|
||||||
@@ -543,8 +497,7 @@ impl CrxImage {
|
|||||||
let mut remaining = width;
|
let mut remaining = width;
|
||||||
let value = src[src_c];
|
let value = src[src_c];
|
||||||
src_c += pixel_size;
|
src_c += pixel_size;
|
||||||
dst[dst_p] = value;
|
dst.push(value);
|
||||||
dst_p += 1;
|
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
continue;
|
continue;
|
||||||
@@ -558,17 +511,14 @@ impl CrxImage {
|
|||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
dst[dst_p] = value;
|
dst.push(value);
|
||||||
dst_p += 1;
|
dst.push(count);
|
||||||
dst[dst_p] = count;
|
|
||||||
dst_p += 1;
|
|
||||||
remaining -= count as u16;
|
remaining -= count as u16;
|
||||||
}
|
}
|
||||||
while remaining > 0 {
|
while remaining > 0 {
|
||||||
let value = src[src_c];
|
let value = src[src_c];
|
||||||
src_c += pixel_size;
|
src_c += pixel_size;
|
||||||
dst[dst_p] = value;
|
dst.push(value);
|
||||||
dst_p += 1;
|
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
if remaining == 0 {
|
if remaining == 0 {
|
||||||
break;
|
break;
|
||||||
@@ -582,27 +532,23 @@ impl CrxImage {
|
|||||||
count += 1;
|
count += 1;
|
||||||
}
|
}
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
dst[dst_p] = value;
|
dst.push(value);
|
||||||
dst_p += 1;
|
dst.push(count);
|
||||||
dst[dst_p] = count;
|
|
||||||
dst_p += 1;
|
|
||||||
remaining -= count as u16;
|
remaining -= count as u16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(dst_p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_row_best(
|
fn encode_row_best(
|
||||||
dst: &mut Vec<u8>,
|
dst: &mut Vec<u8>,
|
||||||
mut dst_p: usize,
|
|
||||||
src: &[u8],
|
src: &[u8],
|
||||||
width: u16,
|
width: u16,
|
||||||
pixel_size: u8,
|
pixel_size: u8,
|
||||||
y: u16,
|
y: u16,
|
||||||
) -> Result<usize> {
|
) -> Result<()> {
|
||||||
let mut buf = vec![0; width as usize * pixel_size as usize];
|
let mut buf = Vec::with_capacity(width as usize * pixel_size as usize);
|
||||||
Self::encode_row0(&mut buf, 0, src, width, pixel_size, y)?;
|
Self::encode_row0(&mut buf, src, width, pixel_size, y);
|
||||||
let mut compressed_len = {
|
let mut compressed_len = {
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
flate2::write::ZlibEncoder::new(MemWriter::new(), flate2::Compression::fast());
|
flate2::write::ZlibEncoder::new(MemWriter::new(), flate2::Compression::fast());
|
||||||
@@ -615,15 +561,14 @@ impl CrxImage {
|
|||||||
if y == 0 && row_type < 4 {
|
if y == 0 && row_type < 4 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut newbuf = vec![0; width as usize * pixel_size as usize];
|
let mut newbuf = Vec::with_capacity(width as usize * pixel_size as usize);
|
||||||
let dst_len = match row_type {
|
match row_type {
|
||||||
1 => Self::encode_row1(&mut newbuf, 0, src, width, pixel_size, y)?,
|
1 => Self::encode_row1(&mut newbuf, src, width, pixel_size, y),
|
||||||
2 => Self::encode_row2(&mut newbuf, 0, src, width, pixel_size, y)?,
|
2 => Self::encode_row2(&mut newbuf, src, width, pixel_size, y),
|
||||||
3 => Self::encode_row3(&mut newbuf, 0, src, width, pixel_size, y)?,
|
3 => Self::encode_row3(&mut newbuf, src, width, pixel_size, y),
|
||||||
4 => Self::encode_row4(&mut newbuf, 0, src, width, pixel_size, y)?,
|
4 => Self::encode_row4(&mut newbuf, src, width, pixel_size, y),
|
||||||
_ => return Err(anyhow::anyhow!("Invalid row type: {}", row_type)),
|
_ => return Err(anyhow::anyhow!("Invalid row type: {}", row_type)),
|
||||||
};
|
};
|
||||||
newbuf.truncate(dst_len);
|
|
||||||
let new_compressed_len = {
|
let new_compressed_len = {
|
||||||
let mut encoder =
|
let mut encoder =
|
||||||
flate2::write::ZlibEncoder::new(MemWriter::new(), flate2::Compression::fast());
|
flate2::write::ZlibEncoder::new(MemWriter::new(), flate2::Compression::fast());
|
||||||
@@ -637,21 +582,17 @@ impl CrxImage {
|
|||||||
buf_row_type = row_type;
|
buf_row_type = row_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dst[dst_p] = buf_row_type;
|
dst.push(buf_row_type);
|
||||||
dst_p += 1;
|
dst.extend_from_slice(&buf);
|
||||||
dst[dst_p..dst_p + buf.len()].copy_from_slice(&buf);
|
Ok(())
|
||||||
dst_p += buf.len();
|
|
||||||
Ok(dst_p)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_image_best(src: &[u8], width: u16, height: u16, pixel_size: u8) -> Result<Vec<u8>> {
|
fn encode_image_best(src: &[u8], width: u16, height: u16, pixel_size: u8) -> Result<Vec<u8>> {
|
||||||
let size = width as usize * height as usize * pixel_size as usize + height as usize;
|
let size = width as usize * height as usize * pixel_size as usize + height as usize;
|
||||||
let mut dst = vec![0; size];
|
let mut dst = Vec::with_capacity(size);
|
||||||
let mut dst_p = 0;
|
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
dst_p = Self::encode_row_best(&mut dst, dst_p, src, width, pixel_size, y)?;
|
Self::encode_row_best(&mut dst, src, width, pixel_size, y)?;
|
||||||
}
|
}
|
||||||
dst.truncate(dst_p);
|
|
||||||
Ok(dst)
|
Ok(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,26 +604,23 @@ impl CrxImage {
|
|||||||
row_type: u8,
|
row_type: u8,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
let size = width as usize * height as usize * pixel_size as usize + height as usize;
|
let size = width as usize * height as usize * pixel_size as usize + height as usize;
|
||||||
let mut dst = vec![0; size];
|
let mut dst = Vec::with_capacity(size);
|
||||||
let mut dst_p = 0;
|
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
let row_type = if y == 0 && row_type != 0 && row_type != 4 {
|
let row_type = if y == 0 && row_type != 0 && row_type != 4 {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
row_type
|
row_type
|
||||||
};
|
};
|
||||||
dst[dst_p] = row_type;
|
dst.push(row_type);
|
||||||
dst_p += 1;
|
|
||||||
match row_type {
|
match row_type {
|
||||||
0 => dst_p = Self::encode_row0(&mut dst, dst_p, src, width, pixel_size, y)?,
|
0 => Self::encode_row0(&mut dst, src, width, pixel_size, y),
|
||||||
1 => dst_p = Self::encode_row1(&mut dst, dst_p, src, width, pixel_size, y)?,
|
1 => Self::encode_row1(&mut dst, src, width, pixel_size, y),
|
||||||
2 => dst_p = Self::encode_row2(&mut dst, dst_p, src, width, pixel_size, y)?,
|
2 => Self::encode_row2(&mut dst, src, width, pixel_size, y),
|
||||||
3 => dst_p = Self::encode_row3(&mut dst, dst_p, src, width, pixel_size, y)?,
|
3 => Self::encode_row3(&mut dst, src, width, pixel_size, y),
|
||||||
4 => dst_p = Self::encode_row4(&mut dst, dst_p, src, width, pixel_size, y)?,
|
4 => Self::encode_row4(&mut dst, src, width, pixel_size, y),
|
||||||
_ => return Err(anyhow::anyhow!("Invalid row type: {}", row_type)),
|
_ => return Err(anyhow::anyhow!("Invalid row type: {}", row_type)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
dst.truncate(dst_p);
|
|
||||||
Ok(dst)
|
Ok(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,22 +635,19 @@ impl CrxImage {
|
|||||||
return Err(anyhow::anyhow!("Row type length does not match height"));
|
return Err(anyhow::anyhow!("Row type length does not match height"));
|
||||||
}
|
}
|
||||||
let size = width as usize * height as usize * pixel_size as usize + height as usize;
|
let size = width as usize * height as usize * pixel_size as usize + height as usize;
|
||||||
let mut dst = vec![0; size];
|
let mut dst = Vec::with_capacity(size);
|
||||||
let mut dst_p = 0;
|
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
let data = row_type[y as usize];
|
let row_type = row_type[y as usize];
|
||||||
dst[dst_p] = data;
|
dst.push(row_type);
|
||||||
dst_p += 1;
|
match row_type {
|
||||||
dst_p = match data {
|
0 => Self::encode_row0(&mut dst, src, width, pixel_size, y),
|
||||||
0 => Self::encode_row0(&mut dst, dst_p, src, width, pixel_size, y)?,
|
1 => Self::encode_row1(&mut dst, src, width, pixel_size, y),
|
||||||
1 => Self::encode_row1(&mut dst, dst_p, src, width, pixel_size, y)?,
|
2 => Self::encode_row2(&mut dst, src, width, pixel_size, y),
|
||||||
2 => Self::encode_row2(&mut dst, dst_p, src, width, pixel_size, y)?,
|
3 => Self::encode_row3(&mut dst, src, width, pixel_size, y),
|
||||||
3 => Self::encode_row3(&mut dst, dst_p, src, width, pixel_size, y)?,
|
4 => Self::encode_row4(&mut dst, src, width, pixel_size, y),
|
||||||
4 => Self::encode_row4(&mut dst, dst_p, src, width, pixel_size, y)?,
|
_ => return Err(anyhow::anyhow!("Invalid row type: {}", row_type)),
|
||||||
_ => return Err(anyhow::anyhow!("Invalid row type: {}", data)),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
dst.truncate(dst_p);
|
|
||||||
Ok(dst)
|
Ok(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user