1717from __future__ import annotations
1818
1919import builtins
20+ from types import CodeType
21+ from typing import Any
2022
2123from . import Image , _imagingmath
2224
2325
2426class _Operand :
2527 """Wraps an image operand, providing standard operators"""
2628
27- def __init__ (self , im ):
29+ def __init__ (self , im : Image . Image ):
2830 self .im = im
2931
30- def __fixup (self , im1 ) :
32+ def __fixup (self , im1 : _Operand | float ) -> Image . Image :
3133 # convert image to suitable mode
3234 if isinstance (im1 , _Operand ):
3335 # argument was an image.
@@ -45,122 +47,131 @@ def __fixup(self, im1):
4547 else :
4648 return Image .new ("F" , self .im .size , im1 )
4749
48- def apply (self , op , im1 , im2 = None , mode = None ):
49- im1 = self .__fixup (im1 )
50+ def apply (
51+ self ,
52+ op : str ,
53+ im1 : _Operand | float ,
54+ im2 : _Operand | float | None = None ,
55+ mode : str | None = None ,
56+ ) -> _Operand :
57+ im_1 = self .__fixup (im1 )
5058 if im2 is None :
5159 # unary operation
52- out = Image .new (mode or im1 .mode , im1 .size , None )
53- im1 .load ()
60+ out = Image .new (mode or im_1 .mode , im_1 .size , None )
61+ im_1 .load ()
5462 try :
55- op = getattr (_imagingmath , op + "_" + im1 .mode )
63+ op = getattr (_imagingmath , op + "_" + im_1 .mode )
5664 except AttributeError as e :
5765 msg = f"bad operand type for '{ op } '"
5866 raise TypeError (msg ) from e
59- _imagingmath .unop (op , out .im .id , im1 .im .id )
67+ _imagingmath .unop (op , out .im .id , im_1 .im .id )
6068 else :
6169 # binary operation
62- im2 = self .__fixup (im2 )
63- if im1 .mode != im2 .mode :
70+ im_2 = self .__fixup (im2 )
71+ if im_1 .mode != im_2 .mode :
6472 # convert both arguments to floating point
65- if im1 .mode != "F" :
66- im1 = im1 .convert ("F" )
67- if im2 .mode != "F" :
68- im2 = im2 .convert ("F" )
69- if im1 .size != im2 .size :
73+ if im_1 .mode != "F" :
74+ im_1 = im_1 .convert ("F" )
75+ if im_2 .mode != "F" :
76+ im_2 = im_2 .convert ("F" )
77+ if im_1 .size != im_2 .size :
7078 # crop both arguments to a common size
71- size = (min (im1 .size [0 ], im2 .size [0 ]), min (im1 .size [1 ], im2 .size [1 ]))
72- if im1 .size != size :
73- im1 = im1 .crop ((0 , 0 ) + size )
74- if im2 .size != size :
75- im2 = im2 .crop ((0 , 0 ) + size )
76- out = Image .new (mode or im1 .mode , im1 .size , None )
77- im1 .load ()
78- im2 .load ()
79+ size = (
80+ min (im_1 .size [0 ], im_2 .size [0 ]),
81+ min (im_1 .size [1 ], im_2 .size [1 ]),
82+ )
83+ if im_1 .size != size :
84+ im_1 = im_1 .crop ((0 , 0 ) + size )
85+ if im_2 .size != size :
86+ im_2 = im_2 .crop ((0 , 0 ) + size )
87+ out = Image .new (mode or im_1 .mode , im_1 .size , None )
88+ im_1 .load ()
89+ im_2 .load ()
7990 try :
80- op = getattr (_imagingmath , op + "_" + im1 .mode )
91+ op = getattr (_imagingmath , op + "_" + im_1 .mode )
8192 except AttributeError as e :
8293 msg = f"bad operand type for '{ op } '"
8394 raise TypeError (msg ) from e
84- _imagingmath .binop (op , out .im .id , im1 .im .id , im2 .im .id )
95+ _imagingmath .binop (op , out .im .id , im_1 .im .id , im_2 .im .id )
8596 return _Operand (out )
8697
8798 # unary operators
88- def __bool__ (self ):
99+ def __bool__ (self ) -> bool :
89100 # an image is "true" if it contains at least one non-zero pixel
90101 return self .im .getbbox () is not None
91102
92- def __abs__ (self ):
103+ def __abs__ (self ) -> _Operand :
93104 return self .apply ("abs" , self )
94105
95- def __pos__ (self ):
106+ def __pos__ (self ) -> _Operand :
96107 return self
97108
98- def __neg__ (self ):
109+ def __neg__ (self ) -> _Operand :
99110 return self .apply ("neg" , self )
100111
101112 # binary operators
102- def __add__ (self , other ) :
113+ def __add__ (self , other : _Operand | float ) -> _Operand :
103114 return self .apply ("add" , self , other )
104115
105- def __radd__ (self , other ) :
116+ def __radd__ (self , other : _Operand | float ) -> _Operand :
106117 return self .apply ("add" , other , self )
107118
108- def __sub__ (self , other ) :
119+ def __sub__ (self , other : _Operand | float ) -> _Operand :
109120 return self .apply ("sub" , self , other )
110121
111- def __rsub__ (self , other ) :
122+ def __rsub__ (self , other : _Operand | float ) -> _Operand :
112123 return self .apply ("sub" , other , self )
113124
114- def __mul__ (self , other ) :
125+ def __mul__ (self , other : _Operand | float ) -> _Operand :
115126 return self .apply ("mul" , self , other )
116127
117- def __rmul__ (self , other ) :
128+ def __rmul__ (self , other : _Operand | float ) -> _Operand :
118129 return self .apply ("mul" , other , self )
119130
120- def __truediv__ (self , other ) :
131+ def __truediv__ (self , other : _Operand | float ) -> _Operand :
121132 return self .apply ("div" , self , other )
122133
123- def __rtruediv__ (self , other ) :
134+ def __rtruediv__ (self , other : _Operand | float ) -> _Operand :
124135 return self .apply ("div" , other , self )
125136
126- def __mod__ (self , other ) :
137+ def __mod__ (self , other : _Operand | float ) -> _Operand :
127138 return self .apply ("mod" , self , other )
128139
129- def __rmod__ (self , other ) :
140+ def __rmod__ (self , other : _Operand | float ) -> _Operand :
130141 return self .apply ("mod" , other , self )
131142
132- def __pow__ (self , other ) :
143+ def __pow__ (self , other : _Operand | float ) -> _Operand :
133144 return self .apply ("pow" , self , other )
134145
135- def __rpow__ (self , other ) :
146+ def __rpow__ (self , other : _Operand | float ) -> _Operand :
136147 return self .apply ("pow" , other , self )
137148
138149 # bitwise
139- def __invert__ (self ):
150+ def __invert__ (self ) -> _Operand :
140151 return self .apply ("invert" , self )
141152
142- def __and__ (self , other ) :
153+ def __and__ (self , other : _Operand | float ) -> _Operand :
143154 return self .apply ("and" , self , other )
144155
145- def __rand__ (self , other ) :
156+ def __rand__ (self , other : _Operand | float ) -> _Operand :
146157 return self .apply ("and" , other , self )
147158
148- def __or__ (self , other ) :
159+ def __or__ (self , other : _Operand | float ) -> _Operand :
149160 return self .apply ("or" , self , other )
150161
151- def __ror__ (self , other ) :
162+ def __ror__ (self , other : _Operand | float ) -> _Operand :
152163 return self .apply ("or" , other , self )
153164
154- def __xor__ (self , other ) :
165+ def __xor__ (self , other : _Operand | float ) -> _Operand :
155166 return self .apply ("xor" , self , other )
156167
157- def __rxor__ (self , other ) :
168+ def __rxor__ (self , other : _Operand | float ) -> _Operand :
158169 return self .apply ("xor" , other , self )
159170
160- def __lshift__ (self , other ) :
171+ def __lshift__ (self , other : _Operand | float ) -> _Operand :
161172 return self .apply ("lshift" , self , other )
162173
163- def __rshift__ (self , other ) :
174+ def __rshift__ (self , other : _Operand | float ) -> _Operand :
164175 return self .apply ("rshift" , self , other )
165176
166177 # logical
@@ -170,46 +181,46 @@ def __eq__(self, other):
170181 def __ne__ (self , other ):
171182 return self .apply ("ne" , self , other )
172183
173- def __lt__ (self , other ) :
184+ def __lt__ (self , other : _Operand | float ) -> _Operand :
174185 return self .apply ("lt" , self , other )
175186
176- def __le__ (self , other ) :
187+ def __le__ (self , other : _Operand | float ) -> _Operand :
177188 return self .apply ("le" , self , other )
178189
179- def __gt__ (self , other ) :
190+ def __gt__ (self , other : _Operand | float ) -> _Operand :
180191 return self .apply ("gt" , self , other )
181192
182- def __ge__ (self , other ) :
193+ def __ge__ (self , other : _Operand | float ) -> _Operand :
183194 return self .apply ("ge" , self , other )
184195
185196
186197# conversions
187- def imagemath_int (self ) :
198+ def imagemath_int (self : _Operand ) -> _Operand :
188199 return _Operand (self .im .convert ("I" ))
189200
190201
191- def imagemath_float (self ) :
202+ def imagemath_float (self : _Operand ) -> _Operand :
192203 return _Operand (self .im .convert ("F" ))
193204
194205
195206# logical
196- def imagemath_equal (self , other ) :
207+ def imagemath_equal (self : _Operand , other : _Operand | float | None ) -> _Operand :
197208 return self .apply ("eq" , self , other , mode = "I" )
198209
199210
200- def imagemath_notequal (self , other ) :
211+ def imagemath_notequal (self : _Operand , other : _Operand | float | None ) -> _Operand :
201212 return self .apply ("ne" , self , other , mode = "I" )
202213
203214
204- def imagemath_min (self , other ) :
215+ def imagemath_min (self : _Operand , other : _Operand | float | None ) -> _Operand :
205216 return self .apply ("min" , self , other )
206217
207218
208- def imagemath_max (self , other ) :
219+ def imagemath_max (self : _Operand , other : _Operand | float | None ) -> _Operand :
209220 return self .apply ("max" , self , other )
210221
211222
212- def imagemath_convert (self , mode ) :
223+ def imagemath_convert (self : _Operand , mode : str ) -> _Operand :
213224 return _Operand (self .im .convert (mode ))
214225
215226
@@ -219,7 +230,7 @@ def imagemath_convert(self, mode):
219230 ops [k [10 :]] = v
220231
221232
222- def eval (expression , _dict = {}, ** kw ) :
233+ def eval (expression : str , _dict : dict [ str , Any ] = {}, ** kw : Any ) -> Any :
223234 """
224235 Evaluates an image expression.
225236
@@ -247,7 +258,7 @@ def eval(expression, _dict={}, **kw):
247258
248259 compiled_code = compile (expression , "<string>" , "eval" )
249260
250- def scan (code ) :
261+ def scan (code : CodeType ) -> None :
251262 for const in code .co_consts :
252263 if type (const ) is type (compiled_code ):
253264 scan (const )
0 commit comments