⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imfheader.cpp

📁 对gif
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}


const PreviewImage &
Header::previewImage () const
{
    return typedAttribute <PreviewImageAttribute> ("preview").value();
}


bool		
Header::hasPreviewImage () const
{
    return findTypedAttribute <PreviewImageAttribute> ("preview") != 0;
}


void		
Header::sanityCheck (bool isTiled) const
{
    //
    // The display window and the data window must each
    // contain at least one pixel.  In addition, the
    // coordinates of the window corners must be small
    // enough to keep expressions like max-min+1 or
    // max+min from overflowing.
    //

    const Box2i &displayWindow = this->displayWindow();

    if (displayWindow.min.x > displayWindow.max.x ||
	displayWindow.min.y > displayWindow.max.y ||
	displayWindow.min.x <= -(INT_MAX / 2) ||
	displayWindow.min.y <= -(INT_MAX / 2) ||
	displayWindow.max.x >=  (INT_MAX / 2) ||
	displayWindow.max.y >=  (INT_MAX / 2))
    {
	throw Iex::ArgExc ("Invalid display window in image header.");
    }

    const Box2i &dataWindow = this->dataWindow();

    if (dataWindow.min.x > dataWindow.max.x ||
	dataWindow.min.y > dataWindow.max.y ||
	dataWindow.min.x <= -(INT_MAX / 2) ||
	dataWindow.min.y <= -(INT_MAX / 2) ||
	dataWindow.max.x >=  (INT_MAX / 2) ||
	dataWindow.max.y >=  (INT_MAX / 2))
    {
	throw Iex::ArgExc ("Invalid data window in image header.");
    }

    if (maxImageWidth > 0 &&
	maxImageWidth < dataWindow.max.x - dataWindow.min.x + 1)
    {
	THROW (Iex::ArgExc, "The width of the data window exceeds the "
			    "maximum width of " << maxImageWidth << "pixels.");
    }

    if (maxImageHeight > 0 &&
	maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1)
    {
	THROW (Iex::ArgExc, "The width of the data window exceeds the "
			    "maximum width of " << maxImageHeight << "pixels.");
    }

    //
    // The pixel aspect ratio must be greater than 0.
    // In applications, numbers like the the display or
    // data window dimensions are likely to be multiplied
    // or divided by the pixel aspect ratio; to avoid
    // arithmetic exceptions, we limit the pixel aspect
    // ratio to a range that is smaller than theoretically
    // possible (real aspect ratios are likely to be close
    // to 1.0 anyway).
    //

    float pixelAspectRatio = this->pixelAspectRatio();

    const float MIN_PIXEL_ASPECT_RATIO = 1e-6;
    const float MAX_PIXEL_ASPECT_RATIO = 1e+6;

    if (pixelAspectRatio < MIN_PIXEL_ASPECT_RATIO ||
	pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO)
    {
	throw Iex::ArgExc ("Invalid pixel aspect ratio in image header.");
    }

    //
    // The screen window width must not be less than 0.
    // The size of the screen window can vary over a wide
    // range (fish-eye lens to astronomical telescope),
    // so we can't limit the screen window width to a
    // small range.
    //

    float screenWindowWidth = this->screenWindowWidth();

    if (screenWindowWidth < 0)
	throw Iex::ArgExc ("Invalid screen window width in image header.");

    //
    // If the file is tiled, verify that the tile description has resonable
    // values and check to see if the lineOrder is one of the predefined 3.
    // If the file is not tiled, then the lineOrder can only be INCREASING_Y
    // or DECREASING_Y.
    //

    LineOrder lineOrder = this->lineOrder();

    if (isTiled)
    {
	if (!hasTileDescription())
	{
	    throw Iex::ArgExc ("Tiled image has no tile "
			       "description attribute.");
	}

	const TileDescription &tileDesc = tileDescription();

	if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0)
	    throw Iex::ArgExc ("Invalid tile size in image header.");

	if (maxTileWidth > 0 &&
	    maxTileWidth < tileDesc.xSize)
	{
	    THROW (Iex::ArgExc, "The width of the tiles exceeds the maximum "
				"width of " << maxTileWidth << "pixels.");
	}

	if (maxTileHeight > 0 &&
	    maxTileHeight < tileDesc.ySize)
	{
	    THROW (Iex::ArgExc, "The width of the tiles exceeds the maximum "
				"width of " << maxTileHeight << "pixels.");
	}

	if (tileDesc.mode != ONE_LEVEL &&
	    tileDesc.mode != MIPMAP_LEVELS &&
	    tileDesc.mode != RIPMAP_LEVELS)
	    throw Iex::ArgExc ("Invalid level mode in image header.");

	if (tileDesc.roundingMode != ROUND_UP &&
	    tileDesc.roundingMode != ROUND_DOWN)
	    throw Iex::ArgExc ("Invalid level rounding mode in image header.");

	if (lineOrder != INCREASING_Y &&
	    lineOrder != DECREASING_Y &&
	    lineOrder != RANDOM_Y)
	    throw Iex::ArgExc ("Invalid line order in image header.");
    }
    else
    {
	if (lineOrder != INCREASING_Y &&
	    lineOrder != DECREASING_Y)
	    throw Iex::ArgExc ("Invalid line order in image header.");
    }

    //
    // The compression method must be one of the predefined values.
    //

    if (!isValidCompression (this->compression()))
	throw Iex::ArgExc ("Unknown compression type in image header.");

    //
    // Check the channel list:
    //
    // If the file is tiled then for each channel, the type must be one of the
    // predefined values, and the x and y sampling must both be 1.
    //
    // If the file is not tiled then for each channel, the type must be one
    // of the predefined values, the x and y coordinates of the data window's
    // upper left corner must be divisible by the x and y subsampling factors,
    // and the width and height of the data window must be divisible by the
    // x and y subsampling factors.
    //

    const ChannelList &channels = this->channels();
    
    if (isTiled)
    {
	for (ChannelList::ConstIterator i = channels.begin();
	     i != channels.end();
	     ++i)
	{
	    if (i.channel().type != UINT &&
		i.channel().type != HALF &&
		i.channel().type != FLOAT)
	    {
		THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" "
			            "image channel is invalid.");
	    }

	    if (i.channel().xSampling != 1)
	    {
		THROW (Iex::ArgExc, "The x subsampling factor for the "
				    "\"" << i.name() << "\" channel "
				    "is not 1.");
	    }	

	    if (i.channel().ySampling != 1)
	    {
		THROW (Iex::ArgExc, "The y subsampling factor for the "
				    "\"" << i.name() << "\" channel "
				    "is not 1.");
	    }	
	}
    }
    else
    {
	for (ChannelList::ConstIterator i = channels.begin();
	     i != channels.end();
	     ++i)
	{
	    if (i.channel().type != UINT &&
		i.channel().type != HALF &&
		i.channel().type != FLOAT)
	    {
		THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" "
			            "image channel is invalid.");
	    }

	    if (i.channel().xSampling < 1)
	    {
		THROW (Iex::ArgExc, "The x subsampling factor for the "
				    "\"" << i.name() << "\" channel "
				    "is invalid.");
	    }

	    if (i.channel().ySampling < 1)
	    {
		THROW (Iex::ArgExc, "The y subsampling factor for the "
				    "\"" << i.name() << "\" channel "
				    "is invalid.");
	    }

	    if (dataWindow.min.x % i.channel().xSampling)
	    {
		THROW (Iex::ArgExc, "The minimum x coordinate of the "
				    "image's data window is not a multiple "
				    "of the x subsampling factor of "
				    "the \"" << i.name() << "\" channel.");
	    }

	    if (dataWindow.min.y % i.channel().ySampling)
	    {
		THROW (Iex::ArgExc, "The minimum y coordinate of the "
				    "image's data window is not a multiple "
				    "of the y subsampling factor of "
				    "the \"" << i.name() << "\" channel.");
	    }

	    if ((dataWindow.max.x - dataWindow.min.x + 1) %
		    i.channel().xSampling)
	    {
		THROW (Iex::ArgExc, "Number of pixels per row in the "
				    "image's data window is not a multiple "
				    "of the x subsampling factor of "
				    "the \"" << i.name() << "\" channel.");
	    }

	    if ((dataWindow.max.y - dataWindow.min.y + 1) %
		    i.channel().ySampling)
	    {
		THROW (Iex::ArgExc, "Number of pixels per column in the "
				    "image's data window is not a multiple "
				    "of the y subsampling factor of "
				    "the \"" << i.name() << "\" channel.");
	    }
	}
    }
}


void		
Header::setMaxImageSize (int maxWidth, int maxHeight)
{
    maxImageWidth = maxWidth;
    maxImageHeight = maxHeight;
}


void		
Header::setMaxTileSize (int maxWidth, int maxHeight)
{
    maxTileWidth = maxWidth;
    maxTileHeight = maxHeight;
}


Int64
Header::writeTo (OStream &os, bool isTiled) const
{
    //
    // Write a "magic number" to identify the file as an image file.
    // Write the current file format version number.
    //

    Xdr::write <StreamIO> (os, MAGIC);

    int version = isTiled ? makeTiled (EXR_VERSION) : EXR_VERSION;
    Xdr::write <StreamIO> (os, version);

    //
    // Write all attributes.  If we have a preview image attribute,
    // keep track of its position in the file.
    //

    Int64 previewPosition = 0;

    const Attribute *preview =
	    findTypedAttribute <PreviewImageAttribute> ("preview");

    for (ConstIterator i = begin(); i != end(); ++i)
    {
	//
	// Write the attribute's name and type.
	//

	Xdr::write <StreamIO> (os, i.name());
	Xdr::write <StreamIO> (os, i.attribute().typeName());

	//
	// Write the size of the attribute value,
	// and the value itself.
	//

	StdOSStream oss;
	i.attribute().writeValueTo (oss, version);

	std::string s = oss.str();
	Xdr::write <StreamIO> (os, (int) s.length());

	if (&i.attribute() == preview)
	    previewPosition = os.tellp();

	os.write (s.data(), s.length());
    }

    //
    // Write zero-length attribute name to mark the end of the header.
    //

    Xdr::write <StreamIO> (os, "");

    return previewPosition;
}


void
Header::readFrom (IStream &is, int &version)
{
    //
    // Read the magic number and the file format version number.
    // Then check if we can read the rest of this file.
    //

    int magic;

    Xdr::read <StreamIO> (is, magic);
    Xdr::read <StreamIO> (is, version);

    if (magic != MAGIC)
    {
	throw Iex::InputExc ("File is not an image file.");
    }

    if (getVersion (version) != EXR_VERSION)
    {
	THROW (Iex::InputExc, "Cannot read "
			      "version " << getVersion (version) << " "
			      "image files.  Current file format version "
			      "is " << EXR_VERSION << ".");
    }
    
    if (!supportsFlags (getFlags (version)))
    {
	THROW (Iex::InputExc, "The file format version number's flag field "
			      "contains unrecognized flags.");
    }

    //
    // Read all attributes.
    //

    while (true)
    {
	//
	// Read the name of the attribute.
	// A zero-length attribute name indicates the end of the header.
	//

	char name[100];
	Xdr::read <StreamIO> (is, sizeof (name), name);

	if (name[0] == 0)
	    break;

	//
	// Read the attribute type and the size of the attribute value.
	//

	char typeName[100];
	int size;

	Xdr::read <StreamIO> (is, sizeof (typeName), typeName);
	Xdr::read <StreamIO> (is, size);

	AttributeMap::iterator i = _map.find (name);

	if (i != _map.end())
	{
	    //
	    // The attribute already exists (for example,
	    // because it is a predefined attribute).
	    // Read the attribute's new value from the file.
	    //

	    if (strncmp (i->second->typeName(), typeName, sizeof (typeName)))
		THROW (Iex::InputExc, "Unexpected type for image attribute "
				      "\"" << name << "\".");

	    i->second->readValueFrom (is, size, version);
	}
	else
	{
	    //
	    // The new attribute does not exist yet.
	    // If the attribute type is of a known type,
	    // read the attribute value.  If the attribute
	    // is of an unknown type, read its value and
	    // store it as an OpaqueAttribute.
	    //

	    Attribute *attr;

	    if (Attribute::knownType (typeName))
		attr = Attribute::newAttribute (typeName);
	    else
		attr = new OpaqueAttribute (typeName);

	    try
	    {
		attr->readValueFrom (is, size, version);
		_map[name] = attr;
	    }
	    catch (...)
	    {
		delete attr;
		throw;
	    }
	}
    }
}


void
staticInitialize ()
{
    static Mutex criticalSection;
    Lock lock (criticalSection);

    static bool initialized = false;

    if (!initialized)
    {
	//
	// One-time initialization -- register
	// some predefined attribute types.
	//
	
	Box2fAttribute::registerAttributeType();
	Box2iAttribute::registerAttributeType();
	ChannelListAttribute::registerAttributeType();
	CompressionAttribute::registerAttributeType();
	ChromaticitiesAttribute::registerAttributeType();
	DoubleAttribute::registerAttributeType();
	EnvmapAttribute::registerAttributeType();
	FloatAttribute::registerAttributeType();
	IntAttribute::registerAttributeType();
	KeyCodeAttribute::registerAttributeType();
	LineOrderAttribute::registerAttributeType();
	M33fAttribute::registerAttributeType();
	M44fAttribute::registerAttributeType();
	PreviewImageAttribute::registerAttributeType();
	RationalAttribute::registerAttributeType();
	StringAttribute::registerAttributeType();
	TileDescriptionAttribute::registerAttributeType();
	TimeCodeAttribute::registerAttributeType();
	V2fAttribute::registerAttributeType();
	V2iAttribute::registerAttributeType();
	V3fAttribute::registerAttributeType();
	V3iAttribute::registerAttributeType();

	initialized = true;
    }
}


} // namespace Imf

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -