Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/dds.imageio/ddsinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,8 @@ DDSInput::seek_subimage(int subimage, int miplevel)
m_spec.attribute("compression", str);
}

m_spec.attribute("oiio:miplevels", (int)m_dds.mipmaps);

uint32_t bpp = 0;
if (m_dds.fmt.bpp
&& (m_dds.fmt.flags
Expand Down
9 changes: 9 additions & 0 deletions src/doc/builtinplugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ red & green channels).
- string
- For environment maps, which cube faces are present (e.g., ``"+x -x
+y -y"`` if *x* & *y* faces are present, but not *z*).
* - ``oiio:miplevels``
- int
- The number of MIP levels.

```

Expand Down Expand Up @@ -1649,6 +1652,9 @@ The official OpenEXR site is <http://www.openexr.com/>.
* - ``oiio:subimages``
- int
- The number of "parts" (subimages) in the file.
* - ``oiio:miplevels``
- int
- The number of MIP levels of the part (subimage).
* - ``smpte:TimeCode``
- int[2]
- SMPTE time code (vecsemantics will be marked as TIMECODE)
Expand Down Expand Up @@ -2234,6 +2240,9 @@ Ptex files at all.
* - ``wrapmode``
- string
- the wrap mode as specified by the Ptex file.
* - ``oiio:miplevels``
- int
- The number of MIP levels of the face (subimage).
* - *other*
-
- Any other arbitrary metadata in the Ptex file will be stored directly
Expand Down
63 changes: 60 additions & 3 deletions src/libOpenImageIO/imagebuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,10 @@ class ImageBufImpl {
void set_thumbnail(const ImageBuf& thumb, DoLock do_lock = DoLock(true));
std::shared_ptr<ImageBuf> get_thumbnail(DoLock do_lock = DoLock(true)) const;

// Count the MIP levels of the current subimage by iterating with
// spec_dimensions(), storing the result in m_nmiplevels (0 on failure).
void count_nmiplevels(DoLock do_lock = DoLock(true));

private:
ImageBuf::IBStorage m_storage
= ImageBuf::UNINITIALIZED; // Pixel storage class
Expand Down Expand Up @@ -562,9 +566,11 @@ ImageBufImpl::ImageBufImpl(const ImageBufImpl& src)
m_nsubimages = 1;
m_current_subimage = 0;
m_current_miplevel = 0;
m_nmiplevels = 0;
m_nmiplevels = 1;
m_spec.erase_attribute("oiio:subimages");
m_nativespec.erase_attribute("oiio:subimages");
m_spec.erase_attribute("oiio:miplevels");
m_nativespec.erase_attribute("oiio:miplevels");
m_pixels_read = true;
}
if (src.m_configspec)
Expand Down Expand Up @@ -871,6 +877,7 @@ ImageBufImpl::clear()
m_name.clear();
m_fileformat.clear();
m_nsubimages = 0;
m_nmiplevels = 0;
m_current_subimage = -1;
m_current_miplevel = -1;
m_spec = ImageSpec();
Expand Down Expand Up @@ -1304,6 +1311,16 @@ ImageBufImpl::init_spec(string_view filename, int subimage, int miplevel,
m_current_subimage = subimage;
m_current_miplevel = miplevel;
m_pixelaspect = m_spec.get_float_attribute("pixelaspectratio", 1.0f);

// Set only for formats that don't support mipmaps or whose MIP level
// count is known up front. Otherwise, it stays 0, and nmiplevels()
// counts the levels lazily by iterating.
if (!input->supports("mipmap")) {
m_nmiplevels = 1;
} else {
m_nmiplevels = m_spec.get_int_attribute("oiio:miplevels");
}

atomic_fetch_add(OIIO::pvt::IB_total_open_time, float(timer()));
// Set last, after every field above is written -- see the comment
// on m_spec_valid's declaration.
Expand Down Expand Up @@ -2106,10 +2123,48 @@ ImageBuf::miplevel() const
}


void
ImageBufImpl::count_nmiplevels(DoLock do_lock)
{
lock_t lock(m_mutex, std::defer_lock_t());
if (do_lock)
lock.lock();
if (!validate_spec(DoLock(false) /* we already hold the lock */)) {
m_nmiplevels = 0;
return;
}

auto input = ImageInput::open(m_name.string(), m_configspec.get(),
m_rioproxy);
if (!input) {
error("Could not open file: {}", OIIO::geterror());
m_nmiplevels = 0;
return;
}

// Count until spec_dimensions() returns a spec whose format is unknown.
int nmip = 0;
while (input->spec_dimensions(m_current_subimage, nmip).format
!= TypeUnknown) {
++nmip;
}
m_nmiplevels = nmip;
}


int
ImageBuf::nmiplevels() const
{
m_impl->validate_spec();
if (!m_impl->validate_spec()) {
m_impl->m_nmiplevels = 0;
} else if (m_impl->m_name.empty() || m_impl->m_fileformat.empty()) {
// No direct reference to a file, so 1 as documented.
m_impl->m_nmiplevels = 1;
} else if (m_impl->m_nmiplevels < 1) {
// Count MIP levels by iteration, only for files whose MIP level count
// was not known up front in init_spec().
m_impl->count_nmiplevels();
}
return m_impl->m_nmiplevels;
}

Expand Down Expand Up @@ -2389,9 +2444,11 @@ ImageBuf::copy_pixels(const ImageBuf& src)
m_impl->m_nsubimages = 1;
m_impl->m_current_subimage = 0;
m_impl->m_current_miplevel = 0;
m_impl->m_nmiplevels = 0;
m_impl->m_nmiplevels = 1;
m_impl->m_spec.erase_attribute("oiio:subimages");
m_impl->m_nativespec.erase_attribute("oiio:subimages");
m_impl->m_spec.erase_attribute("oiio:miplevels");
m_impl->m_nativespec.erase_attribute("oiio:miplevels");

return ok;
}
Expand Down
6 changes: 1 addition & 5 deletions src/openexr.imageio/exrinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ OpenEXRInput::PartInfo::parse_header(OpenEXRInput* in,
if (!query_channels(in, header)) // also sets format
return false;

spec.attribute("oiio:miplevels", nmiplevels);
spec.deep = Strutil::istarts_with(header->type(), "deep");

if (levelmode != Imf::ONE_LEVEL)
Expand Down Expand Up @@ -1156,11 +1157,6 @@ OpenEXRInput::seek_subimage(int subimage, int miplevel)
m_miplevel = miplevel;
m_spec = part.spec;

//! Add the number of miplevels as an attribute for the first miplevel.
//! TOFIX: adding the following attribute breaks unit tests
// if (m_miplevel == 0 && part.nmiplevels > 1)
// m_spec.attribute("oiio:miplevels", part.nmiplevels);

if (!check_open(m_spec, { 0, 1 << 30, 0, 1 << 30, 0, 1, 0, 1 << 12 }))
return false;

Expand Down
6 changes: 1 addition & 5 deletions src/openexr.imageio/exrinput_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ OpenEXRCoreInput::PartInfo::parse_header(OpenEXRCoreInput* in,
if (!query_channels(in, ctxt, subimage)) // also sets format
return false;

spec.attribute("oiio:miplevels", nmiplevels);
spec.deep = (storage == EXR_STORAGE_DEEP_TILED
|| storage == EXR_STORAGE_DEEP_SCANLINE);

Expand Down Expand Up @@ -1144,11 +1145,6 @@ OpenEXRCoreInput::seek_subimage(int subimage, int miplevel)
m_miplevel = miplevel;
m_spec = part.spec;

//! Add the number of miplevels as an attribute for the first miplevel.
//! TOFIX: adding the following attribute breaks unit tests
// if (m_miplevel == 0 && part.nmiplevels > 1)
// m_spec.attribute("oiio:miplevels", part.nmiplevels);

if (!check_open(m_spec, { 0, 1 << 30, 0, 1 << 30, 0, 1, 0, 1 << 12 }))
return false;

Expand Down
5 changes: 1 addition & 4 deletions src/ptex.imageio/ptexinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,7 @@ PtexInput::seek_subimage(int subimage, int miplevel)
m_spec.attribute("oiio:subimages", m_numFaces);
}

// Add the number of miplevels as an attribute for the first miplevel.
if (miplevel == 0 && nmiplevels > 1)
m_spec.attribute("oiio:miplevels", nmiplevels);

m_spec.attribute("oiio:miplevels", nmiplevels);
facedata->release();
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions src/tiff.imageio/tiffinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,10 @@ TIFFInput::readspec(bool read_meta)
m_spec.channelnames[c] = "z";
}

// Set miplevels to 1 if no mipmap emulation.
if (!m_emulate_mipmap)
m_spec.attribute("oiio:miplevels", 1);

/// read color profile
unsigned int icc_datasize = 0;
uint8_t* icc_buf = NULL;
Expand Down
Loading
Loading