The good thing with PIL.crop
is that if we want to crop outside of the image dimensions, it simply works with:
from PIL import Image
img = Image.open("test.jpg")
img.crop((-10, -20, 1000, 500)).save("output.jpg")
Question: how to change the background color of the added region to white (default: black)?
Note:
if possible, I'd like to keep crop
, and avoid to have to create a new image and paste the cropped image there like in Crop image, change black area if not not enough photo region in white.
Here is a download link to original image: https://i.stack.imgur.com/gtA70.jpg (303x341 pixels)
I think it is not possible with one function call due to the relevant C function which seems to zero-out the destination image memory region (see it here: https://github.com/python-pillow/Pillow/blob/master/src/libImaging/Crop.c#L47)
You mentioned as not interested to create new Image and copy over it but i am pasting that kind of solution anyway for reference:
from PIL import Image
img = Image.open("test.jpg")
x1, y1, x2, y2 = -10, -20, 1000, 500 # cropping coordinates
bg = Image.new('RGB', (x2 - x1, y2 - y1), (255, 255, 255))
bg.paste(img, (-x1, -y1))
bg.save("output.jpg")
Output:
You can do what you intend to after using the expand()
function available in ImageOps
module of PIL.
from PIL import Image
from PIL import ImageOps
filename = 'C:/Users/Desktop/Maine_Coon_263.jpg'
img = Image.open(filename)
val = 10 #--- pixels to be cropped
#--- a new image with a border of 10 pixels on all sides
#--- also notice fill takes in the color of white as (255, 255, 255)
new_img = ImageOps.expand(img, border = val, fill = (255, 255, 255))
#--- cropping the image above will not result in any black portion
cropped = new_img.crop((val, val, 150, 150))
The crop()
function only takes one parameter of how much portion has to be cropped. There is no functionality to handle the situation when a negative value is passed in. Hence upon passing a negative value the image gets padded in black pixels.
Using the expand()
function you can set the color of your choice and then go ahead and crop as you wish.
In response to your edit, I have something rather naïve in mind but it works.
numpy.abs()
.numpy.max()
.This code will help you:
#--- Consider these values in a tuple that are to crop your image
crop_vals = (-10, -20, 1000, 500)
#--- get maximum value after obtaining the absolute of each
max_val = np.max(np.abs(crop_vals))
#--- add border to the image using this maximum value and crop
new_img = ImageOps.expand(img, border = max_val, fill = (255, 255, 255))
cropped = new_img.crop((max_val - 10, max_val - 20, new_img.size[0], new_img.size[1]))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With