Blame IlmImf/ImfTiledMisc.cpp

Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
//
Packit Service 6754ca
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
Packit Service 6754ca
// Digital Ltd. LLC
Packit Service 6754ca
// 
Packit Service 6754ca
// All rights reserved.
Packit Service 6754ca
// 
Packit Service 6754ca
// Redistribution and use in source and binary forms, with or without
Packit Service 6754ca
// modification, are permitted provided that the following conditions are
Packit Service 6754ca
// met:
Packit Service 6754ca
// *       Redistributions of source code must retain the above copyright
Packit Service 6754ca
// notice, this list of conditions and the following disclaimer.
Packit Service 6754ca
// *       Redistributions in binary form must reproduce the above
Packit Service 6754ca
// copyright notice, this list of conditions and the following disclaimer
Packit Service 6754ca
// in the documentation and/or other materials provided with the
Packit Service 6754ca
// distribution.
Packit Service 6754ca
// *       Neither the name of Industrial Light & Magic nor the names of
Packit Service 6754ca
// its contributors may be used to endorse or promote products derived
Packit Service 6754ca
// from this software without specific prior written permission. 
Packit Service 6754ca
// 
Packit Service 6754ca
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 6754ca
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit Service 6754ca
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit Service 6754ca
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit Service 6754ca
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit Service 6754ca
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 6754ca
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 6754ca
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 6754ca
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 6754ca
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 6754ca
//
Packit Service 6754ca
///////////////////////////////////////////////////////////////////////////
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
//
Packit Service 6754ca
//	Miscellaneous stuff related to tiled files
Packit Service 6754ca
//
Packit Service 6754ca
//-----------------------------------------------------------------------------
Packit Service 6754ca
Packit Service 6754ca
#include <ImfTiledMisc.h>
Packit Service 6754ca
#include "Iex.h"
Packit Service 6754ca
#include <ImfMisc.h>
Packit Service 6754ca
#include <ImfChannelList.h>
Packit Service 6754ca
#include <ImfTileDescription.h>
Packit Service 6754ca
#include <algorithm>
Packit Service 6754ca
Packit Service 6754ca
#include "ImfNamespace.h"
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit Service 6754ca
Packit Service 6754ca
using IMATH_NAMESPACE::Box2i;
Packit Service 6754ca
using IMATH_NAMESPACE::V2i;
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
levelSize (int min, int max, int l, LevelRoundingMode rmode)
Packit Service 6754ca
{
Packit Service 6754ca
    if (l < 0)
Packit Service 6754ca
	throw IEX_NAMESPACE::ArgExc ("Argument not in valid range.");
Packit Service 6754ca
Packit Service 6754ca
    int a = max - min + 1;
Packit Service 6754ca
    int b = (1 << l);
Packit Service 6754ca
    int size = a / b;
Packit Service 6754ca
Packit Service 6754ca
    if (rmode == ROUND_UP && size * b < a)
Packit Service 6754ca
	size += 1;
Packit Service 6754ca
Packit Service 6754ca
    return std::max (size, 1);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Box2i
Packit Service 6754ca
dataWindowForLevel (const TileDescription &tileDesc,
Packit Service 6754ca
		    int minX, int maxX,
Packit Service 6754ca
		    int minY, int maxY,
Packit Service 6754ca
		    int lx, int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    V2i levelMin = V2i (minX, minY);
Packit Service 6754ca
Packit Service 6754ca
    V2i levelMax = levelMin +
Packit Service 6754ca
		   V2i (levelSize (minX, maxX, lx, tileDesc.roundingMode) - 1,
Packit Service 6754ca
			levelSize (minY, maxY, ly, tileDesc.roundingMode) - 1);
Packit Service 6754ca
Packit Service 6754ca
    return Box2i(levelMin, levelMax);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
Box2i
Packit Service 6754ca
dataWindowForTile (const TileDescription &tileDesc,
Packit Service 6754ca
		   int minX, int maxX,
Packit Service 6754ca
		   int minY, int maxY,
Packit Service 6754ca
		   int dx, int dy,
Packit Service 6754ca
		   int lx, int ly)
Packit Service 6754ca
{
Packit Service 6754ca
    V2i tileMin = V2i (minX + dx * tileDesc.xSize,
Packit Service 6754ca
		       minY + dy * tileDesc.ySize);
Packit Service 6754ca
Packit Service 6754ca
    V2i tileMax = tileMin + V2i (tileDesc.xSize - 1, tileDesc.ySize - 1);
Packit Service 6754ca
Packit Service 6754ca
    V2i levelMax = dataWindowForLevel
Packit Service 6754ca
		       (tileDesc, minX, maxX, minY, maxY, lx, ly).max;
Packit Service 6754ca
Packit Service 6754ca
    tileMax = V2i (std::min (tileMax[0], levelMax[0]),
Packit Service 6754ca
		   std::min (tileMax[1], levelMax[1]));
Packit Service 6754ca
Packit Service 6754ca
    return Box2i (tileMin, tileMax);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
size_t
Packit Service 6754ca
calculateBytesPerPixel (const Header &header)
Packit Service 6754ca
{
Packit Service 6754ca
    const ChannelList &channels = header.channels();
Packit Service 6754ca
Packit Service 6754ca
    size_t bytesPerPixel = 0;
Packit Service 6754ca
Packit Service 6754ca
    for (ChannelList::ConstIterator c = channels.begin();
Packit Service 6754ca
	 c != channels.end();
Packit Service 6754ca
	 ++c)
Packit Service 6754ca
    {
Packit Service 6754ca
	bytesPerPixel += pixelTypeSize (c.channel().type);
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return bytesPerPixel;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
calculateBytesPerLine (const Header &header,
Packit Service 6754ca
                       char* sampleCountBase,
Packit Service 6754ca
                       int sampleCountXStride,
Packit Service 6754ca
                       int sampleCountYStride,
Packit Service 6754ca
                       int minX, int maxX,
Packit Service 6754ca
                       int minY, int maxY,
Packit Service 6754ca
                       std::vector<int>& xOffsets,
Packit Service 6754ca
                       std::vector<int>& yOffsets,
Packit Service 6754ca
                       std::vector<Int64>& bytesPerLine)
Packit Service 6754ca
{
Packit Service 6754ca
    const ChannelList &channels = header.channels();
Packit Service 6754ca
Packit Service 6754ca
    int pos = 0;
Packit Service 6754ca
    for (ChannelList::ConstIterator c = channels.begin();
Packit Service 6754ca
         c != channels.end();
Packit Service 6754ca
         ++c, ++pos)
Packit Service 6754ca
    {
Packit Service 6754ca
        int xOffset = xOffsets[pos];
Packit Service 6754ca
        int yOffset = yOffsets[pos];
Packit Service 6754ca
        int i = 0;
Packit Service 6754ca
        for (int y = minY - yOffset; y <= maxY - yOffset; y++, i++)
Packit Service 6754ca
            for (int x = minX - xOffset; x <= maxX - xOffset; x++)
Packit Service 6754ca
            {
Packit Service 6754ca
                bytesPerLine[i] += sampleCount(sampleCountBase,
Packit Service 6754ca
                                               sampleCountXStride,
Packit Service 6754ca
                                               sampleCountYStride,
Packit Service 6754ca
                                               x, y)
Packit Service 6754ca
                                   * pixelTypeSize (c.channel().type);
Packit Service 6754ca
            }
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
namespace {
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
floorLog2 (int x)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // For x > 0, floorLog2(y) returns floor(log(x)/log(2)).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int y = 0;
Packit Service 6754ca
Packit Service 6754ca
    while (x > 1)
Packit Service 6754ca
    {
Packit Service 6754ca
	y +=  1;
Packit Service 6754ca
	x >>= 1;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return y;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
ceilLog2 (int x)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // For x > 0, ceilLog2(y) returns ceil(log(x)/log(2)).
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int y = 0;
Packit Service 6754ca
    int r = 0;
Packit Service 6754ca
Packit Service 6754ca
    while (x > 1)
Packit Service 6754ca
    {
Packit Service 6754ca
	if (x & 1)
Packit Service 6754ca
	    r = 1;
Packit Service 6754ca
Packit Service 6754ca
	y +=  1;
Packit Service 6754ca
	x >>= 1;
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return y + r;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
roundLog2 (int x, LevelRoundingMode rmode)
Packit Service 6754ca
{
Packit Service 6754ca
    return (rmode == ROUND_DOWN)? floorLog2 (x): ceilLog2 (x);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
calculateNumXLevels (const TileDescription& tileDesc,
Packit Service 6754ca
		     int minX, int maxX,
Packit Service 6754ca
		     int minY, int maxY)
Packit Service 6754ca
{
Packit Service 6754ca
    int num = 0;
Packit Service 6754ca
Packit Service 6754ca
    switch (tileDesc.mode)
Packit Service 6754ca
    {
Packit Service 6754ca
      case ONE_LEVEL:
Packit Service 6754ca
Packit Service 6754ca
	num = 1;
Packit Service 6754ca
	break;
Packit Service 6754ca
Packit Service 6754ca
      case MIPMAP_LEVELS:
Packit Service 6754ca
Packit Service 6754ca
	{
Packit Service 6754ca
	  int w = maxX - minX + 1;
Packit Service 6754ca
	  int h = maxY - minY + 1;
Packit Service 6754ca
	  num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1;
Packit Service 6754ca
	}
Packit Service 6754ca
        break;
Packit Service 6754ca
Packit Service 6754ca
      case RIPMAP_LEVELS:
Packit Service 6754ca
Packit Service 6754ca
	{
Packit Service 6754ca
	  int w = maxX - minX + 1;
Packit Service 6754ca
	  num = roundLog2 (w, tileDesc.roundingMode) + 1;
Packit Service 6754ca
	}
Packit Service 6754ca
	break;
Packit Service 6754ca
Packit Service 6754ca
      default:
Packit Service 6754ca
Packit Service 6754ca
	throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format.");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return num;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
calculateNumYLevels (const TileDescription& tileDesc,
Packit Service 6754ca
		     int minX, int maxX,
Packit Service 6754ca
		     int minY, int maxY)
Packit Service 6754ca
{
Packit Service 6754ca
    int num = 0;
Packit Service 6754ca
Packit Service 6754ca
    switch (tileDesc.mode)
Packit Service 6754ca
    {
Packit Service 6754ca
      case ONE_LEVEL:
Packit Service 6754ca
Packit Service 6754ca
	num = 1;
Packit Service 6754ca
	break;
Packit Service 6754ca
Packit Service 6754ca
      case MIPMAP_LEVELS:
Packit Service 6754ca
Packit Service 6754ca
	{
Packit Service 6754ca
	  int w = maxX - minX + 1;
Packit Service 6754ca
	  int h = maxY - minY + 1;
Packit Service 6754ca
	  num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1;
Packit Service 6754ca
	}
Packit Service 6754ca
        break;
Packit Service 6754ca
Packit Service 6754ca
      case RIPMAP_LEVELS:
Packit Service 6754ca
Packit Service 6754ca
	{
Packit Service 6754ca
	  int h = maxY - minY + 1;
Packit Service 6754ca
	  num = roundLog2 (h, tileDesc.roundingMode) + 1;
Packit Service 6754ca
	}
Packit Service 6754ca
	break;
Packit Service 6754ca
Packit Service 6754ca
      default:
Packit Service 6754ca
Packit Service 6754ca
	throw IEX_NAMESPACE::ArgExc ("Unknown LevelMode format.");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    return num;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
calculateNumTiles (int *numTiles,
Packit Service 6754ca
		   int numLevels,
Packit Service 6754ca
		   int min, int max,
Packit Service 6754ca
		   int size,
Packit Service 6754ca
		   LevelRoundingMode rmode)
Packit Service 6754ca
{
Packit Service 6754ca
    for (int i = 0; i < numLevels; i++)
Packit Service 6754ca
    {
Packit Service 6754ca
	numTiles[i] = (levelSize (min, max, i, rmode) + size - 1) / size;
Packit Service 6754ca
    }
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
} // namespace
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
void
Packit Service 6754ca
precalculateTileInfo (const TileDescription& tileDesc,
Packit Service 6754ca
		      int minX, int maxX,
Packit Service 6754ca
		      int minY, int maxY,
Packit Service 6754ca
		      int *&numXTiles, int *&numYTiles,
Packit Service 6754ca
		      int &numXLevels, int &numYLevels)
Packit Service 6754ca
{
Packit Service 6754ca
    numXLevels = calculateNumXLevels(tileDesc, minX, maxX, minY, maxY);
Packit Service 6754ca
    numYLevels = calculateNumYLevels(tileDesc, minX, maxX, minY, maxY);
Packit Service 6754ca
    
Packit Service 6754ca
    numXTiles = new int[numXLevels];
Packit Service 6754ca
    numYTiles = new int[numYLevels];
Packit Service 6754ca
Packit Service 6754ca
    calculateNumTiles (numXTiles,
Packit Service 6754ca
		       numXLevels,
Packit Service 6754ca
		       minX, maxX,
Packit Service 6754ca
		       tileDesc.xSize,
Packit Service 6754ca
		       tileDesc.roundingMode);
Packit Service 6754ca
Packit Service 6754ca
    calculateNumTiles (numYTiles,
Packit Service 6754ca
		       numYLevels,
Packit Service 6754ca
		       minY, maxY,
Packit Service 6754ca
		       tileDesc.ySize,
Packit Service 6754ca
		       tileDesc.roundingMode);
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
int
Packit Service 6754ca
getTiledChunkOffsetTableSize(const Header& header)
Packit Service 6754ca
{
Packit Service 6754ca
    //
Packit Service 6754ca
    // Save the dataWindow information
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    const Box2i &dataWindow = header.dataWindow();
Packit Service 6754ca
    
Packit Service 6754ca
    //
Packit Service 6754ca
    // Precompute level and tile information.
Packit Service 6754ca
    //
Packit Service 6754ca
Packit Service 6754ca
    int* numXTiles;
Packit Service 6754ca
    int* numYTiles;
Packit Service 6754ca
    int numXLevels;
Packit Service 6754ca
    int numYLevels;
Packit Service 6754ca
    precalculateTileInfo (header.tileDescription(),
Packit Service 6754ca
                          dataWindow.min.x, dataWindow.max.x,
Packit Service 6754ca
                          dataWindow.min.y, dataWindow.max.y,
Packit Service 6754ca
                          numXTiles, numYTiles,
Packit Service 6754ca
                          numXLevels, numYLevels);
Packit Service 6754ca
Packit Service 6754ca
    //
Packit Service 6754ca
    // Calculate lineOffsetSize.
Packit Service 6754ca
    //
Packit Service 6754ca
    int lineOffsetSize = 0;
Packit Service 6754ca
    const TileDescription &desc = header.tileDescription();
Packit Service 6754ca
    switch (desc.mode)
Packit Service 6754ca
    {
Packit Service 6754ca
        case ONE_LEVEL:
Packit Service 6754ca
        case MIPMAP_LEVELS:
Packit Service 6754ca
            for (int i = 0; i < numXLevels; i++)
Packit Service 6754ca
                lineOffsetSize += numXTiles[i] * numYTiles[i];
Packit Service 6754ca
            break;
Packit Service 6754ca
        case RIPMAP_LEVELS:
Packit Service 6754ca
            for (int i = 0; i < numXLevels; i++)
Packit Service 6754ca
                for (int j = 0; j < numYLevels; j++)
Packit Service 6754ca
                    lineOffsetSize += numXTiles[i] * numYTiles[j];
Packit Service 6754ca
            break;
Packit Service 6754ca
        case NUM_LEVELMODES :
Packit Service 6754ca
            throw IEX_NAMESPACE::LogicExc("Bad level mode getting chunk offset table size");
Packit Service 6754ca
    }
Packit Service 6754ca
Packit Service 6754ca
    delete[] numXTiles;
Packit Service 6754ca
    delete[] numYTiles;
Packit Service 6754ca
Packit Service 6754ca
    return lineOffsetSize;
Packit Service 6754ca
}
Packit Service 6754ca
Packit Service 6754ca
Packit Service 6754ca
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT