Skip to content
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

Since 6.0, setting float resolution with dpi argument converts to an integer #4129

Closed
Bolayniuss opened this issue Oct 11, 2019 · 12 comments
Closed
Labels
Projects

Comments

@Bolayniuss
Copy link

Bolayniuss commented Oct 11, 2019

Since Pillow==6.0, when doing this:

pillow_image.save(
    file_path,
    dpi=(812.8, 812.8)
)

the resolution of the of the saved file is (813, 813), even if the dpi value is a PIL.TiffImagePlugin.IFDRational object. (I use Photoshop CS6 to check the resolution)

before 6.0 it was (812.8, 812.8).

I've found that using the resolution argument solve this issue but then the img.info is a bit weird as it gives two different values for the resolution and dpi

{'dpi': (813, 813), 'resolution': (812.8000797477443, 812.8000797477443)}
@radarhere radarhere changed the title Since 6.0, setting the float resolution with dpi argument convert it to an integer. Since 6.0, setting the float resolution with dpi argument convert it to an integer Oct 11, 2019
@radarhere
Copy link
Member

radarhere commented Oct 11, 2019

If you look at PR #3709, you'll see that rounding was deliberately added, to be consistent about the way that DPI was treated across image formats.

@radarhere radarhere added the TIFF label Oct 11, 2019
@Bolayniuss
Copy link
Author

Bolayniuss commented Oct 11, 2019

Alright, I see that it's done an purpose. But I still don't understand why? Why DPI should be magically rounded, especially when a float was previously expected. Why DPI should be constraint to integer, a float resolution is not just an abstract concept, it's something that can exist.

I am also confused by the different behaviour when setting the resolution instead of dpi.

@radarhere radarhere changed the title Since 6.0, setting the float resolution with dpi argument convert it to an integer Since 6.0, setting float resolution with dpi argument converts to an integer Oct 14, 2019
@aclark4life aclark4life added this to New Issues in Pillow Jan 9, 2020
@Bolayniuss
Copy link
Author

Bolayniuss commented Oct 6, 2020

Is there any news about this issue. I am currently dealing with this issue by keeping Pillow under v6 but it will not be manageable any longer. First because of new python versions (since p3.8 is not "officially" supported by Pillow < 6.2.1), Secondly because a lot of our dependencies expect a Pillow version >= 6, it was not a huge deal until now, but PIP change it's way to deal with dependencies and we have conflict now.

To add to the topic, and correct me if I am wrong but resolution is stored as a RATIONAL on TIFF images so why not simply supporting a rational input type?

Thanks to keep me updated.

@awbacker
Copy link

Curious if this will ever be fixed, or adjusted to maybe support setting of a Decimal at least, to alert the code that it shouldn't round. The HP Indigo is 812.8 DPI at least in halftone, and that is an extremely common printer.

I've hacked this floating point resolution into golang and node packages (which are much more primitive imaging libraries), but this one is beyond me for now.

From a forum thread I found:

Most drum scanners were metric, so instead of scanning at a true 150 lpi they digitized files at 60 LCM or 120 PPCM
NOTE: Halftone resolution was commonly half of the digital image resolution or a digital image had 2 pixels per halftone line.
A 60 LCM halftone was actually digitized at 120 PPCM
120 x 2.54 = 304.8
Th e difference between the 2438.4 and 2400 is due to the rounding of the metric halftone resolutions.
304.8/300 = 1.016 ( 2400 x 1.016 =2438.4 )

@fireattack
Copy link

fireattack commented Oct 27, 2020

As the original reporter of #3323 (which originally was about it always rounded up for some formats), I agree not rounding (or rounding to decimal) will be better.

As mentioned above (and in #3323), there are plenty of devices (mainly scanners, printers) that internally use metric units for PPI/DPI. So for these devices, they will always have rounding errors.

@radarhere
Copy link
Member

I've created #5446 to restore float resolutions for TIFF.

Could anyone here let me know what other formats you are concerned about?

@radarhere
Copy link
Member

You can't save PNG or BMP with a float DPI, and I don't see how you could do it for JPEG.

We could remove rounding from JPEG when loading, but searching through our files, I can't see a practical need for this as none of our files have a float DPI, except for a file I probably created for #3709. As for a theoretical need, the idea of rounding only on save seems unbalanced.

I've created #5470 to restore float resolutions for WMF.

That covers all of the formats affected by #3709.

@fireattack
Copy link

fireattack commented May 6, 2021

Do you mean you can't save PNG/BMP with float DPI with pillow or in general?

If you look at the original ticket #3323, that test image (which is generated with my sanner) does have a float DPI and it's pretty common for all the scanners I have used (Epson, Canon, etc.).

(Technically, it doesn't even have a DPI header, just PPC (which itself can be float it seems; and even if it's integer only, converting it to DPI would result in float too.)

It becomes especially annoying to process image resizing if you rely on DPI settings (say, resizing the image from current DPI to 200). It results in different final dimensions (in pixels) from the expectation when image is large.

@awbacker
Copy link

awbacker commented May 6, 2021

I believe he is referring to the data type in the file header(s). PNG & BMP spec specify their resolution in pixels per meter, so as an integer. Divided into a DPI would likely give a floating point.

Tiff expects a rational number (not really floating point), see the tiff spec on XResolution.

We do work with printing/platemaking software which absolutely requires a rational dpi (4064,5) and not (812.79999..545..), and also 1BPP encoding. I've now manually written simple TIFF encoders in multiple languages because of this. Its really a simple format when you don't have to be as flexible as PIL or libtiff.

@fireattack
Copy link

fireattack commented May 6, 2021

Thanks for the info. If it's PPM in integer in specification, yeah that explains why it's decimal in PPC (per centimeter) (either way, it can make DPI float).

After another thought, I think maybe @radarhere meant that PIL/pillow never could have float DPI for BMP/PNG even before v6. So if we simply want to restore the previous behavior, it's absolutely fair to only revert on TIF/WMF. Just feel like this is a good chance to improve on it since the specification of the PNG/BMP does allow float DPI (extra work, I know).

@radarhere
Copy link
Member

Ok, I've realised I was wrong. BMP saves an integer... ppm, not dpi, where ppm is dpi * 39.3701. The same with PNG, where it saves an integer that is the dpi / 0.0254. So Pillow can currently save BMP and PNG with float dpis, it just rounds them when loading.

I've created #5476 to remove the loading on rounding for JPEG, BMP and PNG.

@radarhere
Copy link
Member

radarhere commented May 16, 2021

Okay, the relevant PRs have now been merged.
#5476 addressed BMP, JPEG and PNG - you should now be able to load float DPIs with all of them
#5470 addressed WMF - you should now be able to load float DPIs
#5446 addressed TIFF - you should now be able to load and save float DPIs

This should all be part of the next Pillow release, 8.3.0, due July 1. Let me know if I have missed anything.

Pillow automation moved this from New Issues to Closed May 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Pillow
  
Closed
Development

No branches or pull requests

4 participants