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

test_png.test_pngsuite.test fails on ppc64 (big-endian) #7792

Closed
AdamWill opened this issue Jan 10, 2017 · 12 comments
Closed

test_png.test_pngsuite.test fails on ppc64 (big-endian) #7792

AdamWill opened this issue Jan 10, 2017 · 12 comments
Milestone

Comments

@AdamWill
Copy link
Contributor

Recently I've been looking at errors in the matplotlib test suite when building on Fedora's ppc64 arch, which is big-endian. I've sent a few PRs so far, but there are still some remaining issues, so I'm filing tickets for them.

This ticket is for a failure of the test_png.test_pngsuite.test test. In my ppc64 build, this is the image produced by the test:

pngsuite

Here's the expected image:

pngsuite-expected

The fifth, seventh, thirteenth and fifteenth images clearly differ. Haven't yet dug into why this is.

There is another png-related test that fails, the two may share a common cause:

======================================================================
FAIL: matplotlib.tests.test_png.test_imread_png_uint16
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/builddir/build/BUILDROOT/python-matplotlib-2.0.0-0.7.rc2.fc26.ppc64/usr/lib64/python2.7/site-packages/matplotlib/tests/test_png.py", line 49, in test_imread_png_uint16
    assert np.sum(img.flatten()) == 134184960
AssertionError
@AdamWill
Copy link
Contributor Author

@QuLogic

@AdamWill
Copy link
Contributor Author

The incorrect answer it gets for the np.sum assertion is 126351360 . No idea what that means as of yet.

@AdamWill
Copy link
Contributor Author

AdamWill commented Jan 10, 2017

The four images that are incorrectly rendered are all the 16-bit images. All the images that render correctly are 1, 2, 4 or 8-bit. There's a few if (bit_depth == 16) clauses in src/_png.cpp; I bet that's where we should be looking...

edit: aha! If I just comment out this block:

// Convert big endian to little
if (bit_depth == 16) {
    png_set_swap(png_ptr);
}

it makes the tests pass (both of them). Obviously just unconditionally commenting it out isn't a true fix (it'll break LE arches); I guess we need to conditionalize the bit swap to only happen on LE arches. Now to figure out how to do that...

@QuLogic
Copy link
Member

QuLogic commented Jan 10, 2017

I see a png_set_swap, but it doesn't appear to check if it's a necessary thing. I think that function also doesn't do that check either. Not sure if we have an existing test for endianness.

@AdamWill
Copy link
Contributor Author

snap ;)

@tacaswell
Copy link
Member

Are there regressions from 1.5.x or have we always been broken on BE systems?

@AdamWill
Copy link
Contributor Author

@tacaswell I don't know for sure myself - I only ran into this more or less by accident while doing drive-by Fedora package rebuilds, I didn't know thing one about matplotlib until two days ago. I don't even own any ppc64 systems, I'm testing this in a sandbox container Fedora releng gave me for the purpose.

Some of the font stuff that was broken was definitely new in 2.0, I did notice that, but I think some of the other stuff has been around longer.

@QuLogic
Copy link
Member

QuLogic commented Jan 10, 2017

@tacaswell I think the font problems are new in 2.0.0 as the commit that @AdamWill referenced in his first PR was not in 1.5.3, and it seems like there was a bit of a rewrite there.

Not sure about png, but it did have the CXX removal recently.

@AdamWill
Copy link
Contributor Author

So, really not sure what the best way to go about implementing an endianness check would be. One approach I thought of: you can get the current system's endianness trivially from Python - sys.byteorder gives it. So you could presumably tweak the Python bits (setupext.py, I think) that configure the build process for the C++ bits to define a macro that we can use in _png.cpp to decide whether to do the conversion. But I don't know if that's a good way, really. It wouldn't work for cross-compiling, dunno if that's important.

Googling around for endianness checks gives you all kinds of suggestions and all kinds of reasons why they're all wrong and broken and terrible, so I'm a bit lost as to what the best choice would be...

@QuLogic
Copy link
Member

QuLogic commented Jan 10, 2017

It looks like we have NumPy available there, so maybe PyArray_EquivByteorders will work.

@AdamWill
Copy link
Contributor Author

Aha, yeah, that sounds promising. On a quick look, numpy's check uses the BYTE_ORDER setting from endian.h if it's present (which it is on many, but not all platforms); if it's not, it has a hard coded list of target CPUs with known endianness. That seems to be about as sane an approach as any. I'll try writing a patch which uses PyArray_EquivByteorders, thanks.

@tacaswell tacaswell added this to the 2.0 (style change major release) milestone Jan 11, 2017
AdamWill added a commit to AdamWill/matplotlib that referenced this issue Jan 11, 2017
_png has some code that unconditionally byte-swaps 16-bit PNG
data (which is, per the spec, stored in big-endian order). This
isn't appropriate on a big-endian platform, though: this swap
being done unconditionally breaks the handling of 16-bit PNGs
on big-endian platforms (e.g. Fedora ppc64), as reported in
this swap or not.
AdamWill added a commit to AdamWill/matplotlib that referenced this issue Jan 11, 2017
_png has some code that unconditionally byte-swaps 16-bit PNG
data (which is, per the spec, stored in big-endian order). This
isn't appropriate on a big-endian platform, though: this swap
being done unconditionally breaks the handling of 16-bit PNGs
on big-endian platforms (e.g. Fedora ppc64), as reported in
to decide whether to do this swap or not.
AdamWill added a commit to AdamWill/matplotlib that referenced this issue Jan 11, 2017
_png has some code that unconditionally byte-swaps 16-bit PNG
data (which is, per the spec, stored in big-endian order). This
isn't appropriate on a big-endian platform, though: this swap
being done unconditionally breaks the handling of 16-bit PNGs
on big-endian platforms (e.g. Fedora ppc64) (matplotlib#7792). So, let's
use some macros numpy kindly defines for us to decide whether to
do this swap or not.
mdboom added a commit that referenced this issue Jan 11, 2017
Only byte-swap 16-bit PNGs on little-endian (#7792)
mdboom added a commit that referenced this issue Jan 11, 2017
Only byte-swap 16-bit PNGs on little-endian (#7792)
@AdamWill
Copy link
Contributor Author

So this is fixed now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants