Unloadable large images cause previous image to display instead, with repetition of last row/column of pixels to image height/width

imv[-dir] bug

[This may be the same bug as #51, but that was specifically for PNG images, so...]

It appears that the image library that imv uses to display JPEG images cannot handle wide images (not sure about tall ones, yet). I will explore further, but those I have attempted that were something over 16K pixesl wide have the following behaviour:

If imv-dir is handed the image directly from a folder, it displays as completely white.

If imv-dir is handed the image before that image, and one uses the right arrow to go to it, then the previous image is displayed, but with the last row of pixels duplicated below it, until the height of the image it was supposed to display is reached, and the last column of pixels duplicated to the right, until the width of the image it was supposed to display is reached. Note that NONE of the image that was supposed to be displayed is displayed at all, although the info in the window title and overlay is that of the intended image.

If one goes beyond the image to the next one, and it also is too large, the same thing happens, but with the dimensions of the image corresponding to the second problem image, and STILL showing the image from two files before. If we now go beyond the problem images, and then go BACK to a problem image (left arrow), the problem is the same, but the image displayed is now the image AFTER the problem images.

Thus, it is clear that imv[-dir] does not clear a previously displayed image until a successful loading of a new one. If the loading is unsuccessful, then it displays the un-cleared previous image, but with the dimensions of the image that failed to load.

I will make a short video of the problem as viewed, and either attach it, or upload it to a private youtube page and include a link to it inline. https://youtu.be/NmaPES3Kz1s

scott@ASUS-Prime-B350MA:~$ hostnamectl
 Static hostname: ASUS-Prime-B350MA
       Icon name: computer-desktop
         Chassis: desktop 🖥
      Machine ID: afa17170ef654b46a53bdb748d110973
         Boot ID: 4082ad23b79e40869a521f80152f3a09
Operating System: Debian GNU/Linux trixie/sid     
          Kernel: Linux 6.4.0-3-amd64
    Architecture: x86-64
 Hardware Vendor: ASUSTeK COMPUTER INC.
  Hardware Model: PRIME B350M-A
Firmware Version: 4207
   Firmware Date: Fri 2018-12-07
    Firmware Age: 5y 1month 1d                    
sway 1.8.1-2
libwlroots11 0.16.2-3

imv 4.4.0-1

scott@ASUS-Prime-B350MA:~$ls -l /usr/bin/imv*
lrwxrwxrwx 1 root root     20 Nov 26 20:08 /usr/bin/imv -> /usr/bin/imv-wayland
-rwxr-xr-x 1 root root    132 Sep  5 03:31 /usr/bin/imv-dir
-rwxr-xr-x 1 root root  68928 Sep  5 03:31 /usr/bin/imv-msg
-rwxr-xr-x 1 root root 105984 Sep  5 03:31 /usr/bin/imv-wayland
-rwxr-xr-x 1 root root  97600 Sep  5 03:31 /usr/bin/imv-x11
scott@ASUS-Prime-B350MA:~$ imv -h
imv 4.4.0
See manual for usage information.
This version of imv has been compiled with the following backends:

Name: FreeImage
Description: Open source image library supporting a large number of formats
Website: http://freeimage.sourceforge.net/
License: FreeImage Public License v1.0

Name: libtiff
Description: The de-facto tiff library
Website: http://www.libtiff.org/
License: MIT

Name: libpng
Description: The official PNG reference implementation
Website: http://www.libpng.org/pub/png/libpng.html
License: The libpng license

Name: libRSVG
Description: SVG library developed by GNOME
Website: https://wiki.gnome.org/Projects/LibRsvg
License: GNU Lesser General Public License v2.1+

Name: libheif
Description: ISO/IEC 23008-12:2017 HEIF file format decoder and encoder.
Website: http://www.libheif.org
License: GNU Lesser General Public License

imv's full source code is published under the terms of the MIT
license, and can be found at https://sr.ht/~exec64/imv

imv uses the inih library to parse ini files.
See https://github.com/benhoyt/inih for details.
inih is used under the New (3-clause) BSD license.
scott@ASUS-Prime-B350MA:~$ apt list --installed "*jpeg*"
libjpeg62-turbo/testing,now 1:2.1.5-2 amd64 [installed,automatic]
libmjpegutils-2.1-0/now 1:2.1.0+debian-7 amd64 [installed,upgradable to: 1:2.1.0+debian-8]
scott@ASUS-Prime-B350MA:~$ apt list --installed "*libjxr*"
libjxr-tools/testing,now 1.2~git20170615.f752187-5 amd64 [installed,automatic]
libjxr0/testing,now 1.2~git20170615.f752187-5 amd64 [installed,automatic]
scott@ASUS-Prime-B350MA:~$ apt list --installed "*freeimage*"
libfreeimage3/testing,now 3.18.0+ds2-10 amd64 [installed,automatic]
Assigned to
4 months ago
4 days ago
No labels applied.

~scott092707 2 months ago

Update: Further testing shows that it does not appear to matter which file format is used: if an image width (or presumably height) is larger than ~16,384 (2^14) all one sees is a white box. I have two panoramas, one 16379x2947 and one 16395x3903. The first displays, the second does not.

At first, I thought that FreeImage was at fault, as I work in JPEG, and the default imv package from Debian uses FreeImage for JPEG. However, I downloaded and generated imv, blacklisting FreeImage, and enabling libjpeg, and got exactly the same result. It being unlikely that both libraries would have exactly the same bug, it became clear that imv was where the bug was, at least for JPEG. I then took the two JPEG images (and several others, mostly larger, but one "normal" 4000x3000 image) and converted them to tiff, png, jxl and heic, and each image displayed fine if smaller than 16384, and displayed as a white rectangle if larger. As before, if an image that CAN be displayed is displayed first, and THEN an image that cannot, the prior image is displayed instead, filled out to the undisplayed image's width/height with what is probably the last column/row of pixels.

I was trying to find out how to get imv to log errors, or find out where it was doing so, if it already was, when I discovered that it WAS already doing so... I was invoking imv[-dir] from the terminal, and nothing ever was printed; except now, when a tif was displayed, I got (from the 4000x3000 image) "TIFFReadDirectory: Warning, Unknown field with tag 18246 (0x4746) encountered." So... apparently logging IS being done, and to stderr. What this means, is that when a white rectangle or distorted image is displayed, imv THINKS everything is OK, and that the image is being displayed correctly - since no error message of "cannot load image" or such is displayed.

I will try to investigate this further, but as I am no image-handling expert, I am not sure how much I can find (I already looked for "MAX", thinking that there might be a width-max and/or height-max, but found nothing suitable. I considered that maybe there was a buffer, whose width/height was stored in a variable too small to hold it when it exceeded 2^14 - but what type has a size greater than 8 bits, but smaller than 16? not likely... unless it was using the other 2 bits for something else? )

If anyone has anything to suggest, I (we all?) would be interested in hearing about it...

~scott092707 9 days ago

Well, after looking at a lot of code, I could not find an obvious error, so I reluctantly started looking at the OpenGL functions. It turns out that an attempt is made to nail the image to a "texture" (or the texture to the image...), and that (at least on my system) the maximum texture width/height is ... 16384. So... image smaller than 16384 --> great. Image greater than 16384-->fail. After much hair-tearing, and internet searching, the concept of tiling came up. I have fixed the problem by dividing the image up into as many smaller-than-maximum textures it takes to span the image. The only file needing change is canvas.c, and the only functions changed are imv_canvas_free() and draw_bitmap(). The struct canvas.cache is changed to add texture_count, and "textures" is GLuint * (instead of "texture" being a GLuint .

~quantenzitrone will be happy to know that his image displays correctly now.

Now, all I have to do is find out how to get the modified canvas.c into this website's source, somehow...

~scott092707 referenced this from #51 9 days ago

~txtsd 9 days ago

Now, all I have to do is find out how to get the modified canvas.c into this website's source, somehow...

If you mean how to submit a patch, follow this: https://git-send-email.io/

~scott092707 4 days ago

I just sent a patch. In the cc: that was sent me, it only says [Patch], despite the fact that I invoked the command as follows:

git send-email --compose --subject="[PATCH imv] Handle large images by using multiple OpenGL textures" --to="~exec64/imv-devel@lists.sr.ht" HEAD^

AND I don't see the body text that I added in the editor:

Without this patch, imv fails to display images with width/height
larger than OpenGL's GL_MAX_TEXTURE_SIZE (usually these days: 16384),
as it tries to make a texture equal to the bitmap->width x bitmap->height.
This patch divides up the image into multiple adjoining textures, each of
whose dimensions are smaller than GL_MAX_TEXTURE_SIZE.  To avoid 'slivers',
the width/height of the original image are divided into equal-sized pieces.

I don't know where I went wrong...

~quantenzitrone 4 days ago

where do i find the patch if i want to test it out?

Register here or Log in to comment, or comment via email.