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