Beispiel #1
0
static void headerToCompoundData( const Imf::Header &header, CompoundData *blindData )
{
	for ( Imf::Header::ConstIterator attrIt = header.begin(); attrIt != header.end(); attrIt++ )
	{
		std::string name = attrIt.name();
		DataPtr data = attributeToData( attrIt.attribute() );
		if ( data )
		{
			addHeaderAttribute( name, data, blindData );
		}
	}
}
Beispiel #2
0
void
OpenEXRInput::PartInfo::parse_header (const Imf::Header *header)
{
    if (initialized)
        return;

    ASSERT (header);
    spec = ImageSpec();

    top_datawindow = header->dataWindow();
    top_displaywindow = header->displayWindow();
    spec.x = top_datawindow.min.x;
    spec.y = top_datawindow.min.y;
    spec.z = 0;
    spec.width  = top_datawindow.max.x - top_datawindow.min.x + 1;
    spec.height = top_datawindow.max.y - top_datawindow.min.y + 1;
    spec.depth = 1;
    topwidth = spec.width;      // Save top-level mipmap dimensions
    topheight = spec.height;
    spec.full_x = top_displaywindow.min.x;
    spec.full_y = top_displaywindow.min.y;
    spec.full_z = 0;
    spec.full_width  = top_displaywindow.max.x - top_displaywindow.min.x + 1;
    spec.full_height = top_displaywindow.max.y - top_displaywindow.min.y + 1;
    spec.full_depth = 1;
    spec.tile_depth = 1;

    if (header->hasTileDescription()) {
        const Imf::TileDescription &td (header->tileDescription());
        spec.tile_width = td.xSize;
        spec.tile_height = td.ySize;
        levelmode = td.mode;
        roundingmode = td.roundingMode;
        if (levelmode == Imf::MIPMAP_LEVELS)
            nmiplevels = numlevels (std::max(topwidth,topheight), roundingmode);
        else if (levelmode == Imf::RIPMAP_LEVELS)
            nmiplevels = numlevels (std::max(topwidth,topheight), roundingmode);
        else
            nmiplevels = 1;
    } else {
        spec.tile_width = 0;
        spec.tile_height = 0;
        levelmode = Imf::ONE_LEVEL;
        nmiplevels = 1;
    }
    query_channels (header);   // also sets format

#ifdef USE_OPENEXR_VERSION2
    spec.deep = Strutil::istarts_with (header->type(), "deep");
#endif

    // Unless otherwise specified, exr files are assumed to be linear.
    spec.attribute ("oiio:ColorSpace", "Linear");

    if (levelmode != Imf::ONE_LEVEL)
        spec.attribute ("openexr:roundingmode", roundingmode);

    const Imf::EnvmapAttribute *envmap;
    envmap = header->findTypedAttribute<Imf::EnvmapAttribute>("envmap");
    if (envmap) {
        cubeface = (envmap->value() == Imf::ENVMAP_CUBE);
        spec.attribute ("textureformat", cubeface ? "CubeFace Environment" : "LatLong Environment");
        // OpenEXR conventions for env maps
        if (! cubeface)
            spec.attribute ("oiio:updirection", "y");
        spec.attribute ("oiio:sampleborder", 1);
        // FIXME - detect CubeFace Shadow?
    } else {
        cubeface = false;
        if (spec.tile_width && levelmode == Imf::MIPMAP_LEVELS)
            spec.attribute ("textureformat", "Plain Texture");
        // FIXME - detect Shadow
    }

    const Imf::CompressionAttribute *compressattr;
    compressattr = header->findTypedAttribute<Imf::CompressionAttribute>("compression");
    if (compressattr) {
        const char *comp = NULL;
        switch (compressattr->value()) {
        case Imf::NO_COMPRESSION    : comp = "none"; break;
        case Imf::RLE_COMPRESSION   : comp = "rle"; break;
        case Imf::ZIPS_COMPRESSION  : comp = "zips"; break;
        case Imf::ZIP_COMPRESSION   : comp = "zip"; break;
        case Imf::PIZ_COMPRESSION   : comp = "piz"; break;
        case Imf::PXR24_COMPRESSION : comp = "pxr24"; break;
#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.
        case Imf::B44_COMPRESSION   : comp = "b44"; break;
        case Imf::B44A_COMPRESSION  : comp = "b44a"; break;
#endif
#if defined(OPENEXR_VERSION_MAJOR) && \
    (OPENEXR_VERSION_MAJOR*10000+OPENEXR_VERSION_MINOR*100+OPENEXR_VERSION_PATCH) >= 20200
        case Imf::DWAA_COMPRESSION  : comp = "dwaa"; break;
        case Imf::DWAB_COMPRESSION  : comp = "dwab"; break;
#endif
        default:
            break;
        }
        if (comp)
            spec.attribute ("compression", comp);
    }

    for (Imf::Header::ConstIterator hit = header->begin();
             hit != header->end();  ++hit) {
        const Imf::IntAttribute *iattr;
        const Imf::FloatAttribute *fattr;
        const Imf::StringAttribute *sattr;
        const Imf::M44fAttribute *mattr;
        const Imf::V3fAttribute *v3fattr;
        const Imf::V3iAttribute *v3iattr;
        const Imf::V2fAttribute *v2fattr;
        const Imf::V2iAttribute *v2iattr;
        const Imf::Box2iAttribute *b2iattr;
        const Imf::Box2fAttribute *b2fattr;
        const Imf::TimeCodeAttribute *tattr;
        const Imf::KeyCodeAttribute *kcattr;
#ifdef USE_OPENEXR_VERSION2
        const Imf::StringVectorAttribute *svattr;
#endif
        const char *name = hit.name();
        std::string oname = exr_tag_to_ooio_std[name];
        if (oname.empty())   // Empty string means skip this attrib
            continue;
//        if (oname == name)
//            oname = std::string(format_name()) + "_" + oname;
        const Imf::Attribute &attrib = hit.attribute();
        std::string type = attrib.typeName();
        if (type == "string" && 
            (sattr = header->findTypedAttribute<Imf::StringAttribute> (name)))
            spec.attribute (oname, sattr->value().c_str());
        else if (type == "int" && 
            (iattr = header->findTypedAttribute<Imf::IntAttribute> (name)))
            spec.attribute (oname, iattr->value());
        else if (type == "float" && 
            (fattr = header->findTypedAttribute<Imf::FloatAttribute> (name)))
            spec.attribute (oname, fattr->value());
        else if (type == "m44f" && 
            (mattr = header->findTypedAttribute<Imf::M44fAttribute> (name)))
            spec.attribute (oname, TypeDesc::TypeMatrix, &(mattr->value()));
        else if (type == "v3f" &&
                 (v3fattr = header->findTypedAttribute<Imf::V3fAttribute> (name)))
            spec.attribute (oname, TypeDesc::TypeVector, &(v3fattr->value()));
        else if (type == "v3i" &&
                 (v3iattr = header->findTypedAttribute<Imf::V3iAttribute> (name))) {
            TypeDesc v3 (TypeDesc::INT, TypeDesc::VEC3, TypeDesc::VECTOR);
            spec.attribute (oname, v3, &(v3iattr->value()));
        }
        else if (type == "v2f" &&
                 (v2fattr = header->findTypedAttribute<Imf::V2fAttribute> (name))) {
            TypeDesc v2 (TypeDesc::FLOAT,TypeDesc::VEC2);
            spec.attribute (oname, v2, &(v2fattr->value()));
        }
        else if (type == "v2i" &&
                 (v2iattr = header->findTypedAttribute<Imf::V2iAttribute> (name))) {
            TypeDesc v2 (TypeDesc::INT,TypeDesc::VEC2);
            spec.attribute (oname, v2, &(v2iattr->value()));
        }
#ifdef USE_OPENEXR_VERSION2
        else if (type == "stringvector" &&
            (svattr = header->findTypedAttribute<Imf::StringVectorAttribute> (name))) {
            std::vector<std::string> strvec = svattr->value();
            std::vector<ustring> ustrvec (strvec.size());
            for (size_t i = 0, e = strvec.size();  i < e;  ++i)
                ustrvec[i] = strvec[i];
            TypeDesc sv (TypeDesc::STRING, ustrvec.size());
            spec.attribute(oname, sv, &ustrvec[0]);
        }
#endif
        else if (type == "box2i" &&
                 (b2iattr = header->findTypedAttribute<Imf::Box2iAttribute> (name))) {
            TypeDesc bx (TypeDesc::INT, TypeDesc::VEC2, 2);
            spec.attribute (oname, bx, &b2iattr->value());
        }
        else if (type == "box2f" &&
                 (b2fattr = header->findTypedAttribute<Imf::Box2fAttribute> (name))) {
            TypeDesc bx (TypeDesc::FLOAT, TypeDesc::VEC2, 2);
            spec.attribute (oname, bx, &b2fattr->value());
        }
        else if (type == "timecode" &&
                 (tattr = header->findTypedAttribute<Imf::TimeCodeAttribute> (name))) {
            unsigned int timecode[2];
            timecode[0] = tattr->value().timeAndFlags(Imf::TimeCode::TV60_PACKING); //TV60 returns unchanged _time
            timecode[1] = tattr->value().userData();

            // Elevate "timeCode" to smpte:TimeCode
            if (oname == "timeCode")
                oname = "smpte:TimeCode";
            spec.attribute(oname, TypeDesc::TypeTimeCode, timecode);
        }
        else if (type == "keycode" &&
                 (kcattr = header->findTypedAttribute<Imf::KeyCodeAttribute> (name))) {
            const Imf::KeyCode *k = &kcattr->value();
            unsigned int keycode[7];
            keycode[0] = k->filmMfcCode();
            keycode[1] = k->filmType();
            keycode[2] = k->prefix();
            keycode[3] = k->count();
            keycode[4] = k->perfOffset();
            keycode[5] = k->perfsPerFrame();
            keycode[6] = k->perfsPerCount();

            // Elevate "keyCode" to smpte:KeyCode
            if (oname == "keyCode")
                oname = "smpte:KeyCode";
            spec.attribute(oname, TypeDesc::TypeKeyCode, keycode);
        }
        else {
#if 0
            std::cerr << "  unknown attribute " << type << ' ' << name << "\n";
#endif
        }
    }

#ifdef USE_OPENEXR_VERSION2
    // EXR "name" also gets passed along as "oiio:subimagename".
    if (header->hasName())
        spec.attribute ("oiio:subimagename", header->name());
#endif

    initialized = true;
}
/*!
    Tries to fill the image object with the data read from
    the given input stream. Returns true on success.
*/
bool EXRImageFileType::read(      Image        *image, 
                                  std::istream &is, 
                            const std::string  &mimetype)
{
#ifdef OSG_WITH_IMF
    if (!is.good())
        return false;

    const char *dummy = "";
    StdIStream file(is, dummy);

    Imf::Int64 pos = file.tellg();

    bool check = isOpenExrFile(is);

    file.seekg(pos);

    if (!check)
    {
        FFATAL(( "Wrong format, no %s image given!\n",
                  mimetype.c_str() ));
        return false;
    }

    // just read the header and get the channel count
    int channel_count = 0;
    pos = file.tellg();
    try
    {
        Imf::RgbaInputFile stream(file);
        const Imf::Header &header = stream.header();
        const Imf::ChannelList &channels = header.channels();

        for(Imf::ChannelList::ConstIterator it  = channels.begin();
                                            it != channels.end();
                                          ++it)
        {
            ++channel_count;
        }
    }
    catch(std::exception &e)
    {
        FFATAL(( "Error while trying to read OpenEXR Image from stream: %s\n",
                  e.what() ));
        return false;
    }
    file.seekg(pos);

    if(channel_count <= 4)
    {
        // TODO: check for mipmap levels,
        // look if line order is s.th. else than INCREASING_Y
        try
        {
            Int32 width, height, numImg = 1;
            Imf::RgbaInputFile stream(file);
    
            Imath::Box2i dw = stream.dataWindow();
            Imf::Array2D<Imf::Rgba> pixels;
    
            const Imf::Header &header = stream.header();
//            const Imf::LineOrder &order = header.lineOrder();
    
            const Imf::EnvmapAttribute *envmap =
                header.findTypedAttribute<Imf::EnvmapAttribute>("envmap");
    
            width  = dw.max.x - dw.min.x + 1;
            height = dw.max.y - dw.min.y + 1;
    
            pixels.resizeErase(height, width);
    
            if(envmap && envmap->value() == Imf::ENVMAP_CUBE)
            {
                numImg = 6;
                height /= numImg;
    
                if (width != height)
                {
                    FFATAL(( "Cubemaps must have squared size, "
                             "but w=%d and h=%d!\n", width, height ));
                    return false;
                }
            }
    
            stream.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width,
                                  1, 
                                  width);
            stream.readPixels(dw.min.y, dw.max.y);
    
            image->set( Image::OSG_RGBA_PF, width, height, 1, 1, 1, 0, 0,
                        Image::OSG_FLOAT16_IMAGEDATA, true, numImg );
            image->clearHalf();
    
            // now add custom attributes
            for(Imf::Header::ConstIterator it  = header.begin();
                                           it != header.end();
                                         ++it)
            {
                Imf::Attribute *copy = it.attribute().copy();
                Imf::StringAttribute *sa = 
                    dynamic_cast<Imf::StringAttribute *>(copy);
    
                if(sa != NULL)
                    image->setAttachmentField(it.name(), sa->value());
    
                delete copy;
            }
    
            Real16 *data = reinterpret_cast<Real16*>(image->editData());
    
            for (Int32 side=numImg-1; side >=0; side--)
            {
                Int32 i, j, size = side * width * height * 4;
    
                for (Int32 y=side*height; y<(side+1)*height; y++)
                {
                    for (Int32 x=0; x<width; x++)
                    {
                        if (numImg == 1 || side == 2 || side == 3)
                        {
                            i = (2 * side + 1) * height - (y + 1); // new y
                            j = x;
                        }
                        else
                        {
                            i = y;
                            j = width - x - 1; // new x
                        }
    
                        *(data + size++) = Real16(pixels[i][j].r);
                        *(data + size++) = Real16(pixels[i][j].g);
                        *(data + size++) = Real16(pixels[i][j].b);
                        *(data + size++) = Real16(pixels[i][j].a);
                    }
                }
            }
    
            return true;
        }
        catch(std::exception &e)
        {
            FFATAL(( "Error while trying to read OpenEXR Image from stream: "
                     "%s\n", e.what() ));

            return false;
        }
    }
    else
    {
        try
        {
            if(channel_count % 4 != 0)
            {
                FFATAL(( "Error while trying to read OpenEXR Image from "
                         "stream, channel count of %d is not supported!\n", 
                         channel_count));

                return false;
            }

            int num_img = channel_count / 4;

            Imf::InputFile stream(file);
            const Imf::Header &header = stream.header();
            Imath::Box2i dw = header.dataWindow();

            int width  = dw.max.x - dw.min.x + 1;
            int height = dw.max.y - dw.min.y + 1;

            image->set(Image::OSG_RGBA_PF, width, height, 1, 1, 1, 0, 0,
                       Image::OSG_FLOAT16_IMAGEDATA, true, num_img);
            image->clearHalf();

            // now add custom attributes
            for(Imf::Header::ConstIterator it  = header.begin();
                                           it != header.end();
                                         ++it                  )
            {
                Imf::Attribute *copy = it.attribute().copy();
                Imf::StringAttribute *sa = 
                    dynamic_cast<Imf::StringAttribute *>(copy);
    
                if(sa != NULL)
                    image->setAttachmentField(it.name(), sa->value());
    
                delete copy;
            }

            const Imf::ChannelList &channels = header.channels();

            // do some channel name checks
            bool channel_error = false;
            for(Imf::ChannelList::ConstIterator it=channels.begin();it!=channels.end();++it)
            {
                for(int side=0;side>num_img;++side)
                {
                    char cn[20];
                    sprintf(cn, "%d", side);

                    char name[20];
                    sprintf(name, "R%s", side == 0 ? "" : cn);
                    if(channels.findChannel(name) == NULL)
                        channel_error = true;
                    sprintf(name, "G%s", side == 0 ? "" : cn);
                    if(channels.findChannel(name) == NULL)
                        channel_error = true;
                    sprintf(name, "B%s", side == 0 ? "" : cn);
                    if(channels.findChannel(name) == NULL)
                        channel_error = true;
                    sprintf(name, "A%s", side == 0 ? "" : cn);
                    if(channels.findChannel(name) == NULL)
                        channel_error = true;
                }
            }

            if(channel_error)
            {
                FFATAL(( "Error while trying to read OpenEXR Image from "
                         "stream, expected channel names 'R' 'G' 'B' 'A', "
                         "'R1' 'G1', 'B1', 'A1', ...\n"));

                return false;
            }

            Imf::FrameBuffer frame_buffer;

            // we need to do a vertical flip so we read single scan lines in.
            int current_scan_line = 0;
            for(int i=height-1;i>=0;--i)
            {
                for(int side=0;side<num_img;++side)
                {
                    char *data = 
                        (reinterpret_cast<char *>(image->editData(0, 0, side))) + i * (sizeof(Real16) * 4 * width);

                    data -= current_scan_line * (sizeof(Real16) * 4 * width);

                    char cn[20];
                    sprintf(cn, "%d", side);

                    char name[20];
                    sprintf(name, "R%s", side == 0 ? "" : cn);
                    frame_buffer.insert(name, Imf::Slice(Imf::HALF, data, sizeof(Real16) * 4, sizeof(Real16) * 4 * width));
                    sprintf(name, "G%s", side == 0 ? "" : cn);
                    frame_buffer.insert(name, Imf::Slice(Imf::HALF, data + 1 * sizeof(Real16), sizeof(Real16) * 4, sizeof(Real16) * 4 * width));
                    sprintf(name, "B%s", side == 0 ? "" : cn);
                    frame_buffer.insert(name, Imf::Slice(Imf::HALF, data + 2 * sizeof(Real16), sizeof(Real16) * 4, sizeof(Real16) * 4 * width));
                    sprintf(name, "A%s", side == 0 ? "" : cn);
                    frame_buffer.insert(name, Imf::Slice(Imf::HALF, data + 3 * sizeof(Real16), sizeof(Real16) * 4, sizeof(Real16) * 4 * width));
                }
                stream.setFrameBuffer(frame_buffer);
                stream.readPixels(current_scan_line, current_scan_line);
                ++current_scan_line;
            }

            return true;
        }
        catch(std::exception &e)
        {
            FFATAL(( "Error while trying to read OpenEXR Image from stream: %s\n",
                      e.what() ));
            return false;
        }
    }

#else
    SWARNING << getMimeType()
             << " read is not compiled into the current binary "
             << std::endl;
    return false;
#endif
}
Beispiel #4
0
void
OpenEXRInput::PartInfo::parse_header (const Imf::Header *header)
{
    if (initialized)
        return;

    ASSERT (header);
    spec = ImageSpec();

    top_datawindow = header->dataWindow();
    top_displaywindow = header->displayWindow();
    spec.x = top_datawindow.min.x;
    spec.y = top_datawindow.min.y;
    spec.z = 0;
    spec.width  = top_datawindow.max.x - top_datawindow.min.x + 1;
    spec.height = top_datawindow.max.y - top_datawindow.min.y + 1;
    spec.depth = 1;
    topwidth = spec.width;      // Save top-level mipmap dimensions
    topheight = spec.height;
    spec.full_x = top_displaywindow.min.x;
    spec.full_y = top_displaywindow.min.y;
    spec.full_z = 0;
    spec.full_width  = top_displaywindow.max.x - top_displaywindow.min.x + 1;
    spec.full_height = top_displaywindow.max.y - top_displaywindow.min.y + 1;
    spec.full_depth = 1;
    spec.tile_depth = 1;

    if (header->hasTileDescription()
          && Strutil::icontains(header->type(), "tile")) {
        const Imf::TileDescription &td (header->tileDescription());
        spec.tile_width = td.xSize;
        spec.tile_height = td.ySize;
        levelmode = td.mode;
        roundingmode = td.roundingMode;
        if (levelmode == Imf::MIPMAP_LEVELS)
            nmiplevels = numlevels (std::max(topwidth,topheight), roundingmode);
        else if (levelmode == Imf::RIPMAP_LEVELS)
            nmiplevels = numlevels (std::max(topwidth,topheight), roundingmode);
        else
            nmiplevels = 1;
    } else {
        spec.tile_width = 0;
        spec.tile_height = 0;
        levelmode = Imf::ONE_LEVEL;
        nmiplevels = 1;
    }
    query_channels (header);   // also sets format

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

    // Unless otherwise specified, exr files are assumed to be linear.
    spec.attribute ("oiio:ColorSpace", "Linear");

    if (levelmode != Imf::ONE_LEVEL)
        spec.attribute ("openexr:roundingmode", roundingmode);

    const Imf::EnvmapAttribute *envmap;
    envmap = header->findTypedAttribute<Imf::EnvmapAttribute>("envmap");
    if (envmap) {
        cubeface = (envmap->value() == Imf::ENVMAP_CUBE);
        spec.attribute ("textureformat", cubeface ? "CubeFace Environment" : "LatLong Environment");
        // OpenEXR conventions for env maps
        if (! cubeface)
            spec.attribute ("oiio:updirection", "y");
        spec.attribute ("oiio:sampleborder", 1);
        // FIXME - detect CubeFace Shadow?
    } else {
        cubeface = false;
        if (spec.tile_width && levelmode == Imf::MIPMAP_LEVELS)
            spec.attribute ("textureformat", "Plain Texture");
        // FIXME - detect Shadow
    }

    const Imf::CompressionAttribute *compressattr;
    compressattr = header->findTypedAttribute<Imf::CompressionAttribute>("compression");
    if (compressattr) {
        const char *comp = NULL;
        switch (compressattr->value()) {
        case Imf::NO_COMPRESSION    : comp = "none"; break;
        case Imf::RLE_COMPRESSION   : comp = "rle"; break;
        case Imf::ZIPS_COMPRESSION  : comp = "zips"; break;
        case Imf::ZIP_COMPRESSION   : comp = "zip"; break;
        case Imf::PIZ_COMPRESSION   : comp = "piz"; break;
        case Imf::PXR24_COMPRESSION : comp = "pxr24"; break;
#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.
        case Imf::B44_COMPRESSION   : comp = "b44"; break;
        case Imf::B44A_COMPRESSION  : comp = "b44a"; break;
#endif
#if defined(OPENEXR_VERSION_MAJOR) && \
    (OPENEXR_VERSION_MAJOR*10000+OPENEXR_VERSION_MINOR*100+OPENEXR_VERSION_PATCH) >= 20200
        case Imf::DWAA_COMPRESSION  : comp = "dwaa"; break;
        case Imf::DWAB_COMPRESSION  : comp = "dwab"; break;
#endif
        default:
            break;
        }
        if (comp)
            spec.attribute ("compression", comp);
    }

    for (Imf::Header::ConstIterator hit = header->begin();
             hit != header->end();  ++hit) {
        const Imf::IntAttribute *iattr;
        const Imf::FloatAttribute *fattr;
        const Imf::StringAttribute *sattr;
        const Imf::M33fAttribute *m33fattr;
        const Imf::M44fAttribute *m44fattr;
        const Imf::V3fAttribute *v3fattr;
        const Imf::V3iAttribute *v3iattr;
        const Imf::V2fAttribute *v2fattr;
        const Imf::V2iAttribute *v2iattr;
        const Imf::Box2iAttribute *b2iattr;
        const Imf::Box2fAttribute *b2fattr;
        const Imf::TimeCodeAttribute *tattr;
        const Imf::KeyCodeAttribute *kcattr;
        const Imf::ChromaticitiesAttribute *crattr;
        const Imf::RationalAttribute *rattr;
        const Imf::StringVectorAttribute *svattr;
        const Imf::DoubleAttribute *dattr;
        const Imf::V2dAttribute *v2dattr;
        const Imf::V3dAttribute *v3dattr;
        const Imf::M33dAttribute *m33dattr;
        const Imf::M44dAttribute *m44dattr;
        const char *name = hit.name();
        std::string oname = exr_tag_to_oiio_std[name];
        if (oname.empty())   // Empty string means skip this attrib
            continue;
//        if (oname == name)
//            oname = std::string(format_name()) + "_" + oname;
        const Imf::Attribute &attrib = hit.attribute();
        std::string type = attrib.typeName();
        if (type == "string" &&
            (sattr = header->findTypedAttribute<Imf::StringAttribute> (name)))
            spec.attribute (oname, sattr->value().c_str());
        else if (type == "int" &&
            (iattr = header->findTypedAttribute<Imf::IntAttribute> (name)))
            spec.attribute (oname, iattr->value());
        else if (type == "float" &&
            (fattr = header->findTypedAttribute<Imf::FloatAttribute> (name)))
            spec.attribute (oname, fattr->value());
        else if (type == "m33f" &&
            (m33fattr = header->findTypedAttribute<Imf::M33fAttribute> (name)))
            spec.attribute (oname, TypeMatrix33, &(m33fattr->value()));
        else if (type == "m44f" &&
            (m44fattr = header->findTypedAttribute<Imf::M44fAttribute> (name)))
            spec.attribute (oname, TypeMatrix44, &(m44fattr->value()));
        else if (type == "v3f" &&
                 (v3fattr = header->findTypedAttribute<Imf::V3fAttribute> (name)))
            spec.attribute (oname, TypeVector, &(v3fattr->value()));
        else if (type == "v3i" &&
                 (v3iattr = header->findTypedAttribute<Imf::V3iAttribute> (name))) {
            TypeDesc v3 (TypeDesc::INT, TypeDesc::VEC3, TypeDesc::VECTOR);
            spec.attribute (oname, v3, &(v3iattr->value()));
        }
        else if (type == "v2f" &&
                 (v2fattr = header->findTypedAttribute<Imf::V2fAttribute> (name))) {
            TypeDesc v2 (TypeDesc::FLOAT,TypeDesc::VEC2);
            spec.attribute (oname, v2, &(v2fattr->value()));
        }
        else if (type == "v2i" &&
                 (v2iattr = header->findTypedAttribute<Imf::V2iAttribute> (name))) {
            TypeDesc v2 (TypeDesc::INT,TypeDesc::VEC2);
            spec.attribute (oname, v2, &(v2iattr->value()));
        }
        else if (type == "stringvector" &&
            (svattr = header->findTypedAttribute<Imf::StringVectorAttribute> (name))) {
            std::vector<std::string> strvec = svattr->value();
            std::vector<ustring> ustrvec (strvec.size());
            for (size_t i = 0, e = strvec.size();  i < e;  ++i)
                ustrvec[i] = strvec[i];
            TypeDesc sv (TypeDesc::STRING, ustrvec.size());
            spec.attribute(oname, sv, &ustrvec[0]);
        }
        else if (type == "double" &&
            (dattr = header->findTypedAttribute<Imf::DoubleAttribute> (name))) {
            TypeDesc d (TypeDesc::DOUBLE);
            spec.attribute (oname, d, &(dattr->value()));
        }
        else if (type == "v2d" &&
                 (v2dattr = header->findTypedAttribute<Imf::V2dAttribute> (name))) {
            TypeDesc v2 (TypeDesc::DOUBLE,TypeDesc::VEC2);
            spec.attribute (oname, v2, &(v2dattr->value()));
        }
        else if (type == "v3d" &&
                 (v3dattr = header->findTypedAttribute<Imf::V3dAttribute> (name))) {
            TypeDesc v3 (TypeDesc::DOUBLE,TypeDesc::VEC3, TypeDesc::VECTOR);
            spec.attribute (oname, v3, &(v3dattr->value()));
        }
        else if (type == "m33d" &&
            (m33dattr = header->findTypedAttribute<Imf::M33dAttribute> (name))) {
            TypeDesc m33 (TypeDesc::DOUBLE, TypeDesc::MATRIX33);
            spec.attribute (oname, m33, &(m33dattr->value()));
        }
        else if (type == "m44d" &&
            (m44dattr = header->findTypedAttribute<Imf::M44dAttribute> (name))) {
            TypeDesc m44 (TypeDesc::DOUBLE, TypeDesc::MATRIX44);
            spec.attribute (oname, m44, &(m44dattr->value()));
        }
        else if (type == "box2i" &&
                 (b2iattr = header->findTypedAttribute<Imf::Box2iAttribute> (name))) {
            TypeDesc bx (TypeDesc::INT, TypeDesc::VEC2, 2);
            spec.attribute (oname, bx, &b2iattr->value());
        }
        else if (type == "box2f" &&
                 (b2fattr = header->findTypedAttribute<Imf::Box2fAttribute> (name))) {
            TypeDesc bx (TypeDesc::FLOAT, TypeDesc::VEC2, 2);
            spec.attribute (oname, bx, &b2fattr->value());
        }
        else if (type == "timecode" &&
                 (tattr = header->findTypedAttribute<Imf::TimeCodeAttribute> (name))) {
            unsigned int timecode[2];
            timecode[0] = tattr->value().timeAndFlags(Imf::TimeCode::TV60_PACKING); //TV60 returns unchanged _time
            timecode[1] = tattr->value().userData();

            // Elevate "timeCode" to smpte:TimeCode
            if (oname == "timeCode")
                oname = "smpte:TimeCode";
            spec.attribute(oname, TypeTimeCode, timecode);
        }
        else if (type == "keycode" &&
                 (kcattr = header->findTypedAttribute<Imf::KeyCodeAttribute> (name))) {
            const Imf::KeyCode *k = &kcattr->value();
            unsigned int keycode[7];
            keycode[0] = k->filmMfcCode();
            keycode[1] = k->filmType();
            keycode[2] = k->prefix();
            keycode[3] = k->count();
            keycode[4] = k->perfOffset();
            keycode[5] = k->perfsPerFrame();
            keycode[6] = k->perfsPerCount();

            // Elevate "keyCode" to smpte:KeyCode
            if (oname == "keyCode")
                oname = "smpte:KeyCode";
            spec.attribute(oname, TypeKeyCode, keycode);
        } else if (type == "chromaticities" &&
                   (crattr = header->findTypedAttribute<Imf::ChromaticitiesAttribute> (name))) {
            const Imf::Chromaticities *chroma = &crattr->value();
            spec.attribute (oname, TypeDesc(TypeDesc::FLOAT,8),
                            (const float *)chroma);
        } 
        else if (type == "rational" &&
                   (rattr = header->findTypedAttribute<Imf::RationalAttribute> (name))) {
            const Imf::Rational *rational = &rattr->value();
            int n = rational->n;
            unsigned int d = rational->d;
            if (d < (1UL << 31)) {
                int r[2];
                r[0] = n;
                r[1] = static_cast<int>(d);
                spec.attribute (oname, TypeRational, r);    
            } else if (int f = static_cast<int>(boost::math::gcd<long int>(rational[0], rational[1])) > 1) {
                int r[2];
                r[0] = n / f;
                r[1] = static_cast<int>(d / f);
               spec.attribute (oname, TypeRational, r);
            } else {
                // TODO: find a way to allow the client to accept "close" rational values
                OIIO::debug ("Don't know what to do with OpenEXR Rational attribute %s with value %d / %u that we cannot represent exactly", oname, n, d);
            }
        }
        else {
#if 0
            std::cerr << "  unknown attribute " << type << ' ' << name << "\n";
#endif
        }
    }

    float aspect = spec.get_float_attribute ("PixelAspectRatio", 0.0f);
    float xdensity = spec.get_float_attribute ("XResolution", 0.0f);
    if (xdensity) {
        // If XResolution is found, supply the YResolution and unit.
        spec.attribute ("YResolution", xdensity * (aspect ? aspect : 1.0f));
        spec.attribute ("ResolutionUnit", "in"); // EXR is always pixels/inch
    }

    // EXR "name" also gets passed along as "oiio:subimagename".
    if (header->hasName())
        spec.attribute ("oiio:subimagename", header->name());

    // Squash some problematic texture metadata if we suspect it's wrong
    pvt::check_texture_metadata_sanity (spec);

    initialized = true;
}
Beispiel #5
0
void
OpenEXRInput::PartInfo::parse_header (const Imf::Header *header)
{
    if (initialized)
        return;

    ASSERT (header);
    spec = ImageSpec();

    top_datawindow = header->dataWindow();
    top_displaywindow = header->displayWindow();
    spec.x = top_datawindow.min.x;
    spec.y = top_datawindow.min.y;
    spec.z = 0;
    spec.width  = top_datawindow.max.x - top_datawindow.min.x + 1;
    spec.height = top_datawindow.max.y - top_datawindow.min.y + 1;
    spec.depth = 1;
    topwidth = spec.width;      // Save top-level mipmap dimensions
    topheight = spec.height;
    spec.full_x = top_displaywindow.min.x;
    spec.full_y = top_displaywindow.min.y;
    spec.full_z = 0;
    spec.full_width  = top_displaywindow.max.x - top_displaywindow.min.x + 1;
    spec.full_height = top_displaywindow.max.y - top_displaywindow.min.y + 1;
    spec.full_depth = 1;
    spec.tile_depth = 1;

    if (header->hasTileDescription()) {
        const Imf::TileDescription &td (header->tileDescription());
        spec.tile_width = td.xSize;
        spec.tile_height = td.ySize;
        levelmode = td.mode;
        roundingmode = td.roundingMode;
        if (levelmode == Imf::MIPMAP_LEVELS)
            nmiplevels = numlevels (std::max(topwidth,topheight), roundingmode);
        else if (levelmode == Imf::RIPMAP_LEVELS)
            nmiplevels = numlevels (std::max(topwidth,topheight), roundingmode);
        else
            nmiplevels = 1;
    } else {
        spec.tile_width = 0;
        spec.tile_height = 0;
        levelmode = Imf::ONE_LEVEL;
        nmiplevels = 1;
    }
    query_channels (header);   // also sets format

#ifdef USE_OPENEXR_VERSION2
    spec.deep = Imf::isDeepData (header->type());
#endif

    // Unless otherwise specified, exr files are assumed to be linear.
    spec.attribute ("oiio:ColorSpace", "Linear");

    if (levelmode != Imf::ONE_LEVEL)
        spec.attribute ("openexr:roundingmode", roundingmode);

    const Imf::EnvmapAttribute *envmap;
    envmap = header->findTypedAttribute<Imf::EnvmapAttribute>("envmap");
    if (envmap) {
        cubeface = (envmap->value() == Imf::ENVMAP_CUBE);
        spec.attribute ("textureformat", cubeface ? "CubeFace Environment" : "LatLong Environment");
        // OpenEXR conventions for env maps
        if (! cubeface)
            spec.attribute ("oiio:updirection", "y");
        spec.attribute ("oiio:sampleborder", 1);
        // FIXME - detect CubeFace Shadow?
    } else {
        cubeface = false;
        if (spec.tile_width && levelmode == Imf::MIPMAP_LEVELS)
            spec.attribute ("textureformat", "Plain Texture");
        // FIXME - detect Shadow
    }

    const Imf::CompressionAttribute *compressattr;
    compressattr = header->findTypedAttribute<Imf::CompressionAttribute>("compression");
    if (compressattr) {
        const char *comp = NULL;
        switch (compressattr->value()) {
        case Imf::NO_COMPRESSION    : comp = "none"; break;
        case Imf::RLE_COMPRESSION   : comp = "rle"; break;
        case Imf::ZIPS_COMPRESSION  : comp = "zips"; break;
        case Imf::ZIP_COMPRESSION   : comp = "zip"; break;
        case Imf::PIZ_COMPRESSION   : comp = "piz"; break;
        case Imf::PXR24_COMPRESSION : comp = "pxr24"; break;
#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.
        case Imf::B44_COMPRESSION   : comp = "b44"; break;
        case Imf::B44A_COMPRESSION  : comp = "b44a"; break;
#endif
        default:
            break;
        }
        if (comp)
            spec.attribute ("compression", comp);
    }

    for (Imf::Header::ConstIterator hit = header->begin();
             hit != header->end();  ++hit) {
        const Imf::IntAttribute *iattr;
        const Imf::FloatAttribute *fattr;
        const Imf::StringAttribute *sattr;
        const Imf::M44fAttribute *mattr;
        const Imf::V3fAttribute *vattr;
        const Imf::V2fAttribute *v2attr;
        const char *name = hit.name();
        std::string oname = exr_tag_to_ooio_std[name];
        if (oname.empty())   // Empty string means skip this attrib
            continue;
//        if (oname == name)
//            oname = std::string(format_name()) + "_" + oname;
        const Imf::Attribute &attrib = hit.attribute();
        std::string type = attrib.typeName();
        if (type == "string" && 
            (sattr = header->findTypedAttribute<Imf::StringAttribute> (name)))
            spec.attribute (oname, sattr->value().c_str());
        else if (type == "int" && 
            (iattr = header->findTypedAttribute<Imf::IntAttribute> (name)))
            spec.attribute (oname, iattr->value());
        else if (type == "float" && 
            (fattr = header->findTypedAttribute<Imf::FloatAttribute> (name)))
            spec.attribute (oname, fattr->value());
        else if (type == "m44f" && 
            (mattr = header->findTypedAttribute<Imf::M44fAttribute> (name)))
            spec.attribute (oname, TypeDesc::TypeMatrix, &(mattr->value()));
        else if (type == "v3f" &&
                 (vattr = header->findTypedAttribute<Imf::V3fAttribute> (name)))
            spec.attribute (oname, TypeDesc::TypeVector, &(vattr->value()));
        else if (type == "v2f" &&
                 (v2attr = header->findTypedAttribute<Imf::V2fAttribute> (name))) {
            TypeDesc v2 (TypeDesc::FLOAT,TypeDesc::VEC2);
            spec.attribute (oname, v2, &(v2attr->value()));
        }
        else {
#if 0
            std::cerr << "  unknown attribute " << type << ' ' << name << "\n";
#endif
        }
    }

    initialized = true;
}
Beispiel #6
0
bool
OpenEXRInput::open (const std::string &name, ImageSpec &newspec)
{
    // Quick check to reject non-exr files
    bool tiled;
    if (! Imf::isOpenExrFile (name.c_str(), tiled))
        return false;

    m_spec = ImageSpec(); // Clear everything with default constructor
    
    // Unless otherwise specified, exr files are assumed to be linear.
    m_spec.attribute ("oiio:ColorSpace", "Linear");
    
    try {
        if (tiled) {
            m_input_tiled = new Imf::TiledInputFile (name.c_str());
            m_header = &(m_input_tiled->header());
        } else {
            m_input_scanline = new Imf::InputFile (name.c_str());
            m_header = &(m_input_scanline->header());
        }
    }
    catch (const std::exception &e) {
        error ("OpenEXR exception: %s", e.what());
        return false;
    }
    if (! m_input_scanline && ! m_input_tiled) {
        error ("Unknown error opening EXR file");
        return false;
    }

    Imath::Box2i datawindow = m_header->dataWindow();
    m_spec.x = datawindow.min.x;
    m_spec.y = datawindow.min.y;
    m_spec.z = 0;
    m_spec.width = datawindow.max.x - datawindow.min.x + 1;
    m_spec.height = datawindow.max.y - datawindow.min.y + 1;
    m_spec.depth = 1;
    m_topwidth = m_spec.width;      // Save top-level mipmap dimensions
    m_topheight = m_spec.height;
    Imath::Box2i displaywindow = m_header->displayWindow();
    m_spec.full_x = displaywindow.min.x;
    m_spec.full_y = displaywindow.min.y;
    m_spec.full_z = 0;
    m_spec.full_width = displaywindow.max.x - displaywindow.min.x + 1;
    m_spec.full_height = displaywindow.max.y - displaywindow.min.y + 1;
    m_spec.full_depth = 1;
    if (tiled) {
        m_spec.tile_width = m_input_tiled->tileXSize();
        m_spec.tile_height = m_input_tiled->tileYSize();
    } else {
        m_spec.tile_width = 0;
        m_spec.tile_height = 0;
    }
    m_spec.tile_depth = 1;
    query_channels ();   // also sets format

    m_nsubimages = 1;
    if (tiled) {
        // FIXME: levelmode
        m_levelmode = m_input_tiled->levelMode();
        m_roundingmode = m_input_tiled->levelRoundingMode();
        if (m_levelmode == Imf::MIPMAP_LEVELS) {
            m_nmiplevels = m_input_tiled->numLevels();
            m_spec.attribute ("openexr:roundingmode", m_roundingmode);
        } else if (m_levelmode == Imf::RIPMAP_LEVELS) {
            m_nmiplevels = std::max (m_input_tiled->numXLevels(),
                                     m_input_tiled->numYLevels());
            m_spec.attribute ("openexr:roundingmode", m_roundingmode);
        } else {
            m_nmiplevels = 1;
        }
    } else {
        m_levelmode = Imf::ONE_LEVEL;
        m_nmiplevels = 1;
    }

    const Imf::EnvmapAttribute *envmap;
    envmap = m_header->findTypedAttribute<Imf::EnvmapAttribute>("envmap");
    if (envmap) {
        m_cubeface = (envmap->value() == Imf::ENVMAP_CUBE);
        m_spec.attribute ("textureformat", m_cubeface ? "CubeFace Environment" : "LatLong Environment");
        // OpenEXR conventions for env maps
        if (! m_cubeface)
            m_spec.attribute ("oiio:updirection", "y");
        m_spec.attribute ("oiio:sampleborder", 1);
        // FIXME - detect CubeFace Shadow?
    } else {
        m_cubeface = false;
        if (tiled && m_levelmode == Imf::MIPMAP_LEVELS)
            m_spec.attribute ("textureformat", "Plain Texture");
        // FIXME - detect Shadow
    }

    const Imf::CompressionAttribute *compressattr;
    compressattr = m_header->findTypedAttribute<Imf::CompressionAttribute>("compression");
    if (compressattr) {
        const char *comp = NULL;
        switch (compressattr->value()) {
        case Imf::NO_COMPRESSION    : comp = "none"; break;
        case Imf::RLE_COMPRESSION   : comp = "rle"; break;
        case Imf::ZIPS_COMPRESSION  : comp = "zip"; break;
        case Imf::ZIP_COMPRESSION   : comp = "zip"; break;
        case Imf::PIZ_COMPRESSION   : comp = "piz"; break;
        case Imf::PXR24_COMPRESSION : comp = "pxr24"; break;
#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.
        case Imf::B44_COMPRESSION   : comp = "b44"; break;
        case Imf::B44A_COMPRESSION  : comp = "b44a"; break;
#endif
        default:
            break;
        }
        if (comp)
            m_spec.attribute ("compression", comp);
    }

    for (Imf::Header::ConstIterator hit = m_header->begin();
             hit != m_header->end();  ++hit) {
        const Imf::IntAttribute *iattr;
        const Imf::FloatAttribute *fattr;
        const Imf::StringAttribute *sattr;
        const Imf::M44fAttribute *mattr;
        const Imf::V3fAttribute *vattr;        
        const char *name = hit.name();
        std::string oname = exr_tag_to_ooio_std[name];
        if (oname.empty())   // Empty string means skip this attrib
            continue;
//        if (oname == name)
//            oname = std::string(format_name()) + "_" + oname;
        const Imf::Attribute &attrib = hit.attribute();
        std::string type = attrib.typeName();
        if (type == "string" && 
            (sattr = m_header->findTypedAttribute<Imf::StringAttribute> (name)))
            m_spec.attribute (oname, sattr->value().c_str());
        else if (type == "int" && 
            (iattr = m_header->findTypedAttribute<Imf::IntAttribute> (name)))
            m_spec.attribute (oname, iattr->value());
        else if (type == "float" && 
            (fattr = m_header->findTypedAttribute<Imf::FloatAttribute> (name)))
            m_spec.attribute (oname, fattr->value());
        else if (type == "m44f" && 
            (mattr = m_header->findTypedAttribute<Imf::M44fAttribute> (name)))
            m_spec.attribute (oname, TypeDesc::TypeMatrix, &(mattr->value()));
        else if (type == "v3f" &&
                 (vattr = m_header->findTypedAttribute<Imf::V3fAttribute> (name)))
            m_spec.attribute (oname, TypeDesc::TypeVector, &(vattr->value()));
        else {
#if 0
            std::cerr << "  unknown attribute " << type << ' ' << name << "\n";
#endif
        }
    }

    m_subimage = 0;
    m_miplevel = 0;
    newspec = m_spec;
    return true;
}