GNOME Bugzilla – Bug 766842
Different behavior of GDK_INTERP_NEAREST with gdk_pixbuf_composite () versus other interpolation types when not scaling
Last modified: 2016-05-31 17:45:27 UTC
Created attachment 328443 [details] Demonstration of the issue Interpolation type GDK_INTERP_NEAREST with gdk_pixbuf_composite () does not work the same as other interpolation types when the destination rectangle contains parts not in the transformed source image. Attached is a demonstration program along with the output images. The `apple-red.png' image is from gtk-demo: https://git.gnome.org/browse/gtk+/plain/demos/gtk-demo/apple-red.png Notice with `out-NEAREST.png' that the apple image is tiled horizontally, shifted up 1px each time, and there are artifacts of invalid memory reads. The invalid reads issue causes an occasional SEGFAULT issue in Freeciv on Mac OS. It is difficult to reproduce, but I finally found semi-reliable steps to reproduce the crash using the Homebrew binary of Freeciv 2.5.4 gui-gtk-2.0 on Mac OS X 10.11.5 (15F34) and a particular saved game. Thus, I have been able to see and debug the problem with `lldb` attached. The backtrace is: * thread #1: tid = 0x9bbe, 0x0000000100e037f2 libgdk_pixbuf-2.0.0.dylib`pixops_composite_nearest_noscale(dest_buf="", render_x0=1, render_y0=2, render_x1=64, render_y1=49, dest_rowstride=252, dest_channels=4, dest_has_alpha=1, src_buf="", src_width=64, src_height=48, src_rowstride=5120, src_channels=4, src_has_alpha=1, overall_alpha=255) + 274 at pixops.c:456, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x11061f007) * frame #0: 0x0000000100e037f2 libgdk_pixbuf-2.0.0.dylib`pixops_composite_nearest_noscale(dest_buf="", render_x0=1, render_y0=2, render_x1=64, render_y1=49, dest_rowstride=252, dest_channels=4, dest_has_alpha=1, src_buf="", src_width=64, src_height=48, src_rowstride=5120, src_channels=4, src_has_alpha=1, overall_alpha=255) + 274 at pixops.c:456 frame #1: 0x0000000100dffd72 libgdk_pixbuf-2.0.0.dylib`_pixops_composite_real(dest_buf="", render_x0=1, render_y0=2, render_x1=64, render_y1=49, dest_rowstride=252, dest_channels=4, dest_has_alpha=1, src_buf="", src_width=64, src_height=48, src_rowstride=5120, src_channels=4, src_has_alpha=1, scale_x=1, scale_y=1, interp_type=PIXOPS_INTERP_NEAREST, overall_alpha=255) + 530 at pixops.c:1913 frame #2: 0x0000000100dffb4c libgdk_pixbuf-2.0.0.dylib`_pixops_composite(dest_buf="", dest_width=63, dest_height=47, dest_rowstride=252, dest_channels=4, dest_has_alpha=1, src_buf="", src_width=64, src_height=48, src_rowstride=5120, src_channels=4, src_has_alpha=1, dest_x=0, dest_y=0, dest_region_width=63, dest_region_height=47, offset_x=-1, offset_y=-2, scale_x=1, scale_y=1, interp_type=PIXOPS_INTERP_NEAREST, overall_alpha=255) + 780 at pixops.c:2009 frame #3: 0x0000000100df7c0a libgdk_pixbuf-2.0.0.dylib`gdk_pixbuf_composite(src=0x000000010cabf9e0, dest=0x0000000102df3d80, dest_x=0, dest_y=0, dest_width=63, dest_height=47, offset_x=-1, offset_y=-2, scale_x=1, scale_y=1, interp_type=GDK_INTERP_NEAREST, overall_alpha=255) + 1066 at gdk-pixbuf-scale.c:221 frame #4: 0x00000001000616f1 freeciv-gtk2`canvas_put_sprite + 693 ... The src pixbuf is 64x48 and the destination pixbuf is 63x47. Because the `offset_y' passed to gdk_pixbuf_composite () is -2, this means that the bottom row of pixels in the destination rectangle is not within the source rectangle. See also: Freeciv bug #24298 Freeciv crashes when attempting to view a city using the amplio2 tileset after Machine Tools are discovered: https://gna.org/bugs/?func=detailitem&item_id=24298
Created attachment 328444 [details] out-BILINEAR.png
Created attachment 328445 [details] out-HYPER.png
Created attachment 328446 [details] out-NEAREST.png
Created attachment 328447 [details] out-TILES.png
Created attachment 328705 [details] [review] Patch
Thanks for the debugging and the test