-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexrwrite.cpp
More file actions
166 lines (130 loc) · 3.49 KB
/
exrwrite.cpp
File metadata and controls
166 lines (130 loc) · 3.49 KB
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
/*
* MATLAB MEX function for writing EXR images.
*
* Only supports EXR images with half-precision floating-point data.
*
*/
#include "ImathBox.h"
#include "ImfRgba.h"
#include "ImfRgbaFile.h"
#include "ImfArray.h"
#include "ImfChannelList.h"
#include "ImfPixelType.h"
#include "Iex.h"
#include "mex.h"
#include "matrix.h"
using namespace Imf;
using namespace Imath;
using namespace Iex;
/*
* Check inputs
* Two or three input arguments, last is a string
* no output arguments
* If a mask is specified, it must be 2D and the same size as the image
*
*/
void checkInputs(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
if (nlhs != 0)
mexErrMsgTxt("Too many output arguments");
if (nrhs < 2 || nrhs > 3)
mexErrMsgTxt("Incorrect number of input arguments.");
// Check that last argument is a string
if (mxIsChar(prhs[nrhs-1]) != 1)
mexErrMsgTxt("Last argument must be a string.");
if (mxGetM(prhs[nrhs-1]) != 1)
mexErrMsgTxt("Filename must be a row vector.");
// Check the number of dimensions
int ndims = mxGetNumberOfDimensions(prhs[0]);
if (ndims < 2 || ndims > 3)
mexErrMsgTxt("image must be 2D or 3D.");
// Make sure that image is double precision
if (mxGetElementSize(prhs[0]) != 8)
mexErrMsgTxt("image must be double precision.");
// If a mask is specified, it must be the same size as the image
if (nrhs == 3) {
int ndmask = mxGetNumberOfDimensions(prhs[1]);
if (ndmask != 2)
mexErrMsgTxt("mask must be 2D");
int ydim = mxGetM(prhs[0]);
int xdim = mxGetN(prhs[0]);
if (ndims == 3) {
xdim = mxGetN(prhs[0])/3;
}
int ymask = mxGetM(prhs[1]);
int xmask = mxGetN(prhs[1]);
if (ydim != ymask || xdim != xmask)
mexErrMsgTxt("mask and image must be the same size.");
if (mxGetElementSize(prhs[1]) != 8)
mexErrMsgTxt("mask must be double precision.");
}
return;
}
/*
* Write an EXR file.
* Code follows examples from ReadingAndWritingImageFiles.pdf, found
* here:
* http://www.openexr.com/ReadingAndWritingImageFiles.pdf
*
*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
checkInputs(nlhs, plhs, nrhs, prhs);
char *filename = mxArrayToString(prhs[nrhs-1]);
try {
// Get image size
int ndims = mxGetNumberOfDimensions(prhs[0]);
int ydim = mxGetM(prhs[0]);
int xdim = mxGetN(prhs[0]);
if (ndims == 3)
xdim = mxGetN(prhs[0])/3;
double *img = mxGetPr(prhs[0]);
struct Rgba *px = new struct Rgba[xdim*ydim];
int step = 0;
if (ndims == 3)
step = xdim*ydim;
RgbaChannels mode = WRITE_RGBA;
/*
* alpha specified as second argument
*/
if (nrhs == 3) {
double *msk = mxGetPr(prhs[1]);
for (int i = 0; i < ydim; ++i) {
for (int j = 0; j < xdim; ++j) {
int k = j*ydim+i;
px[i*xdim+j].r = img[k];
px[i*xdim+j].g = img[k+step];
px[i*xdim+j].b = img[k+2*step];
px[i*xdim+j].a = msk[k];
}
}
if (ndims == 2)
mode = WRITE_YA;
/*
* No alpha specified
*/
} else {
for (int i = 0; i < ydim; ++i) {
for (int j = 0; j < xdim; ++j) {
int k = j*ydim+i;
px[i*xdim+j].r = img[k];
px[i*xdim+j].g = img[k+step];
px[i*xdim+j].b = img[k+2*step];
px[i*xdim+j].a = 1.0f;
}
}
mode = WRITE_RGB;
if (ndims == 2)
mode = WRITE_Y;
}
RgbaOutputFile file(filename, xdim, ydim, mode);
file.setFrameBuffer(px, 1, xdim);
file.writePixels(ydim);
mxFree(filename);
delete[] px;
px = NULL;
} catch (const std::exception &exc) {
mxFree(filename);
mexErrMsgTxt(exc.what());
}
return;
}