Справочная информация
Я работаю над проектом, в котором я пытаюсь напечатать огромный плакат, я уже нашел типографию, которая готова помочь мне напечатать его, но я должен отправить им данные в одном файле (желательно в формате JPEG), но мой проект состоит из более чем 2 миллионов файлов. Вот где начинается борьба; У меня дома нет большого сервера, который я мог бы использовать, чтобы быстро сшить эти изображения размером 256 на 256 пикселей вместе, у меня есть только скромный i7 и 16 ГБ ОЗУ.
Метод
I Я использую PIL.Image
для сшивания изображений (приветствуются любые альтернативы).
Мой код работает для файлов меньшего размера, но мои входные данные - это в общей сложности 13 гигабайт файлов JPEG, разделенных на более чем 2 миллиона файлов.
from PIL import Image
"""
1. create a list with pictures
2. stitch them together vertically
>images are all in the folder D:/tiles/ and named after they'r x and y
position: "x_y.jpeg" (e.g.: 2000_642.jpeg)
>vertical lines will be put inside folder D:/output/ and will be named after
they'r x-position (in the code variable j) (e.g.: 2000.jpeg)
>full poster will be put inside D:/poster.jpeg
"""
def joinVert(j,imagePath):
# open pictures
images = [Image.open(x) for x in imagePath]
# get list with width and height
widths, heights = zip(*(i.size for i in images))
# get maximum width and total height to find the size of target image
max_width = max(widths)
total_height = sum(heights)
# create target image
new_im = Image.new('RGB', (max_width, total_height))
# y_offset defines the amounts of px to top border -- will increase by
# height of last pic
y_offset = 0
# iterate trough images and paste them into new image
for im in images:
new_im.paste(im, (0,y_offset))
y_offset += im.size[1]
# save new picture to output
tgt='D:/output/'+str(j)+'.jpeg'
new_im.save(tgt)
return tgt
def joinHor(path,imagePath):
# open pictures
images = [Image.open(x) for x in imagePath]
# get list with width and height
widths, heights = zip(*(i.size for i in images))
# get maximum height and total width to find the size of target image
max_height = max(heights)
total_width = sum(widths)
# create target image
new_im = Image.new('RGB', (total_width, max_height))
#x_offset defines the amounts of px to left border -- will increase by
# width of last pic
x_offset = 0
# iterate trough images and paste them into new image
for im in images:
new_im.paste(im, (x_offset,0))
x_offset += im.size[0]
# save new picture to path
new_im.save(path)
# list of paths to output files --> will be stiched together later
targets=[]
for j in range(700,715):
# create a list with all the pictures in this row
imagePath = []
for i in range(700,715):
imagePath.append("D:/tiles/"+str(j)+"_"+str(i)+".jpeg")
# join all pictures vertically in the list to one, returns path of outputfile
targets.append(joinVert(j,imagePath))
joinHor("D:/poster.jpeg",targets)
Проблема
AFAIK PIL.Image
помещает все данные в ОЗУ. Мой процессор и оперативная память не подыгрывают мне из-за невероятного объема обрабатываемых данных - как бы вы, ребята, записали в файл изображения, который будет больше, чем ваша оперативная память? Любые идеи приветствуются.