Coverage Report

Created: 2024-07-27 06:04

/src/openexr/src/lib/OpenEXR/ImfRgbaFile.h
Line
Count
Source (jump to first uncovered line)
1
//
2
// SPDX-License-Identifier: BSD-3-Clause
3
// Copyright (c) Contributors to the OpenEXR Project.
4
//
5
6
#ifndef INCLUDED_IMF_RGBA_FILE_H
7
#define INCLUDED_IMF_RGBA_FILE_H
8
9
//-----------------------------------------------------------------------------
10
//
11
//  Simplified RGBA image I/O
12
//
13
//  class RgbaOutputFile
14
//  class RgbaInputFile
15
//
16
//-----------------------------------------------------------------------------
17
18
#include "ImfExport.h"
19
#include "ImfNamespace.h"
20
21
#include "ImfFrameBuffer.h"
22
#include "ImfHeader.h"
23
#include "ImfRgba.h"
24
25
#include "ImfThreading.h"
26
#include <ImathBox.h>
27
#include <ImathVec.h>
28
#include <half.h>
29
#include <string>
30
31
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
32
33
//-------------------------------------------------------
34
// Utility to compute the origin-based pointer address
35
//
36
// With large offsets for the data window, the naive code
37
// can wrap around, especially on 32-bit machines.
38
// This can be used to avoid that
39
//-------------------------------------------------------
40
41
inline const Rgba*
42
ComputeBasePointer (
43
    const Rgba*                 ptr,
44
    const IMATH_NAMESPACE::V2i& origin,
45
    int64_t                     w,
46
    size_t                      xStride = 1,
47
    size_t                      yStride = 0)
48
0
{
49
0
    if (yStride == 0) yStride = w;
50
0
    int64_t offx = static_cast<int64_t> (origin.x);
51
0
    offx *= xStride;
52
0
    int64_t offy = static_cast<int64_t> (origin.y);
53
0
    offy *= yStride;
54
0
    return ptr - offx - offy;
55
0
}
56
57
inline const Rgba*
58
ComputeBasePointer (const Rgba* ptr, const IMATH_NAMESPACE::Box2i& dataWindow)
59
0
{
60
0
    return ComputeBasePointer (
61
0
        ptr,
62
0
        dataWindow.min,
63
0
        static_cast<int64_t> (dataWindow.max.x) -
64
0
            static_cast<int64_t> (dataWindow.min.x) + 1);
65
0
}
66
67
inline Rgba*
68
ComputeBasePointer (
69
    Rgba*                       ptr,
70
    const IMATH_NAMESPACE::V2i& origin,
71
    int64_t                     w,
72
    size_t                      xStride = 1,
73
    size_t                      yStride = 0)
74
0
{
75
0
    if (yStride == 0) yStride = w;
76
0
    int64_t offx = static_cast<int64_t> (origin.x);
77
0
    offx *= xStride;
78
0
    int64_t offy = static_cast<int64_t> (origin.y);
79
0
    offy *= yStride;
80
0
    return ptr - offx - offy;
81
0
}
82
83
inline Rgba*
84
ComputeBasePointer (Rgba* ptr, const IMATH_NAMESPACE::Box2i& dataWindow)
85
0
{
86
0
    return ComputeBasePointer (
87
0
        ptr,
88
0
        dataWindow.min,
89
0
        static_cast<int64_t> (dataWindow.max.x) -
90
0
            static_cast<int64_t> (dataWindow.min.x) + 1);
91
0
}
92
93
//
94
// RGBA output file.
95
//
96
97
class IMF_EXPORT_TYPE RgbaOutputFile
98
{
99
public:
100
    //---------------------------------------------------
101
    // Constructor -- header is constructed by the caller
102
    //---------------------------------------------------
103
104
    IMF_EXPORT
105
    RgbaOutputFile (
106
        const char    name[],
107
        const Header& header,
108
        RgbaChannels  rgbaChannels = WRITE_RGBA,
109
        int           numThreads   = globalThreadCount ());
110
111
    //----------------------------------------------------
112
    // Constructor -- header is constructed by the caller,
113
    // file is opened by the caller, destructor will not
114
    // automatically close the file.
115
    //----------------------------------------------------
116
117
    IMF_EXPORT
118
    RgbaOutputFile (
119
        OPENEXR_IMF_INTERNAL_NAMESPACE::OStream& os,
120
        const Header&                            header,
121
        RgbaChannels                             rgbaChannels = WRITE_RGBA,
122
        int numThreads = globalThreadCount ());
123
124
    //----------------------------------------------------------------
125
    // Constructor -- header data are explicitly specified as function
126
    // call arguments (empty dataWindow means "same as displayWindow")
127
    //----------------------------------------------------------------
128
129
    IMF_EXPORT
130
    RgbaOutputFile (
131
        const char                    name[],
132
        const IMATH_NAMESPACE::Box2i& displayWindow,
133
        const IMATH_NAMESPACE::Box2i& dataWindow   = IMATH_NAMESPACE::Box2i (),
134
        RgbaChannels                  rgbaChannels = WRITE_RGBA,
135
        float                         pixelAspectRatio = 1,
136
        const IMATH_NAMESPACE::V2f    screenWindowCenter =
137
            IMATH_NAMESPACE::V2f (0, 0),
138
        float       screenWindowWidth = 1,
139
        LineOrder   lineOrder         = INCREASING_Y,
140
        Compression compression       = PIZ_COMPRESSION,
141
        int         numThreads        = globalThreadCount ());
142
143
    //-----------------------------------------------
144
    // Constructor -- like the previous one, but both
145
    // the display window and the data window are
146
    // Box2i (V2i (0, 0), V2i (width - 1, height -1))
147
    //-----------------------------------------------
148
149
    IMF_EXPORT
150
    RgbaOutputFile (
151
        const char                 name[],
152
        int                        width,
153
        int                        height,
154
        RgbaChannels               rgbaChannels     = WRITE_RGBA,
155
        float                      pixelAspectRatio = 1,
156
        const IMATH_NAMESPACE::V2f screenWindowCenter =
157
            IMATH_NAMESPACE::V2f (0, 0),
158
        float       screenWindowWidth = 1,
159
        LineOrder   lineOrder         = INCREASING_Y,
160
        Compression compression       = PIZ_COMPRESSION,
161
        int         numThreads        = globalThreadCount ());
162
163
    //-----------
164
    // Destructor
165
    //-----------
166
167
    IMF_EXPORT
168
    virtual ~RgbaOutputFile ();
169
170
    //------------------------------------------------
171
    // Define a frame buffer as the pixel data source:
172
    // Pixel (x, y) is at address
173
    //
174
    //  base + x * xStride + y * yStride
175
    //
176
    //------------------------------------------------
177
178
    IMF_EXPORT
179
    void setFrameBuffer (const Rgba* base, size_t xStride, size_t yStride);
180
181
    //---------------------------------------------
182
    // Write pixel data (see class Imf::OutputFile)
183
    //---------------------------------------------
184
185
    IMF_EXPORT
186
    void writePixels (int numScanLines = 1);
187
    IMF_EXPORT
188
    int currentScanLine () const;
189
190
    //--------------------------
191
    // Access to the file header
192
    //--------------------------
193
194
    IMF_EXPORT
195
    const Header& header () const;
196
    IMF_EXPORT
197
    const FrameBuffer& frameBuffer () const;
198
    IMF_EXPORT
199
    const IMATH_NAMESPACE::Box2i& displayWindow () const;
200
    IMF_EXPORT
201
    const IMATH_NAMESPACE::Box2i& dataWindow () const;
202
    IMF_EXPORT
203
    float pixelAspectRatio () const;
204
    IMF_EXPORT
205
    const IMATH_NAMESPACE::V2f screenWindowCenter () const;
206
    IMF_EXPORT
207
    float screenWindowWidth () const;
208
    IMF_EXPORT
209
    LineOrder lineOrder () const;
210
    IMF_EXPORT
211
    Compression compression () const;
212
    IMF_EXPORT
213
    RgbaChannels channels () const;
214
215
    // --------------------------------------------------------------------
216
    // Update the preview image (see Imf::OutputFile::updatePreviewImage())
217
    // --------------------------------------------------------------------
218
219
    IMF_EXPORT
220
    void updatePreviewImage (const PreviewRgba[]);
221
222
    //-----------------------------------------------------------------------
223
    // Rounding control for luminance/chroma images:
224
    //
225
    // If the output file contains luminance and chroma channels (WRITE_YC
226
    // or WRITE_YCA), then the significands of the luminance and
227
    // chroma values are rounded to roundY and roundC bits respectively (see
228
    // function half::round()).  Rounding improves compression with minimal
229
    // image degradation, usually much less than the degradation caused by
230
    // chroma subsampling.  By default, roundY is 7, and roundC is 5.
231
    //
232
    // If the output file contains RGB channels or a luminance channel,
233
    // without chroma, then no rounding is performed.
234
    //-----------------------------------------------------------------------
235
236
    IMF_EXPORT
237
    void setYCRounding (unsigned int roundY, unsigned int roundC);
238
239
    //----------------------------------------------------
240
    // Break a scan line -- for testing and debugging only
241
    // (see Imf::OutputFile::updatePreviewImage()
242
    //
243
    // Warning: Calling this function usually results in a
244
    // broken image file.  The file or parts of it may not
245
    // be readable, or the file may contain bad data.
246
    //
247
    //----------------------------------------------------
248
249
    IMF_EXPORT
250
    void breakScanLine (int y, int offset, int length, char c);
251
252
private:
253
    RgbaOutputFile (const RgbaOutputFile&)            = delete;
254
    RgbaOutputFile& operator= (const RgbaOutputFile&) = delete;
255
    RgbaOutputFile (RgbaOutputFile&&)                 = delete;
256
    RgbaOutputFile& operator= (RgbaOutputFile&&)      = delete;
257
258
    class IMF_HIDDEN ToYca;
259
260
    OutputFile* _outputFile;
261
    ToYca*      _toYca;
262
};
263
264
//
265
// RGBA input file
266
//
267
268
class IMF_EXPORT_TYPE RgbaInputFile
269
{
270
public:
271
    //-------------------------------------------------------
272
    // Constructor -- opens the file with the specified name,
273
    // destructor will automatically close the file.
274
    //-------------------------------------------------------
275
276
    IMF_EXPORT
277
    RgbaInputFile (const char name[], int numThreads = globalThreadCount ());
278
279
    //-----------------------------------------------------------
280
    // Constructor -- attaches the new RgbaInputFile object to a
281
    // file that has already been opened by the caller.
282
    // Destroying the RgbaInputFile object will not automatically
283
    // close the file.
284
    //-----------------------------------------------------------
285
286
    IMF_EXPORT
287
    RgbaInputFile (
288
        OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is,
289
        int numThreads = globalThreadCount ());
290
291
    //--------------------------------------------------------------
292
    // Constructors -- the same as the previous two, but the names
293
    // of the red, green, blue, alpha, luminance and chroma channels
294
    // are expected to be layerName.R, layerName.G, etc.
295
    //--------------------------------------------------------------
296
297
    IMF_EXPORT
298
    RgbaInputFile (
299
        const char         name[],
300
        const std::string& layerName,
301
        int                numThreads = globalThreadCount ());
302
303
    IMF_EXPORT
304
    RgbaInputFile (
305
        OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is,
306
        const std::string&                       layerName,
307
        int numThreads = globalThreadCount ());
308
309
    //--------------------------------------------------------------
310
    // Constructors -- the same as the previous, but the specified
311
    // part is opened instead of the first (or only) part within the file
312
    //--------------------------------------------------------------
313
314
    IMF_EXPORT
315
    RgbaInputFile (
316
        int        partNumber,
317
        const char name[],
318
        int        numThreads = globalThreadCount ());
319
320
    IMF_EXPORT
321
    RgbaInputFile (
322
        int                partNumber,
323
        const char         name[],
324
        const std::string& layerName,
325
        int                numThreads = globalThreadCount ());
326
327
    IMF_EXPORT
328
    RgbaInputFile (
329
        int                                      partNumber,
330
        OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is,
331
        int numThreads = globalThreadCount ());
332
333
    IMF_EXPORT
334
    RgbaInputFile (
335
        int                                      partNumber,
336
        OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is,
337
        const std::string&                       layerName,
338
        int numThreads = globalThreadCount ());
339
340
    //-----------
341
    // Destructor
342
    //-----------
343
344
    IMF_EXPORT
345
    virtual ~RgbaInputFile ();
346
347
    //-----------------------------------------------------
348
    // Define a frame buffer as the pixel data destination:
349
    // Pixel (x, y) is at address
350
    //
351
    //  base + x * xStride + y * yStride
352
    //
353
    //-----------------------------------------------------
354
355
    IMF_EXPORT
356
    void setFrameBuffer (Rgba* base, size_t xStride, size_t yStride);
357
358
    //----------------------------------------------------------------
359
    // Switch to a different layer within the current part
360
    //
361
    // subsequent calls to readPixels()
362
    // will read channels layerName.R, layerName.G, etc.
363
    // After each call to setLayerName(), setFrameBuffer() must be
364
    // called at least once before the next call to readPixels().
365
    //----------------------------------------------------------------
366
367
    IMF_EXPORT
368
    void setLayerName (const std::string& layerName);
369
370
    //-------------------------------
371
    // Return number of parts in file
372
    //-------------------------------
373
    IMF_EXPORT
374
    int parts () const;
375
376
    //----------------------------------------------------------------
377
    // Switch to a different part  -- subsequent calls to readPixels()
378
    // will read channels from given part
379
    // After each call to setPart() or setPartAndLayer(), setFrameBuffer() must be
380
    // called at least once before the next call to readPixels().
381
    //----------------------------------------------------------------
382
383
    IMF_EXPORT
384
    void setPart (int part);
385
386
    //--------------------------
387
    // Equivalent to 'setPart(part) ; setLayerName(layerName);'
388
    //----------------------------
389
    IMF_EXPORT
390
    void setPartAndLayer (int part, const std::string& layerName);
391
392
    //-------------------------------------------
393
    // Read pixel data (see class Imf::InputFile)
394
    //-------------------------------------------
395
396
    IMF_EXPORT
397
    void readPixels (int scanLine1, int scanLine2);
398
399
    IMF_EXPORT
400
    void readPixels (int scanLine);
401
402
    //--------------------------
403
    // Access to the file header
404
    //--------------------------
405
406
    IMF_EXPORT
407
    const Header& header () const;
408
    IMF_EXPORT
409
    const FrameBuffer& frameBuffer () const;
410
    IMF_EXPORT
411
    const IMATH_NAMESPACE::Box2i& displayWindow () const;
412
    IMF_EXPORT
413
    const IMATH_NAMESPACE::Box2i& dataWindow () const;
414
    IMF_EXPORT
415
    float pixelAspectRatio () const;
416
    IMF_EXPORT
417
    const IMATH_NAMESPACE::V2f screenWindowCenter () const;
418
    IMF_EXPORT
419
    float screenWindowWidth () const;
420
    IMF_EXPORT
421
    LineOrder lineOrder () const;
422
    IMF_EXPORT
423
    Compression compression () const;
424
    IMF_EXPORT
425
    RgbaChannels channels () const;
426
    IMF_EXPORT
427
    const char* fileName () const;
428
    IMF_EXPORT
429
    bool isComplete () const;
430
431
    //----------------------------------
432
    // Access to the file format version
433
    //----------------------------------
434
435
    IMF_EXPORT
436
    int version () const;
437
438
private:
439
    RgbaInputFile (const RgbaInputFile&)            = delete;
440
    RgbaInputFile& operator= (const RgbaInputFile&) = delete;
441
    RgbaInputFile (RgbaInputFile&&)                 = delete;
442
    RgbaInputFile& operator= (RgbaInputFile&&)      = delete;
443
444
    class IMF_HIDDEN FromYca;
445
446
    MultiPartInputFile* _multiPartFile;
447
    InputPart*          _inputPart;
448
    FromYca*            _fromYca;
449
    std::string         _channelNamePrefix;
450
};
451
452
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
453
454
#endif