Coverage Report

Created: 2026-09-14 07:15

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