0

I'm trying to take a few png images add them an enumerated grid and save them each image by itself as a single tiff file

the output I get is, first image with grid and numbers as required,

the first image is shorter then the others if that matters

other images are only numbered but without a grid

this is my code

from PIL import Image, ImageDraw, ImageOps, ImageFont
import os
import glob

path = r'D:\in'
out = r"d:\1.tif"

font = ImageFont.truetype(r"D:\python1\New folder\keyer_layout\films.EPISODE1.ttf",32)

def add_grid(path):
    im  = Image.open(path)
    im = ImageOps.expand(im, border=50, fill = 'rgb(255,255,255)') #add margin to the image
    draw = ImageDraw.Draw(im)
    y_start = 0
    y_end = im.height
    step_size = int(im.width / 10)
    li = 0
    for x in range(0, im.width, step_size):
            line = ((x, y_start), (x, y_end))
            draw.line(line, fill=200)
            draw.text((x, y_start),str(li),'rgb(0,0,0)',font=font)
            li+=1
    
    x_start = 0
    x_end = im.width
    li = 0
    for y in range(0, im.height, step_size):
        line = ((x_start, y), (x_end, y))
        draw.line(line, fill=128)
        draw.text((x_start, y),str(li),'rgb(0,0,0)',font=font)
        li+=1
    
    del draw
    return im

pics_path = os.path.join(path,"*.png")
pics = glob.glob(pics_path)
pics_arr = []

for i in pics:
    pics_arr.append(add_grid(i))


pics_arr[0].save(r"d:\test.tif", append_images = pics_arr[1:],save_all = True)

I tried to add im.show() inside the function the images looked the same first one with grid others without

when I tried to skip the first image, non of the images had a grid on it

Thanks

trigonom
  • 528
  • 4
  • 9
  • It seems, you can't just to append static image (tif, png, etc) to another static image. You can append page to pdf file, you can append frame to animated gif file only. But I'm not exactly expert in PIL I may be wrong. I would be glad to know the right answer as well. – Yuri Khristich Nov 04 '20 at 11:49
  • Probably you need to combine your images directly: https://stackoverflow.com/questions/30227466/combine-several-images-horizontally-with-python before or after you add the grid (I didn't get, if you want one grid for all images, or you want that every original image has its own grid before the combining) – Yuri Khristich Nov 04 '20 at 12:10
  • @YuriKhristich Thank you for your time, i want to save every image by itself with grid on it, on a single tif file, i added im.show() inside the function and the images had no grid on them beside the first one, so i don't think its a problem with save – trigonom Nov 04 '20 at 12:12
  • Look at your last line. It actually saves the first image only. If you change [0] to [1] it will save the second image (with grid), etc. You can loop through the pics_arr and save all your images (you need to use different names of course). After that you can combine these gridded images into the one big image (see the link in my previous comment). The option 'append_images', in this case doesn't work at all. – Yuri Khristich Nov 04 '20 at 12:38

1 Answers1

1

Firstly, instead of the last line there should be something like this:

for i, pict in enumerate(pics_arr):
    pict.save(r"d:\test" + str(i) + ".tif")

This way you will get all your images with the grid on them as a bunch of tif files.

After that you need to combine them into one big file. It can be done this way: Combine several images horizontally with Python


The final script could look like this:

from PIL import Image, ImageDraw, ImageOps, ImageFont
import os
import glob

path = r'd:\in'
out = r'd:\out'

# font = ImageFont.truetype() <-- sorry, I have no your font at hand

def add_grid(path):
    im  = Image.open(path)
    im = ImageOps.expand(im, border=50, fill = 'rgb(255,255,255)') #add margin to the image
    draw = ImageDraw.Draw(im)
    y_start = 0
    y_end = im.height
    step_size = int(im.width / 10)
    li = 0
    for x in range(0, im.width, step_size):
        line = ((x, y_start), (x, y_end))
        draw.line(line, fill=(200,200,200))  #  <----- light gray RGB color
        draw.text((x, y_start),str(li),'rgb(0,0,0)') #,font=font)
        li+=1

    x_start = 0
    x_end = im.width
    li = 0
    for y in range(0, im.height, step_size):
        line = ((x_start, y), (x_end, y))
        draw.line(line, fill=(128,128,128))  #  <----- gray RGB color
        draw.text((x_start, y),str(li),'rgb(0,0,0)') #,font=font)
        li+=1

    del draw
    return im

pics_path = os.path.join(path,"*.png")
pics = glob.glob(pics_path)
pics_arr = []

for i in pics:
    pics_arr.append(add_grid(i))


# save gridded images

for i, pict in enumerate(pics_arr):
    pict.save(out +"\test" + str(i) + ".png")


# combine the gridded images into the one tif

pics_path = os.path.join(out, "*.png")
pics = glob.glob(pics_path)

images = [Image.open(x) for x in pics]
widths, heights = zip(*(i.size for i in images))

total_width = sum(widths)
max_height = max(heights)

new_im = Image.new('RGB', (total_width, max_height))

x_offset = 0
for im in images:
  new_im.paste(im, (x_offset,0))
  x_offset += im.size[0]

new_im.save(out + '/test.tif')

Input:

enter image description here

Step 1:

enter image description here

Output:

enter image description here

Yuri Khristich
  • 13,448
  • 2
  • 8
  • 23
  • Thanks again, I wanted them on different pages in same file, I moved from fill = 125 to fill = 'rgb(0,0,0)' and it worked, no idea why – trigonom Nov 04 '20 at 16:59
  • If you mean 'fill=120' and 'fill=200', I have an idea where the problem can be. The '120' and '200' somehow return so-called 'transparent' pixels. It's likely you got the grid on every page of the multi-page TIFF (an exotic thing for me, so I've got confused) well. But the app you're using failed to show the transparent grid correctly. The regular RGB colors like (0,0,0) or (128,128,128), etc have no transparency component. – Yuri Khristich Nov 04 '20 at 17:27