-
Notifications
You must be signed in to change notification settings - Fork 457
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
opj_compress fails to compress lossless on gcc/x86 (-m32) #571
Comments
Steps from debian/jessie i386: $ image_to_j2k -i lossless_issue.pgm -o lossless_issue.j2k |
I can reproduce the exact same behavior using openjpeg 2.1.0 (as packaged in debian). |
It seems the compression step is not working as expected:
|
The good news is that if I run:
Everything works as expected. So valgrind is doing some kind of initialisation (rounding?) step that is missing in normal code executition. |
If I use now clang-3.5 from my sid 32bits chroot everything works nicely. So the issue is not within the libc and such, but rather in the code generated by gcc. |
gcc-4.8, gcc-4.9 and gcc-5.2 all have the same symptoms |
If I recompile openjpeg with /home/mathieu/tmp/opj-bug/openjpeg/src/lib/openjp2/t1.c:1517:28: ref: https://github.com/uclouvain/openjpeg/blob/master/src/lib/openjp2/t1.c#L1517 |
EVen if I fix the code using: tiledp[tileIndex] *= (1 << T1_NMSEDEC_FRACBITS); it still fails |
Now if I compile the whole code using gcc and then do:
the code works as expected |
It appears that the issue is within this function https://github.com/uclouvain/openjpeg/blob/master/src/lib/openjp2/tcd.c#L218 |
To fix the symptoms one could use excess precision using: |
It is still not clear why such minor change leads to a lossy compressed stream, this must only be the tip of the iceberg. |
So the patch is simply, replace:
with:
Then compile the code with |
The gcc documentation states that |
Confirmed by upstream gcc dev here. We really need to understand why the code is so sensible to excess precision. |
I had a look at the piece of code that's mentioned here. This can be shown easily with this piece of code (with a bit of context): if (!dr) {
if (dd != 0)
n = passno + 1;
continue;
}
if ((dd / dr) < 0.45) {
printf("%.32f - %.32f\n", (dd / dr), thresh);
}
if ((dd / dr) >= thresh) {
n = passno + 1;
if ((dd / dr) < 0.45) {
printf("True compare\n");
}
}
}
layer->numpasses = n - cblk->numpassesinlayers; We should not rely on "==" comparison for floats. |
I'll add this specific image to the test suite if needed |
Just in case my series of comments were not clear:
And finally as discussed with Antonin, I fail to understand this piece of code. So removing the excess precision using compiler specific option is just plain wrong. One would need to understand why this piece of code is so damn sensible to excess precision. Thanks for adding the dataset to the test suite ! |
Add non regression data for uclouvain/openjpeg#571
Should I re-open this issue for opj 1.5 branch ? |
The issue can only be affected to one milestone... |
Note that even if you remove the excess precision, your code might still be affected by double rounding (which occurs with a probability of 1/2048 on random data). So, you really need to understand the code and how it can be affected by floating-point rounding errors. |
Salut Vincent ! Indeed I had seen this at least once through a funky example. Do you believe that simply increasing the precision for DBL_EPSILON will make the issue go away ? |
Depending on the context, a bound like DBL_EPSILON or something larger may or may not be correct. First, the code should be commented so that the reader can know what it tries to do, for instance some mathematical specification. |
I am having an issue with OPJ 1.5 and the following file:
http://gdcm.sourceforge.net/thingies/lossless_issue.pgm
It looks as if I cannot do a round-trip lossless compression / decompression, within a 32bits schroot. Everything is fine within a 64bits schroot system (debian jessie if that matter).
The text was updated successfully, but these errors were encountered: