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; }
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; }