df_ocr_switcher/input/
tiff.rs1use std::io::BufReader;
7use std::path::Path;
8
9use image::{DynamicImage, RgbImage};
10use tiff::ColorType as TiffColorType;
11use tiff::decoder::{Decoder, DecodingResult};
12
13use crate::error::{Error, Result};
14
15pub fn load_tiff_pages(path: impl AsRef<Path>) -> Result<Vec<RgbImage>> {
18 let path = path.as_ref();
19 let file = BufReader::new(std::fs::File::open(path)?);
20 let mut dec = Decoder::new(file)
21 .map_err(|e| Error::Tiff(format!("init decoder: {e}")))?;
22
23 let mut pages = Vec::new();
24 loop {
25 let page = decode_current(&mut dec, pages.len())?;
26 pages.push(page);
27 if dec.more_images() {
28 dec.next_image()
29 .map_err(|e| Error::Tiff(format!("next_image pag.{}: {e}", pages.len())))?;
30 } else {
31 break;
32 }
33 }
34 Ok(pages)
35}
36
37fn decode_current<R: std::io::Read + std::io::Seek>(
40 dec: &mut Decoder<R>,
41 page_idx: usize,
42) -> Result<RgbImage> {
43 let (w, h) = dec.dimensions()
44 .map_err(|e| Error::Tiff(format!("dimensions pag.{page_idx}: {e}")))?;
45 let color = dec.colortype()
46 .map_err(|e| Error::Tiff(format!("colortype pag.{page_idx}: {e}")))?;
47 let buf = dec.read_image()
48 .map_err(|e| Error::Tiff(format!("read_image pag.{page_idx}: {e}")))?;
49
50 let dyn_img: DynamicImage = match (color, buf) {
51 (TiffColorType::Gray(8), DecodingResult::U8(b)) =>
52 DynamicImage::ImageLuma8(
53 image::ImageBuffer::from_raw(w, h, b)
54 .ok_or_else(|| tiff_err(page_idx, "Luma8 from_raw"))?),
55
56 (TiffColorType::RGB(8), DecodingResult::U8(b)) =>
57 DynamicImage::ImageRgb8(
58 image::ImageBuffer::from_raw(w, h, b)
59 .ok_or_else(|| tiff_err(page_idx, "RGB8 from_raw"))?),
60
61 (TiffColorType::RGBA(8), DecodingResult::U8(b)) =>
62 DynamicImage::ImageRgba8(
63 image::ImageBuffer::from_raw(w, h, b)
64 .ok_or_else(|| tiff_err(page_idx, "RGBA8 from_raw"))?),
65
66 (TiffColorType::Gray(16), DecodingResult::U16(b)) => {
68 let b8: Vec<u8> = b.iter().map(|&v| (v >> 8) as u8).collect();
69 DynamicImage::ImageLuma8(
70 image::ImageBuffer::from_raw(w, h, b8)
71 .ok_or_else(|| tiff_err(page_idx, "Gray16→8 from_raw"))?)
72 }
73
74 (TiffColorType::RGB(16), DecodingResult::U16(b)) => {
75 let b8: Vec<u8> = b.iter().map(|&v| (v >> 8) as u8).collect();
76 DynamicImage::ImageRgb8(
77 image::ImageBuffer::from_raw(w, h, b8)
78 .ok_or_else(|| tiff_err(page_idx, "RGB16→8 from_raw"))?)
79 }
80
81 (ct, _) => return Err(Error::Tiff(
82 format!("pag.{page_idx}: tipo colore non gestito: {ct:?}"))),
83 };
84
85 Ok(dyn_img.to_rgb8())
86}
87
88fn tiff_err(page: usize, msg: &str) -> Error {
89 Error::Tiff(format!("pag.{page}: {msg} fallito"))
90}