创建演示文稿并使用python-pptx插入图片时,如何获取图片占位符的尺寸以调整图片大小?

问题描述:

我正在尝试使用python-pptx从模板插入经过调整大小以适合图片占位符尺寸的图片.我不认为我可以从文档中找到该API的直接访问权限.是否有关于使用库或其他方法如何执行此操作的建议?

I'm trying to insert a picture that is re-sized to fit the dimensions of the picture placeholder from a template using python-pptx. I don't believe the API has direct access to this from what I can find out in the docs. Is there any suggestion of how I might be able to do this, using the library or other?

我有一个运行代码,它将一系列图像插入一组模板幻灯片中,以使用Powerpoint自动创建报告.

I have a running code that will insert a series of images into a set of template slides to automatically create a report using Powerpoint.

这里是从事大部分相关工作的职能.该应用程序的其他部分正在创建演示文稿并插入幻灯片等.

Here is the function that is doing the majority of the work relevant. Other parts of the app are creating the Presentation and inserting a slide etc.

def insert_images(slide, slide_num, images_path, image_df):

    """
    Insert images into a slide.
    :param slide: = slide object from Presentation class 
    :param slide_num: the template slide number for formatting
    :param images_path: the directory to the folder with all the images
    :param image_df: Pandas data frame regarding information of each image in images_path
    :return: None
    """

    placeholders = get_image_placeholders(slide)
    #print(placeholders)
    image_pool = image_df[image_df['slide_num'] == slide_num]

    try:
        assert len(placeholders) == len(image_pool.index)
    except AssertionError:
        print('Length of placeholders in slide does not match image naming.')
    i = 0
    for idx, image in image_pool.iterrows():
        #print(image)
        image_path = os.path.join(images_path, image.path)
        pic = slide.placeholders[placeholders[i]].insert_picture(image_path)
        #print(image.path)
        # TODO: Add resize - get dimensions of pic placeholder
        line = pic.line
        print(image['view'])
        if image['view'] == 'red':
            line.color.rgb = RGBColor(255, 0, 0)
        elif image['view'] == 'green':
            line.color.rgb = RGBColor(0, 255, 0)
        elif image['view'] == 'blue':
            line.color.rgb = RGBColor(0, 0, 255)
        else:
            line.color.rgb = RGBColor(0, 0, 0)
        line.width = Pt(2.25)
        i+=1

问题是当我将图片插入图片占位符时,图片被裁剪,而不是调整大小.我不希望用户知道在我的脚本中进行硬编码的尺寸.如果使用的图像相对较大,则可能会裁切很大一部分,而无法使用.

The issue is that when I insert a picture into the picture placeholder, the image is cropped, not re-sized. I don't want the user to know the dimensions to hard code into my script. If the image used is relatively large it can crop a very large portion and just not be usable.

PicturePlaceholder.insert_picture()返回的图片对象的位置和大小与其所源自的占位符相同.它被裁剪以完全填充该空间.根据占位符和插入图像的相对长宽比,裁剪顶部和底部或左侧或右侧.当您将图片插入图片占位符时,PowerPoint表现出相同的行为.

The picture object returned by PicturePlaceholder.insert_picture() has the same position and size as the placeholder it derives from. It is cropped to completely fill that space. Either the tops and bottoms are cropped or the left and right sides, depending on the relative aspect ratio of the placeholder and the image you insert. This is the same behavior PowerPoint exhibits when you insert a picture into a picture placeholder.

如果要删除裁剪,只需将所有裁剪值设置为0:

If you want to remove the cropping, simply set all cropping values to 0:

picture = placeholder.insert_picture(...)
picture.crop_top = 0
picture.crop_left = 0
picture.crop_bottom = 0
picture.crop_right = 0

这不会更改位置(位于左上角),但几乎总是会更改大小,从而使其变宽或变高(但不能同时变高).

This will not change the position (of the top-left corner) but will almost always change the size, making it either wider or taller (but not both).

因此,这很容易解决了第一个问题,但是当然为您提供了第二个问题,即如何将图片放置在所需位置以及如何在不更改纵横比(拉伸或压缩)的情况下适当缩放图片.

So this solves the first problem easily, but of course presents you with a second one, which is how to position the picture where you want it and how to scale it appropriately without changing the aspect ratio (stretching or squeezing it).

这在很大程度上取决于您要完成的工作以及您最满意的结果.这就是为什么它不是自动的;只是无法预测.

This depends a great deal on what you're trying to accomplish and what outcome you find most pleasing. This is why it is not automatic; it's just not possible to predict.

您可以找到图像的本机"宽度和高度,如下所示:

You can find the "native" width and height of the image like this:

width, height = picture.image.size  # ---width and height are int pixel-counts

从那里,您需要比较原始占位符和插入的图像的长宽比,并调整图片形状的宽度或高度.

From there you'll need to compare aspect ratios of the original placeholder and the image you inserted and either adjust the width or height of the picture shape.

因此,您要保持相同的位置,但将占位符的宽度和高度保持为各自的最大值,以使整个图片适合该空间,但在底部或右侧有一个边距":

So say you wanted to keep the same position but maintain the width and height of the placeholder as respective maximums such that the entire picture fits in the space but has a "margin" either on the bottom or the right:

available_width = picture.width
available_height = picture.height
image_width, image_height = picture.image.size
placeholder_aspect_ratio = float(available_width) / float(available_height)
image_aspect_ratio = float(image_width) / float(image_height)

picture.crop_top = 0
picture.crop_left = 0
picture.crop_bottom = 0
picture.crop_right = 0

# ---if the placeholder is "wider" in aspect, shrink the picture width while
# ---maintaining the image aspect ratio
if placeholder_aspect_ratio > image_aspect_ratio:
    picture.width = int(image_aspect_ratio * available_height)
# ---otherwise shrink the height
else:
    picture.height = int(available_width/image_aspect_ratio)

可以将其详细说明为将图像居中"在原始空间内,并可能使用负裁切"来保留原始占位符大小.

This could be elaborated to "center" the image within the original space and perhaps to use "negative cropping" to retain the original placeholder size.

我还没有测试过,您可能需要进行一些调整,但是希望这可以使您了解如何进行操作.提取到自己的功能(如adjust_picture_to_fit(picture))是一件好事.

I haven't tested this and you might need to make some adjustments, but hopefully this gives you an idea how to proceed. This would be a good thing to extract to its own function, like adjust_picture_to_fit(picture).