pub(crate) mod decode;
mod encode;
use crate::decode::DecodeOutput;
use crate::error::BitmapError;
use crate::limits::{self, Limits};
use crate::pixel::PixelLayout;
use alloc::vec::Vec;
use enough::Stop;
pub(crate) fn decode<'a>(
data: &'a [u8],
limits: Option<&Limits>,
stop: &dyn Stop,
) -> Result<DecodeOutput<'a>, BitmapError> {
let header = decode::parse_header(data)?;
let width = header.width as u32;
let height = header.height as u32;
if let Some(limits) = limits {
limits.check(width, height)?;
}
let out_channels: usize = if matches!(header.image_type, 3 | 11) {
1
} else if header.pixel_depth == 32
|| (matches!(header.image_type, 1 | 9) && header.color_map_depth == 32)
|| (header.descriptor & 0x0F) > 0
{
4
} else {
3
};
let out_bytes = (width as usize)
.checked_mul(height as usize)
.and_then(|px| px.checked_mul(out_channels))
.ok_or_else(|| BitmapError::LimitExceeded("output size overflows usize".into()))?;
limits::check_output_size(out_bytes, limits)?;
stop.check()?;
let (pixels, layout) = decode::decode_pixels(data, &header, stop)?;
Ok(DecodeOutput::owned(pixels, width, height, layout))
}
pub(crate) fn encode(
pixels: &[u8],
width: u32,
height: u32,
layout: PixelLayout,
stop: &dyn Stop,
) -> Result<Vec<u8>, BitmapError> {
encode::encode_tga(pixels, width, height, layout, stop)
}