fix(ImageBuf): IB::nmiplevels() returns 0 for non-IC ImageBuf - #5437
luna-y-kim wants to merge 1 commit into
Conversation
|
I'm worried that this is quite expensive, since seek_subimage will read/decode all the MIP image metadata. It will make opening a file with an ImageBuf bear the expense of seek_subimage calls even if no mip levels will ever be needed. I'm wondering a few things:
Or, another possibility is that we don't do it as part of the read() at all, but instead use the separate ImageBuf::nmiplevels() method for this. Right now it returns m_nmiplevels, which obviously might not know. But it could instead figure it out by doing the seeks or spec_dimensions or whatever, if it doesn't already set it. In other words, we split the responsibilities to figure this out lazily:
So that would prevent/postpone the expensive kind of search until the occasion that the user actually needs to know the answer, conveyed by calling nmiplevels(). Thoughts? |
|
Oops, it was an oversight. Here are my thoughts after some investigation:
So I think the next steps are:
Am I missing something?..... Or would checking |
9fc4d66 to
ea0183e
Compare
nmiplevels() returned 0 for non-IC ImageBuf|
The test reference |
|
Yeah, this is kind of an icky one-time switch and I'm hoping to get it merged soon. Just want to give people a chance to air any concerns. But inspecting the results, it looks like everything translated just fine, and I challenge anyone to find a visible difference compared to the docs in rst. (Of course, it cheats a little by lapsing into rst for short sections within the md files when it needs to.) |
The ImageBuf constructor path without an ImageCache ends in `init_spec()`. There, the non-IC branch only reset `m_nmiplevels = 0` and never assigned a real value, so `nmiplevels()` always returned 0. Now `init_spec()` sets `m_nmiplevels = 1` if the format doesn't support mipmaps, or assigns the number of MIP levels if it can be known up front. If a format does support mipmaps but the count requires walking through the levels, then it's counted by iteration, lazily on the `nmiplevels()` call. The iteration calls `spec_dimensions()` repeatedly until it returns an empty ImageSpec. This improves EXR, DDS, and Ptex to set the "oiio:miplevels" attribute when read (Ptex previously set it only for MIP-mapped files), so that `init_spec()` can get the attribute's value and save it to `ImageBufImpl::m_nmiplevels`. For TIFF, it only sets the attribute to 1 when a file has no texture format tag, because an iteration would be needed to get the number of MIP levels otherwise. Setting the attribute to 1 up front avoids an unnecessary open for non-mipmapped TIFF files. Additionally, an ImageBuf that doesn't have a direct reference to a file returns 1 as documented. A test for `IB::nmiplevels()` is added to the python-imagebuf testsuite. Also test reference files affected by the new "oiio:miplevels" attribute are all updated accordingly. Fixes AcademySoftwareFoundation#5409 Signed-off-by: Luna Kim <177369799+luna-y-kim@users.noreply.github.com>
ea0183e to
602f286
Compare
The ImageBuf constructor path without an ImageCache ends in
init_spec(). There, the non-IC branch only resetm_nmiplevels = 0and never assigned a real value, sonmiplevels()always returned 0.Now
init_spec()setsm_nmiplevels = 1if the format doesn't support mipmaps, or assigns the number of MIP levels if it can be known up front. If a format does support mipmaps but the count requires walking through the levels, then it's counted by iteration, lazily on thenmiplevels()call. The iteration callsspec_dimensions()repeatedly until it returns an empty ImageSpec.This improves EXR, DDS, and Ptex to set the "oiio:miplevels" attribute when read (Ptex previously set it only for MIP-mapped files), so that
init_spec()can get the attribute's value and save it toImageBufImpl::m_nmiplevels. For TIFF, it only sets the attribute to 1 when a file has no texture format tag, because an iteration would be needed to get the number of MIP levels otherwise. Setting the attribute to 1 up front avoids an unnecessary open for non-mipmapped TIFF files.Additionally, an ImageBuf that doesn't have a direct reference to a file returns 1 as documented.
A test for
IB::nmiplevels()is added to the python-imagebuf testsuite. Also test reference files affected by the new "oiio:miplevels" attribute are all updated accordingly.Fixes #5409