-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathEXRFile.cs
177 lines (159 loc) · 6.46 KB
/
EXRFile.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SharpEXR {
public class EXRFile {
public EXRVersion Version { get; protected set; }
public List<EXRHeader> Headers { get; protected set; }
public List<OffsetTable> OffsetTables { get; protected set; }
public List<EXRPart> Parts { get; protected set; }
public EXRFile() {
}
public void Read(IEXRReader reader) {
// first four bytes of an OpenEXR file are always 0x76, 0x2f, 0x31 and 0x01 or 20000630
var magicNumber = reader.ReadInt32();
if (magicNumber != 20000630) {
throw new EXRFormatException("Invalid or corrupt EXR layout: First four bytes were not 20000630.");
}
var versionValue = reader.ReadInt32();
Version = new EXRVersion(versionValue);
Headers = new List<EXRHeader>();
if (Version.IsMultiPart) {
while (true) {
var header = new EXRHeader();
header.Read(this, reader);
if (header.IsEmpty) {
break;
}
Headers.Add(header);
}
throw new NotImplementedException("Multi part EXR files are not currently supported");
}
else {
if (Version.IsSinglePartTiled) {
throw new NotImplementedException("Tiled EXR files are not currently supported");
}
var header = new EXRHeader();
header.Read(this, reader);
Headers.Add(header);
}
OffsetTables = new List<OffsetTable>();
foreach (var header in Headers) {
int offsetTableSize;
if (Version.IsMultiPart) {
offsetTableSize = header.ChunkCount;
}
else if (Version.IsSinglePartTiled) {
// TODO: Implement
offsetTableSize = 0;
}
else {
var compression = header.Compression;
var dataWindow = header.DataWindow;
var linesPerBlock = GetScanLinesPerBlock(compression);
var blockCount = (int)Math.Ceiling(dataWindow.Height / (double)linesPerBlock);
offsetTableSize = blockCount;
}
var table = new OffsetTable(offsetTableSize);
table.Read(reader, offsetTableSize);
OffsetTables.Add(table);
}
}
public static int GetScanLinesPerBlock(EXRCompression compression) {
switch (compression) {
default:
return 1;
case EXRCompression.ZIP:
case EXRCompression.PXR24:
return 16;
case EXRCompression.PIZ:
case EXRCompression.B44:
case EXRCompression.B44A:
return 32;
}
}
public static int GetBytesPerPixel(ImageDestFormat format) {
switch (format) {
case ImageDestFormat.RGB16:
case ImageDestFormat.BGR16:
return 6;
case ImageDestFormat.RGB32:
case ImageDestFormat.BGR32:
return 12;
case ImageDestFormat.RGB8:
case ImageDestFormat.BGR8:
return 3;
case ImageDestFormat.PremultipliedRGBA16:
case ImageDestFormat.PremultipliedBGRA16:
case ImageDestFormat.RGBA16:
case ImageDestFormat.BGRA16:
return 8;
case ImageDestFormat.PremultipliedRGBA32:
case ImageDestFormat.PremultipliedBGRA32:
case ImageDestFormat.RGBA32:
case ImageDestFormat.BGRA32:
return 16;
case ImageDestFormat.PremultipliedRGBA8:
case ImageDestFormat.PremultipliedBGRA8:
case ImageDestFormat.RGBA8:
case ImageDestFormat.BGRA8:
return 4;
}
throw new ArgumentException("Unrecognized destination format", "format");
}
public static int GetBitsPerPixel(ImageDestFormat format) {
switch (format) {
case ImageDestFormat.PremultipliedRGBA32:
case ImageDestFormat.PremultipliedBGRA32:
case ImageDestFormat.RGBA32:
case ImageDestFormat.BGRA32:
case ImageDestFormat.RGB32:
case ImageDestFormat.BGR32:
return 32;
case ImageDestFormat.PremultipliedRGBA8:
case ImageDestFormat.PremultipliedBGRA8:
case ImageDestFormat.RGBA8:
case ImageDestFormat.BGRA8:
case ImageDestFormat.RGB8:
case ImageDestFormat.BGR8:
return 8;
case ImageDestFormat.RGB16:
case ImageDestFormat.BGR16:
case ImageDestFormat.PremultipliedRGBA16:
case ImageDestFormat.PremultipliedBGRA16:
case ImageDestFormat.RGBA16:
case ImageDestFormat.BGRA16:
return 16;
}
throw new ArgumentException("Unrecognized destination format", "format");
}
#if DOTNET
public static EXRFile FromFile(string file) {
var reader = new EXRReader(new FileStream(file, FileMode.Open, FileAccess.Read));
var result = FromReader(reader);
reader.Dispose();
return result;
}
#endif
public static EXRFile FromStream(Stream stream) {
var reader = new EXRReader(new BinaryReader(stream));
var result = FromReader(reader);
reader.Dispose();
return result;
}
public static EXRFile FromReader(IEXRReader reader) {
var img = new EXRFile();
img.Read(reader);
img.Parts = new List<EXRPart>();
for (int i = 0; i < img.Headers.Count; i++) {
var part = new EXRPart(img.Version, img.Headers[i], img.OffsetTables[i]);
img.Parts.Add(part);
//part.ReadPixelData(reader);
}
return img;
}
}
}