mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-15 15:55:33 +00:00
fix(create): preserve version-four PCX compatibility
This commit is contained in:
@@ -562,7 +562,11 @@ fn pcx(name: &str, bytes: &[u8]) -> Result<Embedded, CreateError> {
|
||||
// is black/white and an indexed file without its VGA palette is interpreted as gray.
|
||||
// The shared reader owns all RLE, plane unpacking and palette application.
|
||||
let has_vga = bytes.len().checked_sub(769).is_some_and(|at| at >= 128 && bytes.get(at) == Some(&0x0C));
|
||||
let normalize = (bits == 1 && planes == 1) || (bits == 8 && planes == 1 && !has_vga);
|
||||
// The pinned decoder predates shared version-4 recognition. Its version byte is
|
||||
// only a header acceptance check, not a switch for pixel or palette semantics.
|
||||
// Keep this app's existing version-4 acceptance without replacing the shared pin.
|
||||
let version_four = byte(1) == 4;
|
||||
let normalize = version_four || (bits == 1 && planes == 1) || (bits == 8 && planes == 1 && !has_vga);
|
||||
let mut input = std::borrow::Cow::Borrowed(bytes);
|
||||
if normalize {
|
||||
// Normalization must not add an unbounded copy of hostile compressed input.
|
||||
@@ -572,11 +576,18 @@ fn pcx(name: &str, bytes: &[u8]) -> Result<Embedded, CreateError> {
|
||||
let mut copy = Vec::new();
|
||||
copy.try_reserve_exact(bytes.len()).map_err(|_| bad("not enough memory for this image"))?;
|
||||
copy.extend_from_slice(bytes);
|
||||
if bits == 1 {
|
||||
if version_four && let Some(version) = copy.get_mut(1) {
|
||||
*version = 5;
|
||||
}
|
||||
if bits == 1 && planes == 1 {
|
||||
if let Some(palette) = copy.get_mut(16..22) {
|
||||
palette.copy_from_slice(&[0, 0, 0, 255, 255, 255]);
|
||||
}
|
||||
} else if let Some(info) = copy.get_mut(68..70) {
|
||||
} else if bits == 8
|
||||
&& planes == 1
|
||||
&& !has_vga
|
||||
&& let Some(info) = copy.get_mut(68..70)
|
||||
{
|
||||
info.copy_from_slice(&2u16.to_le_bytes());
|
||||
}
|
||||
input = std::borrow::Cow::Owned(copy);
|
||||
|
||||
@@ -3144,3 +3144,16 @@ fn shared_pcx_rejects_zero_length_runs_and_oversized_planes() {
|
||||
let rgba = pcx_header(5, 8, 4, 1, 1, 1);
|
||||
assert!(super::pcx("rgba.pcx", &rgba).is_err(), "do not silently expand accepted layouts");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shared_pcx_keeps_version_four_rgb_and_palette_pixels() {
|
||||
let mut rgb = pcx_header(4, 8, 3, 1, 1, 1);
|
||||
rgb.extend_from_slice(&[10, 20, 30]);
|
||||
assert!(super::is_image(&rgb));
|
||||
assert_eq!(super::pcx("windows.pcx", &rgb).unwrap().data, [10, 20, 30]);
|
||||
let mut palette = pcx_header(4, 1, 2, 1, 1, 1);
|
||||
palette[25..28].copy_from_slice(&[4, 5, 6]);
|
||||
palette.extend_from_slice(&[0x80, 0x80]);
|
||||
assert_eq!(super::pcx("windows.pcx", &palette).unwrap().data, [4, 5, 6]);
|
||||
assert!(from_images(&[("windows.pcx".into(), rgb)]).is_ok());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user