Beispiel #1
0
bool
ImageBuf::read (int subimage, int miplevel, bool force, TypeDesc convert,
               ProgressCallback progress_callback,
               void *progress_callback_data)
{
    if (pixels_valid() && !force &&
            subimage == this->subimage() && miplevel == this->miplevel())
        return true;

    if (! init_spec (m_name.string(), subimage, miplevel)) {
        m_badfile = true;
        m_spec_valid = false;
        return false;
    }

    // Set our current spec to the requested subimage
    if (! m_imagecache->get_imagespec (m_name, m_spec, subimage, miplevel) ||
        ! m_imagecache->get_imagespec (m_name, m_nativespec, subimage, miplevel, true)) {
        m_err = m_imagecache->geterror ();
        return false;
    }
    m_current_subimage = subimage;
    m_current_miplevel = miplevel;

#if 1
    // If we don't already have "local" pixels, and we aren't asking to
    // convert the pixels to a specific (and different) type, then take an
    // early out by relying on the cache.
    int peltype = TypeDesc::UNKNOWN;
    m_imagecache->get_image_info (m_name, subimage, miplevel,
                                  ustring("cachedpixeltype"),
                                  TypeDesc::TypeInt, &peltype);
    m_cachedpixeltype = TypeDesc ((TypeDesc::BASETYPE)peltype);
    if (! m_localpixels && ! force &&
        (convert == m_cachedpixeltype || convert == TypeDesc::UNKNOWN)) {
        m_spec.format = m_cachedpixeltype;
#ifdef DEBUG
        std::cerr << "read was not necessary -- using cache\n";
#endif
        return true;
    } else {
#ifdef DEBUG
        std::cerr << "going to have to read " << m_name << ": "
                  << m_spec.format.c_str() << " vs " << convert.c_str() << "\n";
#endif
    }        
#endif

    if (convert != TypeDesc::UNKNOWN)
        m_spec.format = convert;
    m_orientation = m_spec.get_int_attribute ("orientation", 1);
    m_pixelaspect = m_spec.get_float_attribute ("pixelaspectratio", 1.0f);

    realloc ();
    if (m_imagecache->get_pixels (m_name, subimage, miplevel,
                                  m_spec.x, m_spec.x+m_spec.width,
                                  m_spec.y, m_spec.y+m_spec.height,
                                  m_spec.z, m_spec.z+m_spec.depth,
                                  m_spec.format, &m_pixels[0])) {
        m_pixels_valid = true;
        m_localpixels = true;
    } else {
        m_pixels_valid = false;
        m_err = m_imagecache->geterror ();
    }

    return m_pixels_valid;
}
Beispiel #2
0
bool
OpenEXROutput::put_parameter (const std::string &name, TypeDesc type,
                              const void *data)
{
    // Translate
    std::string xname = name;
    if (istarts_with (xname, "oiio:"))
        return false;
    else if (iequals(xname, "worldtocamera"))
        xname = "worldToCamera";
    else if (iequals(xname, "worldtoscreen"))
        xname = "worldToNDC";
    else if (iequals(xname, "DateTime"))
        xname = "capDate";
    else if (iequals(xname, "description") || iequals(xname, "ImageDescription"))
        xname = "comments";
    else if (iequals(xname, "Copyright"))
        xname = "owner";
    else if (iequals(xname, "PixelAspectRatio"))
        xname = "pixelAspectRatio";
    else if (iequals(xname, "ExposureTime"))
        xname = "expTime";
    else if (iequals(xname, "FNumber"))
        xname = "aperture";
    else if (istarts_with (xname, format_prefix))
        xname = std::string (xname.begin()+format_prefix.size(), xname.end());

//    std::cerr << "exr put '" << name << "' -> '" << xname << "'\n";

    // Special cases
    if (iequals(xname, "Compression") && type == TypeDesc::STRING) {
        const char *str = *(char **)data;
        m_header->compression() = Imf::ZIP_COMPRESSION;  // Default
        if (str) {
            if (iequals (str, "none"))
                m_header->compression() = Imf::NO_COMPRESSION;
            else if (iequals (str, "deflate") || iequals (str, "zip")) 
                m_header->compression() = Imf::ZIP_COMPRESSION;
            else if (iequals (str, "rle")) 
                m_header->compression() = Imf::RLE_COMPRESSION;
            else if (iequals (str, "zips")) 
                m_header->compression() = Imf::ZIPS_COMPRESSION;
            else if (iequals (str, "piz")) 
                m_header->compression() = Imf::PIZ_COMPRESSION;
            else if (iequals (str, "pxr24")) 
                m_header->compression() = Imf::PXR24_COMPRESSION;
#ifdef IMF_B44_COMPRESSION
            // The enum Imf::B44_COMPRESSION is not defined in older versions
            // of OpenEXR, and there are no explicit version numbers in the
            // headers.  BUT this other related #define is present only in
            // the newer version.
            else if (iequals (str, "b44"))
                m_header->compression() = Imf::B44_COMPRESSION;
            else if (iequals (str, "b44a"))
                m_header->compression() = Imf::B44A_COMPRESSION;
#endif
        }
        return true;
    }

    if (iequals (xname, "openexr:lineOrder") && type == TypeDesc::STRING) {
        const char *str = *(char **)data;
        m_header->lineOrder() = Imf::INCREASING_Y;   // Default
        if (str) {
            if (iequals (str, "randomY"))
                m_header->lineOrder() = Imf::RANDOM_Y;
            else if (iequals (str, "decreasingY"))
                m_header->lineOrder() = Imf::DECREASING_Y;
        }
        return true;
    }

    // Supress planarconfig!
    if (iequals (xname, "planarconfig") || iequals (xname, "tiff:planarconfig"))
        return true;

    // General handling of attributes
    // FIXME -- police this if we ever allow arrays
    if (type == TypeDesc::INT || type == TypeDesc::UINT) {
        m_header->insert (xname.c_str(), Imf::IntAttribute (*(int*)data));
        return true;
    }
    if (type == TypeDesc::INT16) {
        m_header->insert (xname.c_str(), Imf::IntAttribute (*(short*)data));
        return true;
    }
    if (type == TypeDesc::UINT16) {
        m_header->insert (xname.c_str(), Imf::IntAttribute (*(unsigned short*)data));
        return true;
    }
    if (type == TypeDesc::FLOAT) {
        m_header->insert (xname.c_str(), Imf::FloatAttribute (*(float*)data));
        return true;
    }
    if (type == TypeDesc::HALF) {
        m_header->insert (xname.c_str(), Imf::FloatAttribute ((float)*(half*)data));
        return true;
    }
    if (type == TypeDesc::TypeMatrix) {
        m_header->insert (xname.c_str(), Imf::M44fAttribute (*(Imath::M44f*)data));
        return true;
    }
    if (type == TypeDesc::TypeString) {
        m_header->insert (xname.c_str(), Imf::StringAttribute (*(char**)data));
        return true;
    }
    if (type == TypeDesc::TypeVector) {
        m_header->insert (xname.c_str(), Imf::V3fAttribute (*(Imath::V3f*)data));
        return true;
    }

#ifdef DEBUG
    std::cerr << "Don't know what to do with " << type.c_str() << ' ' << xname << "\n";
#endif

    return false;
}
std::string
ShaderGroup::serialize () const
{
    std::ostringstream out;
    out.imbue (std::locale::classic());  // force C locale
    out.precision (9);
    lock_guard lock (m_mutex);
    for (int i = 0, nl = nlayers(); i < nl; ++i) {
        const ShaderInstance *inst = m_layers[i].get();

        bool dstsyms_exist = inst->symbols().size();
        for (int p = 0;  p < inst->lastparam(); ++p) {
            const Symbol *s = dstsyms_exist ? inst->symbol(p) : inst->mastersymbol(p);
            ASSERT (s);
            if (s->symtype() != SymTypeParam && s->symtype() != SymTypeOutputParam)
                continue;
            Symbol::ValueSource vs = dstsyms_exist ? s->valuesource()
                                                   : inst->instoverride(p)->valuesource();
            if (vs == Symbol::InstanceVal) {
                TypeDesc type = s->typespec().simpletype();
                int offset = s->dataoffset();
                if (type.is_unsized_array() && ! dstsyms_exist) {
                    // If we're being asked to serialize a group that isn't
                    // yet optimized, any "unsized" arrays will have their
                    // concrete length and offset in the SymOverrideInfo,
                    // not in the Symbol belonging to the instance.
                    type.arraylen = inst->instoverride(p)->arraylen();
                    offset = inst->instoverride(p)->dataoffset();
                }
                out << "param " << type << ' ' << s->name();
                int nvals = type.numelements() * type.aggregate;
                if (type.basetype == TypeDesc::INT) {
                    const int *vals = &inst->m_iparams[offset];
                    for (int i = 0; i < nvals; ++i)
                        out << ' ' << vals[i];
                } else if (type.basetype == TypeDesc::FLOAT) {
                    const float *vals = &inst->m_fparams[offset];
                    for (int i = 0; i < nvals; ++i)
                        out << ' ' << vals[i];
                } else if (type.basetype == TypeDesc::STRING) {
                    const ustring *vals = &inst->m_sparams[offset];
                    for (int i = 0; i < nvals; ++i)
                        out << ' ' << '\"' << Strutil::escape_chars(vals[i]) << '\"';
                } else {
                    ASSERT_MSG (0, "unknown type for serialization: %s (%s)",
                                   type.c_str(), s->typespec().c_str());
                }
                bool lockgeom = dstsyms_exist ? s->lockgeom()
                                              : inst->instoverride(p)->lockgeom();
                if (! lockgeom)
                    out << Strutil::sprintf (" [[int lockgeom=%d]]", lockgeom);
                out << " ;\n";
            }
        }
        out << "shader " << inst->shadername() << ' ' << inst->layername() << " ;\n";
        for (int c = 0, nc = inst->nconnections(); c < nc; ++c) {
            const Connection &con (inst->connection(c));
            ASSERT (con.srclayer >= 0);
            const ShaderInstance *srclayer = m_layers[con.srclayer].get();
            ASSERT (srclayer);
            ustring srclayername = srclayer->layername();
            ASSERT (con.src.param >= 0 && con.dst.param >= 0);
            bool srcsyms_exist = srclayer->symbols().size();
            ustring srcparam = srcsyms_exist ? srclayer->symbol(con.src.param)->name()
                                             : srclayer->mastersymbol(con.src.param)->name();
            ustring dstparam = dstsyms_exist ? inst->symbol(con.dst.param)->name()
                                             : inst->mastersymbol(con.dst.param)->name();
            // FIXME: Assertions to be sure we don't yet support individual
            // channel or array element connections. Fix eventually.
            ASSERT (con.src.arrayindex == -1 && con.src.channel == -1);
            ASSERT (con.dst.arrayindex == -1 && con.dst.channel == -1);
            out << "connect " <<  srclayername << '.' << srcparam << ' '
                << inst->layername() << '.' << dstparam << " ;\n";
        }
    }
    return out.str();
}
OSL_SHADEOP int
osl_getmessage (ShaderGlobals *sg, const char *source_, const char *name_,
                long long type_, void *val, int derivs,
                int layeridx, const char* sourcefile_, int sourceline)
{
    const ustring &source (USTR(source_));
    const ustring &name (USTR(name_));
    const ustring &sourcefile (USTR(sourcefile_));

    // recreate TypeDesc -- we just crammed it into an int!
    TypeDesc type (*(TypeDesc *)&type_);
    bool is_closure = (type.basetype == TypeDesc::UNKNOWN); // secret code for closure
    if (is_closure)
        type.basetype = TypeDesc::PTR;  // for closures, we store a pointer

    static ustring ktrace ("trace");
    if (source == ktrace) {
        // Source types where we need to ask the renderer
        RendererServices *renderer = sg->context->renderer();
        return renderer->getmessage (sg, source, name, type, val, derivs);
    }

    MessageList &messages (sg->context->messages());
    const Message* m = messages.find(name);
    if (m != NULL) {
        if (m->name == name) {
            if (m->type != type) {
                // found message, but types don't match
                sg->context->error(
                    "type mismatch for message \"%s\" (%s as %s here: %s:%d)"
                    " cannot fetch as %s from %s:%d",
                    name.c_str(),
                    m->has_data() ? "created" : "queried",
                    m->type == TypeDesc::PTR ? "closure color" : m->type.c_str(),
                    m->sourcefile.c_str(),
                    m->sourceline,
                    is_closure ? "closure color" : type.c_str(),
                    sourcefile.c_str(),
                    sourceline);
                return 0;
            }
            if (!m->has_data()) {
                // getmessage ran before and found nothing - just return 0
                return 0;
            }
            if (m->layeridx > layeridx) {
                // found message, but was set by a layer deeper than the one querying the message
                sg->context->error(
                    "message \"%s\" was set by layer #%d (%s:%d)"
                    " but is being queried by layer #%d (%s:%d)"
                    " - messages may only be transfered from nodes "
                    "that appear earlier in the shading network",
                    name.c_str(),
                    m->layeridx,
                    m->sourcefile.c_str(),
                    m->sourceline,
                    layeridx,
                    sourcefile.c_str(),
                    sourceline);
                return 0;
            }
            // Message found!
            size_t size = type.size();
            memcpy (val, m->data, size);
            if (derivs) // TODO: move this to llvm code gen?
                memset (((char *)val)+size, 0, 2*size);
            return 1;
        }
    }
    // Message not found -- we must record this event in case another layer tries to set the message again later on
    if (sg->context->shadingsys().strict_messages())
        messages.add(name, NULL, type, layeridx, sourcefile, sourceline);
    return 0;
}