ImageRec::ImageRec (ImageBufRef img, bool copy_pixels) : m_name(img->name()), m_elaborated(true), m_metadata_modified(false), m_pixels_modified(false), m_imagecache(img->imagecache()) { m_subimages.resize (1); m_subimages[0].m_miplevels.resize (1); m_subimages[0].m_specs.push_back (img->spec()); if (copy_pixels) { m_subimages[0].m_miplevels[0].reset (new ImageBuf (*img)); } else { m_subimages[0].m_miplevels[0] = img; } }
bool ImageRec::read (ReadPolicy readpolicy, string_view channel_set) { if (elaborated()) return true; static ustring u_subimages("subimages"), u_miplevels("miplevels"); static boost::regex regex_sha ("SHA-1=[[:xdigit:]]*[ ]*"); int subimages = 0; ustring uname (name()); if (! m_imagecache->get_image_info (uname, 0, 0, u_subimages, TypeDesc::TypeInt, &subimages)) { error ("file not found: \"%s\"", name()); return false; // Image not found } m_subimages.resize (subimages); bool allok = true; for (int s = 0; s < subimages; ++s) { int miplevels = 0; m_imagecache->get_image_info (uname, s, 0, u_miplevels, TypeDesc::TypeInt, &miplevels); m_subimages[s].m_miplevels.resize (miplevels); m_subimages[s].m_specs.resize (miplevels); for (int m = 0; m < miplevels; ++m) { // Force a read now for reasonable-sized first images in the // file. This can greatly speed up the multithread case for // tiled images by not having multiple threads working on the // same image lock against each other on the file handle. // We guess that "reasonable size" is 50 MB, that's enough to // hold a 2048x1536 RGBA float image. Larger things will // simply fall back on ImageCache. bool forceread = (s == 0 && m == 0 && m_imagecache->imagespec(uname,s,m)->image_bytes() < 50*1024*1024); ImageBufRef ib (new ImageBuf (name(), m_imagecache)); bool post_channel_set_action = false; std::vector<std::string> newchannelnames; std::vector<int> channel_set_channels; std::vector<float> channel_set_values; int chbegin = 0, chend = -1; if (channel_set.size()) { decode_channel_set (ib->nativespec(), channel_set, newchannelnames, channel_set_channels, channel_set_values); for (size_t c = 0, e = channel_set_channels.size(); c < e; ++c) { if (channel_set_channels[c] < 0) post_channel_set_action = true; // value fill-in else if (c>=1 && channel_set_channels[c] != channel_set_channels[c-1]+1) post_channel_set_action = true; // non-consecutive chans } if (ib->deep()) post_channel_set_action = true; if (! post_channel_set_action) { chbegin = channel_set_channels.front(); chend = channel_set_channels.back()+1; forceread = true; } } // If we were requested to bypass the cache, force a full read. if (readpolicy & ReadNoCache) forceread = true; // Convert to float unless asked to keep native or override. TypeDesc convert = TypeDesc::FLOAT; if (m_input_dataformat != TypeDesc::UNKNOWN) { convert = m_input_dataformat; forceread = true; } else if (readpolicy & ReadNative) convert = ib->nativespec().format; if (! forceread && convert != TypeDesc::UINT8 && convert != TypeDesc::UINT16 && convert != TypeDesc::HALF && convert != TypeDesc::FLOAT) { // If we're still trying to use the cache but it doesn't // support the native type, force a full read. forceread = true; } bool ok = ib->read (s, m, chbegin, chend, forceread, convert); if (ok && post_channel_set_action) { ImageBufRef allchan_buf; std::swap (allchan_buf, ib); ok = ImageBufAlgo::channels (*ib, *allchan_buf, (int)channel_set_channels.size(), &channel_set_channels[0], &channel_set_values[0], &newchannelnames[0], false); } if (!ok) error ("%s", ib->geterror()); allok &= ok; // Remove any existing SHA-1 hash from the spec. ib->specmod().erase_attribute ("oiio:SHA-1"); std::string desc = ib->spec().get_string_attribute ("ImageDescription"); if (desc.size()) ib->specmod().attribute ("ImageDescription", boost::regex_replace (desc, regex_sha, "")); m_subimages[s].m_miplevels[m] = ib; m_subimages[s].m_specs[m] = ib->spec(); // For ImageRec purposes, we need to restore a few of the // native settings. const ImageSpec &nativespec (ib->nativespec()); // m_subimages[s].m_specs[m].format = nativespec.format; m_subimages[s].m_specs[m].tile_width = nativespec.tile_width; m_subimages[s].m_specs[m].tile_height = nativespec.tile_height; m_subimages[s].m_specs[m].tile_depth = nativespec.tile_depth; } } m_time = Filesystem::last_write_time (name()); m_elaborated = true; return allok; }