PageRenderTime 42ms CodeModel.GetById 2ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/OpenEXR/IlmImf/ImfTileOffsets.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 385 lines | 222 code | 84 blank | 79 comment | 36 complexity | e1df6fb95e4d04407c8481a0f3d30203 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////
  2//
  3// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
  4// Digital Ltd. LLC
  5// 
  6// All rights reserved.
  7// 
  8// Redistribution and use in source and binary forms, with or without
  9// modification, are permitted provided that the following conditions are
 10// met:
 11// *       Redistributions of source code must retain the above copyright
 12// notice, this list of conditions and the following disclaimer.
 13// *       Redistributions in binary form must reproduce the above
 14// copyright notice, this list of conditions and the following disclaimer
 15// in the documentation and/or other materials provided with the
 16// distribution.
 17// *       Neither the name of Industrial Light & Magic nor the names of
 18// its contributors may be used to endorse or promote products derived
 19// from this software without specific prior written permission. 
 20// 
 21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32//
 33///////////////////////////////////////////////////////////////////////////
 34
 35
 36//-----------------------------------------------------------------------------
 37//
 38//	class TileOffsets
 39//
 40//-----------------------------------------------------------------------------
 41
 42#include <ImfTileOffsets.h>
 43#include <ImfXdr.h>
 44#include <ImfIO.h>
 45#include "Iex.h"
 46
 47namespace Imf {
 48
 49
 50TileOffsets::TileOffsets (LevelMode mode,
 51			  int numXLevels, int numYLevels,
 52			  const int *numXTiles, const int *numYTiles)
 53:
 54    _mode (mode),
 55    _numXLevels (numXLevels),
 56    _numYLevels (numYLevels)
 57{
 58    switch (_mode)
 59    {
 60      case ONE_LEVEL:
 61      case MIPMAP_LEVELS:
 62
 63        _offsets.resize (_numXLevels);
 64
 65        for (unsigned int l = 0; l < _offsets.size(); ++l)
 66        {
 67            _offsets[l].resize (numYTiles[l]);
 68
 69            for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
 70	    {
 71                _offsets[l][dy].resize (numXTiles[l]);
 72            }
 73        }
 74        break;
 75
 76      case RIPMAP_LEVELS:
 77
 78        _offsets.resize (_numXLevels * _numYLevels);
 79
 80        for (unsigned int ly = 0; ly < _numYLevels; ++ly)
 81        {
 82            for (unsigned int lx = 0; lx < _numXLevels; ++lx)
 83            {
 84                int l = ly * _numXLevels + lx;
 85                _offsets[l].resize (numYTiles[ly]);
 86
 87                for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
 88                {
 89                    _offsets[l][dy].resize (numXTiles[lx]);
 90                }
 91            }
 92        }
 93        break;
 94    }
 95}
 96
 97
 98bool
 99TileOffsets::anyOffsetsAreInvalid () const
100{
101    for (unsigned int l = 0; l < _offsets.size(); ++l)
102	for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
103	    for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
104		if (_offsets[l][dy][dx] <= 0)
105		    return true;
106    
107    return false;
108}
109
110
111void
112TileOffsets::findTiles (IStream &is)
113{
114    for (unsigned int l = 0; l < _offsets.size(); ++l)
115    {
116	for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
117	{
118	    for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
119	    {
120		Int64 tileOffset = is.tellg();
121
122		int tileX;
123		Xdr::read <StreamIO> (is, tileX);
124
125		int tileY;
126		Xdr::read <StreamIO> (is, tileY);
127
128		int levelX;
129		Xdr::read <StreamIO> (is, levelX);
130
131		int levelY;
132		Xdr::read <StreamIO> (is, levelY);
133
134		int dataSize;
135		Xdr::read <StreamIO> (is, dataSize);
136
137		Xdr::skip <StreamIO> (is, dataSize);
138
139		if (!isValidTile(tileX, tileY, levelX, levelY))
140		    return;
141
142		operator () (tileX, tileY, levelX, levelY) = tileOffset;
143	    }
144	}
145    }
146}
147
148
149void
150TileOffsets::reconstructFromFile (IStream &is)
151{
152    //
153    // Try to reconstruct a missing tile offset table by sequentially
154    // scanning through the file, and recording the offsets in the file
155    // of the tiles we find.
156    //
157
158    Int64 position = is.tellg();
159
160    try
161    {
162	findTiles (is);
163    }
164    catch (...)
165    {
166        //
167        // Suppress all exceptions.  This function is called only to
168	// reconstruct the tile offset table for incomplete files,
169	// and exceptions are likely.
170        //
171    }
172
173    is.clear();
174    is.seekg (position);
175}
176
177
178void
179TileOffsets::readFrom (IStream &is, bool &complete)
180{
181    //
182    // Read in the tile offsets from the file's tile offset table
183    //
184
185    for (unsigned int l = 0; l < _offsets.size(); ++l)
186	for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
187	    for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
188		Xdr::read <StreamIO> (is, _offsets[l][dy][dx]);
189
190    //
191    // Check if any tile offsets are invalid.
192    //
193    // Invalid offsets mean that the file is probably incomplete
194    // (the offset table is the last thing written to the file).
195    // Either some process is still busy writing the file, or
196    // writing the file was aborted.
197    //
198    // We should still be able to read the existing parts of the
199    // file.  In order to do this, we have to make a sequential
200    // scan over the scan tile to reconstruct the tile offset
201    // table.
202    //
203
204    if (anyOffsetsAreInvalid())
205    {
206	complete = false;
207	reconstructFromFile (is);
208    }
209    else
210    {
211	complete = true;
212    }
213
214}
215
216
217Int64
218TileOffsets::writeTo (OStream &os) const
219{
220    //
221    // Write the tile offset table to the file, and
222    // return the position of the start of the table
223    // in the file.
224    //
225    
226    Int64 pos = os.tellp();
227
228    if (pos == -1)
229	Iex::throwErrnoExc ("Cannot determine current file position (%T).");
230
231    for (unsigned int l = 0; l < _offsets.size(); ++l)
232	for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
233	    for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
234		Xdr::write <StreamIO> (os, _offsets[l][dy][dx]);
235
236    return pos;
237}
238
239
240bool
241TileOffsets::isEmpty () const
242{
243    for (unsigned int l = 0; l < _offsets.size(); ++l)
244	for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
245	    for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
246		if (_offsets[l][dy][dx] != 0)
247		    return false;
248    return true;
249}
250
251
252bool
253TileOffsets::isValidTile (int dx, int dy, int lx, int ly) const
254{
255    switch (_mode)
256    {
257      case ONE_LEVEL:
258
259        if (lx == 0 &&
260	    ly == 0 &&
261	    _offsets.size() > 0 &&
262            _offsets[0].size() > dy &&
263            _offsets[0][dy].size() > dx)
264	{
265            return true;
266	}
267
268        break;
269
270      case MIPMAP_LEVELS:
271
272        if (lx < _numXLevels &&
273	    ly < _numYLevels &&
274            _offsets.size() > lx &&
275            _offsets[lx].size() > dy &&
276            _offsets[lx][dy].size() > dx)
277	{
278            return true;
279	}
280
281        break;
282
283      case RIPMAP_LEVELS:
284
285        if (lx < _numXLevels &&
286	    ly < _numYLevels &&
287            _offsets.size() > lx + ly * _numXLevels &&
288            _offsets[lx + ly * _numXLevels].size() > dy &&
289            _offsets[lx + ly * _numXLevels][dy].size() > dx)
290	{
291            return true;
292	}
293
294        break;
295
296      default:
297
298        return false;
299    }
300    
301    return false;
302}
303
304
305Int64 &
306TileOffsets::operator () (int dx, int dy, int lx, int ly)
307{
308    //
309    // Looks up the value of the tile with tile coordinate (dx, dy)
310    // and level number (lx, ly) in the _offsets array, and returns
311    // the cooresponding offset.
312    //
313
314    switch (_mode)
315    {
316      case ONE_LEVEL:
317
318        return _offsets[0][dy][dx];
319        break;
320
321      case MIPMAP_LEVELS:
322
323        return _offsets[lx][dy][dx];
324        break;
325
326      case RIPMAP_LEVELS:
327
328        return _offsets[lx + ly * _numXLevels][dy][dx];
329        break;
330
331      default:
332
333        throw Iex::ArgExc ("Unknown LevelMode format.");
334    }
335}
336
337
338Int64 &
339TileOffsets::operator () (int dx, int dy, int l)
340{
341    return operator () (dx, dy, l, l);
342}
343
344
345const Int64 &
346TileOffsets::operator () (int dx, int dy, int lx, int ly) const
347{
348    //
349    // Looks up the value of the tile with tile coordinate (dx, dy)
350    // and level number (lx, ly) in the _offsets array, and returns
351    // the cooresponding offset.
352    //
353
354    switch (_mode)
355    {
356      case ONE_LEVEL:
357
358        return _offsets[0][dy][dx];
359        break;
360
361      case MIPMAP_LEVELS:
362
363        return _offsets[lx][dy][dx];
364        break;
365
366      case RIPMAP_LEVELS:
367
368        return _offsets[lx + ly * _numXLevels][dy][dx];
369        break;
370
371      default:
372
373        throw Iex::ArgExc ("Unknown LevelMode format.");
374    }
375}
376
377
378const Int64 &
379TileOffsets::operator () (int dx, int dy, int l) const
380{
381    return operator () (dx, dy, l, l);
382}
383
384
385} // namespace Imf