-
-
Notifications
You must be signed in to change notification settings - Fork 705
fix alpha shift during colourspace conversion #4302
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
Conversation
The colour functions were not shifting alpha channels, just casting them, so operations which changed depth, like `icc_transform --depth 8` on a 16-bit image, could have an incorrectly scaled alpha. See #4301 Thanks frederikrosenberg
As an aside, I noticed that shifting (un)signed integers seems to produce non-deterministic results.
#!/usr/bin/env python3
import sys
import pyvips
im = pyvips.Image.new_from_file(sys.argv[1])
for fmt in ["uchar", "ushort", "uint",
"char", "short", "int",
"float", "double",
"complex", "dpcomplex"]:
x = im.cast(fmt, shift=True)
print(fmt, x.avg()) $ curl -LO https://wsrv.nl/zebra.jpg
$ diff <(python test.py zebra.jpg) <(python test.py zebra.jpg)
3c3
< uint 1632942049.5186381
---
> uint 1632942049.5186388
6c6
< int 520656999.7738505
---
> int 520656999.7738506 UBSan details$ LD_PRELOAD=$ASAN_DSO python test.py zebra.jpg
uchar 96.83188217684959
ushort 24916.21924385296
../libvips/conversion/cast.c:380:4: runtime error: left shift of 160 by 24 places cannot be represented in type 'int'
#0 0x7f894197dab0 in vips_cast_gen /home/kleisauke/libvips/build/../libvips/conversion/cast.c:380:4
#1 0x7f8941cc14f7 in vips_region_generate /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1624:6
#2 0x7f8941ca97de in vips_region_fill /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:881:7
#3 0x7f8941cc0fd5 in vips_region_prepare /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1692:7
#4 0x7f89419470f7 in vips_copy_gen /home/kleisauke/libvips/build/../libvips/conversion/copy.c:140:6
#5 0x7f8941cc14f7 in vips_region_generate /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1624:6
#6 0x7f8941ca97de in vips_region_fill /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:881:7
#7 0x7f8941cc0fd5 in vips_region_prepare /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1692:7
#8 0x7f8941c58ca7 in vips_image_write_gen /home/kleisauke/libvips/build/../libvips/iofuncs/image.c:2606:6
#9 0x7f8941cc14f7 in vips_region_generate /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1624:6
#10 0x7f8941ca97de in vips_region_fill /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:881:7
#11 0x7f8941cc0fd5 in vips_region_prepare /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1692:7
#12 0x7f8941c77f60 in sink_work /home/kleisauke/libvips/build/../libvips/iofuncs/sink.c:416:11
#13 0x7f8941c0bb52 in vips_worker_work_unit /home/kleisauke/libvips/build/../libvips/iofuncs/threadpool.c:373:6
#14 0x7f8941c0bb52 in vips_thread_main_loop /home/kleisauke/libvips/build/../libvips/iofuncs/threadpool.c:400:3
#15 0x7f8941c07b36 in vips_threadset_work /home/kleisauke/libvips/build/../libvips/iofuncs/threadset.c:182:3
#16 0x7f8941c04d31 in vips_thread_run /home/kleisauke/libvips/build/../libvips/iofuncs/thread.c:148:11
#17 0x7f8941153d42
8000
(/lib64/libglib-2.0.so.0+0x72d42) (BuildId: 865a88f51bbf48869c7166397a8c69259849ea68)
#18 0x7f89546d340a (/usr/bin/../lib/clang/19/lib/x86_64-redhat-linux-gnu/libclang_rt.asan.so+0xd340a) (BuildId: 307751fccc0dd258dd57b3df6a8253b687e8b363)
#19 0x7f8953e7ccd6 in start_thread (/lib64/libc.so.6+0x70cd6) (BuildId: b6c381bfdcb5e08ea82c1c39cf16580181fb6cfc)
#20 0x7f8953f00c8b in __GI___clone3 (/lib64/libc.so.6+0xf4c8b) (BuildId: b6c381bfdcb5e08ea82c1c39cf16580181fb6cfc)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../libvips/conversion/cast.c:380:4
uint 1632942049.5186386
char 30.534526897833825
short 7944.0962924249225
../libvips/conversion/cast.c:380:4: runtime error: left shift of 153 by 24 places cannot be represented in type 'int'
#0 0x7f8941989700 in vips_cast_gen /home/kleisauke/libvips/build/../libvips/conversion/cast.c:380:4
#1 0x7f8941cc14f7 in vips_region_generate /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1624:6
#2 0x7f8941ca97de in vips_region_fill /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:881:7
#3 0x7f8941cc0fd5 in vips_region_prepare /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1692:7
#4 0x7f89419470f7 in vips_copy_gen /home/kleisauke/libvips/build/../libvips/conversion/copy.c:140:6
#5 0x7f8941cc14f7 in vips_region_generate /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1624:6
#6 0x7f8941ca97de in vips_region_fill /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:881:7
#7 0x7f8941cc0fd5 in vips_region_prepare /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1692:7
#8 0x7f8941c58ca7 in vips_image_write_gen /home/kleisauke/libvips/build/../libvips/iofuncs/image.c:2606:6
#9 0x7f8941cc14f7 in vips_region_generate /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1624:6
#10 0x7f8941ca97de in vips_region_fill /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:881:7
#11 0x7f8941cc0fd5 in vips_region_prepare /home/kleisauke/libvips/build/../libvips/iofuncs/region.c:1692:7
#12 0x7f8941c77f60 in sink_work /home/kleisauke/libvips/build/../libvips/iofuncs/sink.c:416:11
#13 0x7f8941c0bb52 in vips_worker_work_unit /home/kleisauke/libvips/build/../libvips/iofuncs/threadpool.c:373:6
#14 0x7f8941c0bb52 in vips_thread_main_loop /home/kleisauke/libvips/build/../libvips/iofuncs/threadpool.c:400:3
#15 0x7f8941c07b36 in vips_threadset_work /home/kleisauke/libvips/build/../libvips/iofuncs/threadset.c:182:3
#16 0x7f8941c04d31 in vips_thread_run /home/kleisauke/libvips/build/../libvips/iofuncs/thread.c:148:11
#17 0x7f8941153d42 (/lib64/libglib-2.0.so.0+0x72d42) (BuildId: 865a88f51bbf48869c7166397a8c69259849ea68)
#18 0x7f89546d340a (/usr/bin/../lib/clang/19/lib/x86_64-redhat-linux-gnu/libclang_rt.asan.so+0xd340a) (BuildId: 307751fccc0dd258dd57b3df6a8253b687e8b363)
#19 0x7f8953e7ccd6 in start_thread (/lib64/libc.so.6+0x70cd6) (BuildId: b6c381bfdcb5e08ea82c1c39cf16580181fb6cfc)
#20 0x7f8953f00c8b in __GI___clone3 (/lib64/libc.so.6+0xf4c8b) (BuildId: b6c381bfdcb5e08ea82c1c39cf16580181fb6cfc)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../libvips/conversion/cast.c:380:4
int 520656999.77385056
float 96.83188217684959
double 96.83188217684959
complex 96.83188217684959
dpcomplex 96.83188217684959 |
Yes, that's very odd. I see:
I had to repeat a few times to get a different answer. |
Ah, it's avg, of course:
I suppose the accumulator is overflowing. |
Ah I see (sorry), Maybe we should use an int64 accumulator for int types (though this is probably a minor problem). |
The colour functions were not shifting alpha channels, just casting them, so
operations which changed depth, like
icc_transform --depth 8
on a16-bit image, could have an incorrectly scaled alpha.
See #4301
Thanks frederikrosenberg