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#ifndef INCLUDED_IMF_TILED_OUTPUT_FILE_H
37#define INCLUDED_IMF_TILED_OUTPUT_FILE_H
38
39//-----------------------------------------------------------------------------
40//
41//	class TiledOutputFile
42//
43//-----------------------------------------------------------------------------
44
45#include <ImfHeader.h>
46#include <ImfFrameBuffer.h>
47#include "ImathBox.h"
48#include <ImfTileDescription.h>
49#include <ImfThreading.h>
50
51namespace Imf {
52
53class TiledInputFile;
54class InputFile;
55struct PreviewRgba;
56
57
58class TiledOutputFile
59{
60  public:
61
62    //-------------------------------------------------------------------
63    // A constructor that opens the file with the specified name, and
64    // writes the file header.  The file header is also copied into the
65    // TiledOutputFile object, and can later be accessed via the header()
66    // method.
67    //
68    // Destroying TiledOutputFile constructed with this constructor
69    // automatically closes the corresponding files.
70    //
71    // The header must contain a TileDescriptionAttribute called "tiles".
72    //
73    // The x and y subsampling factors for all image channels must be 1;
74    // subsampling is not supported.
75    //
76    // Tiles can be written to the file in arbitrary order.  The line
77    // order attribute can be used to cause the tiles to be sorted in
78    // the file.  When the file is read later, reading the tiles in the
79    // same order as they are in the file tends to be significantly
80    // faster than reading the tiles in random order (see writeTile,
81    // below).
82    //-------------------------------------------------------------------
83
84    TiledOutputFile (const char fileName[],
85		     const Header &header,
86                     int numThreads = globalThreadCount ());
87
88
89    // ----------------------------------------------------------------
90    // A constructor that attaches the new TiledOutputFile object to
91    // a file that has already been opened.  Destroying TiledOutputFile
92    // objects constructed with this constructor does not automatically
93    // close the corresponding files.
94    // ----------------------------------------------------------------
95
96    TiledOutputFile (OStream &os,
97		     const Header &header,
98                     int numThreads = globalThreadCount ());
99
100
101    //-----------------------------------------------------
102    // Destructor
103    //
104    // Destroying a TiledOutputFile object before all tiles
105    // have been written results in an incomplete file.
106    //-----------------------------------------------------
107
108    virtual ~TiledOutputFile ();
109
110
111    //------------------------
112    // Access to the file name
113    //------------------------
114
115    const char *	fileName () const;
116
117
118    //--------------------------
119    // Access to the file header
120    //--------------------------
121
122    const Header &	header () const;
123
124
125    //-------------------------------------------------------
126    // Set the current frame buffer -- copies the FrameBuffer
127    // object into the TiledOutputFile object.
128    //
129    // The current frame buffer is the source of the pixel
130    // data written to the file.  The current frame buffer
131    // must be set at least once before writeTile() is
132    // called.  The current frame buffer can be changed
133    // after each call to writeTile().
134    //-------------------------------------------------------
135
136    void		setFrameBuffer (const FrameBuffer &frameBuffer);
137
138
139    //-----------------------------------
140    // Access to the current frame buffer
141    //-----------------------------------
142
143    const FrameBuffer &	frameBuffer () const;
144
145
146    //-------------------
147    // Utility functions:
148    //-------------------
149
150    //---------------------------------------------------------
151    // Multiresolution mode and tile size:
152    // The following functions return the xSize, ySize and mode
153    // fields of the file header's TileDescriptionAttribute.
154    //---------------------------------------------------------
155
156    unsigned int	tileXSize () const;
157    unsigned int	tileYSize () const;
158    LevelMode		levelMode () const;
159    LevelRoundingMode	levelRoundingMode () const;
160
161
162    //--------------------------------------------------------------------
163    // Number of levels:
164    //
165    // numXLevels() returns the file's number of levels in x direction.
166    //
167    //	if levelMode() == ONE_LEVEL:
168    //      return value is: 1
169    //
170    //	if levelMode() == MIPMAP_LEVELS:
171    //      return value is: rfunc (log (max (w, h)) / log (2)) + 1
172    //
173    //	if levelMode() == RIPMAP_LEVELS:
174    //      return value is: rfunc (log (w) / log (2)) + 1
175    //
176    //	where
177    //	    w is the width of the image's data window,  max.x - min.x + 1,
178    //	    y is the height of the image's data window, max.y - min.y + 1,
179    //	    and rfunc(x) is either floor(x), or ceil(x), depending on
180    //	    whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP.
181    //
182    // numYLevels() returns the file's number of levels in y direction.
183    //
184    //	if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
185    //      return value is the same as for numXLevels()
186    //
187    //	if levelMode() == RIPMAP_LEVELS:
188    //      return value is: rfunc (log (h) / log (2)) + 1
189    //
190    //
191    // numLevels() is a convenience function for use with MIPMAP_LEVELS
192    // files.
193    //
194    //	if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
195    //      return value is the same as for numXLevels()
196    //
197    //	if levelMode() == RIPMAP_LEVELS:
198    //      an Iex::LogicExc exception is thrown
199    //
200    // isValidLevel(lx, ly) returns true if the file contains
201    // a level with level number (lx, ly), false if not.
202    //
203    //--------------------------------------------------------------------
204
205    int			numLevels () const;
206    int			numXLevels () const;
207    int			numYLevels () const;
208    bool		isValidLevel (int lx, int ly) const;
209
210
211    //---------------------------------------------------------
212    // Dimensions of a level:
213    //
214    // levelWidth(lx) returns the width of a level with level
215    // number (lx, *), where * is any number.
216    //
217    //	return value is:
218    //      max (1, rfunc (w / pow (2, lx)))
219    //
220    //
221    // levelHeight(ly) returns the height of a level with level
222    // number (*, ly), where * is any number.
223    //
224    //	return value is:
225    //      max (1, rfunc (h / pow (2, ly)))
226    //
227    //---------------------------------------------------------
228
229    int			levelWidth  (int lx) const;
230    int			levelHeight (int ly) const;
231
232
233    //----------------------------------------------------------
234    // Number of tiles:
235    //
236    // numXTiles(lx) returns the number of tiles in x direction
237    // that cover a level with level number (lx, *), where * is
238    // any number.
239    //
240    //	return value is:
241    //      (levelWidth(lx) + tileXSize() - 1) / tileXSize()
242    //
243    //
244    // numYTiles(ly) returns the number of tiles in y direction
245    // that cover a level with level number (*, ly), where * is
246    // any number.
247    //
248    //	return value is:
249    //      (levelHeight(ly) + tileXSize() - 1) / tileXSize()
250    //
251    //----------------------------------------------------------
252
253    int			numXTiles (int lx = 0) const;
254    int			numYTiles (int ly = 0) const;
255
256
257    //---------------------------------------------------------
258    // Level pixel ranges:
259    //
260    // dataWindowForLevel(lx, ly) returns a 2-dimensional
261    // region of valid pixel coordinates for a level with
262    // level number (lx, ly)
263    //
264    //	return value is a Box2i with min value:
265    //      (dataWindow.min.x, dataWindow.min.y)
266    //
267    //	and max value:
268    //      (dataWindow.min.x + levelWidth(lx) - 1,
269    //       dataWindow.min.y + levelHeight(ly) - 1)
270    //
271    // dataWindowForLevel(level) is a convenience function used
272    // for ONE_LEVEL and MIPMAP_LEVELS files.  It returns
273    // dataWindowForLevel(level, level).
274    //
275    //---------------------------------------------------------
276
277    Imath::Box2i	dataWindowForLevel (int l = 0) const;
278    Imath::Box2i	dataWindowForLevel (int lx, int ly) const;
279
280
281    //-------------------------------------------------------------------
282    // Tile pixel ranges:
283    //
284    // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional
285    // region of valid pixel coordinates for a tile with tile coordinates
286    // (dx,dy) and level number (lx, ly).
287    //
288    //	return value is a Box2i with min value:
289    //      (dataWindow.min.x + dx * tileXSize(),
290    //       dataWindow.min.y + dy * tileYSize())
291    //
292    //	and max value:
293    //      (dataWindow.min.x + (dx + 1) * tileXSize() - 1,
294    //       dataWindow.min.y + (dy + 1) * tileYSize() - 1)
295    //
296    // dataWindowForTile(dx, dy, level) is a convenience function
297    // used for ONE_LEVEL and MIPMAP_LEVELS files.  It returns
298    // dataWindowForTile(dx, dy, level, level).
299    //
300    //-------------------------------------------------------------------
301
302    Imath::Box2i	dataWindowForTile (int dx, int dy,
303					   int l = 0) const;
304
305    Imath::Box2i	dataWindowForTile (int dx, int dy,
306					   int lx, int ly) const;
307
308    //------------------------------------------------------------------
309    // Write pixel data:
310    //
311    // writeTile(dx, dy, lx, ly) writes the tile with tile
312    // coordinates (dx, dy), and level number (lx, ly) to
313    // the file.
314    //
315    //   dx must lie in the interval [0, numXTiles(lx) - 1]
316    //   dy must lie in the interval [0, numYTiles(ly) - 1]
317    //
318    //   lx must lie in the interval [0, numXLevels() - 1]
319    //   ly must lie in the inverval [0, numYLevels() - 1]
320    //
321    // writeTile(dx, dy, level) is a convenience function
322    // used for ONE_LEVEL and MIPMAP_LEVEL files.  It calls
323    // writeTile(dx, dy, level, level).
324    //
325    // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow
326    // writing multiple tiles at once.  If multi-threading is used
327    // multiple tiles are written concurrently.  The tile coordinates,
328    // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile
329    // coordinates.  It is valid for dx1 < dx2 or dy1 < dy2; the
330    // tiles are always written in the order specified by the line
331    // order attribute.  Hence, it is not possible to specify an
332    // "invalid" or empty tile range.
333    //
334    // Pixels that are outside the pixel coordinate range for the tile's
335    // level, are never accessed by writeTile().
336    //
337    // Each tile in the file must be written exactly once.
338    //
339    // The file's line order attribute determines the order of the tiles
340    // in the file:
341    //
342    //	 INCREASING_Y	In the file, the tiles for each level are stored
343    //	 		in a contiguous block.  The levels are ordered
344    //	 		like this:
345    //
346    //			    (0, 0)   (1, 0)   ... (nx-1, 0)
347    //			    (0, 1)   (1, 1)   ... (nx-1, 1)
348    //			     ...
349    //			    (0,ny-1) (1,ny-1) ... (nx-1,ny-1)
350    //
351    //			where nx = numXLevels(), and ny = numYLevels().
352    //			In an individual level, (lx, ly), the tiles
353    //			are stored in the following order:
354    //
355    //			    (0, 0)   (1, 0)   ... (tx-1, 0)
356    //			    (0, 1)   (1, 1)   ... (tx-1, 1)
357    //			     ...
358    //			    (0,ty-1) (1,ty-1) ... (tx-1,ty-1)
359    //
360    //			where tx = numXTiles(lx),
361    //			and   ty = numYTiles(ly).
362    //
363    //	 DECREASING_Y   As for INCREASING_Y, the tiles for each level
364    //			are stored in a contiguous block.  The levels
365    //			are ordered the same way as for INCREASING_Y,
366    //			but within an individual level, the tiles
367    //			are stored in this order:
368    //
369    //			    (0,ty-1) (1,ty-1) ... (tx-1,ty-1)
370    //			     ...
371    //			    (0, 1)   (1, 1)   ... (tx-1, 1)
372    //			    (0, 0)   (1, 0)   ... (tx-1, 0)
373    //
374    //
375    //	 RANDOM_Y	The order of the calls to writeTile() determines
376    //	 		the order of the tiles in the file.
377    //
378    //------------------------------------------------------------------
379
380    void		writeTile  (int dx, int dy, int l = 0);
381    void		writeTile  (int dx, int dy, int lx, int ly);
382
383    void		writeTiles (int dx1, int dx2, int dy1, int dy2,
384                                    int lx, int ly);
385
386    void		writeTiles (int dx1, int dx2, int dy1, int dy2,
387                                    int l = 0);
388
389
390    //------------------------------------------------------------------
391    // Shortcut to copy all pixels from a TiledInputFile into this file,
392    // without uncompressing and then recompressing the pixel data.
393    // This file's header must be compatible with the TiledInputFile's
394    // header:  The two header's "dataWindow", "compression",
395    // "lineOrder", "channels", and "tiles" attributes must be the same.
396    //------------------------------------------------------------------
397
398    void		copyPixels (TiledInputFile &in);
399
400
401    //------------------------------------------------------------------
402    // Shortcut to copy all pixels from an InputFile into this file,
403    // without uncompressing and then recompressing the pixel data.
404    // This file's header must be compatible with the InputFile's
405    // header:  The two header's "dataWindow", "compression",
406    // "lineOrder", "channels", and "tiles" attributes must be the same.
407    //
408    // To use this function, the InputFile must be tiled.
409    //------------------------------------------------------------------
410
411    void		copyPixels (InputFile &in);
412
413
414    //--------------------------------------------------------------
415    // Updating the preview image:
416    //
417    // updatePreviewImage() supplies a new set of pixels for the
418    // preview image attribute in the file's header.  If the header
419    // does not contain a preview image, updatePreviewImage() throws
420    // an Iex::LogicExc.
421    //
422    // Note: updatePreviewImage() is necessary because images are
423    // often stored in a file incrementally, a few tiles at a time,
424    // while the image is being generated.  Since the preview image
425    // is an attribute in the file's header, it gets stored in the
426    // file as soon as the file is opened, but we may not know what
427    // the preview image should look like until we have written the
428    // last tile of the main image.
429    //
430    //--------------------------------------------------------------
431
432    void		updatePreviewImage (const PreviewRgba newPixels[]);
433
434
435    //-------------------------------------------------------------
436    // Break a tile -- for testing and debugging only:
437    //
438    // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the
439    // output file by writing n copies of character c, starting
440    // p bytes from the beginning of the tile with tile coordinates
441    // (dx, dy) and level number (lx, ly).
442    //
443    // Warning: Calling this function usually results in a broken
444    // image file.  The file or parts of it may not be readable,
445    // or the file may contain bad data.
446    //
447    //-------------------------------------------------------------
448
449    void		breakTile  (int dx, int dy,
450				    int lx, int ly,
451				    int offset,
452				    int length,
453				    char c);
454    struct Data;
455
456  private:
457
458    TiledOutputFile (const TiledOutputFile &);		    // not implemented
459    TiledOutputFile & operator = (const TiledOutputFile &); // not implemented
460
461    void		initialize (const Header &header);
462
463    bool		isValidTile (int dx, int dy,
464				     int lx, int ly) const;
465
466    size_t		bytesPerLineForTile (int dx, int dy,
467					     int lx, int ly) const;
468
469    Data *		_data;
470};
471
472
473} // namespace Imf
474
475#endif
476