将裁剪图像的文件夹填充到最大宽度
Posted
技术标签:
【中文标题】将裁剪图像的文件夹填充到最大宽度【英文标题】:Pad Folder Of Cropped Images To Maximum Width 【发布时间】:2019-12-25 12:37:44 【问题描述】:有没有办法获取裁剪图像的文件夹,取它们的最大宽度,然后在右侧用白色填充其余部分,使它们的宽度都相同?
我编写了一个 python 脚本,它获取一个图像文件夹,裁剪掉它们的白色边框,然后在第二步中将它们重新缩放为 PDF。图片是来自脚本的引理,这就是为什么不是所有图片都填满整个线宽的原因。
问题是,如果一个图像在裁剪前没有填满线宽,白色会被自动裁剪掉,然后图像宽度太窄,如果再粘贴到PDF中,它就会被放大,并且方式超出比例。 因此,最好先裁剪它们,然后填充它们,然后继续创建 PDF。
下面是整个代码,虽然只有 trim 和 crop 方法可能会受到这个问题的影响。
# All the necessary parameters are accessible after line 55,
# but can of course be changed manually in the Code
# imports for the crop, rename to avoid conflict with reportlab Image import
from PIL import Image as imgPIL
from PIL import ImageChops
import os.path, sys
# import for the PDF creation
import glob
from reportlab.lib.pagesizes import A4
from reportlab.lib import utils
from reportlab.platypus import Image, SimpleDocTemplate, Spacer
from reportlab.lib.units import mm, inch
# get os path for Cropping
path = (os.path.dirname(os.path.abspath("cropPDF.py")))
dirs = os.listdir(path)
def trim(im, border="white"):
bg = imgPIL.new(im.mode, im.size, border)
diff = ImageChops.difference(im, bg)
bbox = diff.getbbox()
if bbox:
return im.crop(bbox)
def crop():
for item in dirs:
try:
fullpath = os.path.join(path, item)
if os.path.isfile(fullpath):
im = imgPIL.open(fullpath)
f, e = os.path.splitext(fullpath)
imCrop = trim(im, "white")
imCrop.save(f + ".png", "PNG", quality=100)
except:
pass
def add_page_number(canvas, doc):
canvas.saveState()
canvas.setFont('Times-Roman', numberFontSize)
page_number_text = "%d" % (doc.page)
canvas.drawCentredString(
pageNumberSpacing * mm,
pageNumberSpacing * mm,
page_number_text
)
canvas.restoreState()
#############################
executeCrop = True
outputName = "output.pdf"
margin = 0.5
imageWidthDefault = 550
spacerHeight = 7
scalingIfImageTooTall = 0.95 # larger than 95 can result in an empty page after the image
includePagenumbers = True
numberFontSize = 10
pageNumberSpacing = 5
############################
if executeCrop:
crop()
filelist = glob.glob("*.png") # Get a list of files in the current directory
filelist.sort()
doc = SimpleDocTemplate(
outputName,
topMargin=margin * mm,
leftMargin=margin * mm,
rightMargin=margin * mm,
bottomMargin=margin * mm,
pagesize=A4
)
story = [] # create the list of images for the PDF
for fn in filelist:
img = utils.ImageReader(fn)
img_width, img_height = img.getSize() # necessary for the aspect ratio
aspect = img_height / float(img_width)
documentHeight = doc.height
imageWidth = imageWidthDefault
imageHeight = imageWidth * aspect
if imageHeight > documentHeight:
imageHeight = documentHeight * scalingIfImageTooTall
imageWidth = imageHeight / aspect
img = Image(
fn,
width=imageWidth,
height=imageHeight
)
story.append(img)
space = Spacer(width=0, height=spacerHeight)
story.append(space)
if includePagenumbers and not len(filelist) == 0: # if pagenumbers are desired, or not
doc.build(
story,
onFirstPage=add_page_number,
onLaterPages=add_page_number,
)
elif not len(filelist) == 0:
doc.build(story)
else: # to prevent an empty PDF that can't be opened
print("no files found")
【问题讨论】:
【参考方案1】:我现在使用from PIL import ImageOps
创建了一个解决方案
这两个新方法提供了所需的功能,第一个找到所有图像的最大宽度,第二个为文件夹中的每个图像创建一个空白图像,并将原始图像粘贴到顶部:
def findMaxWidth():
maxWidth = 0
for item in dirs:
try:
fullpath = os.path.join(path, item)
if os.path.isfile(fullpath):
im = imgPIL.open(fullpath)
maxWidth = max(maxWidth, im.size[0])
except:
pass
return maxWidth
def padImages():
maxWidth = findMaxWidth()
for item in dirs:
try:
fullpath = os.path.join(path, item)
if os.path.isfile(fullpath):
im = imgPIL.open(fullpath)
f, e = os.path.splitext(fullpath)
width,height = im.size #get the image dimensions, the height is needed for the blank image
image = imgPIL.new('RGB', (maxWidth, height), (255, 255, 255)) #create a white image with the max width
image.paste(im, (0,0) ) #paste the original image overtop the blank one, flush on the left side
image.save(f + ".png", "PNG", quality=100)
except:
pass
【讨论】:
以上是关于将裁剪图像的文件夹填充到最大宽度的主要内容,如果未能解决你的问题,请参考以下文章