1+ use std:: collections:: HashMap ;
2+ use std:: fmt:: Debug ;
13use std:: io:: { Cursor , Read } ;
24
35use bytes:: Bytes ;
@@ -7,47 +9,138 @@ use tiff::{TiffError, TiffUnsupportedError};
79
810use crate :: error:: Result ;
911
12+ /// A registry of decoders.
13+ #[ derive( Debug ) ]
14+ pub struct DecoderRegistry ( HashMap < CompressionMethod , Box < dyn Decoder > > ) ;
15+
16+ impl DecoderRegistry {
17+ /// Create a new decoder registry with no decoders registered
18+ pub fn new ( ) -> Self {
19+ Self ( HashMap :: new ( ) )
20+ }
21+ }
22+
23+ impl AsRef < HashMap < CompressionMethod , Box < dyn Decoder > > > for DecoderRegistry {
24+ fn as_ref ( & self ) -> & HashMap < CompressionMethod , Box < dyn Decoder > > {
25+ & self . 0
26+ }
27+ }
28+
29+ impl AsMut < HashMap < CompressionMethod , Box < dyn Decoder > > > for DecoderRegistry {
30+ fn as_mut ( & mut self ) -> & mut HashMap < CompressionMethod , Box < dyn Decoder > > {
31+ & mut self . 0
32+ }
33+ }
34+
35+ impl Default for DecoderRegistry {
36+ fn default ( ) -> Self {
37+ let mut registry = HashMap :: with_capacity ( 5 ) ;
38+ registry. insert ( CompressionMethod :: None , Box :: new ( UncompressedDecoder ) as _ ) ;
39+ registry. insert ( CompressionMethod :: Deflate , Box :: new ( DeflateDecoder ) as _ ) ;
40+ registry. insert ( CompressionMethod :: OldDeflate , Box :: new ( DeflateDecoder ) as _ ) ;
41+ registry. insert ( CompressionMethod :: LZW , Box :: new ( LZWDecoder ) as _ ) ;
42+ registry. insert ( CompressionMethod :: ModernJPEG , Box :: new ( JPEGDecoder ) as _ ) ;
43+ Self ( registry)
44+ }
45+ }
46+
47+ /// A trait to decode a TIFF tile.
48+ pub trait Decoder : Debug + Send + Sync {
49+ fn decode_tile (
50+ & self ,
51+ buffer : Bytes ,
52+ photometric_interpretation : PhotometricInterpretation ,
53+ jpeg_tables : Option < & [ u8 ] > ,
54+ ) -> Result < Bytes > ;
55+ }
56+
57+ #[ derive( Debug , Clone ) ]
58+ pub struct DeflateDecoder ;
59+
60+ impl Decoder for DeflateDecoder {
61+ fn decode_tile (
62+ & self ,
63+ buffer : Bytes ,
64+ _photometric_interpretation : PhotometricInterpretation ,
65+ _jpeg_tables : Option < & [ u8 ] > ,
66+ ) -> Result < Bytes > {
67+ let mut decoder = ZlibDecoder :: new ( Cursor :: new ( buffer) ) ;
68+ let mut buf = Vec :: new ( ) ;
69+ decoder. read_to_end ( & mut buf) ?;
70+ Ok ( buf. into ( ) )
71+ }
72+ }
73+
74+ #[ derive( Debug , Clone ) ]
75+ pub struct JPEGDecoder ;
76+
77+ impl Decoder for JPEGDecoder {
78+ fn decode_tile (
79+ & self ,
80+ buffer : Bytes ,
81+ photometric_interpretation : PhotometricInterpretation ,
82+ jpeg_tables : Option < & [ u8 ] > ,
83+ ) -> Result < Bytes > {
84+ decode_modern_jpeg ( buffer, photometric_interpretation, jpeg_tables)
85+ }
86+ }
87+
88+ #[ derive( Debug , Clone ) ]
89+ pub struct LZWDecoder ;
90+
91+ impl Decoder for LZWDecoder {
92+ fn decode_tile (
93+ & self ,
94+ buffer : Bytes ,
95+ _photometric_interpretation : PhotometricInterpretation ,
96+ _jpeg_tables : Option < & [ u8 ] > ,
97+ ) -> Result < Bytes > {
98+ // https://github.com/image-rs/image-tiff/blob/90ae5b8e54356a35e266fb24e969aafbcb26e990/src/decoder/stream.rs#L147
99+ let mut decoder = weezl:: decode:: Decoder :: with_tiff_size_switch ( weezl:: BitOrder :: Msb , 8 ) ;
100+ let decoded = decoder. decode ( & buffer) . expect ( "failed to decode LZW data" ) ;
101+ Ok ( decoded. into ( ) )
102+ }
103+ }
104+
105+ #[ derive( Debug , Clone ) ]
106+ pub struct UncompressedDecoder ;
107+
108+ impl Decoder for UncompressedDecoder {
109+ fn decode_tile (
110+ & self ,
111+ buffer : Bytes ,
112+ _photometric_interpretation : PhotometricInterpretation ,
113+ _jpeg_tables : Option < & [ u8 ] > ,
114+ ) -> Result < Bytes > {
115+ Ok ( buffer)
116+ }
117+ }
118+
10119// https://github.com/image-rs/image-tiff/blob/3bfb43e83e31b0da476832067ada68a82b378b7b/src/decoder/image.rs#L370
11120pub ( crate ) fn decode_tile (
12121 buf : Bytes ,
13122 photometric_interpretation : PhotometricInterpretation ,
14123 compression_method : CompressionMethod ,
15124 // compressed_length: u64,
16- jpeg_tables : Option < & Vec < u8 > > ,
125+ jpeg_tables : Option < & [ u8 ] > ,
126+ decoder_registry : & DecoderRegistry ,
17127) -> Result < Bytes > {
18- match compression_method {
19- CompressionMethod :: None => Ok ( buf) ,
20- CompressionMethod :: LZW => decode_lzw ( buf) ,
21- CompressionMethod :: Deflate | CompressionMethod :: OldDeflate => decode_deflate ( buf) ,
22- CompressionMethod :: ModernJPEG => {
23- decode_modern_jpeg ( buf, photometric_interpretation, jpeg_tables)
24- }
25- method => Err ( TiffError :: UnsupportedError (
26- TiffUnsupportedError :: UnsupportedCompressionMethod ( method) ,
27- )
28- . into ( ) ) ,
29- }
30- }
31-
32- fn decode_lzw ( buf : Bytes ) -> Result < Bytes > {
33- // https://github.com/image-rs/image-tiff/blob/90ae5b8e54356a35e266fb24e969aafbcb26e990/src/decoder/stream.rs#L147
34- let mut decoder = weezl:: decode:: Decoder :: with_tiff_size_switch ( weezl:: BitOrder :: Msb , 8 ) ;
35- let decoded = decoder. decode ( & buf) . expect ( "failed to decode LZW data" ) ;
36- Ok ( decoded. into ( ) )
37- }
128+ let decoder =
129+ decoder_registry
130+ . 0
131+ . get ( & compression_method)
132+ . ok_or ( TiffError :: UnsupportedError (
133+ TiffUnsupportedError :: UnsupportedCompressionMethod ( compression_method) ,
134+ ) ) ?;
38135
39- fn decode_deflate ( buf : Bytes ) -> Result < Bytes > {
40- let mut decoder = ZlibDecoder :: new ( Cursor :: new ( buf) ) ;
41- let mut buf = Vec :: new ( ) ;
42- decoder. read_to_end ( & mut buf) ?;
43- Ok ( buf. into ( ) )
136+ decoder. decode_tile ( buf, photometric_interpretation, jpeg_tables)
44137}
45138
46139// https://github.com/image-rs/image-tiff/blob/3bfb43e83e31b0da476832067ada68a82b378b7b/src/decoder/image.rs#L389-L450
47140fn decode_modern_jpeg (
48141 buf : Bytes ,
49142 photometric_interpretation : PhotometricInterpretation ,
50- jpeg_tables : Option < & Vec < u8 > > ,
143+ jpeg_tables : Option < & [ u8 ] > ,
51144) -> Result < Bytes > {
52145 // Construct new jpeg_reader wrapping a SmartReader.
53146 //
@@ -76,13 +169,9 @@ fn decode_modern_jpeg(
76169
77170 match photometric_interpretation {
78171 PhotometricInterpretation :: RGB => decoder. set_color_transform ( jpeg:: ColorTransform :: RGB ) ,
79- PhotometricInterpretation :: WhiteIsZero => {
80- decoder. set_color_transform ( jpeg:: ColorTransform :: None )
81- }
82- PhotometricInterpretation :: BlackIsZero => {
83- decoder. set_color_transform ( jpeg:: ColorTransform :: None )
84- }
85- PhotometricInterpretation :: TransparencyMask => {
172+ PhotometricInterpretation :: WhiteIsZero
173+ | PhotometricInterpretation :: BlackIsZero
174+ | PhotometricInterpretation :: TransparencyMask => {
86175 decoder. set_color_transform ( jpeg:: ColorTransform :: None )
87176 }
88177 PhotometricInterpretation :: CMYK => decoder. set_color_transform ( jpeg:: ColorTransform :: CMYK ) ,
0 commit comments