11use std:: collections:: HashMap ;
2+ use std:: fmt:: Debug ;
23use std:: ops:: Range ;
4+ use std:: sync:: Arc ;
35
46use bytes:: Bytes ;
57use num_enum:: TryFromPrimitive ;
@@ -17,6 +19,48 @@ use crate::tile::Tile;
1719
1820const DOCUMENT_NAME : u16 = 269 ;
1921
22+ /// Trait to implement for custom tags, such as Geo, EXIF, OME, etc
23+ pub trait ExtraTags : ExtraTagsCloneArc + std:: any:: Any + Debug {
24+ /// a list of tags this entry processes
25+ /// e.g. for Geo this would be [34735, 34736, 34737]
26+ fn tags ( & self ) -> & ' static [ Tag ] ;
27+ /// process a single tag
28+ fn process_tag ( & mut self , tag : u16 , value : Value ) -> AsyncTiffResult < ( ) > ;
29+ }
30+
31+ //
32+ pub trait ExtraTagsCloneArc {
33+ fn clone_arc ( & self ) -> Arc < dyn ExtraTags > ;
34+ }
35+
36+ impl < T > ExtraTagsCloneArc for T
37+ where
38+ T : ' static + ExtraTags + Clone
39+ {
40+ fn clone_arc ( & self ) -> Arc < dyn ExtraTags > {
41+ Arc :: new ( self . clone ( ) )
42+ }
43+ }
44+
45+ #[ derive( Debug , Clone ) ]
46+ pub struct ExtraTagsRegistry ( HashMap < Tag , Arc < dyn ExtraTags > > ) ;
47+
48+ impl ExtraTagsRegistry {
49+ pub fn register ( & mut self , tags : Arc < dyn ExtraTags > ) -> AsyncTiffResult < ( ) > {
50+ // check for duplicates
51+ for tag in tags. tags ( ) {
52+ if self . 0 . contains_key ( tag) {
53+ return Err ( AsyncTiffError :: General ( format ! ( "Tag {tag:?} already registered in {self:?}!" ) ) ) ;
54+ }
55+ }
56+ // add to self
57+ for tag in tags. tags ( ) {
58+ self . 0 . insert ( * tag, tags. clone ( ) ) ;
59+ }
60+ Ok ( ( ) )
61+ }
62+ }
63+
2064/// An ImageFileDirectory representing Image content
2165// The ordering of these tags matches the sorted order in TIFF spec Appendix A
2266#[ allow( dead_code) ]
@@ -133,6 +177,8 @@ pub struct ImageFileDirectory {
133177
134178 pub ( crate ) copyright : Option < String > ,
135179
180+ pub ( crate ) extra_tags : ExtraTagsRegistry ,
181+
136182 // Geospatial tags
137183 pub ( crate ) geo_key_directory : Option < GeoKeyDirectory > ,
138184 pub ( crate ) model_pixel_scale : Option < Vec < f64 > > ,
@@ -149,6 +195,7 @@ impl ImageFileDirectory {
149195 pub fn from_tags (
150196 tag_data : HashMap < Tag , Value > ,
151197 endianness : Endianness ,
198+ extra_tags_registry : ExtraTagsRegistry
152199 ) -> AsyncTiffResult < Self > {
153200 let mut new_subfile_type = None ;
154201 let mut image_width = None ;
@@ -398,6 +445,7 @@ impl ImageFileDirectory {
398445 geo_key_directory,
399446 model_pixel_scale,
400447 model_tiepoint,
448+ extra_tags : extra_tags_registry,
401449 other_tags,
402450 } )
403451 }
0 commit comments