Question: I am currently trying to draw a progress bar, based on a calculated percentage. However, I am not able to display it in the right format. I orientated myself on another answer from this site here (How do you make a progress bar and put it on an image? & Is it possible to add a blue bar using PIL or Pillow?) But either the case is that the progress bar is too long and the width restriction does not work or the bar shows no progress. Example 1: async def rank(self, ctx, member: discord.Member): member = ctx.author data = await database.find_user(collection_user, ctx.guild.id, ctx.author.id) already_earned = data["exp"] to_reach= ((50 * (data['lvl'] ** 2)) + (50 * (data['lvl'] - 1))) percentage = ((data["exp"] / next_level_xp ) * 100) # Get the percentage ## Rank card img = Image.open("leveling/rank.png") draw = ImageDraw.Draw(img) font = ImageFont.truetype("settings/myfont.otf", 35) font1 = ImageFont.truetype("settings/myfont.otf", 24) async with aiohttp.ClientSession() as session: async with session.get(str(ctx.author.avatar)) as response: image = await response.read() icon = Image.open(BytesIO(image)).convert("RGBA") img.paste(icon.resize((156, 156)), (50, 60)) # Some text drawn, this works ### From StackOverflow ### def drawProgressBar(d, x, y, w, h, progress, bg=(129, 66, 97), fg=(211,211,211)): # draw background draw.ellipse((x+w, y, x+h+w, y+h), fill=bg) draw.ellipse((x, y, x+h, y+h), fill=bg) draw.rectangle((x+(h/2), y, x+w+(h/2), y+h), fill=bg, width=10) # draw progress bar progress = ((already_earned / to_reach ) * 100) w *= progress draw.ellipse((x+w, y, x+h+w, y+h),fill=fg) draw.ellipse((x, y, x+h, y+h),fill=fg) draw.rectangle((x+(h/2), y, x+w+(h/2), y+h),fill=fg, width=10) return d drawProgressBar(img, 10, 10, 100, 25, 0.5) ### From StackOverflow ### img.save('leveling/infoimg2.png') # Save it and send it out  This looks like this:  Second example: async def rank(self, ctx, member: discord.Member): member = ctx.author data = await database.find_user(collection_user, ctx.guild.id, ctx.author.id) already_earned = data["exp"] to_reach = ((50 * (data['lvl'] ** 2)) + (50 * (data['lvl'] - 1))) percentage = ((already_earned / to_reach) * 100) # Get the percentage img = Image.open("leveling/rank.png") draw = ImageDraw.Draw(img) ### From StackOverflow ### color=(129, 66, 97) x, y, diam = percentage, 8, 34 draw.ellipse([x,y,x+diam,y+diam], fill=color) ImageDraw.floodfill(img, xy=(14,24), value=color, thresh=40) ### From StackOverflow ### font = ImageFont.truetype("settings/myfont.otf", 35) font1 = ImageFont.truetype("settings/myfont.otf", 24) async with aiohttp.ClientSession() as session: async with session.get(str(ctx.author.avatar)) as response: image = await response.read() icon = Image.open(BytesIO(image)).convert("RGBA") img.paste(icon.resize((156, 156)), (50, 60)) # Draw some other text here, this works though img.save('leveling/infoimg2.png') # Save the file and output it  Which looks like this:  Both results do not match the pictures shown in the answers and questions. Is somebody able to tell me where I went wrong? I also tried to increase x in the second example or set img = Image.open("pic.png").format('RGB') but nothing seems to work. The progress bar is either too long or too short. I tried to achieve that my progress bar is restricted to some size, always matches 100% and that my defined progress will adapt to it.

Answer: The issue with your code was that the background and progress bar sections were of the same color, and as such, you couldn't see it. This can be fixed by coloring them differently. The line progress = ((already_earned / to_reach ) * 100) also sets progress to a percentage [0, 100]. You then multiply width by this. For the input of 100, a fill amount of 50% for example makes the ellipse go 5000 pixels - way off the screen and overwriting everything that was already drawn there. @client.command(name='rank') async def rank(ctx, progress: float): # Open the image and do stuff # I tested this with a blank 800x400 RGBA def new_bar(x, y, width, height, progress, bg=(129, 66, 97), fg=(211,211,211), fg2=(15,15,15)): # Draw the background draw.rectangle((x+(height/2), y, x+width+(height/2), y+height), fill=fg2, width=10) draw.ellipse((x+width, y, x+height+width, y+height), fill=fg2) draw.ellipse((x, y, x+height, y+height), fill=fg2) width = int(width*progress) # Draw the part of the progress bar that is actually filled draw.rectangle((x+(height/2), y, x+width+(height/2), y+height), fill=fg, width=10) draw.ellipse((x+width, y, x+height+width, y+height), fill=fg) draw.ellipse((x, y, x+height, y+height), fill=fg) new_bar(10, 10, 100, 25, progress) # send   Example: progress = 0.25  progress = 0.9   As to the second code snippet, it's using floodfill() incorrectly. thresh is the "maximum tolerable difference of a pixel value from the ‘background’ in order for it to be replaced." This means that the floodfill does literally nothing, and you only drew the ellipse (and not the part of the progress bar that goes before it).  # this draws a circle with bounding box `x,y` and `x+diam,y+diam` # note that `x` is dependent on the progress value: higher progress means larger x, which means the circle is drawn more to the right draw.ellipse([x,y, x+diam,y+diam], fill=color) # If you look at the post where the code was given, you can see the error. # In that post, the entirety of the progress bar already exists, and is a very different color (allowing the use of the threshold value). # In this code, no progress bar exists yet, meaning everything else is just one solid color, and then the floodfill cannot do anything. # Also, xy is specified as arbitrary coordinates, which you would need to change to fit your bar. # This does nothing. ImageDraw.floodfill(img, xy=(14,24), value=color, thresh=40)  If you want to fix this, you need to fill in the color to the left of the progress bar. The first function above already does this. If you want, you can remove the first 3 lines to avoid drawing a background, producing the same results.