Пример #1
0
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;
    }
}
Пример #2
0
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;
}