1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright (c) Contributors to the OpenEXR Project.
4 //
5 
6 
7 #ifndef INCLUDED_IMF_DEEP_SCAN_LINE_OUTPUT_FILE_H
8 #define INCLUDED_IMF_DEEP_SCAN_LINE_OUTPUT_FILE_H
9 
10 //-----------------------------------------------------------------------------
11 //
12 //      class DeepScanLineOutputFile
13 //
14 //-----------------------------------------------------------------------------
15 
16 #include "ImfHeader.h"
17 #include "ImfFrameBuffer.h"
18 #include "ImfThreading.h"
19 #include "ImfGenericOutputFile.h"
20 #include "ImfNamespace.h"
21 #include "ImfForward.h"
22 #include "ImfExport.h"
23 
24 OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
25 
26 
27 struct PreviewRgba;
28 
29 class DeepScanLineOutputFile : public GenericOutputFile
30 {
31   public:
32 
33     //-----------------------------------------------------------
34     // Constructor -- opens the file and writes the file header.
35     // The file header is also copied into the DeepScanLineOutputFile
36     // object, and can later be accessed via the header() method.
37     // Destroying this DeepScanLineOutputFile object automatically closes
38     // the file.
39     //
40     // numThreads determines the number of threads that will be
41     // used to write the file (see ImfThreading.h).
42     //-----------------------------------------------------------
43 
44     IMF_EXPORT
45     DeepScanLineOutputFile (const char fileName[], const Header &header,
46                 int numThreads = globalThreadCount());
47 
48 
49     //------------------------------------------------------------
50     // Constructor -- attaches the new DeepScanLineOutputFile object
51     // to a file that has already been opened, and writes the file header.
52     // The file header is also copied into the DeepScanLineOutputFile
53     // object, and can later be accessed via the header() method.
54     // Destroying this DeepScanLineOutputFile object does not automatically
55     // close the file.
56     //
57     // numThreads determines the number of threads that will be
58     // used to write the file (see ImfThreading.h).
59     //------------------------------------------------------------
60 
61     IMF_EXPORT
62     DeepScanLineOutputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::OStream &os, const Header &header,
63                 int numThreads = globalThreadCount());
64 
65 
66     //-------------------------------------------------
67     // Destructor
68     //
69     // Destroying the DeepScanLineOutputFile object
70     // before writing all scan lines within the data
71     // window results in an incomplete file.
72     //-------------------------------------------------
73 
74     IMF_EXPORT
75     virtual ~DeepScanLineOutputFile ();
76 
77 
78     //------------------------
79     // Access to the file name
80     //------------------------
81 
82     IMF_EXPORT
83     const char *        fileName () const;
84 
85 
86     //--------------------------
87     // Access to the file header
88     //--------------------------
89 
90     IMF_EXPORT
91     const Header &      header () const;
92 
93 
94     //-------------------------------------------------------
95     // Set the current frame buffer -- copies the FrameBuffer
96     // object into the OutputFile object.
97     //
98     // The current frame buffer is the source of the pixel
99     // data written to the file.  The current frame buffer
100     // must be set at least once before writePixels() is
101     // called.  The current frame buffer can be changed
102     // after each call to writePixels.
103     //-------------------------------------------------------
104 
105     IMF_EXPORT
106     void                setFrameBuffer (const DeepFrameBuffer &frameBuffer);
107 
108 
109     //-----------------------------------
110     // Access to the current frame buffer
111     //-----------------------------------
112 
113     IMF_EXPORT
114     const DeepFrameBuffer & frameBuffer () const;
115 
116 
117     //-------------------------------------------------------------------
118     // Write pixel data:
119     //
120     // writePixels(n) retrieves the next n scan lines worth of data from
121     // the current frame buffer, starting with the scan line indicated by
122     // currentScanLine(), and stores the data in the output file, and
123     // progressing in the direction indicated by header.lineOrder().
124     //
125     // To produce a complete and correct file, exactly m scan lines must
126     // be written, where m is equal to
127     // header().dataWindow().max.y - header().dataWindow().min.y + 1.
128     //-------------------------------------------------------------------
129 
130     IMF_EXPORT
131     void                writePixels (int numScanLines = 1);
132 
133 
134     //------------------------------------------------------------------
135     // Access to the current scan line:
136     //
137     // currentScanLine() returns the y coordinate of the first scan line
138     // that will be read from the current frame buffer during the next
139     // call to writePixels().
140     //
141     // If header.lineOrder() == INCREASING_Y:
142     //
143     //  The current scan line before the first call to writePixels()
144     //  is header().dataWindow().min.y.  After writing each scan line,
145     //  the current scan line is incremented by 1.
146     //
147     // If header.lineOrder() == DECREASING_Y:
148     //
149     //  The current scan line before the first call to writePixels()
150     //  is header().dataWindow().max.y.  After writing each scan line,
151     //  the current scan line is decremented by 1.
152     //
153     //------------------------------------------------------------------
154 
155     IMF_EXPORT
156     int                 currentScanLine () const;
157 
158 
159     //--------------------------------------------------------------
160     // Shortcut to copy all pixels from an InputFile into this file,
161     // without uncompressing and then recompressing the pixel data.
162     // This file's header must be compatible with the InputFile's
163     // header:  The two header's "dataWindow", "compression",
164     // "lineOrder" and "channels" attributes must be the same.
165     //--------------------------------------------------------------
166 
167     IMF_EXPORT
168     void                copyPixels (DeepScanLineInputFile &in);
169 
170     // --------------------------------------------------------------
171     // Shortcut to copy pixels from a given part of a multipart file
172     // --------------------------------------------------------------
173     IMF_EXPORT
174     void                copyPixels (DeepScanLineInputPart &in);
175 
176 
177     //--------------------------------------------------------------
178     // Updating the preview image:
179     //
180     // updatePreviewImage() supplies a new set of pixels for the
181     // preview image attribute in the file's header.  If the header
182     // does not contain a preview image, updatePreviewImage() throws
183     // an IEX_NAMESPACE::LogicExc.
184     //
185     // Note: updatePreviewImage() is necessary because images are
186     // often stored in a file incrementally, a few scan lines at a
187     // time, while the image is being generated.  Since the preview
188     // image is an attribute in the file's header, it gets stored in
189     // the file as soon as the file is opened, but we may not know
190     // what the preview image should look like until we have written
191     // the last scan line of the main image.
192     //
193     //--------------------------------------------------------------
194 
195     IMF_EXPORT
196     void                updatePreviewImage (const PreviewRgba newPixels[]);
197 
198 
199     struct Data;
200 
201   private:
202 
203     //------------------------------------------------------------
204     // Constructor -- attaches the OutputStreamMutex to the
205     // given one from MultiPartOutputFile. Set the previewPosition
206     // and lineOffsetsPosition which have been acquired from
207     // the constructor of MultiPartOutputFile as well.
208     //------------------------------------------------------------
209     DeepScanLineOutputFile (const OutputPartData* part);
210 
211     DeepScanLineOutputFile (const DeepScanLineOutputFile &) = delete;
212     DeepScanLineOutputFile & operator = (const DeepScanLineOutputFile &) = delete;
213     DeepScanLineOutputFile (DeepScanLineOutputFile &&) = delete;
214     DeepScanLineOutputFile & operator = (DeepScanLineOutputFile &&) = delete;
215 
216     void                initialize (const Header &header);
217     void                initializeLineBuffer();
218 
219     Data *              _data;
220 
221 
222 
223     friend class MultiPartOutputFile;
224 };
225 
226 OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
227 
228 #endif
229