Extending an image (PIL/Pillow) - python

I can use the following code to draw a black strip (or rectangle) atop a base image:
base_width, base_height = img.size
background = Image.new('RGBA', (base_width, base_height/3),(0,0,0,146))
offset = (0,base_height/2)
img.paste(background,offset,mask=background)
Result:
But how do I extend the height of the image such that the said black strip appears attached below the image's bottom border, outside the image itself?
If I move the offset in my code above, the black strip can't move beyond the borders of the base image, so that's not a viable solution.

Here's one way:
Create a new_img that is (base_width, base_height + background.height) in size
Paste the original img into new_img at (0, 0)
Paste the background into new_img at (0, base_height)

Related

Pygame change image colour but preserve transparency

I've got a function that takes an image and adjusts all of the RGB values by a given amount:
def colour(self,img,col):
img = self.my_image.copy()
col = (col[0],col[1],col[2],0)
img.fill(col, None, pygame.BLEND_RGBA_ADD)
return img
I want to apply this to a partially transparent image. But when I apply this to the image, the transparent pixels become coloured. I want these pixels to stay transparent, but any opaque pixels to be coloured as normal. Is there any way I can do this, without having to loop through every pixel and check if each one is transparent before adjusting it? Thanks
fill treats the color to be solid. You have to use blit.
Create a transparent image the size of the source image and fill it with the color. Finally, mix both images:
def colour(self, img, col):
img = self.my_image.copy()
color_img = pygame.Surface(img.get_size(), pygame.SRCALPHA)
color_img.fill((col[0], col[1], col[2], 0))
img.blit(color_img, (0, 0), special_flags = pygame.BLEND_RGBA_ADD)
return img
See also Is it possible to change sprite colours in Pygame?

Remove the black border and keep the image size same in python

I am rotating an image 45 degree. When I rotate the image it has a black border and the image size changes from 256x256 to 364x364. I want to remove the values of this black border and keep the size 256. In pillow if I put fill color then the black border will go away but the size is still the same. Is there any way that I can remove the black border and retain the original shape
code to rotate
path = "E:\\download\\1.jpeg"
image = cv2.imread(path)
rotated = imutils.rotate_bound(image, -33)
Original Image
Rotate image
Keeping the shape while rotating an image is simply not possible in the way you want to. Just like rotating a square-shaped sheet of paper, the horizontal width would enlarge when rotating by e.g. 45°. If you now crop the image on 256x256, you would obtain again black area in the image (see example below). So you would have too crop it even more or zoom in then.
you can try to crop the image as much as part of the image you want. Although the cropping in python is possible in the form of pixels. Hence, you can try to crop the image as much is required.
The following code might help you to crop
im=Image.open(r"specify the path of the image")`
width, height = im.size
left = "specify the value in pixels"
top = "specify the value in pixels"
right = "specify the value in pixels"
bottom = "specify the value in pixels"
# Cropped image of above dimension
# (It will not change original image)
im1 = im.crop((left, top, right, bottom))
#im1.show()
im1.save('specify destination path')

PIL Resizes Image

So I have this code
from PIL import Image
def get_concat_h_cut(im1, im2):
dst = Image.new('RGB', (im1.width + im2.width,
min(im1.height, im2.height)))
dst.paste(im1, (0, 0))
dst.paste(im2, (im1.width, 0))
return dst
def get_concat_v_cut(im1, im2):
dst = Image.new(
'RGB', (min(im1.width, im2.width), im1.height + im2.height))
dst.paste(im1, (0, 0))
dst.paste(im2, (0, im1.height))
return dst
FileA = Image.open("dog.jpg")
FileB = Image.open("cat.jpg")
get_concat_v_cut(FileA, FileB).save('pillow_concat_v_cut.jpg')
But since the reolsution of the cat image is small, the program resizes the entire image, thus I can't see most of the dog image. How do I make it so I can see both the cat and dog?
Cat image: https://i.ibb.co/j58TRnt/cat.jpg
Dog image: https://i.ibb.co/d6jdsBC/dog.jpg
Image that the program generates: https://i.ibb.co/WkDdPTD/pillow-concat-v-cut.jpg
Thank you for your help.
If you wish to keep the width of the dog image the same, which will fill in black space to the right of the cat image on the output image, you can change the size argument for Image.new in your concat function to
(max(im1.width, im2.width), im1.height+im2.height)
The same would apply to your h-cut concat function, just applied to the height argument.
If you're trying to scale them to the same size, you can invoke the .resize() method on whichever one you want to scale, and pass it the other image's height and width variables as it's size argument.
You can find more info here:
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.resize

Overwriting a border on an image in Python PIL

I have a gallery application where the users upload photos and my code gives it a border, writes some of the photo attributes on the border and stores it.
image2 = Image.open('media/' + str(image.file))
width, height = image2.size;
image2 = ImageOps.expand(image2, border=(int(width/25),int(height/20),int(width/25),int(height/10)), fill='rgb(0,0,0)')
(Note that here my bottom border is longer than the top because I am writing attributes on the bottom border.)
Now I'm building an edit feature for the uploaded images where the user can change the attributes of the uploaded images. But the attributes that are already written on the border have to be overwritten.
So here, my approach is to put a black patch on the bottom border and re-write the new attributes without changes the top and side borders and without changing the aspect ratio. All of this has to be done using PIL.
Question is how do I put a black box on the bottom border?
I tried ImageOps.fit() as mentioned here https://pillow.readthedocs.io/en/3.3.x/reference/ImageOps.html#PIL.ImageOps.fit, but the aspect ratio doesn't seem to be right and I want to overwrite on the black border a black box and not crop the photo.
To me it seems like the easiest solution is just quickly draw the black pixels in the area that you want using a couple loops and Image.putpixel
from PIL import Image
img = Image.open('red.png')
for x in range(img.width):
for y in range(img.height - 40, img.height):
img.putpixel((x, y), (0, 0, 0))
img.save('red2.png')
The simplest way in my opinion is to create a new black image and paste onto your existing image -
from PIL import Image
im = Image.open('test.png')
blackBox = Image.new(im.mode, (im.width, 50), '#000')
im.paste(blackBox, (0, im.height - blackBox.height))
Alternatively, you could use ImageDraw - http://pillow.readthedocs.io/en/5.2.x/reference/ImageDraw.html - which you could use to draw rectangles and other shapes.
from PIL import Image, ImageDraw
im = Image.open('test.png')
d = ImageDraw.Draw(im)
d.rectangle((0, im.height - 50, im.width, im.height), fill='#000')

Python: Combining images using paste with overlapping pixels and areas with alpha channel=0

I am trying to combine three images together. The image I want on the bottom is a 700x900 image with all black pixels. On top of that I want to paste an image that is 400x400 with an offset of 100,200. On top of that I want to paste an image border that is 700x900. The image border has alpha=0 in the inside of it and alpha=0 around it because it doesn't have straight edges. When I run the code I have pasted below I encounter 2 problems:
1) Everywhere on the border image where the alpha channel = 0, the alpha channel has been set to 255 and the color white shows instead of the black background and the image I am putting the border around.
2) The border image's quality has been significantly reduced and looks a lot different than it should.
Also: part of the border image will cover part of the Image I am putting the border around. So I can't just switch the order that I am pasting.
Thanks in advance for any help.
#!/usr/bin/python -tt
from PIL import ImageTk, Image
old_im2 = Image.open('backgroundImage1.jpg') # size = 400x400
old_im = Image.open('topImage.png') # size = 700x900
new_size = (700,900)
new_im = Image.new("RGBA", new_size) # makes the black image
new_im.paste(old_im2, (100, 200))
new_im.paste(old_im,(0,0))
new_im.show()
new_im.save('final.jpg')
I think you have a misconception about images - the border image does have pixels everywhere. It's not possible for it to be "missing" pixels. It is possible to have an image with an alpha channel, which is a channel like the R, G, and B channels, but indicates transparency.
Try this:
1. Make sure that topImage.png has a transparency channel, and that the pixels that you want to be "missing" are transparent (i.e. have a maximum alpha value). You can double check this way:
print old_im.mode # This should print "RGBA" if it has an alpha channel.
2. Create new_im in "RGBA" mode:
new_im = Image.new("RGBA", new_size) # makes the black image
# Note the "A" --------^
3. Try this paste statement instead:
new_im.paste(old_im,(0,0), mask=old_im) # Using old_im as the mask argument should tell the paste function to use old_im's alpha channel to combine the two images.

Categories