I just wanted to write some text on picture using PIL and Python 3.8.6 in my Discord Bot while a member joined but it did not shows correctly, Here is my code and result picture.
background = Image.open("./photos/Sans titre 1.png").convert("RGBA")
basewidth = 227
img = Image.open(BytesIO(response.content)).convert("RGBA")
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
cercle = Image.open("./photos/cercle_orange.png").convert("RGBA")
img_w, img_h = img.size
cr_w,cr_h = cercle.size
# make a blank image for the text, initialized to transparent text color
txt = Image.new("RGBA", background.size, (255,255,255,0))
msg = "WELCOME"
new_member = u"{}#{}".format(member.name,member.discriminator)
fnt = ImageFont.truetype("./fonts/DejaVuSans.ttf", 80)
fntname = ImageFont.truetype("./fonts/DejaVuSans.ttf",50)
# get a drawing context
d = ImageDraw.Draw(txt)
bg_w, bg_h = background.size
offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2)
w, h = d.textsize(msg,font=fnt)
w2, h2 = d.textsize(new_member,font=fntname)
d.text(((bg_w-w)/2,((bg_h-h)/2)+160), msg, font=fnt, fill='#FFAA39')
d.text((((bg_w-w2)/2),((bg_h-h2)/2)+220), new_member, font=fntname, fill=(255,255,255,255))
background.paste(profile, offset, profile)
my bot welcome picture in Discord
Discord Welcome Picture
i already search how to transfer the text to unicode and it didn't work however i changed the font that i use in my bot code, i want it to show the name π―πππ€ ππ’π§πΎπ correctly in my code as this second picture from Koya Bot:
Koya Welcome Picture in Discord
Koya Welcome Picture
i Hope you can help me,Thank you guys for listening.
This behaviour of displaying squares typically happens when the font cannot render the specified characters, which could mean that the font is corrupted or simply that the specified font is missing glyphs for those specific characters. Most commonly used fonts have a wide range of glyphs that cover common scripts (latin, greek, hebrew, cyrillic, arabic, etc).
You might want to try changing the font to see if it that works, if it does, then the problem is the font, you might want to try finding another source for that font to see if it includes the necessary glyphs, or directly change the font.
Related
I'm trying to render every character in different fonts, and some fonts give me empty boxes instead of characters, and I honestly don't know what I'm doing wrong, I tried to change the layout engine, I was playing with encoding, but still I sometimes get empty boxes, and I really don't want to go through 250 thousand images to remove these empty boxes
My code is presented below:
def draw_glyph(font_file, unicode_char, glyph_size=128):
try:
font = ImageFont.truetype(
font=f"{font_file}",
encoding="",
size=glyph_size,
layout_engine=ImageFont.LAYOUT_RAQM,
)
except Exception:
font = None
if font is not None:
img = Image.new('L', (glyph_size, glyph_size), 'white')
draw = ImageDraw.Draw(img)
draw.text(
xy=(64, 64),
text=unicode_char,
font=font,
anchor='mm',
)
return img
return None
[SOLVED]
Please don't judge the code. I just need to fix one bug with capturing canvas into file.
As you can see I've tried multiple solutions and still while saving file is all-white...
Do you have any soulutions to that?
This app is to generate randomly dots on canvas with option to save it.
it works when number of dots is above 40000 and rectangle is black.
But otherwise is white.
HEIGTH = 207
WIDTH = 207
def snapsaveCanvas():
fname = filename.get()
my_window.update_idletasks()
my_window.update()
canvas.update()
canvas.update_idletasks()
ps = canvas.postscript(colormode='color')
img = Image.open(io.BytesIO(ps.encode('utf-8')))
img.save(fname + ".bmp", 'bmp')
print("done")
canvas = tk.Canvas(frame2, width=HEIGTH, height=WIDTH, background='white')
canvas.grid(row=0, column=0)
canvas.create_rectangle(4, 4, 206, 206)
Ok, thanks for links.
I've tested several methods and one of them works.
taken from How can I convert canvas content to an image?
import win32gui
def snapsaveCanvas():
fileName = filename.get()
canvas.update()
canvas.update_idletasks()
HWND = canvas.winfo_id() # get the handle of the canvas
rect = win32gui.GetWindowRect(HWND) # get the coordinate of the canvas
im = ImageGrab.grab(rect).save(fileName + ".bmp")
print("done")
So I have this code:
import win32gui
import win32ui
from ctypes import windll
from PIL import Image
hwnd = win32gui.FindWindow(None, "#chat - Discord")
# Change the line below depending on whether you want the whole window
# or just the client area.
left, top, right, bot = win32gui.GetClientRect(hwnd)
#left, top, right, bot = win32gui.GetWindowRect(hwnd)
w = right - left
h = bot - top
hwndDC = win32gui.GetWindowDC(hwnd)
mfcDC = win32ui.CreateDCFromHandle(hwndDC)
saveDC = mfcDC.CreateCompatibleDC()
saveBitMap = win32ui.CreateBitmap()
saveBitMap.CreateCompatibleBitmap(mfcDC, w, h)
saveDC.SelectObject(saveBitMap)
# Change the line below depending on whether you want the whole window
# or just the client area.
result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 1)
#result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), 0)
bmpinfo = saveBitMap.GetInfo()
bmpstr = saveBitMap.GetBitmapBits(True)
im = Image.frombuffer(
'RGB',
(bmpinfo['bmWidth'], bmpinfo['bmHeight']),
bmpstr, 'raw', 'BGRX', 0, 1)
if result:
#PrintWindow Succeeded
im.show()
win32gui.DeleteObject(saveBitMap.GetHandle())
saveDC.DeleteDC()
mfcDC.DeleteDC()
win32gui.ReleaseDC(hwnd, hwndDC)
The problem with it is that the screenshot it takes is all black. It does this with all windows, not just Discord. What is wrong with it, and what do I need to do to fix it?
Also as a side question - when I take screenshots the command prompt opens and then close real quick, is there also a way to stop that from happening?
The problem with it is that the screenshot it takes is all black.
I understand that you want to take a screenshot?
from PIL.ImageGrab import grab
image = grab()
image.save('Screenshot.png')
If you have the coordinates of the window, try this instead:
from PIL.ImageGrab import grab
box = (0,0,200,200)
image = grab(box)
image.save('Screenshot.png')
PIL has been discontinued though, so you may be able to use this code only for the next immediate future. Also, the command prompt does not appear with this code.
I have a gif that I'm breaking up frame by frame and saving them as images. I wrote text on them using ImageDraw, but now I'm running into a problem. The text is going outside of the border. The catch is that I'm grabbing a random gif from the internet using a script, so I can't hardcode either in the size of the font nor the amount text to write. How can I ensure that the text I add to the image stays inside the borders of the image?
Example of what's happening:
Screenshot
The section of code that deals with writing on the image:
meme_text = "When your kitten is thinking about tuna but has none"
for i in range(0,max_frame_int + 1):
writeimg = Image.open("frameinstance" + str(i) + ".png")
newimg = Image.new("RGB", writeimg.size)
newimg.paste(writeimg)
width_image = newimg.size[0]
height_image = newimg.size[1]
draw = ImageDraw.Draw(newimg)
# font = ImageFont.truetype(<font-file>, <font-size>)
font = ImageFont.truetype("impact.ttf", 50)
# draw.text((x, y),"Sample Text",(r,g,b))
draw.text((int(0.05*width_image), int(0.7*height_image)),meme_text,(255,255,255),font=font)
newimg.save("newimg" + str(i) +".png")
Your problem is you're not accounting for the size of the text that will be rendered vs. the width of the picture. if you change the font = ImageFont... line to the following:
for font_size in range(50, 0, -1):
font = ImageFont.truetype("impact.ttf", font_size)
if font.getsize(meme_text)[0] <= width_image:
break
else:
print 'no fonts fit!'
the script will find the largest font size that will fit all of the text.
My Problem:
As soon as I convert the input GIF Image into a RGBA to process it, I'm enjoying quality loss on the image. (You can see the both pictures below the code)
The code shown below "works" just I don't got a clue, why i loose quality.
Any suggestions??
My Code:
from PIL import ImageTk, Image as Im
from Tkinter import *
class App:
def __init__(self):
self.root = Tk()
self.root.geometry('1171x900')
self.maskPng = Im.open("Images/mask.gif")
self.maskPng = self.maskPng.convert("RGBA")
self.mask = ImageTk.PhotoImage(self.maskPng)
self.show = Canvas(self.root, width = 1170, height = 780)
self.show.pack()
self.show.create_image(0, 0, image = self.mask, anchor = NW)
self.speedBTN = Button(self.root, text = "hello", command = self.speed).pack(side = "right")
self.changed = False
def speed(self):
self.speedImg = Im.open("Images/speed/3_1.gif")
self.speedImg = self.speedImg.convert("RGBA")
self.maskPng.paste(self.speedImg, (0,0), self.speedImg)
self.maskPng.save("Images/speed/test.gif", "GIF")
self.render()
def render(self):
self.mask = ImageTk.PhotoImage(Im.open('Images/speed/test.gif'))
self.show.create_image(0,0, image = self.mask, anchor = NW)
self.show.image = self.mask
def draw(self):
self.root.mainloop()
main = App()
main.root.mainloop()
Images:
This is my mask.gif:
This is my 3_1.gif:
(What it white on stackoverflow is transparent in the gif)
This is the grainy, harrowing result:
(I marked the most "grainy" areas with red rectangles)
Thanks for your help! :)
Facing the same issue but I might have solution for your use case.
It doesn't seem like you actually do anything with the image so why don't you use the base64 encoded image and read it directly like below:
import Tkinter as tk # Python 2
import tkinter as tk # Python 3
# base64 encoded image data
image = ''
root = tk.Tk()
# Pass the base64 encoded data directly to your PhotoImage()
root.image = tk.PhotoImage(data=image)
# Display image in any way you need.
label = tk.Label(root, image=root.image, bg='white')
root.overrideredirect(True)
root.geometry("+250+250")
root.lift()
root.wm_attributes("-topmost", True)
root.wm_attributes("-disabled", True)
root.wm_attributes("-transparentcolor", "white")
label.pack()
label.mainloop()
The question is old so it's unlikely that you are still working on this but I hope it will help someone else.
The issue seems to be only with RGBA, RGB works just fine but it obviously doesn't have Alpha channel. The code above will render image in its original form.
My problem is slightly different but relates to this issue. I'm trying to manipulate pixels so I have to load it as RGBA, process it and save again.
Final Edit:
After filling the issue report on github I got reply from the author.
https://github.com/python-pillow/Pillow/issues/3059
The relevant part is :
It's quantization issue.
This gives the same result:
(Image.open('./37943912.gif')
.convert('RGBA')
.quantize()
.save('_out.png'))
This is now verified and should be considered a final answer.