or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcpp-api.mdfile-io.mdimage-data.mdindex.mdmetadata.md

cpp-api.mddocs/

0

# C++ API Reference

1

2

Low-level C++ interface for maximum performance, custom integrations, and advanced use cases requiring direct control over encoding/decoding operations.

3

4

## Capabilities

5

6

### Core File I/O Classes

7

8

Primary interfaces for reading and writing EXR files with full control over threading, memory management, and format options.

9

10

```cpp { .api }

11

#include <OpenEXR/ImfInputFile.h>

12

#include <OpenEXR/ImfOutputFile.h>

13

#include <OpenEXR/ImfHeader.h>

14

#include <OpenEXR/ImfFrameBuffer.h>

15

16

namespace OPENEXR_IMF_NAMESPACE {

17

18

class InputFile {

19

public:

20

// Constructors

21

InputFile(const char filename[], int numThreads = globalThreadCount());

22

InputFile(IStream& is, int numThreads = globalThreadCount());

23

24

// File information

25

const Header& header() const;

26

const char* fileName() const;

27

int version() const;

28

bool isComplete() const;

29

30

// Reading operations

31

void setFrameBuffer(const FrameBuffer& frameBuffer);

32

void readPixels(int scanLine1, int scanLine2);

33

void readPixels(int scanLine);

34

35

// Destructor

36

~InputFile();

37

};

38

39

class OutputFile {

40

public:

41

// Constructors

42

OutputFile(const char name[], const Header& header, int numThreads = globalThreadCount());

43

OutputFile(OStream& os, const Header& header, int numThreads = globalThreadCount());

44

45

// File information

46

const Header& header() const;

47

const FrameBuffer& frameBuffer() const;

48

int currentScanLine() const;

49

50

// Writing operations

51

void setFrameBuffer(const FrameBuffer& frameBuffer);

52

void writePixels(int numScanLines = 1);

53

54

// Destructor

55

~OutputFile();

56

};

57

58

} // namespace OPENEXR_IMF_NAMESPACE

59

```

60

61

### Tiled Image Support

62

63

High-performance tiled image access for random access patterns and multi-resolution workflows.

64

65

```cpp { .api }

66

#include <OpenEXR/ImfTiledInputFile.h>

67

#include <OpenEXR/ImfTiledOutputFile.h>

68

#include <OpenEXR/ImfTileDescription.h>

69

70

namespace OPENEXR_IMF_NAMESPACE {

71

72

class TiledInputFile {

73

public:

74

// Constructors

75

TiledInputFile(const char name[], int numThreads = globalThreadCount());

76

TiledInputFile(IStream& is, int numThreads = globalThreadCount());

77

78

// File information

79

const Header& header() const;

80

const char* fileName() const;

81

int version() const;

82

83

// Tile information

84

unsigned int tileXSize() const;

85

unsigned int tileYSize() const;

86

LevelMode levelMode() const;

87

LevelRoundingMode levelRoundingMode() const;

88

int numXLevels() const;

89

int numYLevels() const;

90

int numXTiles(int lx = 0) const;

91

int numYTiles(int ly = 0) const;

92

93

// Reading operations

94

void setFrameBuffer(const FrameBuffer& frameBuffer);

95

void readTile(int dx, int dy, int lx = 0, int ly = 0);

96

void readTiles(int dxMin, int dxMax, int dyMin, int dyMax, int lx = 0, int ly = 0);

97

void readAllTiles(int lx = 0, int ly = 0);

98

99

// Destructor

100

~TiledInputFile();

101

};

102

103

class TiledOutputFile {

104

public:

105

// Constructors

106

TiledOutputFile(const char name[], const Header& header, int numThreads = globalThreadCount());

107

TiledOutputFile(OStream& os, const Header& header, int numThreads = globalThreadCount());

108

109

// File information

110

const Header& header() const;

111

const FrameBuffer& frameBuffer() const;

112

113

// Tile information

114

unsigned int tileXSize() const;

115

unsigned int tileYSize() const;

116

LevelMode levelMode() const;

117

LevelRoundingMode levelRoundingMode() const;

118

int numXLevels() const;

119

int numYLevels() const;

120

int numXTiles(int lx = 0) const;

121

int numYTiles(int ly = 0) const;

122

123

// Writing operations

124

void setFrameBuffer(const FrameBuffer& frameBuffer);

125

void writeTile(int dx, int dy, int lx = 0, int ly = 0);

126

void writeTiles(int dxMin, int dxMax, int dyMin, int dyMax, int lx = 0, int ly = 0);

127

void writeTiles(int dx1, int dx2, int dy1, int dy2, int l);

128

129

// Destructor

130

~TiledOutputFile();

131

};

132

133

} // namespace OPENEXR_IMF_NAMESPACE

134

```

135

136

### Multi-Part File Access

137

138

Unified access to multi-part EXR files with support for different part types and efficient part switching.

139

140

```cpp { .api }

141

#include <OpenEXR/ImfMultiPartInputFile.h>

142

#include <OpenEXR/ImfMultiPartOutputFile.h>

143

#include <OpenEXR/ImfInputPart.h>

144

#include <OpenEXR/ImfOutputPart.h>

145

146

namespace OPENEXR_IMF_NAMESPACE {

147

148

class MultiPartInputFile {

149

public:

150

// Constructors

151

MultiPartInputFile(const char name[], int numThreads = globalThreadCount());

152

MultiPartInputFile(IStream& is, int numThreads = globalThreadCount());

153

154

// File information

155

int parts() const;

156

const Header& header(int n) const;

157

const char* fileName() const;

158

int version() const;

159

160

// Destructor

161

~MultiPartInputFile();

162

};

163

164

class MultiPartOutputFile {

165

public:

166

// Constructors

167

MultiPartOutputFile(const char name[], int numParts, const Header headers[],

168

int numThreads = globalThreadCount());

169

MultiPartOutputFile(OStream& os, int numParts, const Header headers[],

170

int numThreads = globalThreadCount());

171

172

// File information

173

int parts() const;

174

const Header& header(int n) const;

175

176

// Destructor

177

~MultiPartOutputFile();

178

};

179

180

// Part-based access classes

181

class InputPart {

182

public:

183

InputPart(MultiPartInputFile& multiPartFile, int partNumber);

184

185

// File information

186

const Header& header() const;

187

int version() const;

188

bool isComplete() const;

189

190

// Reading operations (scanline)

191

void setFrameBuffer(const FrameBuffer& frameBuffer);

192

void readPixels(int scanLine1, int scanLine2);

193

void readPixels(int scanLine);

194

};

195

196

class OutputPart {

197

public:

198

OutputPart(MultiPartOutputFile& multiPartFile, int partNumber);

199

200

// File information

201

const Header& header() const;

202

const FrameBuffer& frameBuffer() const;

203

int currentScanLine() const;

204

205

// Writing operations (scanline)

206

void setFrameBuffer(const FrameBuffer& frameBuffer);

207

void writePixels(int numScanLines = 1);

208

};

209

210

class TiledInputPart {

211

public:

212

TiledInputPart(MultiPartInputFile& multiPartFile, int partNumber);

213

214

// Tiled operations

215

void setFrameBuffer(const FrameBuffer& frameBuffer);

216

void readTile(int dx, int dy, int lx = 0, int ly = 0);

217

void readTiles(int dxMin, int dxMax, int dyMin, int dyMax, int lx = 0, int ly = 0);

218

219

// Tile information

220

unsigned int tileXSize() const;

221

unsigned int tileYSize() const;

222

LevelMode levelMode() const;

223

LevelRoundingMode levelRoundingMode() const;

224

};

225

226

class TiledOutputPart {

227

public:

228

TiledOutputPart(MultiPartOutputFile& multiPartFile, int partNumber);

229

230

// Tiled operations

231

void setFrameBuffer(const FrameBuffer& frameBuffer);

232

void writeTile(int dx, int dy, int lx = 0, int ly = 0);

233

void writeTiles(int dxMin, int dxMax, int dyMin, int dyMax, int lx = 0, int ly = 0);

234

235

// Tile information

236

unsigned int tileXSize() const;

237

unsigned int tileYSize() const;

238

LevelMode levelMode() const;

239

LevelRoundingMode levelRoundingMode() const;

240

};

241

242

} // namespace OPENEXR_IMF_NAMESPACE

243

```

244

245

### Deep Image Support

246

247

Advanced deep compositing support with variable sample counts per pixel.

248

249

```cpp { .api }

250

#include <OpenEXR/ImfDeepScanLineInputFile.h>

251

#include <OpenEXR/ImfDeepScanLineOutputFile.h>

252

#include <OpenEXR/ImfDeepTiledInputFile.h>

253

#include <OpenEXR/ImfDeepTiledOutputFile.h>

254

#include <OpenEXR/ImfDeepFrameBuffer.h>

255

256

namespace OPENEXR_IMF_NAMESPACE {

257

258

class DeepScanLineInputFile {

259

public:

260

DeepScanLineInputFile(const char name[], int numThreads = globalThreadCount());

261

DeepScanLineInputFile(IStream& is, int numThreads = globalThreadCount());

262

263

// File information

264

const Header& header() const;

265

const char* fileName() const;

266

int version() const;

267

268

// Deep reading operations

269

void setFrameBuffer(const DeepFrameBuffer& frameBuffer);

270

void readPixelSampleCounts(int scanline1, int scanline2);

271

void readPixelSampleCounts(int scanline);

272

void readPixels(int scanline1, int scanline2);

273

void readPixels(int scanline);

274

275

// Sample count access

276

int firstScanLineInChunk(int y) const;

277

int lastScanLineInChunk(int y) const;

278

};

279

280

class DeepScanLineOutputFile {

281

public:

282

DeepScanLineOutputFile(const char name[], const Header& header,

283

int numThreads = globalThreadCount());

284

DeepScanLineOutputFile(OStream& os, const Header& header,

285

int numThreads = globalThreadCount());

286

287

// File information

288

const Header& header() const;

289

const DeepFrameBuffer& frameBuffer() const;

290

int currentScanLine() const;

291

292

// Deep writing operations

293

void setFrameBuffer(const DeepFrameBuffer& frameBuffer);

294

void writePixels(int numScanLines = 1);

295

};

296

297

// Deep frame buffer structures

298

struct DeepSlice {

299

PixelType type; // Pixel data type

300

char* base; // Base pointer to sample data

301

size_t xStride; // Stride between pixels

302

size_t yStride; // Stride between scanlines

303

size_t sampleStride; // Stride between samples

304

int xSampling; // Horizontal subsampling

305

int ySampling; // Vertical subsampling

306

bool fillValue; // Fill value for missing data

307

bool xTileCoords; // Use tile coordinates

308

bool yTileCoords; // Use tile coordinates

309

310

DeepSlice(PixelType type = HALF,

311

char* base = 0,

312

size_t xStride = 0,

313

size_t yStride = 0,

314

size_t sampleStride = 0,

315

int xSampling = 1,

316

int ySampling = 1,

317

double fillValue = 0.0,

318

bool xTileCoords = false,

319

bool yTileCoords = false);

320

};

321

322

class DeepFrameBuffer {

323

public:

324

void insert(const char name[], const DeepSlice& slice);

325

void insert(const std::string& name, const DeepSlice& slice);

326

327

DeepSlice& operator[](const char name[]);

328

const DeepSlice& operator[](const char name[]) const;

329

DeepSlice& operator[](const std::string& name);

330

const DeepSlice& operator[](const std::string& name) const;

331

332

DeepSlice* findSlice(const char name[]);

333

const DeepSlice* findSlice(const char name[]) const;

334

DeepSlice* findSlice(const std::string& name);

335

const DeepSlice* findSlice(const std::string& name) const;

336

337

typedef std::map<Name, DeepSlice> SliceMap;

338

339

typedef SliceMap::iterator Iterator;

340

typedef SliceMap::const_iterator ConstIterator;

341

342

Iterator begin();

343

ConstIterator begin() const;

344

Iterator end();

345

ConstIterator end() const;

346

Iterator find(const char name[]);

347

ConstIterator find(const char name[]) const;

348

Iterator find(const std::string& name);

349

ConstIterator find(const std::string& name) const;

350

};

351

352

} // namespace OPENEXR_IMF_NAMESPACE

353

```

354

355

### Header and Metadata Management

356

357

Comprehensive header and attribute management for custom metadata and format configuration.

358

359

```cpp { .api }

360

#include <OpenEXR/ImfHeader.h>

361

#include <OpenEXR/ImfAttribute.h>

362

#include <OpenEXR/ImfStandardAttributes.h>

363

#include <OpenEXR/ImfChannelList.h>

364

365

namespace OPENEXR_IMF_NAMESPACE {

366

367

class Header {

368

public:

369

// Constructors

370

Header(int width = 64, int height = 64,

371

float pixelAspectRatio = 1,

372

const IMATH_NAMESPACE::V2f& screenWindowCenter = IMATH_NAMESPACE::V2f(0, 0),

373

float screenWindowWidth = 1,

374

LineOrder lineOrder = INCREASING_Y,

375

Compression compression = ZIP_COMPRESSION);

376

377

Header(const IMATH_NAMESPACE::Box2i& displayWindow,

378

const IMATH_NAMESPACE::Box2i& dataWindow,

379

float pixelAspectRatio = 1,

380

const IMATH_NAMESPACE::V2f& screenWindowCenter = IMATH_NAMESPACE::V2f(0, 0),

381

float screenWindowWidth = 1,

382

LineOrder lineOrder = INCREASING_Y,

383

Compression compression = ZIP_COMPRESSION);

384

385

// Copy constructor and assignment

386

Header(const Header& other);

387

Header& operator=(const Header& other);

388

389

// Attribute management

390

void insert(const char name[], const Attribute& attribute);

391

void insert(const std::string& name, const Attribute& attribute);

392

void erase(const char name[]);

393

void erase(const std::string& name);

394

395

Attribute& operator[](const char name[]);

396

const Attribute& operator[](const char name[]) const;

397

Attribute& operator[](const std::string& name);

398

const Attribute& operator[](const std::string& name) const;

399

400

// Attribute lookup

401

Iterator find(const char name[]);

402

ConstIterator find(const char name[]) const;

403

Iterator find(const std::string& name);

404

ConstIterator find(const std::string& name) const;

405

406

// Standard attribute accessors

407

IMATH_NAMESPACE::Box2i& displayWindow();

408

const IMATH_NAMESPACE::Box2i& displayWindow() const;

409

IMATH_NAMESPACE::Box2i& dataWindow();

410

const IMATH_NAMESPACE::Box2i& dataWindow() const;

411

float& pixelAspectRatio();

412

const float& pixelAspectRatio() const;

413

IMATH_NAMESPACE::V2f& screenWindowCenter();

414

const IMATH_NAMESPACE::V2f& screenWindowCenter() const;

415

float& screenWindowWidth();

416

const float& screenWindowWidth() const;

417

ChannelList& channels();

418

const ChannelList& channels() const;

419

LineOrder& lineOrder();

420

const LineOrder& lineOrder() const;

421

Compression& compression();

422

const Compression& compression() const;

423

424

// Type checking for different file types

425

bool hasType() const;

426

void setType(const std::string& type);

427

bool isTiled() const;

428

bool isComplete() const;

429

430

// Multi-part support

431

bool hasName() const;

432

void setName(const std::string& name);

433

434

// Validation

435

void sanityCheck(bool isTiled = false, bool isMultipartFile = false) const;

436

437

// Iterator support

438

typedef std::map<Name, Attribute*> AttributeMap;

439

typedef AttributeMap::iterator Iterator;

440

typedef AttributeMap::const_iterator ConstIterator;

441

442

Iterator begin();

443

ConstIterator begin() const;

444

Iterator end();

445

ConstIterator end() const;

446

};

447

448

// Typed attribute template

449

template <class T>

450

class TypedAttribute : public Attribute {

451

public:

452

typedef T ValueType;

453

454

TypedAttribute();

455

TypedAttribute(const T& value);

456

TypedAttribute(const TypedAttribute<T>& other);

457

virtual ~TypedAttribute();

458

459

virtual const char* typeName() const;

460

virtual Attribute* copy() const;

461

virtual void writeValueTo(OStream& os, int version) const;

462

virtual void readValueFrom(IStream& is, int size, int version);

463

virtual void copyValueFrom(const Attribute& other);

464

465

T& value();

466

const T& value() const;

467

468

TypedAttribute& operator=(const TypedAttribute<T>& other);

469

};

470

471

// Channel list management

472

class ChannelList {

473

public:

474

// Channel insertion and removal

475

void insert(const char name[], const Channel& channel);

476

void insert(const std::string& name, const Channel& channel);

477

void erase(const char name[]);

478

void erase(const std::string& name);

479

480

// Channel access

481

Channel& operator[](const char name[]);

482

const Channel& operator[](const char name[]) const;

483

Channel& operator[](const std::string& name);

484

const Channel& operator[](const std::string& name) const;

485

486

// Channel lookup

487

Iterator find(const char name[]);

488

ConstIterator find(const char name[]) const;

489

Iterator find(const std::string& name);

490

ConstIterator find(const std::string& name) const;

491

492

// Utilities

493

bool operator==(const ChannelList& other) const;

494

bool operator!=(const ChannelList& other) const;

495

496

// Iteration support

497

typedef std::map<Name, Channel> ChannelMap;

498

typedef ChannelMap::iterator Iterator;

499

typedef ChannelMap::const_iterator ConstIterator;

500

501

Iterator begin();

502

ConstIterator begin() const;

503

Iterator end();

504

ConstIterator end() const;

505

};

506

507

struct Channel {

508

PixelType type; // Data type (UINT, HALF, FLOAT)

509

int xSampling; // Horizontal subsampling factor

510

int ySampling; // Vertical subsampling factor

511

bool pLinear; // Perceptually linear flag

512

513

Channel(PixelType type = HALF,

514

int xSampling = 1,

515

int ySampling = 1,

516

bool pLinear = false);

517

518

bool operator==(const Channel& other) const;

519

bool operator!=(const Channel& other) const;

520

};

521

522

} // namespace OPENEXR_IMF_NAMESPACE

523

```

524

525

### Frame Buffer Management

526

527

Efficient pixel data management with support for different layouts and zero-copy operations.

528

529

```cpp { .api }

530

#include <OpenEXR/ImfFrameBuffer.h>

531

#include <OpenEXR/ImfPixelType.h>

532

533

namespace OPENEXR_IMF_NAMESPACE {

534

535

struct Slice {

536

PixelType type; // Pixel data type

537

char* base; // Base pointer to pixel data

538

size_t xStride; // Bytes between horizontally adjacent pixels

539

size_t yStride; // Bytes between vertically adjacent pixels

540

int xSampling; // Horizontal subsampling factor

541

int ySampling; // Vertical subsampling factor

542

double fillValue; // Fill value for missing pixels

543

bool xTileCoords; // Use tile coordinates for addressing

544

bool yTileCoords; // Use tile coordinates for addressing

545

546

Slice(PixelType type = HALF,

547

char* base = 0,

548

size_t xStride = 0,

549

size_t yStride = 0,

550

int xSampling = 1,

551

int ySampling = 1,

552

double fillValue = 0.0,

553

bool xTileCoords = false,

554

bool yTileCoords = false);

555

};

556

557

class FrameBuffer {

558

public:

559

// Slice management

560

void insert(const char name[], const Slice& slice);

561

void insert(const std::string& name, const Slice& slice);

562

563

Slice& operator[](const char name[]);

564

const Slice& operator[](const char name[]) const;

565

Slice& operator[](const std::string& name);

566

const Slice& operator[](const std::string& name) const;

567

568

// Slice lookup

569

Iterator find(const char name[]);

570

ConstIterator find(const char name[]) const;

571

Iterator find(const std::string& name);

572

ConstIterator find(const std::string& name) const;

573

574

Slice* findSlice(const char name[]);

575

const Slice* findSlice(const char name[]) const;

576

Slice* findSlice(const std::string& name);

577

const Slice* findSlice(const std::string& name) const;

578

579

// Iteration support

580

typedef std::map<Name, Slice> SliceMap;

581

typedef SliceMap::iterator Iterator;

582

typedef SliceMap::const_iterator ConstIterator;

583

584

Iterator begin();

585

ConstIterator begin() const;

586

Iterator end();

587

ConstIterator end() const;

588

};

589

590

// Pixel type enumeration

591

enum PixelType {

592

UINT = 0, // 32-bit unsigned integer

593

HALF = 1, // 16-bit floating point (half precision)

594

FLOAT = 2, // 32-bit floating point (single precision)

595

NUM_PIXELTYPES

596

};

597

598

// Pixel type utilities

599

int pixelTypeSize(PixelType type);

600

const char* pixelTypeToString(PixelType type);

601

602

} // namespace OPENEXR_IMF_NAMESPACE

603

```

604

605

### RGBA Convenience Interface

606

607

Simplified high-level interface for common RGBA workflows with automatic format conversions.

608

609

```cpp { .api }

610

#include <OpenEXR/ImfRgbaFile.h>

611

#include <OpenEXR/ImfRgba.h>

612

#include <OpenEXR/ImfArray.h>

613

614

namespace OPENEXR_IMF_NAMESPACE {

615

616

struct Rgba {

617

half r, g, b, a;

618

619

Rgba();

620

Rgba(half r, half g, half b, half a = 1.f);

621

Rgba(float r, float g, float b, float a = 1.f);

622

};

623

624

enum RgbaChannels {

625

WRITE_R = 0x01, // Red channel

626

WRITE_G = 0x02, // Green channel

627

WRITE_B = 0x04, // Blue channel

628

WRITE_A = 0x08, // Alpha channel

629

WRITE_Y = 0x10, // Luminance channel

630

WRITE_C = 0x20, // Chroma channels

631

WRITE_RGB = 0x07, // Red, green, blue

632

WRITE_RGBA = 0x0f, // Red, green, blue, alpha

633

WRITE_YC = 0x30, // Luminance, chroma

634

WRITE_YA = 0x18, // Luminance, alpha

635

WRITE_YCA = 0x38 // Luminance, chroma, alpha

636

};

637

638

class RgbaOutputFile {

639

public:

640

// Constructors

641

RgbaOutputFile(const char name[], const Header& header, RgbaChannels rgbaChannels = WRITE_RGBA,

642

int numThreads = globalThreadCount());

643

RgbaOutputFile(const char name[], int width, int height, RgbaChannels rgbaChannels = WRITE_RGBA,

644

float pixelAspectRatio = 1, const IMATH_NAMESPACE::V2f& screenWindowCenter = IMATH_NAMESPACE::V2f(0, 0),

645

float screenWindowWidth = 1, LineOrder lineOrder = INCREASING_Y,

646

Compression compression = ZIP_COMPRESSION, int numThreads = globalThreadCount());

647

RgbaOutputFile(OStream& os, const Header& header, RgbaChannels rgbaChannels = WRITE_RGBA,

648

int numThreads = globalThreadCount());

649

RgbaOutputFile(OStream& os, int width, int height, RgbaChannels rgbaChannels = WRITE_RGBA,

650

float pixelAspectRatio = 1, const IMATH_NAMESPACE::V2f& screenWindowCenter = IMATH_NAMESPACE::V2f(0, 0),

651

float screenWindowWidth = 1, LineOrder lineOrder = INCREASING_Y,

652

Compression compression = ZIP_COMPRESSION, int numThreads = globalThreadCount());

653

654

// File operations

655

void setFrameBuffer(const Rgba* base, size_t xStride, size_t yStride);

656

void writePixels(int numScanLines = 1);

657

void writePixels(const Rgba* base, int scanLine1, int scanLine2);

658

659

// File information

660

const Header& header() const;

661

const FrameBuffer& frameBuffer() const;

662

const IMATH_NAMESPACE::Box2i& displayWindow() const;

663

const IMATH_NAMESPACE::Box2i& dataWindow() const;

664

float pixelAspectRatio() const;

665

const IMATH_NAMESPACE::V2f& screenWindowCenter() const;

666

float screenWindowWidth() const;

667

LineOrder lineOrder() const;

668

Compression compression() const;

669

RgbaChannels channels() const;

670

671

// Utilities

672

int currentScanLine() const;

673

674

// Destructor

675

~RgbaOutputFile();

676

};

677

678

class RgbaInputFile {

679

public:

680

// Constructors

681

RgbaInputFile(const char name[], int numThreads = globalThreadCount());

682

RgbaInputFile(IStream& is, int numThreads = globalThreadCount());

683

684

// File operations

685

void setFrameBuffer(const Rgba* base, size_t xStride, size_t yStride);

686

void readPixels(int scanLine1, int scanLine2);

687

void readPixels(int scanLine);

688

void readPixels(Rgba* base, int scanLine1, int scanLine2);

689

690

// File information

691

const Header& header() const;

692

const FrameBuffer& frameBuffer() const;

693

const IMATH_NAMESPACE::Box2i& displayWindow() const;

694

const IMATH_NAMESPACE::Box2i& dataWindow() const;

695

float pixelAspectRatio() const;

696

const IMATH_NAMESPACE::V2f& screenWindowCenter() const;

697

float screenWindowWidth() const;

698

LineOrder lineOrder() const;

699

Compression compression() const;

700

RgbaChannels channels() const;

701

const char* fileName() const;

702

int version() const;

703

bool isComplete() const;

704

705

// Destructor

706

~RgbaInputFile();

707

};

708

709

// Array template for managing RGBA pixel arrays

710

template <class T>

711

class Array {

712

public:

713

typedef T value_type;

714

715

// Constructors

716

Array();

717

Array(long size);

718

Array(long size, bool initialize, const T& value = T());

719

Array(const Array& other);

720

721

// Assignment

722

Array& operator=(const Array& other);

723

724

// Access

725

T& operator[](long i);

726

const T& operator[](long i) const;

727

728

// Size management

729

void resizeErase(long size);

730

void resizeEraseUnsafe(long size);

731

void resizeNoErase(long size);

732

long size() const;

733

734

// Destructor

735

~Array();

736

};

737

738

typedef Array<Rgba> Array2D;

739

740

} // namespace OPENEXR_IMF_NAMESPACE

741

```

742

743

### Threading and Performance

744

745

Multi-threading support and performance optimization utilities.

746

747

```cpp { .api }

748

#include <OpenEXR/ImfThreading.h>

749

#include <IlmThread/IlmThread.h>

750

#include <IlmThread/IlmThreadPool.h>

751

752

namespace OPENEXR_IMF_NAMESPACE {

753

754

// Global threading control

755

void setGlobalThreadCount(int count);

756

int globalThreadCount();

757

758

} // namespace OPENEXR_IMF_NAMESPACE

759

760

namespace ILMTHREAD_NAMESPACE {

761

762

class Thread {

763

public:

764

Thread();

765

virtual ~Thread();

766

767

void start();

768

void join();

769

bool joinable() const;

770

771

protected:

772

virtual void run() = 0;

773

774

private:

775

// Implementation details hidden

776

struct Data;

777

Data* _data;

778

};

779

780

class Mutex {

781

public:

782

Mutex();

783

~Mutex();

784

785

void lock();

786

void unlock();

787

788

private:

789

// Implementation details hidden

790

struct Data;

791

Data* _data;

792

};

793

794

class Lock {

795

public:

796

Lock(const Mutex& m, bool autoLock = true);

797

~Lock();

798

799

void acquire();

800

void release();

801

bool locked() const;

802

803

private:

804

const Mutex* _mutex;

805

bool _locked;

806

};

807

808

class Semaphore {

809

public:

810

Semaphore(unsigned int value = 0);

811

virtual ~Semaphore();

812

813

void wait();

814

bool tryWait();

815

void post();

816

int value() const;

817

818

private:

819

// Implementation details hidden

820

struct Data;

821

Data* _data;

822

};

823

824

class Task {

825

public:

826

Task(TaskGroup* g);

827

virtual ~Task();

828

829

virtual void execute() = 0;

830

831

TaskGroup* group();

832

833

private:

834

TaskGroup* _group;

835

};

836

837

class TaskGroup {

838

public:

839

TaskGroup();

840

~TaskGroup();

841

842

void addTask(Task* task);

843

void executeAndDestroy();

844

845

private:

846

// Implementation details hidden

847

struct Data;

848

Data* _data;

849

};

850

851

class ThreadPool {

852

public:

853

ThreadPool(unsigned int nthreads = 0);

854

virtual ~ThreadPool();

855

856

int numThreads() const;

857

void setNumThreads(int count);

858

859

void addTask(Task* task);

860

void addGlobalTask(Task* task);

861

862

static ThreadPool& globalThreadPool();

863

static void addGlobalTask(Task* task);

864

865

private:

866

// Implementation details hidden

867

struct Data;

868

Data* _data;

869

};

870

871

} // namespace ILMTHREAD_NAMESPACE

872

```

873

874

## Usage Examples

875

876

### Basic C++ Reading and Writing

877

878

```cpp

879

#include <OpenEXR/ImfInputFile.h>

880

#include <OpenEXR/ImfOutputFile.h>

881

#include <OpenEXR/ImfChannelList.h>

882

#include <OpenEXR/ImfFrameBuffer.h>

883

#include <OpenEXR/ImfHeader.h>

884

#include <OpenEXR/ImfArray.h>

885

#include <iostream>

886

887

using namespace OPENEXR_IMF_NAMESPACE;

888

using namespace IMATH_NAMESPACE;

889

890

void writeBasicEXR(const char* filename, int width, int height) {

891

// Create pixel data arrays

892

Array2D<float> rPixels(height, width);

893

Array2D<float> gPixels(height, width);

894

Array2D<float> bPixels(height, width);

895

Array2D<float> aPixels(height, width);

896

897

// Fill with sample data

898

for (int y = 0; y < height; ++y) {

899

for (int x = 0; x < width; ++x) {

900

rPixels[y][x] = float(x) / width;

901

gPixels[y][x] = float(y) / height;

902

bPixels[y][x] = 0.5f;

903

aPixels[y][x] = 1.0f;

904

}

905

}

906

907

// Create header

908

Header header(width, height);

909

header.channels().insert("R", Channel(FLOAT));

910

header.channels().insert("G", Channel(FLOAT));

911

header.channels().insert("B", Channel(FLOAT));

912

header.channels().insert("A", Channel(FLOAT));

913

header.compression() = ZIP_COMPRESSION;

914

915

// Custom attributes

916

header.insert("software", StringAttribute("C++ Example v1.0"));

917

header.insert("comments", StringAttribute("Basic RGB+A image"));

918

919

// Create output file

920

OutputFile file(filename, header);

921

922

// Set up frame buffer

923

FrameBuffer frameBuffer;

924

frameBuffer.insert("R", Slice(FLOAT, (char*)&rPixels[0][0],

925

sizeof(float), sizeof(float) * width));

926

frameBuffer.insert("G", Slice(FLOAT, (char*)&gPixels[0][0],

927

sizeof(float), sizeof(float) * width));

928

frameBuffer.insert("B", Slice(FLOAT, (char*)&bPixels[0][0],

929

sizeof(float), sizeof(float) * width));

930

frameBuffer.insert("A", Slice(FLOAT, (char*)&aPixels[0][0],

931

sizeof(float), sizeof(float) * width));

932

933

file.setFrameBuffer(frameBuffer);

934

file.writePixels(height);

935

936

std::cout << "Wrote " << filename << " (" << width << "x" << height << ")\n";

937

}

938

939

void readBasicEXR(const char* filename) {

940

// Open file for reading

941

InputFile file(filename);

942

943

// Get file information

944

const Header& header = file.header();

945

Box2i dw = header.dataWindow();

946

int width = dw.max.x - dw.min.x + 1;

947

int height = dw.max.y - dw.min.y + 1;

948

949

std::cout << "Reading " << filename << " (" << width << "x" << height << ")\n";

950

std::cout << "Compression: " << header.compression() << std::endl;

951

952

// Check available channels

953

const ChannelList& channels = header.channels();

954

for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {

955

const char* name = i.name();

956

const Channel& channel = i.channel();

957

std::cout << "Channel: " << name << " (type=" << channel.type << ")\n";

958

}

959

960

// Allocate pixel arrays

961

Array2D<float> rPixels(height, width);

962

Array2D<float> gPixels(height, width);

963

Array2D<float> bPixels(height, width);

964

965

// Set up frame buffer for reading

966

FrameBuffer frameBuffer;

967

frameBuffer.insert("R", Slice(FLOAT, (char*)&rPixels[0][0] - dw.min.x - dw.min.y * width,

968

sizeof(float), sizeof(float) * width, 1, 1, 0.0));

969

frameBuffer.insert("G", Slice(FLOAT, (char*)&gPixels[0][0] - dw.min.x - dw.min.y * width,

970

sizeof(float), sizeof(float) * width, 1, 1, 0.0));

971

frameBuffer.insert("B", Slice(FLOAT, (char*)&bPixels[0][0] - dw.min.x - dw.min.y * width,

972

sizeof(float), sizeof(float) * width, 1, 1, 0.0));

973

974

file.setFrameBuffer(frameBuffer);

975

file.readPixels(dw.min.y, dw.max.y);

976

977

// Print sample values

978

std::cout << "Sample pixel values at (100, 100):\n";

979

if (100 < height && 100 < width) {

980

std::cout << " R=" << rPixels[100][100]

981

<< " G=" << gPixels[100][100]

982

<< " B=" << bPixels[100][100] << std::endl;

983

}

984

}

985

986

int main() {

987

writeBasicEXR("basic_cpp.exr", 1920, 1080);

988

readBasicEXR("basic_cpp.exr");

989

return 0;

990

}

991

```

992

993

### Multi-Part C++ Implementation

994

995

```cpp

996

#include <OpenEXR/ImfMultiPartInputFile.h>

997

#include <OpenEXR/ImfMultiPartOutputFile.h>

998

#include <OpenEXR/ImfInputPart.h>

999

#include <OpenEXR/ImfOutputPart.h>

1000

#include <OpenEXR/ImfPartType.h>

1001

#include <OpenEXR/ImfArray.h>

1002

#include <vector>

1003

1004

using namespace OPENEXR_IMF_NAMESPACE;

1005

using namespace IMATH_NAMESPACE;

1006

1007

void createMultiPartEXR(const char* filename, int width, int height) {

1008

// Create headers for different parts

1009

std::vector<Header> headers(3);

1010

1011

// Beauty pass header

1012

headers[0] = Header(width, height);

1013

headers[0].setName("beauty");

1014

headers[0].setType(SCANLINEIMAGE);

1015

headers[0].channels().insert("R", Channel(HALF));

1016

headers[0].channels().insert("G", Channel(HALF));

1017

headers[0].channels().insert("B", Channel(HALF));

1018

headers[0].channels().insert("A", Channel(HALF));

1019

headers[0].compression() = DWAA_COMPRESSION;

1020

headers[0].insert("renderPass", StringAttribute("beauty"));

1021

1022

// Depth pass header

1023

headers[1] = Header(width, height);

1024

headers[1].setName("depth");

1025

headers[1].setType(SCANLINEIMAGE);

1026

headers[1].channels().insert("Z", Channel(FLOAT));

1027

headers[1].compression() = ZIP_COMPRESSION;

1028

headers[1].insert("renderPass", StringAttribute("depth"));

1029

1030

// Normal pass header

1031

headers[2] = Header(width, height);

1032

headers[2].setName("normal");

1033

headers[2].setType(SCANLINEIMAGE);

1034

headers[2].channels().insert("N.X", Channel(HALF));

1035

headers[2].channels().insert("N.Y", Channel(HALF));

1036

headers[2].channels().insert("N.Z", Channel(HALF));

1037

headers[2].compression() = ZIP_COMPRESSION;

1038

headers[2].insert("renderPass", StringAttribute("normal"));

1039

1040

// Create multi-part output file

1041

MultiPartOutputFile file(filename, 3, &headers[0]);

1042

1043

// Create pixel data

1044

Array2D<half> beautyR(height, width), beautyG(height, width),

1045

beautyB(height, width), beautyA(height, width);

1046

Array2D<float> depth(height, width);

1047

Array2D<half> normalX(height, width), normalY(height, width), normalZ(height, width);

1048

1049

// Fill sample data

1050

for (int y = 0; y < height; ++y) {

1051

for (int x = 0; x < width; ++x) {

1052

// Beauty data

1053

beautyR[y][x] = half(float(x) / width);

1054

beautyG[y][x] = half(float(y) / height);

1055

beautyB[y][x] = half(0.5f);

1056

beautyA[y][x] = half(1.0f);

1057

1058

// Depth data

1059

depth[y][x] = 10.0f + float(x + y) * 0.01f;

1060

1061

// Normal data (pointing toward camera)

1062

normalX[y][x] = half(0.0f);

1063

normalY[y][x] = half(0.0f);

1064

normalZ[y][x] = half(1.0f);

1065

}

1066

}

1067

1068

// Write beauty pass (Part 0)

1069

{

1070

OutputPart part(file, 0);

1071

FrameBuffer frameBuffer;

1072

1073

frameBuffer.insert("R", Slice(HALF, (char*)&beautyR[0][0],

1074

sizeof(half), sizeof(half) * width));

1075

frameBuffer.insert("G", Slice(HALF, (char*)&beautyG[0][0],

1076

sizeof(half), sizeof(half) * width));

1077

frameBuffer.insert("B", Slice(HALF, (char*)&beautyB[0][0],

1078

sizeof(half), sizeof(half) * width));

1079

frameBuffer.insert("A", Slice(HALF, (char*)&beautyA[0][0],

1080

sizeof(half), sizeof(half) * width));

1081

1082

part.setFrameBuffer(frameBuffer);

1083

part.writePixels(height);

1084

}

1085

1086

// Write depth pass (Part 1)

1087

{

1088

OutputPart part(file, 1);

1089

FrameBuffer frameBuffer;

1090

1091

frameBuffer.insert("Z", Slice(FLOAT, (char*)&depth[0][0],

1092

sizeof(float), sizeof(float) * width));

1093

1094

part.setFrameBuffer(frameBuffer);

1095

part.writePixels(height);

1096

}

1097

1098

// Write normal pass (Part 2)

1099

{

1100

OutputPart part(file, 2);

1101

FrameBuffer frameBuffer;

1102

1103

frameBuffer.insert("N.X", Slice(HALF, (char*)&normalX[0][0],

1104

sizeof(half), sizeof(half) * width));

1105

frameBuffer.insert("N.Y", Slice(HALF, (char*)&normalY[0][0],

1106

sizeof(half), sizeof(half) * width));

1107

frameBuffer.insert("N.Z", Slice(HALF, (char*)&normalZ[0][0],

1108

sizeof(half), sizeof(half) * width));

1109

1110

part.setFrameBuffer(frameBuffer);

1111

part.writePixels(height);

1112

}

1113

1114

std::cout << "Created multi-part EXR: " << filename << std::endl;

1115

}

1116

1117

void readMultiPartEXR(const char* filename) {

1118

// Open multi-part file

1119

MultiPartInputFile file(filename);

1120

1121

int numParts = file.parts();

1122

std::cout << "Multi-part file has " << numParts << " parts:\n";

1123

1124

// Examine each part

1125

for (int partNum = 0; partNum < numParts; ++partNum) {

1126

const Header& header = file.header(partNum);

1127

1128

// Get part information

1129

std::string partName = "unnamed";

1130

if (header.hasName()) {

1131

partName = header.typedAttribute<StringAttribute>("name").value();

1132

}

1133

1134

std::string renderPass = "unknown";

1135

try {

1136

renderPass = header.typedAttribute<StringAttribute>("renderPass").value();

1137

} catch (...) {}

1138

1139

std::cout << "Part " << partNum << ": " << partName

1140

<< " (pass: " << renderPass << ")\n";

1141

1142

// List channels

1143

const ChannelList& channels = header.channels();

1144

std::cout << " Channels: ";

1145

for (ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {

1146

std::cout << i.name() << " ";

1147

}

1148

std::cout << std::endl;

1149

1150

// Get dimensions

1151

Box2i dw = header.dataWindow();

1152

int width = dw.max.x - dw.min.x + 1;

1153

int height = dw.max.y - dw.min.y + 1;

1154

std::cout << " Size: " << width << "x" << height << std::endl;

1155

std::cout << " Compression: " << header.compression() << std::endl;

1156

1157

// Read sample data from first channel

1158

InputPart part(file, partNum);

1159

ChannelList::ConstIterator firstChannel = channels.begin();

1160

if (firstChannel != channels.end()) {

1161

const char* channelName = firstChannel.name();

1162

const Channel& channel = firstChannel.channel();

1163

1164

if (channel.type == HALF) {

1165

Array2D<half> pixels(height, width);

1166

FrameBuffer frameBuffer;

1167

frameBuffer.insert(channelName,

1168

Slice(HALF, (char*)&pixels[0][0] - dw.min.x - dw.min.y * width,

1169

sizeof(half), sizeof(half) * width));

1170

1171

part.setFrameBuffer(frameBuffer);

1172

part.readPixels(dw.min.y, dw.max.y);

1173

1174

std::cout << " Sample " << channelName << " value at (100,100): "

1175

<< float(pixels[100][100]) << std::endl;

1176

}

1177

else if (channel.type == FLOAT) {

1178

Array2D<float> pixels(height, width);

1179

FrameBuffer frameBuffer;

1180

frameBuffer.insert(channelName,

1181

Slice(FLOAT, (char*)&pixels[0][0] - dw.min.x - dw.min.y * width,

1182

sizeof(float), sizeof(float) * width));

1183

1184

part.setFrameBuffer(frameBuffer);

1185

part.readPixels(dw.min.y, dw.max.y);

1186

1187

std::cout << " Sample " << channelName << " value at (100,100): "

1188

<< pixels[100][100] << std::endl;

1189

}

1190

}

1191

1192

std::cout << std::endl;

1193

}

1194

}

1195

1196

int main() {

1197

createMultiPartEXR("multipart_cpp.exr", 1920, 1080);

1198

readMultiPartEXR("multipart_cpp.exr");

1199

return 0;

1200

}

1201

```

1202

1203

### High-Performance Tiled Access

1204

1205

```cpp

1206

#include <OpenEXR/ImfTiledInputFile.h>

1207

#include <OpenEXR/ImfTiledOutputFile.h>

1208

#include <OpenEXR/ImfTileDescription.h>

1209

#include <OpenEXR/ImfArray.h>

1210

#include <OpenEXR/ImfThreading.h>

1211

#include <chrono>

1212

1213

using namespace OPENEXR_IMF_NAMESPACE;

1214

using namespace IMATH_NAMESPACE;

1215

1216

void createTiledEXR(const char* filename, int width, int height,

1217

int tileWidth = 64, int tileHeight = 64) {

1218

// Create tiled header

1219

Header header(width, height);

1220

header.setType(TILEDIMAGE);

1221

header.channels().insert("R", Channel(HALF));

1222

header.channels().insert("G", Channel(HALF));

1223

header.channels().insert("B", Channel(HALF));

1224

header.compression() = ZIP_COMPRESSION;

1225

1226

// Configure tiling with mipmaps

1227

header.setTileDescription(TileDescription(tileWidth, tileHeight, MIPMAP_LEVELS));

1228

1229

// Add metadata

1230

header.insert("software", StringAttribute("Tiled C++ Example"));

1231

header.insert("tileOptimized", IntAttribute(1));

1232

1233

// Enable multi-threading for better performance

1234

setGlobalThreadCount(8);

1235

1236

TiledOutputFile file(filename, header);

1237

1238

// Create pixel data

1239

Array2D<half> rPixels(height, width);

1240

Array2D<half> gPixels(height, width);

1241

Array2D<half> bPixels(height, width);

1242

1243

// Generate test pattern

1244

for (int y = 0; y < height; ++y) {

1245

for (int x = 0; x < width; ++x) {

1246

float fx = float(x) / width;

1247

float fy = float(y) / height;

1248

1249

rPixels[y][x] = half(fx * fy);

1250

gPixels[y][x] = half(fx * (1.0f - fy));

1251

bPixels[y][x] = half((1.0f - fx) * fy);

1252

}

1253

}

1254

1255

// Set up frame buffer

1256

FrameBuffer frameBuffer;

1257

frameBuffer.insert("R", Slice(HALF, (char*)&rPixels[0][0],

1258

sizeof(half), sizeof(half) * width));

1259

frameBuffer.insert("G", Slice(HALF, (char*)&gPixels[0][0],

1260

sizeof(half), sizeof(half) * width));

1261

frameBuffer.insert("B", Slice(HALF, (char*)&bPixels[0][0],

1262

sizeof(half), sizeof(half) * width));

1263

1264

file.setFrameBuffer(frameBuffer);

1265

1266

// Write all tiles at base level (level 0)

1267

auto start = std::chrono::high_resolution_clock::now();

1268

1269

int numXTiles = file.numXTiles(0);

1270

int numYTiles = file.numYTiles(0);

1271

1272

file.writeTiles(0, numXTiles - 1, 0, numYTiles - 1, 0);

1273

1274

auto end = std::chrono::high_resolution_clock::now();

1275

auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

1276

1277

std::cout << "Created tiled EXR: " << filename << std::endl;

1278

std::cout << "Image size: " << width << "x" << height << std::endl;

1279

std::cout << "Tile size: " << tileWidth << "x" << tileHeight << std::endl;

1280

std::cout << "Number of tiles: " << numXTiles << "x" << numYTiles

1281

<< " = " << (numXTiles * numYTiles) << std::endl;

1282

std::cout << "Write time: " << duration.count() << "ms" << std::endl;

1283

std::cout << "Mipmap levels: " << file.numXLevels() << std::endl;

1284

}

1285

1286

void readTiledEXRRandomAccess(const char* filename) {

1287

TiledInputFile file(filename);

1288

1289

const Header& header = file.header();

1290

Box2i dw = header.dataWindow();

1291

int width = dw.max.x - dw.min.x + 1;

1292

int height = dw.max.y - dw.min.y + 1;

1293

1294

std::cout << "\nReading tiled file: " << filename << std::endl;

1295

std::cout << "Tile size: " << file.tileXSize() << "x" << file.tileYSize() << std::endl;

1296

std::cout << "Level mode: " << file.levelMode() << std::endl;

1297

1298

// Allocate memory for one tile

1299

int tileWidth = file.tileXSize();

1300

int tileHeight = file.tileYSize();

1301

Array2D<half> tileR(tileHeight, tileWidth);

1302

Array2D<half> tileG(tileHeight, tileWidth);

1303

Array2D<half> tileB(tileHeight, tileWidth);

1304

1305

// Set up frame buffer for tile reading

1306

FrameBuffer frameBuffer;

1307

frameBuffer.insert("R", Slice(HALF, (char*)&tileR[0][0] - dw.min.x - dw.min.y * tileWidth,

1308

sizeof(half), sizeof(half) * tileWidth, 1, 1, 0.0, true, true));

1309

frameBuffer.insert("G", Slice(HALF, (char*)&tileG[0][0] - dw.min.x - dw.min.y * tileWidth,

1310

sizeof(half), sizeof(half) * tileWidth, 1, 1, 0.0, true, true));

1311

frameBuffer.insert("B", Slice(HALF, (char*)&tileB[0][0] - dw.min.x - dw.min.y * tileWidth,

1312

sizeof(half), sizeof(half) * tileWidth, 1, 1, 0.0, true, true));

1313

1314

file.setFrameBuffer(frameBuffer);

1315

1316

// Random access pattern - read specific tiles

1317

auto start = std::chrono::high_resolution_clock::now();

1318

1319

int numXTiles = file.numXTiles(0);

1320

int numYTiles = file.numYTiles(0);

1321

1322

// Read every 4th tile in a pattern

1323

for (int ty = 0; ty < numYTiles; ty += 4) {

1324

for (int tx = 0; tx < numXTiles; tx += 4) {

1325

file.readTile(tx, ty, 0); // Read single tile at level 0

1326

1327

// Process tile data (example: compute average)

1328

float avgR = 0, avgG = 0, avgB = 0;

1329

for (int y = 0; y < tileHeight; ++y) {

1330

for (int x = 0; x < tileWidth; ++x) {

1331

avgR += float(tileR[y][x]);

1332

avgG += float(tileG[y][x]);

1333

avgB += float(tileB[y][x]);

1334

}

1335

}

1336

int pixels = tileWidth * tileHeight;

1337

avgR /= pixels;

1338

avgG /= pixels;

1339

avgB /= pixels;

1340

1341

std::cout << "Tile (" << tx << "," << ty << ") average RGB: "

1342

<< avgR << ", " << avgG << ", " << avgB << std::endl;

1343

}

1344

}

1345

1346

auto end = std::chrono::high_resolution_clock::now();

1347

auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

1348

1349

int tilesRead = ((numXTiles + 3) / 4) * ((numYTiles + 3) / 4);

1350

std::cout << "Random access read " << tilesRead << " tiles in "

1351

<< duration.count() << "ms" << std::endl;

1352

}

1353

1354

int main() {

1355

// Create large tiled image

1356

createTiledEXR("tiled_cpp.exr", 4096, 4096, 128, 128);

1357

1358

// Demonstrate random access

1359

readTiledEXRRandomAccess("tiled_cpp.exr");

1360

1361

return 0;

1362

}

1363

```