@@ -53,7 +53,16 @@ def horz_dpi(self):
5353 and ResolutionUnit tags of the IFD; defaults to 72 if those tags are
5454 not present.
5555 """
56- raise NotImplementedError
56+ return self ._dpi (TIFF_TAG .X_RESOLUTION )
57+
58+ @property
59+ def vert_dpi (self ):
60+ """
61+ The vertical dots per inch value calculated from the XResolution and
62+ ResolutionUnit tags of the IFD; defaults to 72 if those tags are not
63+ present.
64+ """
65+ return self ._dpi (TIFF_TAG .Y_RESOLUTION )
5766
5867 @property
5968 def px_height (self ):
@@ -73,15 +82,6 @@ def px_width(self):
7382 """
7483 return self ._ifd_entries .get (TIFF_TAG .IMAGE_WIDTH )
7584
76- @property
77- def vert_dpi (self ):
78- """
79- The vertical dots per inch value calculated from the XResolution and
80- ResolutionUnit tags of the IFD; defaults to 72 if those tags are not
81- present.
82- """
83- raise NotImplementedError
84-
8585 @classmethod
8686 def _detect_endian (cls , stream ):
8787 """
@@ -92,6 +92,23 @@ def _detect_endian(cls, stream):
9292 endian_str = stream .read (2 )
9393 return BIG_ENDIAN if endian_str == b'MM' else LITTLE_ENDIAN
9494
95+ def _dpi (self , resolution_tag ):
96+ """
97+ Return the dpi value calculated for *resolution_tag*, which can be
98+ either TIFF_TAG.X_RESOLUTION or TIFF_TAG.Y_RESOLUTION. The
99+ calculation is based on the values of both that tag and the
100+ TIFF_TAG.RESOLUTION_UNIT tag in this parser's |_IfdEntries| instance.
101+ """
102+ if resolution_tag not in self ._ifd_entries :
103+ return 72
104+ resolution_unit = self ._ifd_entries [TIFF_TAG .RESOLUTION_UNIT ]
105+ if resolution_unit == 1 : # aspect ratio only
106+ return 72
107+ # resolution_unit == 2 for inches, 3 for centimeters
108+ units_per_inch = 1 if resolution_unit == 2 else 2.54
109+ dots_per_unit = self ._ifd_entries [resolution_tag ]
110+ return int (round (dots_per_unit * units_per_inch ))
111+
95112 @classmethod
96113 def _make_stream_reader (cls , stream ):
97114 """
@@ -112,6 +129,18 @@ def __init__(self, entries):
112129 super (_IfdEntries , self ).__init__ ()
113130 self ._entries = entries
114131
132+ def __contains__ (self , key ):
133+ """
134+ Provides ``in`` operator, e.g. ``tag in ifd_entries``
135+ """
136+ return self ._entries .__contains__ (key )
137+
138+ def __getitem__ (self , key ):
139+ """
140+ Provides indexed access, e.g. ``tag_value = ifd_entries[tag_code]``
141+ """
142+ return self ._entries .__getitem__ (key )
143+
115144 @classmethod
116145 def from_stream (cls , stream , offset ):
117146 """
0 commit comments