import os from PIL import Image, ImageDraw, ImageFile, ImageFont picSize = (1920, 1080) itemSize = (320, 320) margin = 50 itemNum = 10 fontSize = 26 fontMargin = 20 actualSize = (itemSize[0], itemSize[1] + fontMargin + int(fontSize * 1.5)) font = ImageFont.truetype("./font/HarmonyOS_Sans_SC_Medium.ttf", fontSize) num = len(os.listdir('./sucai')) # num = 10 # 计算某行的实际宽度 vSize = num * (itemSize[0] + num - 1) if num <= 5 else 5 * (itemSize[0] + num - 1) # 计算左右边距以确保当前行居中展示 mSize = (picSize[0] - vSize) / 2 - margin * 2 # 如果只有一行,则计算居中,如果两行,则设置为200 marginTop = int(picSize[1] / 2) - int(itemSize[1] / 2) if num <= 5 else 200 nextYStart = marginTop + actualSize[1] + 50 if num > 5 else -1 nextViewSize = (num % 5) * (itemSize[0] + num - 1) if num < 10 else 5 * (itemSize[0] + num - 1) nextMarginSize = (picSize[0] - nextViewSize) / 2 - margin * 2 print(nextMarginSize) # colNum = int(num / 5) + 1 # # print(colNum) def cutPic(img: ImageFile) -> Image: # 等比放小50% img = img.resize((int(img.width * 0.5), int(img.height * 0.5))) left = (img.width - itemSize[0])/2 top = (img.height - itemSize[1])/2 right = (img.width + itemSize[0])/2 bottom = (img.height + itemSize[1])/2 return img.crop((left, top, right, bottom)) def drawComponent(pic: ImageFile, text: str, startX: int = 0, startY: int = 0) -> Image: components = Image.new('RGBA', actualSize, color=(0, 0, 0, 0)) components.paste(cutPic(pic), (0, 0)) draw = ImageDraw.Draw(components) text_bbox = draw.textbbox((0, 0), text, font=font) # 计算文本宽度(文本框实际宽度) text_width = text_bbox[2] - text_bbox[0] # 计算文本居中 item_center_x = (startX + (itemSize[0] / 2)) text_y = startY + itemSize[1] + fontMargin draw.text((item_center_x - (text_width / 2), text_y), text, fill=(255, 255, 255), font=font) return components backImage = Image.new('RGB', picSize, color=(255, 255, 255)) backImage.paste(Image.open('./pic/luoxiaohei.jpg'), (0, 0)) # backImage.paste(drawComponent(Image.open('./sucai/1.jpg'), "我真的很长很长很长的文本", 0, 0), (200, 200)) for idx, img in enumerate(os.listdir('./sucai')): calc_X = int((itemSize[0] + margin) * idx + mSize) if idx < 5 else int((itemSize[0] + margin) * (idx % 5) + nextMarginSize) calc_Y = marginTop if idx < 5 else nextYStart print((calc_X, calc_Y)) component = drawComponent(Image.open('./sucai/' + img), img, 0, 0) backImage.paste(component, (calc_X, calc_Y), mask=component) # 写入结果 with open('./final.png', 'wb') as f: backImage.save(f) exit(0) for idx, file in enumerate(os.listdir('./sucai')): # 将图片修剪为指定大小 img = Image.open('./sucai/' + file) # img = img.resize(itemSize) # img.thumbnail(itemSize) # 再居中裁剪 img = cutPic(img) # 粘贴到背景图 backImage.paste(img, (int((itemSize[0] + margin) * idx + mSize) , marginTop)) # 在图片下面嵌字 draw = ImageDraw.Draw(backImage) font = ImageFont.load_default() # 使用24px大小的字体 # 绘制文本 # 计算文本宽度 text = "我真的很长很长很长的文本" text_bbox = draw.textbbox((0, 0), text, font=font) text_width = text_bbox[2] - text_bbox[0] # 计算图片项的中心位置 item_center_x = ((itemSize[0] + margin) * idx + mSize) + (itemSize[0] / 2) # 计算文本的起始x坐标,使其居中 text_x = item_center_x - (text_width / 2) text_y = marginTop + itemSize[1] + fontMargin draw.text((text_x, text_y), text, fill=(255, 255, 255), font=font) # 写入结果 with open('./luoxiaohei.jpg', 'wb') as f: backImage.save(f)