@@ -210,8 +210,8 @@ def scale(*args, **kwargs):
210
210
return resize (* args , ** kwargs )
211
211
212
212
213
- def pad (img , padding , fill = 0 ):
214
- """Pad the given PIL Image on all sides with the given "pad" value.
213
+ def pad (img , padding , fill = 0 , padding_mode = 'constant' ):
214
+ """Pad the given PIL Image on all sides with speficified padding mode and fill value.
215
215
216
216
Args:
217
217
img (PIL Image): Image to be padded.
@@ -220,8 +220,18 @@ def pad(img, padding, fill=0):
220
220
on left/right and top/bottom respectively. If a tuple of length 4 is provided
221
221
this is the padding for the left, top, right and bottom borders
222
222
respectively.
223
- fill: Pixel fill value. Default is 0. If a tuple of
223
+ fill: Pixel fill value for constant fill . Default is 0. If a tuple of
224
224
length 3, it is used to fill R, G, B channels respectively.
225
+ This value is only used when the padding_mode is constant
226
+ padding_mode: Type of padding. Should be: constant, edge, reflect or symmetric. Default is constant.
227
+ constant: pads with a constant value, this value is specified with fill
228
+ edge: pads with the last value on the edge of the image
229
+ reflect: pads with reflection of image (without repeating the last value on the edge)
230
+ padding [1, 2, 3, 4] with 2 elements on both sides in reflect mode
231
+ will result in [3, 2, 1, 2, 3, 4, 3, 2]
232
+ symmetric: pads with reflection of image (repeating the last value on the edge)
233
+ padding [1, 2, 3, 4] with 2 elements on both sides in symmetric mode
234
+ will result in [2, 1, 1, 2, 3, 4, 4, 3]
225
235
226
236
Returns:
227
237
PIL Image: Padded image.
@@ -233,12 +243,39 @@ def pad(img, padding, fill=0):
233
243
raise TypeError ('Got inappropriate padding arg' )
234
244
if not isinstance (fill , (numbers .Number , str , tuple )):
235
245
raise TypeError ('Got inappropriate fill arg' )
246
+ if not isinstance (padding_mode , str ):
247
+ raise TypeError ('Got inappropriate padding_mode arg' )
236
248
237
249
if isinstance (padding , collections .Sequence ) and len (padding ) not in [2 , 4 ]:
238
250
raise ValueError ("Padding must be an int or a 2, or 4 element tuple, not a " +
239
251
"{} element tuple" .format (len (padding )))
240
252
241
- return ImageOps .expand (img , border = padding , fill = fill )
253
+ assert padding_mode in ['constant' , 'edge' , 'reflect' , 'symmetric' ], \
254
+ 'Padding mode should be either constant, edge, reflect or symmetric'
255
+
256
+ if padding_mode == 'constant' :
257
+ return ImageOps .expand (img , border = padding , fill = fill )
258
+ else :
259
+ if isinstance (padding , int ):
260
+ pad_left = pad_right = pad_top = pad_bottom = padding
261
+ if isinstance (padding , collections .Sequence ) and len (padding ) == 2 :
262
+ pad_left = pad_right = padding [0 ]
263
+ pad_top = pad_bottom = padding [1 ]
264
+ if isinstance (padding , collections .Sequence ) and len (padding ) == 4 :
265
+ pad_left = padding [0 ]
266
+ pad_top = padding [1 ]
267
+ pad_right = padding [2 ]
268
+ pad_bottom = padding [3 ]
269
+
270
+ img = np .asarray (img )
271
+ # RGB image
272
+ if len (img .shape ) == 3 :
273
+ img = np .pad (img , ((pad_top , pad_bottom ), (pad_left , pad_right ), (0 , 0 )), padding_mode )
274
+ # Grayscale image
275
+ if len (img .shape ) == 2 :
276
+ img = np .pad (img , ((pad_top , pad_bottom ), (pad_left , pad_right )), padding_mode )
277
+
278
+ return Image .fromarray (img )
242
279
243
280
244
281
def crop (img , i , j , h , w ):
0 commit comments