pub fn extract_jfif_thumbnail(data: &[u8]) -> Option<Vec<u8>> {
if data.len() < 6 {
return None;
}
if data[0] != 0xFF || data[1] != 0xD8 {
return None;
}
let mut pos: usize = 2;
while pos + 4 <= data.len() {
if data[pos] != 0xFF {
return None;
}
let marker_code: u8 = data[pos + 1];
if marker_code == 0xFF {
pos += 1;
continue;
}
if marker_code == 0xE0 {
return parse_jfif_app0(&data[pos + 2..]);
}
if pos + 4 > data.len() {
return None;
}
let seg_length: usize = u16::from_be_bytes([data[pos + 2], data[pos + 3]]) as usize;
if seg_length < 2 {
return None;
}
pos += 2 + seg_length;
}
None
}
fn parse_jfif_app0(data: &[u8]) -> Option<Vec<u8>> {
if data.len() < 2 {
return None;
}
let seg_length: usize = u16::from_be_bytes([data[0], data[1]]) as usize;
if seg_length < 16 {
return None;
}
let payload: &[u8] = &data[2..];
if payload.len() < seg_length - 2 {
return None;
}
if payload.len() < 14 || &payload[..5] != b"JFIF\0" {
return None;
}
let thumb_w: u8 = payload[12];
let thumb_h: u8 = payload[13];
if thumb_w == 0 || thumb_h == 0 {
return None;
}
let thumb_size: usize = thumb_w as usize * thumb_h as usize * 3;
let thumb_start: usize = 14;
if payload.len() < thumb_start + thumb_size {
return None;
}
Some(payload[thumb_start..thumb_start + thumb_size].to_vec())
}