Document performance cost of using transparent PNG images #142

Closed
opened 2 years ago by ayoon · 5 comments
ayoon commented 2 years ago

As I hooked up img2pdf for the first time today in my project, I was surprised to see it was running quite slow converting a series of PNG images into PDF. My understanding was that since PNG images would be embedded directly into the PDFs without re-encoding, it should be very fast. I ran my code under a profiler and was surprised to see img2pdf seemed to be re-encoding the image in to_png_data(). After skimming that code I made a guess that using non-transparent images might avoid that step, which turned out to be correct.

It would be helpful if this performance penalty were documented somewhere, or even explicitly warned about in the same log line about "...will be stored as a separate soft mask..." (which to me is PDF jargon I didn't understand the implications of).

(ps - thanks for such a great library!)

As I hooked up img2pdf for the first time today in my project, I was surprised to see it was running quite slow converting a series of PNG images into PDF. My understanding was that since PNG images would be embedded directly into the PDFs without re-encoding, it should be very fast. I ran my code under a profiler and was surprised to see `img2pdf` seemed to be re-encoding the image in `to_png_data()`. After skimming that code I made a guess that using non-transparent images might avoid that step, which turned out to be correct. It would be helpful if this performance penalty were documented somewhere, or even explicitly warned about in the same log line about "...will be stored as a separate soft mask..." (which to me is PDF jargon I didn't understand the implications of). (ps - thanks for such a great library!)
josch commented 2 years ago
Owner

Good point! What do you think about this re-phrasing:

--- a/src/img2pdf.py
+++ b/src/img2pdf.py
@@ -1823,8 +1842,8 @@ def read_images(rawdata, colorspace, first_frame_only=False, rot=None):
 
                 smaskidat, _, _ = to_png_data(a)
                 logger.warning(
-                    "Image contains an alpha channel which will be stored "
-                    "as a separate soft mask (/SMask) image in PDF."
+                    "Image contains an alpha channel. Creating a separate "
+                    "soft mask (/SMask) image to store transparency in PDF."
                 )
             elif color in [Colorspace.P, Colorspace.PA] and iccp is not None:
                 # PDF does not support palette images with icc profile

Does this make clear what happens?

Good point! What do you think about this re-phrasing: ```diff --- a/src/img2pdf.py +++ b/src/img2pdf.py @@ -1823,8 +1842,8 @@ def read_images(rawdata, colorspace, first_frame_only=False, rot=None): smaskidat, _, _ = to_png_data(a) logger.warning( - "Image contains an alpha channel which will be stored " - "as a separate soft mask (/SMask) image in PDF." + "Image contains an alpha channel. Creating a separate " + "soft mask (/SMask) image to store transparency in PDF." ) elif color in [Colorspace.P, Colorspace.PA] and iccp is not None: # PDF does not support palette images with icc profile ``` Does this make clear what happens?
ayoon commented 2 years ago
Poster

That's an improvement, but from an image encoding newbie's perspective it would be even more helpful if it said something explicitly like 'Encoding separate soft mast (/SMask) to support transparency at a performance cost'.

As an aside, I wonder if it could be a nice option to automatically flatten transparent images, since I can't think of a use-case for transparent images in the "one-image-per-page" function I understand this library serves.

That's an improvement, but from an image encoding newbie's perspective it would be even more helpful if it said something explicitly like 'Encoding separate soft mast (/SMask) to support transparency at a performance cost'. As an aside, I wonder if it could be a nice option to automatically flatten transparent images, since I can't think of a use-case for transparent images in the "one-image-per-page" function I understand this library serves.
ayoon commented 2 years ago
Poster

Also, it might be helpful to update the readme so the format-colorspace-result table has a separate entry for transparent PNGs, so the behavior is documented outside that log line

Also, it might be helpful to update the readme so the format-colorspace-result table has a separate entry for transparent PNGs, so the behavior is documented outside that log line
josch commented 2 years ago
Owner

That's an improvement, but from an image encoding newbie's perspective it would be even more helpful if it said something explicitly like 'Encoding separate soft mast (/SMask) to support transparency at a performance cost'.

Everything done on a computer is "at a performance cost". The only thing not to have a performance cost is to do the same thing or to not do anything. How about replacing "Creating" by "Computing"?

As an aside, I wonder if it could be a nice option to automatically flatten transparent images, since I can't think of a use-case for transparent images in the "one-image-per-page" function I understand this library serves.

That's why before support for transparent images was added, img2pdf would throw an error when you tried to convert images with transparency to PDF. The one thing that makes img2pdf special is, that it's lossless. That's why img2pdf will not remove the alpha channel from the input because that will be lossy. If you are fine with lossy conversions, then there are a lot of other tools that can convert images to PDF.

Also, it might be helpful to update the readme so the format-colorspace-result table has a separate entry for transparent PNGs, so the behavior is documented outside that log line

No separate entry is needed but the PNG line has to be changed so that it documents direct inclusion only happens for input that doesn't have transparency:

--- a/README.md
+++ b/README.md
@@ -27,15 +27,15 @@ software, because the raw pixel data never has to be loaded into memory.
 The following table shows how img2pdf handles different input depending on the
 input file format and image color space.
 
-| Format               | Colorspace                     | Result        |
-| -------------------- | ------------------------------ | ------------- |
-| JPEG                 | any                            | direct        |
-| JPEG2000             | any                            | direct        |
-| PNG (non-interlaced) | any                            | direct        |
-| TIFF (CCITT Group 4) | monochrome                     | direct        |
-| any                  | any except CMYK and monochrome | PNG Paeth     |
-| any                  | monochrome                     | CCITT Group 4 |
-| any                  | CMYK                           | flate         |
+| Format                                | Colorspace                     | Result        |
+| ------------------------------------- | ------------------------------ | ------------- |
+| JPEG                                  | any                            | direct        |
+| JPEG2000                              | any                            | direct        |
+| PNG (non-interlaced, no transparency) | any                            | direct        |
+| TIFF (CCITT Group 4)                  | monochrome                     | direct        |
+| any                                   | any except CMYK and monochrome | PNG Paeth     |
+| any                                   | monochrome                     | CCITT Group 4 |
+| any                                   | CMYK                           | flate         |
 
 For JPEG, JPEG2000, non-interlaced PNG and TIFF images with CCITT Group 4
 encoded data, img2pdf directly embeds the image data into the PDF without
> That's an improvement, but from an image encoding newbie's perspective it would be even more helpful if it said something explicitly like 'Encoding separate soft mast (/SMask) to support transparency at a performance cost'. Everything done on a computer is "at a performance cost". The only thing not to have a performance cost is to do the same thing or to not do anything. How about replacing "Creating" by "Computing"? > As an aside, I wonder if it could be a nice option to automatically flatten transparent images, since I can't think of a use-case for transparent images in the "one-image-per-page" function I understand this library serves. That's why before support for transparent images was added, img2pdf would throw an error when you tried to convert images with transparency to PDF. The one thing that makes img2pdf special is, that it's lossless. That's why img2pdf will not remove the alpha channel from the input because that will be lossy. If you are fine with lossy conversions, then there are a lot of other tools that can convert images to PDF. > Also, it might be helpful to update the readme so the format-colorspace-result table has a separate entry for transparent PNGs, so the behavior is documented outside that log line No separate entry is needed but the `PNG` line has to be changed so that it documents `direct` inclusion only happens for input that doesn't have transparency: ```diff --- a/README.md +++ b/README.md @@ -27,15 +27,15 @@ software, because the raw pixel data never has to be loaded into memory. The following table shows how img2pdf handles different input depending on the input file format and image color space. -| Format | Colorspace | Result | -| -------------------- | ------------------------------ | ------------- | -| JPEG | any | direct | -| JPEG2000 | any | direct | -| PNG (non-interlaced) | any | direct | -| TIFF (CCITT Group 4) | monochrome | direct | -| any | any except CMYK and monochrome | PNG Paeth | -| any | monochrome | CCITT Group 4 | -| any | CMYK | flate | +| Format | Colorspace | Result | +| ------------------------------------- | ------------------------------ | ------------- | +| JPEG | any | direct | +| JPEG2000 | any | direct | +| PNG (non-interlaced, no transparency) | any | direct | +| TIFF (CCITT Group 4) | monochrome | direct | +| any | any except CMYK and monochrome | PNG Paeth | +| any | monochrome | CCITT Group 4 | +| any | CMYK | flate | For JPEG, JPEG2000, non-interlaced PNG and TIFF images with CCITT Group 4 encoded data, img2pdf directly embeds the image data into the PDF without ```
ayoon commented 2 years ago
Poster

Those suggestions work for me. I think that doc change in particular would have led me to figuring out the issue much quicker. Thanks!

Those suggestions work for me. I think that doc change in particular would have led me to figuring out the issue much quicker. Thanks!
josch closed this issue 2 years ago
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: josch/img2pdf#142
Loading…
There is no content yet.