Skip to content

Commit e9883a4

Browse files
committed
Lazy parse sBIT
1 parent 2ff6055 commit e9883a4

File tree

2 files changed

+50
-41
lines changed

2 files changed

+50
-41
lines changed

src/common.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Common types shared between the encoder and decoder
2+
use crate::decoder::stream::FormatErrorInner;
23
use crate::text_metadata::{ITXtChunk, TEXtChunk, ZTXtChunk};
3-
use crate::{chunk, encoder};
4+
use crate::{chunk, encoder, DecodingError};
45
use io::Write;
56
use std::{borrow::Cow, convert::TryFrom, fmt, io};
67

@@ -759,6 +760,54 @@ impl Info<'_> {
759760
self.srgb = Some(rendering_intent);
760761
self.icc_profile = None;
761762
}
763+
764+
/// Number of significant bits per channel, according to sBIT chunk
765+
pub fn sbit(&self) -> Result<Option<&[u8]>, DecodingError> {
766+
let Some(sbit) = self.sbit.as_deref() else {
767+
return Ok(None);
768+
};
769+
770+
let (color_type, bit_depth) = (self.color_type, self.bit_depth);
771+
// The sample depth for color type 3 is fixed at eight bits.
772+
let sample_depth = if color_type == ColorType::Indexed {
773+
BitDepth::Eight
774+
} else {
775+
bit_depth
776+
};
777+
778+
// expected lenth of the chunk
779+
let expected = match color_type {
780+
ColorType::Grayscale => 1,
781+
ColorType::Rgb | ColorType::Indexed => 3,
782+
ColorType::GrayscaleAlpha => 2,
783+
ColorType::Rgba => 4,
784+
};
785+
786+
// Check if the sbit chunk size is valid.
787+
if expected != sbit.len() {
788+
return Err(DecodingError::Format(
789+
FormatErrorInner::InvalidSbitChunkSize {
790+
color_type,
791+
expected,
792+
len: sbit.len(),
793+
}
794+
.into(),
795+
));
796+
}
797+
798+
for &depth in sbit {
799+
if depth < 1 || depth > sample_depth as u8 {
800+
return Err(DecodingError::Format(
801+
FormatErrorInner::InvalidSbit {
802+
sample_depth,
803+
sbit: depth,
804+
}
805+
.into(),
806+
));
807+
}
808+
}
809+
Ok(Some(sbit))
810+
}
762811
}
763812

764813
impl BytesPerPixel {

src/decoder/stream.rs

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,47 +1128,7 @@ impl StreamingDecoder {
11281128
));
11291129
}
11301130

1131-
let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
1132-
// The sample depth for color type 3 is fixed at eight bits.
1133-
let sample_depth = if color_type == ColorType::Indexed {
1134-
BitDepth::Eight
1135-
} else {
1136-
bit_depth
1137-
};
11381131
let vec = mem::take(&mut self.current_chunk.raw_bytes);
1139-
let len = vec.len();
1140-
1141-
// expected lenth of the chunk
1142-
let expected = match color_type {
1143-
ColorType::Grayscale => 1,
1144-
ColorType::Rgb | ColorType::Indexed => 3,
1145-
ColorType::GrayscaleAlpha => 2,
1146-
ColorType::Rgba => 4,
1147-
};
1148-
1149-
// Check if the sbit chunk size is valid.
1150-
if expected != len {
1151-
return Err(DecodingError::Format(
1152-
FormatErrorInner::InvalidSbitChunkSize {
1153-
color_type,
1154-
expected,
1155-
len,
1156-
}
1157-
.into(),
1158-
));
1159-
}
1160-
1161-
for sbit in &vec {
1162-
if *sbit < 1 || *sbit > sample_depth as u8 {
1163-
return Err(DecodingError::Format(
1164-
FormatErrorInner::InvalidSbit {
1165-
sample_depth,
1166-
sbit: *sbit,
1167-
}
1168-
.into(),
1169-
));
1170-
}
1171-
}
11721132
info.sbit = Some(Cow::Owned(vec));
11731133
Ok(Decoded::Nothing)
11741134
};

0 commit comments

Comments
 (0)