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