#π how do you add text to a image with pillow?
157 messages Β· Page 1 of 1 (latest)
@late herald
Remember to:
- Ask your Python question, not if you can ask or if there's an expert who can help.
- Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
- Explain what you expect to happen and what actually happens.
:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.
you need to create a separate draw object first by passing in your original image so you can draw on it
think of it like putting a sheet of glass over your image that you can then draw on
I1 = ImageDraw.Draw(base_image)
myFont = ImageFont.truetype('FreeMono.ttf', 65)
I1.text((10, 250), "test", font=myFont, fill =(255, 0, 0))```
this?
bc i get error
What does the error say?
how can i use a defult font
or one i have installed with windows already
or smth
hmm it should be able to pull from installed fonts
Do I need to do smth different?
are you sure that's the font name?
can you show the font in your windows Fonts folder?
No Iβm not sure I used a w2s example so I should probably change that
@wide marsh
[2024-10-29 16:11:01] [ERROR ] discord.ui.modal: Ignoring exception in modal <BarcodeInputModal timeout=None children=2>:
Traceback (most recent call last):
File "C:\Users\littl\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\ui\modal.py", line 189, in _scheduled_task
await self.on_submit(interaction)
File "C:\Users\littl\OneDrive\Documents\test", line 82, in on_submit
I1.text((10, 250), "test", font=ImageFont.truetype('ARIALBD.ttf', 65), fill=(255, 0, 0))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\littl\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\ImageFont.py", line 1008, in truetype
return freetype(font)
^^^^^^^^^^^^^^
File "C:\Users\littl\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\ImageFont.py", line 1005, in freetype
return FreeTypeFont(font, size, index, encoding, layout_engine)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\littl\AppData\Local\Programs\Python\Python311\Lib\site-packages\PIL\ImageFont.py", line 255, in __init__
self.font = core.getfont(
^^^^^^^^^^^^^
OSError: cannot open resource```
Yes, I'm saying that it cannot find the font
should i just say that path then?
sure you can try that
I1.text((10, 250), "test", font=ImageFont.truetype('ARIALBD.ttf', 65), fill=(255, 0, 0))
to
I1.text((10, 250), "test", font=ImageFont.truetype('C:\\WINDOWS\\FONTS\\ARIALBD.ttf', 65), fill=(255, 0, 0))
would that work?
try it and see
it works thank you
@wide marsh is there a way to wrap text automatilly if it goes off the image?
you can use the textwrap module and set a max width. It will automatically handle wrapping
!e
import textwrap
message = 'this is a really long message and I want it to wrap around'
print(textwrap.fill(message, width=16))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | this is a really
002 | long message and
003 | I want it to
004 | wrap around
is there a way to know how many text warps its doing?
so i can increase the starting poistion for the text
there's a text bbox method for getting the size of the resulting text
then you need to do a bit of math to offset it based on that
how do i do that
ohh
just .len
the do mod
no, there's an actual method for getting the resulting measure
you can do draw.textbbox
it won't actually perform the drawing, but it will give you the resulting bounding box as if it were to add the text
wait so
draw isnt defined tho
message = textwrap.fill(self.value, width=16)
amount = draw.textbbox(message)
I1.text((38, (50 * amount) + 910)), textwrap.fill(message, width=16), font=ImageFont.truetype('C:\\WINDOWS\\FONTS\\ARIALBD.ttf', 40), fill=(0, 0, 0))```
this?
draw should be your draw object
I1 in your case
you also need to give it a starting position and your font
i did didnt i
not to the textbbox you didn't
it returns a tuple of your top, left, bottom, right
so you can use these values to work out how to center the text based on your canvas and text size
so amount = draw.textbbox(message, (38,910), font=ImageFont.truetype('C:\\WINDOWS\\FONTS\\ARIALBD.ttf', 40))
thats confusing
bbox = draw.textbbox((0, 0), fit_text, font=font)
text_width = (bbox[2] - bbox[0])
text_height = (bbox[-1] - bbox[1])
mid_x = (bbox[0] + bbox[2]) // 2
mid_y = (bbox[-1] + bbox[1]) // 2
x_placement = (size[0] // 2) - abs(mid_x - text_width)
y_placement = (size[1] // 2) - abs(mid_y - text_height)
here's an example from one of my previous works
size is the total size of my image
here's a result
okay so this?
draw = ImageDraw.Draw(base_image)
bbox = draw.textbbox((38, 910), self.value, font=ImageFont.truetype('C:\\WINDOWS\\FONTS\\ARIALBD.ttf', 25))
text_width = (bbox[2] - bbox[0])
text_height = (bbox[-1] - bbox[1])
mid_x = (bbox[0] + bbox[2]) // 2
mid_y = (bbox[-1] + bbox[1]) // 2
x_placement = (604[0] // 2) - abs(mid_x - text_width)
y_placement = (1334[1] // 2) - abs(mid_y - text_height)```
what do i do with x_placement and y_placement
and the bbox varible that potision should be my starting poitstion right?
draw.text((x_placement, y_placement),
fit_text,
fill='black',
font=font,
align='center')
and then it will move up right
ahh sorry, forgot the final line
don't just blindly copy what I have. Follow the steps and apply it to your own data
(604[0] // 2)
indexing an int doesn't make sense here
my fit_text is my text after being modified by textwrap.fill
what would i put instead (604,1334)
you can always get the size of your image using base_image.size
so you can do size = base_image.size
how do i do that? its not in your code
that is the size of image
604,1334
fit_text = textwrap.fill(self.text, width=MAX_TEXT_WIDTH)
yes, so use the width for x placement and the height for y placement
(604[0] // 2)
(604 // 2)
you can't index ints
oh yeah
I really recommend making variables for this so you aren't using "random" numbers
it makes it so much easier to make changes if needed
so now its in a strange poisition
will dop
i want the last line
to be at x=38 y=910
not cenetered
then that's not going to be the same math
how do i find how many lines its done?
the fit text
you don't need to, you only need to know the height which you get from the bbox
then?
but how can i move it where i want it
bc that still puts it randomly
i dont need to change x
just the last y line should be 910
i dont wanna center it
I'm saying if you already have it centered
ohh
thats gonna be hard getting it to the posistion i want
yes
and the red box is where your text currently is
yes
you know the height of your window, and you know the height of your text box
yes
you can get the size of this space
center point + half height of the text box
that gets you the bottom
and then you have to get the difference between the image size and the bottom
how do i get the center point?
mid_y is the center
get the difference between 910 and your image height
and subtract that from the result
look at my code, we already have the variables
you want text_height // 2
ohh okay
and then how do i get the last row to equal 910
using this
so
910 - (mid_y + (text_height // 2))
will get me where i want it to be?
no, you need the difference between 910 and your image height
is that not what i done?
base_image.size[0] - 910
I don't see that anywhere
and it should be subtracted from the result, not the other way around
focus on just getting it flush with the bottom of the screen first, then worry about the offset to 910 after
okay
can you show me what your image looks like?
This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.