Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions crates/pdf-image/src/decoded_samples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,41 @@ impl DecodedSamples {
objects: &dyn ObjectResolver,
metadata: &ImageMetadata,
) -> Result<Self, PdfImageError> {
if let Some(decoded_samples) = Self::decode_preconverted_jpx(raw_data, metadata) {
return Ok(decoded_samples);
}
let decoded_samples = if let Some(decoded_samples) =
Self::decode_preconverted_jpx(raw_data, metadata)
{
decoded_samples
} else if let Some(decoded_samples) = Self::decode_preconverted_dct(raw_data, metadata) {
decoded_samples
} else {
match metadata.color_space.as_ref() {
Some(ColorSpace::Indexed(indexed)) => {
Self::decode_indexed(dictionary, raw_data, objects, metadata, indexed)
}
_ => Self::decode_direct(dictionary, raw_data, objects, metadata),
}?
};

if let Some(decoded_samples) = Self::decode_preconverted_dct(raw_data, metadata) {
return Ok(decoded_samples);
decoded_samples.validate(metadata)?;
Ok(decoded_samples)
}

/// Ensures the decoded component stream is large enough for the declared dimensions.
fn validate(&self, metadata: &ImageMetadata) -> Result<(), PdfImageError> {
if self.num_color_components == 0 {
return Err(PdfImageError::InvalidColorComponentCount);
}

match metadata.color_space.as_ref() {
Some(ColorSpace::Indexed(indexed)) => {
Self::decode_indexed(dictionary, raw_data, objects, metadata, indexed)
}
_ => Self::decode_direct(dictionary, raw_data, objects, metadata),
let num_pixels = metadata.width.saturating_mul(metadata.height);
let expected_bytes = num_pixels.saturating_mul(self.num_color_components);
if self.image_data.len() < expected_bytes {
return Err(PdfImageError::TruncatedImageData {
expected_bytes,
actual_bytes: self.image_data.len(),
});
}

Ok(())
}

/// Uses DCT decoder output as display samples when the JPEG decoder already converted color.
Expand Down
22 changes: 0 additions & 22 deletions crates/pdf-image/src/image_xobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ impl ImageXObject {
metadata: &ImageMetadata,
) -> Result<Self, PdfImageError> {
let decoded_samples = DecodedSamples::decode(dictionary, raw_data, objects, metadata)?;
Self::validate_decoded_samples(metadata, &decoded_samples)?;
let (data, pixel_format) = Self::assemble_pixel_data(metadata, &decoded_samples, soft_mask);

Ok(Self {
Expand All @@ -108,27 +107,6 @@ impl ImageXObject {
})
}

/// Ensures the decoded component stream is large enough for the declared dimensions.
fn validate_decoded_samples(
metadata: &ImageMetadata,
decoded_samples: &DecodedSamples,
) -> Result<(), PdfImageError> {
if decoded_samples.num_color_components == 0 {
return Err(PdfImageError::InvalidColorComponentCount);
}

let num_pixels = metadata.width.saturating_mul(metadata.height);
let expected_bytes = num_pixels.saturating_mul(decoded_samples.num_color_components);
if decoded_samples.image_data.len() < expected_bytes {
return Err(PdfImageError::TruncatedImageData {
expected_bytes,
actual_bytes: decoded_samples.image_data.len(),
});
}

Ok(())
}

/// Builds the final pixel buffer and pixel format after optional soft-mask application.
fn assemble_pixel_data(
metadata: &ImageMetadata,
Expand Down
Loading