Alternatives to PIL/Pillow for overlaying an image with text - python

Do any Python alternatives exist for overlaying an image with text? I tried with PIL/Pillow, but the output is really grainy and artifacted.
Here is my code:
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
img = Image.open("image.jpg")
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("Comic Sans MS.ttf", 24)
draw.text((150, 20),"Sample Text",(170,14,179), font=font)
img.save('sample-out123.jpg')
and the output:
You can see artifacting around the text as well as a light purple glow.

This is a known problem with JPEG images.
Try changing the image quality:
img.save('sample-out123.jpg', quality=95)
Or, save as a PNG.
img.save('sample-out123.png')

Related

How to change the background of an image using PIL?

I was trying to find how to remove/change the background of a grayscale image in Python using PIL package but I failed. What I have is an RGB image which has a white background and I would like to load it, resize, change the background from white to black and save. So far I can do the beginning:
from PIL import Image
img = Image.open('my_picture.jpg').convert('LA')
# im1 = img.crop((left, top, right, bottom))
which gives me a grayscale image of a size I want but now I do not know how to change the background. I have found a really good post using cv2 for cropping the image out from a green bg and also another setting the background directly, but I couldn't find it for PIL. Is there such an option?
Convert image into RGB and get the data. Then do follow the step.
from PIL import Image
img = Image.open("test_image.jpg")
img = img.convert("RGB")
datas = img.getdata()
new_image_data = []
for item in datas:
if item[0] in list(range(190, 256)):
new_image_data.append((255, 204, 100))
else:
new_image_data.append(item)
img.putdata(new_image_data)
img.save("test_image_altered_background.jpg")
img.show()
You can get some idea from here

How to create an exact match of an image using PIL in python?

I'm seeing a tiny difference in image I created using PIL of python than the actual one and because of this difference my sikuli script fails to click since its an image based automation tool.
The approach is to create an image & click it, based on the object name to be clicked on screen during run-time.
Code to create image :
import PIL
from PIL import ImageFont
from PIL import Image
from PIL import ImageDraw
from PIL import ImageEnhance
font = ImageFont.truetype("C:\\SikuliWS\\R419\\Fonts\\calibri.ttf",11)
img=Image.new("RGBA", (0,0)) #To create an empty white background
draw = ImageDraw.Draw(img) #draw an image with 0,0
textsze = draw.textsize(imageString) #Create a text to capture w/h
print textsze
img=Image.new("RGBA", (textsze[0],textsze[1]+3),(255,255,255)) #create a white background as per the w/h of text passed
draw = ImageDraw.Draw(img)
draw.text((0, 0),imageString,(13,13,13),font=font)
img.save("imageString.png", format='PNG',quality=100)
Output:
Actual image created:
Expected image:
Notice the tiny difference between characters ID and the space between characters because of which sikuli fails to click.
How do I create an exact match of image using python 2.7? Please help.

How to convert a 24 color bmp image to 16 color bmp in python

For my current task, I need to convert a 24 color bmp, to a 16 color bmp file. and Print the image in the pdf file. I tired using the PIL module,but it didn't helped me.
from PIL import Image
path = r'C:\Display_Icon_Testing\Captured_Images\Impl_Modulation_Screen.bmp'
im = Image.open(path)
print im
im1 = Image.open(path).convert('P')
print im1
please help me with this.
The code below will read an image in any format that PIL understands, convert it to 16 colors, and save it as a PDF file. By default, PIL uses Floyd-Steinberg dithering to improve the image quality when converting a 24 bit image to a palette-based image.
I'm using the Pillow fork of PIL, since the original PIL is no longer maintained, but this code should work properly on original PIL or Pillow.
from PIL import Image
iname = 'test.bmp'
oname = 'test.pdf'
img = Image.open(iname)
newimg = img.convert(mode='P', colors=16)
newimg.save(oname)

PIL - Add semi-transparent polygon to JPEG

I'm trying to use this this approach to add a semi-transparent polygon to an image. The problem is the image is a JPEG. I know that JPEGs don't have an alpha channel, so I was hoping there was a way I could have PIL take in a JPEG, convert it to a form which has an alpha channel, add the semi-transparent mask, then merge the mask with the image and convert it back into a JPEG for saving. Can PIL accomplish this? If not, how else might I go about doing this? Thanks!
That's easy. Just paste the jpeg into a new rgba Image():
#!/usr/bin/env python3
from PIL import Image
from PIL import ImageDraw
im = Image.open("existing.jpg")
logo = Image.open("python-32.png")
back = Image.new('RGBA', im.size)
back.paste(im)
poly = Image.new('RGBA', (512,512))
pdraw = ImageDraw.Draw(poly)
pdraw.polygon([(128,128),(384,384),(128,384),(384,128)],
fill=(255,255,255,127),outline=(255,255,255,255))
back.paste(poly, (0,0), mask=poly)
back.paste(logo, (im.size[0]-logo.size[0], im.size[1]-logo.size[1]), mask=logo)
back.show()
This additionally adds a png (with transparency) to the image.

How to convert a Pyglet image to a PIL image?

i want to convert a Pyglet.AbstractImage object to an PIL image for further manipulation
here are my codes
from pyglet import image
from PIL import Image
pic = image.load('pic.jpg')
data = pic.get_data('RGB', pic.pitch)
im = Image.fromstring('RGB', (pic.width, pic.height), data)
im.show()
but the image shown went wrong.
so how to convert an image from pyglet to PIL properly?
I think I find the solution
the pitch in Pyglet.AbstractImage instance is not compatible with PIL
I found in pyglet 1.1 there is a codec function to encode the Pyglet image to PIL
here is the link to the source
so the code above should be modified to this
from pyglet import image
from PIL import Image
pic = image.load('pic.jpg')
pitch = -(pic.width * len('RGB'))
data = pic.get_data('RGB', pitch) # using the new pitch
im = Image.fromstring('RGB', (pic.width, pic.height), data)
im.show()
I'm using a 461x288 image in this case and find that pic.pitch is -1384
but the new pitch is -1383
This is an open wishlist item:
AbstractImage to/from PIL image.

Categories