PIL Issue, OSError: cannot open resource
Asked Answered
U

19

53

I'm attempting to write a program that places text onto an image, I'm trying to get my head round PIL and have run into the error: OSError: cannot open resource. This is my first python program so apologies if the error is obvious.

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont


im = Image.open("example.jpg")
font_type = ImageFont.truetype("Arial.ttf", 18)
draw = ImageDraw.Draw(im)
draw.text(xy=(50, 50), text= "Text One", fill =(255,69,0), font = font_type)
im.show()

I get the error:

Traceback (most recent call last):
File "C:\Users\laurence.maskell\Desktop\attempt.py", line 7, in <module>
font_type = ImageFont.truetype("Arial.ttf", 18)
File "C:\Python34\lib\site-packages\PIL\ImageFont.py", line 259, in truetype
return FreeTypeFont(font, size, index, encoding, layout_engine)
File "C:\Python34\lib\site-packages\PIL\ImageFont.py", line 143, in __init__
self.font = core.getfont(font, size, index, encoding, 
layout_engine=layout_engine)
OSError: cannot open resource
Ungraceful answered 7/12, 2017 at 11:46 Comment(1)
Try to set full path to font in ImageFont.truetype, something like r"C:\Windows\Fonts\Arial.ttf".Kaikaia
D
38

I fixed the problem by using default font.

font = ImageFont.load_default()

If you just need to put some text (font style is not matter to you) then this might be a simple solution.

font = ImageFont.load_default()

draw = ImageDraw.Draw(pil_img)
draw.text(( 20, 32), "text_string", (255,0,0), font=font)
Decedent answered 13/12, 2019 at 9:55 Comment(1)
the documentation link is brokenEldaelden
G
22
from PIL import Image, ImageDraw, ImageFont

im = Image.open("mak.png")
font_type = ImageFont.truetype("arial.ttf", 18)
draw = ImageDraw.Draw(im)
draw.text(xy=(120, 120), text= "download font you want to use", fill=(255,69,0), font=font_type)
im.show()

Its "arial.ttf" not "Arial.ttf"

Here is the link to download arial.ttf font.

Grof answered 30/7, 2018 at 7:51 Comment(1)
After downloading arial.tff I was able to get my program to work after moving the .tff file into the same directory as the script (I actually just use wget $URL in the directory) and then I used ./arial.tff (this uses the one in your directory) instead of arial.tff (this one searches your system for the file)Annisannissa
M
9

I have also met this issue on Windows 10 Pro with PIL 5.3.0.

On my machine, the error is caused by non-ASCII font file names. If I change the the font name to only contain ASCII characters, I can open the font without any error.

Edit (2019-07-29): this is indeed a bug with ImageFont.truetype() method and it has been fixed in this pull request.

Missive answered 28/11, 2018 at 3:27 Comment(0)
R
5

For Linux I used:

$ locate .ttf

/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-BI.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-C.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-L.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-LI.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-M.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-MI.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-R.ttf
/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-RI.ttf
/usr/share/fonts/truetype/ubuntu-font-family/UbuntuMono-B.ttf
/usr/share/fonts/truetype/ubuntu-font-family/UbuntuMono-BI.ttf
/usr/share/fonts/truetype/ubuntu-font-family/UbuntuMono-R.ttf
/usr/share/fonts/truetype/ubuntu-font-family/UbuntuMono-RI.ttf

It actually returned A LOT MORE than that!

Then I took the python code posted here in Stack Overflow:

Plugged in the font name "Ubuntu-R.ttf" returned by locate:

color_palette = [BLUE, GREEN, RED]
image_w=200
image_h=200
region = Rect(0, 0, image_w, image_h)
imgx, imgy = region.max.x+1, region.max.y+1
image = Image.new("RGB", (imgx, imgy), WHITE)
draw = ImageDraw.Draw(image)
vert_gradient(draw, region, gradient_color, color_palette)
#image.text((40, 80),"No Artwork",(255,255,255))
#font = ImageFont.truetype(r'C:\Users\System-Pc\Desktop\arial.ttf', 40)
#font = ImageFont.load_default()
font = ImageFont.truetype("Ubuntu-R.ttf", int(float(image_w) / 6))
draw.text((int(image_w/12), int(image_h / 2.5)), "No Artwork", \
           fill=(0,0,0), font=font)
image.show()

And voila! I now have an image to display when there is no image to display in a music file I'm playing:

No Artwork.png

Responsible answered 1/8, 2020 at 0:17 Comment(0)
F
2

I was also facing the same issue. but later found out it was an issue with the slash. So, if anybody else missed this small thing, it's for you.

I had the font inside the font folder. When I tried to import the font using font/<font_name>.ttf, the code couldn't locate it. Replaced / with \ and it could locate the font.

Fortyniner answered 11/12, 2020 at 19:41 Comment(0)
E
2

As I have understood, a problem with location of the file: "Arial.ttf"

As I have understood the Arial.ttf file is with the program, but start is made from other place.

In this case it is necessary to add the Arial.ttf file to a full path:

# __file__ contain full path to the py scrypt
# for python 3.9 and later 

import os
path = os.path.dirname(__file__) + '/'

im = Image.open("example.jpg")
font_type = ImageFont.truetype(path + "Arial.ttf", 18)

For older py version see more at: How do I get the full path of the current file's directory?

Equipoise answered 27/6, 2022 at 10:33 Comment(0)
R
1

If you are on Windows, by the following method my problem was resolved:

  • go to the Font folder in C:\Windows\Fonts
  • Right-click on the font that you want to use and click on "Properties"
  • go to the Security tab and copy the address of "Object name:"
  • then place the above path (*****) in the following code:

ImageFont.truetype("*****", int(float(image_w) / 6))

Riddell answered 3/10, 2022 at 12:5 Comment(0)
J
0

PIL cannot find the specified font. Check that it exists, and that it is named with the exact same case. You can also try to copy it directly in the project folder.

Jene answered 24/2, 2018 at 22:50 Comment(0)
C
0

I think you should move the font to fonts or any folder. I had the same issue on heroku. After i moved the font to fonts directory it works

Camala answered 11/5, 2021 at 12:19 Comment(0)
H
0

When I ran into this issue in Linux, I solved by:

  1. Install the .ttf into Linux

  2. Run the code with the actual .tff in ~. For some reason, even with the font installed and the .py running inn another dir, it needed to have the .tff in the home dir.

Hoopla answered 17/3, 2022 at 3:6 Comment(0)
F
0

This issue also crops up in PIL for android. While it is quite possible to copy a font file into the project directory as others have noted, if more than a few android fonts are wanted it may be tidier to add the android font directory to the ImageFont.py search path instead. I altered it like this between lines 870-871:

870     elif sys.platform in ("linux", "linux2"):
            if 'ANDROID_BOOTLOGO' in os.environ:
                # kludge added for android
                dirs += [
                    "/system/fonts"
                ]
            else:
871             lindirs = os.environ.get("XDG_DATA_DIRS", "")
872             if not lindirs:
...                 # According to the freedesktop spec, XDG_DATA_DIRS should
                    # default to /usr/share
                    lindirs = "/usr/share"
                dirs += [os.path.join(lindir, "fonts") for lindir in lindirs.split(":")]
Fraction answered 27/5, 2022 at 1:33 Comment(0)
C
0

It's just that the name of the .ttf file does'nt match with the filename you pass to ImageFont.truetype().

Make sure that the case and spelling are correct. There is no other external factor that could affect merely loading a font from a ttf file.

Ceroplastics answered 17/7, 2022 at 9:24 Comment(0)
M
0

I solved it simply by doing the following steps:

  1. Created a hidden folder named fonts (.fonts) in the home directory.
  2. Downloaded my desired font from the web. Note: You can download any font you want by typing "font_name.tiff download" on Google.
  3. Copy and paste the downloaded .ttf file into the .fonts folder.
  4. Copy and paste the new path of your .ttf file in the code as shown below.
im_show = draw_ocr(image, boxes, txts, scores, font_path='/.fonts/simfang.ttf')

That's how it worked for me.

You can follow this link as a visual aid. https://www.youtube.com/watch?v=Q5GO_glHXyQ&t=35s

Manley answered 25/7, 2022 at 9:49 Comment(0)
U
0

I used the following solution for PaddleOCR draw_structure_result:

Download .tiff file(you can use https://www.wfonts.com/font/tiff-heavy) and store them in a folder and give the path of that folder:

im_show = draw_structure_result(img, result, font_path='/content/TIFFH.ttf')
Uphill answered 2/3, 2023 at 10:2 Comment(0)
S
0

Confirm if the font-path (file) exists in the described path.

Sacculate answered 16/12, 2023 at 21:9 Comment(0)
S
0

I've just solved it by giving the absolute path to ImageFont.truetype. Like my .ttf file was in E Drive, and the absolute path would be: path='E:\arial.ttf'

Streak answered 9/2, 2024 at 10:27 Comment(0)
H
0

You need to specify full path to TTF file:

full_path_to_file = Path(__file__).resolve().parent.joinpath('Arial.ttf')
im = Image.open("example.jpg")
font_type = ImageFont.truetype(str(full_path_to_file), 18)
Hornstone answered 19/2, 2024 at 8:22 Comment(0)
U
0

The solution to the specific problem above is that the regular Arial font is named 'arial.ttf' and not 'Arial.ttf'. More generally, I've found that OSError: cannot open resource can occur in PIL in one of two ways: the font name passed to ImageFont.truetype does not match the font object in the Windows Fonts folder, or the font is located in your Local AppData folder despite being shown in the Windows Fonts folder.

To solve the first issue, you need to check the name of the font by going to the Windows\Fonts folder, opening the Properties for your font from the right-click menu, and verifying the name shown at the top of the window.

The second issue can be solved by manually defining the absolute path to the font in AppData, but since your code should ideally work no matter which font you choose, you can define a function to use the 'cannot open resource error' as follows:

from PIL import Image, ImageDraw, ImageFont
import os

def build_font(ttf_font, font_size):
    try:
        font = ImageFont.truetype(ttf_font, font_size)
        return font
    except OSError as e:
        if str(e) == "cannot open resource":
            font_path = (
                os.environ["LOCALAPPDATA"] + "/Microsoft/Windows/Fonts/"
                + ttf_font
            )
            try:
                font = ImageFont.truetype(font_path, font_size)
                return font
            except:
                raise
        else:
            raise

im = Image.open("example.jpg")
font_type = build_font("arial.ttf", 18)
draw = ImageDraw.Draw(im)
draw.text(xy=(50, 50), text="Text One", fill=(255, 69, 0), font=font_type)
im.show()

The build_font function first tries the standard Pillow locations for installed fonts since that's where all system fonts live, and then checks the AppData\Local folder for any fonts that you may have downloaded and installed. If the font is still not found or another error occurs, then it raises the error. This lets you use any font listed in Windows\Fonts without worrying about where it is saved and avoids having to make copies of fonts in arbitrary locations.

Urquhart answered 18/4, 2024 at 17:45 Comment(0)
A
0

I had to use fc-list to locate my Ubuntu 22.04 server font locations, which is limited to DejaVu. This code worked:

from sys import platform
match platform:
    case 'linux':
        FONT = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
    case 'linux2':
        FONT = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'
    case 'darwin':
        FONT = '/Library/Fonts/Arial.ttf'
    case "win32":
        FONT = 'arial.ttf'
    case _:
        print(f"Unknown platform {platform}")
Alliber answered 21/5, 2024 at 4:19 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.