Skip to content

Fix setting of TIFF ExtraSamples tag#1059

Closed
anntzer wants to merge 10 commits intopython-pillow:masterfrom
anntzer:tiff-extra-samples
Closed

Fix setting of TIFF ExtraSamples tag#1059
anntzer wants to merge 10 commits intopython-pillow:masterfrom
anntzer:tiff-extra-samples

Conversation

@anntzer
Copy link
Contributor

@anntzer anntzer commented Dec 28, 2014

@wiredfool
Copy link
Member

ok, will check

@wiredfool wiredfool added the TIFF label Dec 29, 2014
@wiredfool
Copy link
Member

We're going to need more than this to conform to the spec when writing tags. (ref: http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html)

This winds up calling TIFFVSetField with variable args -- with the arguments for specific tags being the correct types as listed in the doc referenced. Unfortunately, it's not consistent where arrays are represented as ct, [number]. Some of them are [number] with a fixed length (e.g. TIFFTAG_PRIMARYCHROMATICITIES), some are ct, [number]* (e.g. TIFFTAG_EXTRASAMPLES).

What we're going to need to do to do this properly is to list the known tags & types, and make sure that we're emitting the right types and data for those. Additionally, we'd then know which are the unknown tags, which would then need to be dealt with separately by adding them to the tiff types dictionary prior to adding the tag. (#983, #660)

@anntzer
Copy link
Contributor Author

anntzer commented Dec 30, 2014

I gave in and just rewrote the whole thing.

@wiredfool
Copy link
Member

Wow, that you did.

@wiredfool wiredfool mentioned this pull request Jan 6, 2015
@landscape-bot
Copy link

Code Health
Repository health decreased by 0.79% when pulling a6a6dbe on anntzer:tiff-extra-samples into cdfddc8 on python-pillow:master.

@anntzer
Copy link
Contributor Author

anntzer commented Jan 13, 2015

I just noticed your comment on #520 about incompatibilities. Do you have any specific suggestions? It is not clear to me how to keep full backwards compatibility there...

@wiredfool
Copy link
Member

I don't have specific suggestions yet -- I haven't gotten in the headspace to go through and see what all is failing from the tests (since right now, they're fail fast, there could be many hiding behind the one failure), and even if the tests are actually covering what needs to be covered.

Breaking user's code is something that I don't want to do, at least without some deprecation warnings and a phase in over some time. (From a quick look, the two things that concern me are changing some of the test items -- but I need to look closer to see if that's changing internal implementation details, or changing the only way people had to get that information, and the changes in the way that the TiffTags are done, especially removing a huge chunk of tags that we did have in there. )

I think what I'd probably look at doing is building up the IFD info in whatever api and structure works for it, including supporting EXIF (since it's the same thing), then blessing the new api as the way to do it. I'd then go back and make the old api work in a best-effort / best-guess approach, building on the new, working core.

@landscape-bot
Copy link

Code Health
Repository health decreased by 0.76% when pulling b58fdaa on anntzer:tiff-extra-samples into cdfddc8 on python-pillow:master.

@anntzer anntzer force-pushed the tiff-extra-samples branch from b58fdaa to c3be6d4 Compare January 14, 2015 07:18
@anntzer
Copy link
Contributor Author

anntzer commented Jan 14, 2015

The removal of a huge chunk of tags is simply due to the fact that I was too lazy to figure out the type of each of the tags, as this is now needed. This can easily be added back once we have decided on the actual API, which I agree is the main issue.
I had not noticed that some tests were failing, because in fact, trying to run all the tests at once fails locally, but I can run single test files so I'm just catching whatever Travis is complaining about, one file at a time. So now MPO should be fixed (basically, now, values for unknown tags are returned as tuples, so I needed to enter the MPO tags in the TiffTags database. (The other test was due to the use of dict comprehensions and implicit format string indexing, not supported by Python 2.6).

@anntzer anntzer force-pushed the tiff-extra-samples branch from c3be6d4 to d1e2db6 Compare January 14, 2015 07:45
@coveralls
Copy link

Coverage Status

Changes Unknown when pulling d1e2db6 on anntzer:tiff-extra-samples into * on python-pillow:master*.

@hugovk
Copy link
Member

hugovk commented Jan 14, 2015

@anntzer Some tips.

Make full use of Travis CI to run the full test suite on all Python versions. I recommend enabling Travis (and Coveralls, seeing as you're making a big change) for your own account, so you can have your own branches fully tested. They're free for open source.

See https://github.com/python-pillow/Pillow/blob/master/CONTRIBUTING.md for guidelines.

If you want to temporarily disable fail-first and see all test failures, remove the x option in this line of .travis.yml:

coverage run --append --include=PIL/* -m nose -vx Tests/test_*.py

It'll need to be re-enabled when everything is all done and the PR is ready for merging.

Ideally all changed code should be covered by tests, and especially for big changes, it's wise to make sure there are specific tests for the functionality being changed.

@anntzer anntzer force-pushed the tiff-extra-samples branch from d1e2db6 to 3b0e0bf Compare January 14, 2015 09:18
@landscape-bot
Copy link

Code Health
Repository health decreased by 0.63% when pulling 3b0e0bf on anntzer:tiff-extra-samples into 264f5d0 on python-pillow:master.

@anntzer
Copy link
Contributor Author

anntzer commented Feb 6, 2015

I don't really want to shoehorn the old API on top of the new one, so what about the following: have a global tag (e.g., TIFF_API = "2.7" or "2.8", the default value being obviously a policy issue rather than a code issue) that'll switch between either API? The tag would live in the PIL namespace, so that it can be checked for when TiffImagePlugin is imported for the first time.

@aclark4life
Copy link
Member

@anntzer Any progress on this?

@aclark4life aclark4life added this to the 2.9.0 milestone Apr 1, 2015
@anntzer
Copy link
Contributor Author

anntzer commented Apr 1, 2015

Did you see the Feb 25th commits? I was waiting for your opinion on the approach (providing a legacy_api attribute on IFD objects, defaulting to False).

@aclark4life
Copy link
Member

Ah, thanks. We probably need @wiredfool or @hugovk to review.

anntzer added a commit to anntzer/Pillow that referenced this pull request Apr 23, 2015
cf. python-pillow#1191.

Only TiffImagePlugin and OLEFileIO still rely on a DEBUG flag.  I left
TiffImagePlugin as it is because I hope python-pillow#1059 gets merged in first, and
OLEFileIO because it uses its own logic.

Untested, as usual.
anntzer added 3 commits June 29, 2015 12:45
To have the old API that always returns tuples, and fractions as pairs,
set the `legacy_api` attribute of the IFD to True.

This should alleviate concerns about backwards compatibility.
Some programs generate SamplesPerPixel entries in ExtraSamples instead
of SamplesPerPixel-3, cf. python-pillow#1227.  This is a stopgap measure to support
them.  One could also decide to add generic code to always support
having SamplesPerPixel entries (by dropping the first 3).
By interleaving little and big-endian entries we make sure entries
exist for both cases.  Some additional entries created when the
big-endian was missing.  I am not sure of what entry to create for the
big-endian, 4-bit case (what is the order of the two entries within the
byte?).
@anntzer anntzer force-pushed the tiff-extra-samples branch from 662e815 to 752d463 Compare June 29, 2015 19:47
@aclark4life
Copy link
Member

Currently seeing failures here
screen shot 2015-06-29 at 4 56 01 pm

@anntzer
Copy link
Contributor Author

anntzer commented Jun 29, 2015

Sorry, I rebased mostly just to get a new appveyor build (I guess something went wrong during the transition).
I knew that there would be some failures, as mentioned in my previous message. I would like to revert the behavior recently introduced in ed2cca1 which leads to loading corrupted exif data with just a warning rather than with an exception. IMHO, there is no reason to guess what the exif data should be when it is corrupted.
On the other hand I wouldn't mind raising an exception other than struct.error (which can legitimately considered to be an implementation detail).

@anntzer anntzer force-pushed the tiff-extra-samples branch from 309984e to d27cddd Compare June 30, 2015 01:37
@anntzer
Copy link
Contributor Author

anntzer commented Jun 30, 2015

Can someone reproduce Travis's failures locally? Despite my best attempts I cannot reproduce them (on Linux 64bit).

In theory I could "fix" the failures by replacing calls to assertEqual by calls to assertAlmostEqual (what the tests previously did, which amounts to admitting that the code cannot actually roundtrip the data correctly), but obviously it would be better to avoid that.

@radarhere
Copy link
Member

I am unable to reproduce on OS X.

@wiredfool
Copy link
Member

I can reproduce on Ubuntu 12.04/x64. Changing the assert to

      self.assertEqual(val, value, msg="%s didn't roundtrip. %s, %s" % (tag, val, value))

yields:

Traceback (most recent call last):
  File "/home/erics/Pillow/Tests/test_file_libtiff.py", line 144, in test_write_metadata
    self.assertEqual(val, value, msg="%s didn't roundtrip. %s, %s" % (tag, val, value))
AssertionError: YResolution didn't roundtrip. ((4294967295, 113653537),), ((634011008, 16777216),)

They are roughly equivalent, but different representations.

@anntzer
Copy link
Contributor Author

anntzer commented Jun 30, 2015

Sorry, I won't have the time to work on this in the next few days. We could switch back to assertAlmostEqual (which as I mentioned earlier was already used by the earlier tests) for now...

@aclark4life aclark4life modified the milestones: Future, 2.9.0 Jun 30, 2015
@anntzer
Copy link
Contributor Author

anntzer commented Jun 30, 2015

The problem is that I have no idea of where (634011008, 16777216) comes from. It is not that hard to see that the value actually stored in the file is (4294967295, 113653537) (hex dump ffff ffff 2137 c606 towards the end of the file) and this is also the value I see if I print the values in the test.
Likewise these are the values that appear when running master (before any TIFF patching). Can you run the tests with the current master, and print the values at lines 142 and 153 of test_file_libtiff.py?

@anntzer anntzer force-pushed the tiff-extra-samples branch 3 times, most recently from f6e453a to 95d619a Compare July 1, 2015 01:36
@anntzer
Copy link
Contributor Author

anntzer commented Jul 1, 2015

Half-fudging it, but not really: libtiff's precision for "rationals" is limited to C floats, not C doubles, so it should be enough to require roundtripping up to that precision.

@anntzer
Copy link
Contributor Author

anntzer commented Jul 2, 2015

Sad.

@wiredfool wiredfool modified the milestones: 3.0.0, Future Sep 9, 2015
@wiredfool wiredfool self-assigned this Sep 9, 2015
@wiredfool wiredfool mentioned this pull request Sep 11, 2015
8 tasks
@wiredfool
Copy link
Member

See #1419

@wiredfool
Copy link
Member

Closing, merged #1419 which contains this branch.

@wiredfool wiredfool closed this Sep 20, 2015
@radarhere radarhere changed the title Fix setting of TIFF ExtraSamples tag. Fix setting of TIFF ExtraSamples tag Dec 21, 2020
@anntzer anntzer deleted the tiff-extra-samples branch June 10, 2022 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants