-
Notifications
You must be signed in to change notification settings - Fork 13
Extending replace_picture() to scale images:
#9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
e995f82
948ab46
1a3aca6
badd26f
2fe3714
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,14 +33,47 @@ def replace_text(self, label: str, new_text: str) -> None: | |
| for shape in shapes: | ||
| shape.text = new_text | ||
|
|
||
| def replace_picture(self, label: str, filename: _Pathlike) -> None: | ||
| def replace_picture(self, label: str, filename: _Pathlike, *, do_not_scale_up: bool = False) -> None: | ||
| """Replaces rectangle placeholders on one or many slides. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor rewording please: ... on one or many slides with an image. |
||
|
|
||
| Args: | ||
| label (str): label of the placeholder (without curly braces) | ||
| filename (path-like): path to an image file | ||
| do_not_scale_up (bool): deactivates that the image is enlarged (default: False) | ||
| """ | ||
m-entrup marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| pass | ||
| shapes_to_replace = self._find_shapes(label) | ||
m-entrup marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if not shapes_to_replace: | ||
| raise ValueError(f"The label '{label}' can't be found in the template.") | ||
| if isinstance(filename, str): | ||
m-entrup marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| filename = pathlib.Path(filename) | ||
| if not filename.is_file(): | ||
m-entrup marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| raise FileNotFoundError(f"The file does not exist: {filename}") | ||
| with open(filename, "rb") as img_file: | ||
| old_shape: BaseShape | ||
| for old_shape in shapes_to_replace: | ||
| slide_shapes = old_shape._parent | ||
| img_shape = slide_shapes.add_picture( | ||
| image_file=img_file, | ||
| left=old_shape.left, | ||
| top=old_shape.top, | ||
| ) | ||
| # Scaling the image if `do_not_scale == False`: | ||
| if img_shape.height <= old_shape.height and img_shape.width <= old_shape.width and not do_not_scale_up: | ||
| old_aspect_ratio = old_shape.width / old_shape.height | ||
| new_aspect_ratio = img_shape.width / img_shape.height | ||
| if old_aspect_ratio >= new_aspect_ratio: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using an image in portrait mode, the width of the image is set to the width of old_shape, which results in an overflow in y direction. This logic seems broken? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Vice versa, an image in landscape mode overflows in x direction. Replacing |
||
| img_shape.width = old_shape.width | ||
| img_shape.height = int(img_shape.width / new_aspect_ratio) | ||
| else: | ||
| img_shape.height = old_shape.height | ||
| img_shape.width = int(img_shape.height * new_aspect_ratio) | ||
| # Centering the image at the extent of the placeholder: | ||
| img_shape.top += int((old_shape.height - img_shape.height) / 2) | ||
| img_shape.left += int((old_shape.width - img_shape.width) / 2) | ||
| del slide_shapes[slide_shapes.index(old_shape)] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For me running on Python 3.6.9 (installed via pyenv, test suite is OK), the deletion is not working: |
||
| # Removing shapes is performed at the lxml level. | ||
| # The `element` attribute contains an instance of `lxml.etree._Element`. | ||
| slide_shapes.element.remove(old_shape.element) | ||
|
|
||
| def replace_table(self, label: str, data) -> None: | ||
| """Replaces rectangle placeholders on one or many slides. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the motivation / usecase szenario for
do_not_scale_up?I would want the following behaviors in the future (might be in a future PR).
Note, that
do_not_scale_upandscaleare sort of orthogonal.Naming: One might want to use
scale_policyinstead ofdo_not_scale_up; with values "shrink-only", "enlarge-only",None.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With my implementation the image does always fit into the size of the replaced shape. By calculating the aspect ratio I am able to defect if
heightorwidthis the limiting dimension. This is the same asscale='fit'.I don't like the idea of adding the options 'fit-width' and 'fit-height'. Allowing the image to get larger than the placeholder will result in overlapping with other shapes.
The
scale_up=Falseis useful if an image is only a little to small. Scaling it up by a view percent will reduce the image quality. By preventing up scaling we will get the best image quality.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not saying that they should be default. But we shouldn't assume too much on the user's intention. I can imagine situations in which you'd really want to force the width/height - no matter the cost.
I agree that preventing upscaling might be desirable. Similarly, somebody might want to prevent downscaling since it reduces the information in the image.