1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2013 Academy of Motion Picture Arts and Sciences
3 // ("A.M.P.A.S."). Portions contributed by others as indicated.
4 // All rights reserved.
5 //
6 // A worldwide, royalty-free, non-exclusive right to copy, modify, create
7 // derivatives, and use, in source and binary forms, is hereby granted,
8 // subject to acceptance of this license. Performance of any of the
9 // aforementioned acts indicates acceptance to be bound by the following
10 // terms and conditions:
11 //
12 // * Copies of source code, in whole or in part, must retain the
13 // above copyright notice, this list of conditions and the
14 // Disclaimer of Warranty.
15 //
16 // * Use in binary form must retain the above copyright notice,
17 // this list of conditions and the Disclaimer of Warranty in the
18 // documentation and/or other materials provided with the distribution.
19 //
20 // * Nothing in this license shall be deemed to grant any rights to
21 // trademarks, copyrights, patents, trade secrets or any other
22 // intellectual property of A.M.P.A.S. or any contributors, except
23 // as expressly stated herein.
24 //
25 // * Neither the name "A.M.P.A.S." nor the name of any other
26 // contributors to this software may be used to endorse or promote
27 // products derivative of or based on this software without express
28 // prior written permission of A.M.P.A.S. or the contributors, as
29 // appropriate.
30 //
31 // This license shall be construed pursuant to the laws of the State of
32 // California, and any disputes related thereto shall be subject to the
33 // jurisdiction of the courts therein.
34 //
35 // Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND
36 // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
37 // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
38 // FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO
39 // EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE
40 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY,
41 // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
46 // THE POSSIBILITY OF SUCH DAMAGE.
47 //
48 // WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY
49 // SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER
50 // RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY
51 // COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER
52 // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED.
53 ///////////////////////////////////////////////////////////////////////////
54
55 //-----------------------------------------------------------------------------
56 //
57 // exrdpx -- an OpenEXR/DPX file converter
58 //
59 //-----------------------------------------------------------------------------
60
61 #include <dpxToExr.h>
62 #include <exrToDpx.h>
63 #include <ImfTestFile.h>
64 #include <ImfThreading.h>
65 #include <iostream>
66 #include <string>
67 #include <cstring>
68 #include <cstdlib>
69 #include <exception>
70
71 using namespace std;
72 using namespace Imf;
73
74 namespace {
75
76 void
usageMessage(const char argv0[],bool verbose=false)77 usageMessage (const char argv0[], bool verbose = false)
78 {
79 cerr << "usage: " << argv0 << " [options] dpxFile exrFile" << endl;
80 cerr << "or: " << argv0 << " [options] exrFile dpxFile" << endl;
81
82 if (verbose)
83 {
84 cerr << "\n"
85 "Converts an OpenEXR file into a DPX file\n"
86 "or a DPX file into an OpenEXR file.\n"
87 "\n"
88 "Options:\n"
89 "\n"
90 "-C s CTL transform s is applied to the input pixels\n"
91 " before the output file is written. Option -C can\n"
92 " be specified multiple times to apply a series of\n"
93 " transforms to the pixels. The transforms are\n"
94 " applied in the order in which they appear on the\n"
95 " command line.\n"
96 "\n"
97 "-z x sets the data compression for the OpenEXR output\n"
98 " file to x (none/rle/zip/piz/pxr24/b44, default\n"
99 " is piz)\n"
100 "\n"
101 "-xyz the OpenEXR output file will contain CIE XYZ\n"
102 " instead of Rec. 709 pixel data\n"
103 "\n"
104 "-yc the pixels in the OpenEXR output file will be\n"
105 " in luminance/chroma instead of RGB format\n"
106 "\n"
107 "-s the header of the DPX input file is checked less\n"
108 " strictly; some fields are ignored even though they\n"
109 " are part of the core set.\n"
110 "\n"
111 "-t n process the pixels using n parallel threads\n"
112 "\n"
113 "-v verbose mode\n"
114 "\n"
115 "-h prints this message\n"
116 "\n"
117 "CTL transforms:\n"
118 "\n"
119 " If one or more CTL transforms are specified on\n"
120 " the command line (using the -C flag), then those\n"
121 " transforms are applied to the input pixels.\n"
122 " If no CTL transforms are specified then a default\n"
123 " transform is applied. The name of the default\n"
124 " transform is \"transform_EXR_DPX\" for OpenEXR to\n"
125 " DPX conversion and \"transform_DPX_EXR\" for DPX to\n"
126 " OpenEXR conversion.\n"
127 " The files that contain the transforms are located\n"
128 " using the CTL_MODULE_PATH environment variable.\n";
129
130 cerr << endl;
131 }
132
133 exit (1);
134 }
135
136
137 Compression
getCompression(const string & str)138 getCompression (const string &str)
139 {
140 Compression c;
141
142 if (str == "no" || str == "none" || str == "NO" || str == "NONE")
143 {
144 c = NO_COMPRESSION;
145 }
146 else if (str == "rle" || str == "RLE")
147 {
148 c = RLE_COMPRESSION;
149 }
150 else if (str == "zip" || str == "ZIP")
151 {
152 c = ZIP_COMPRESSION;
153 }
154 else if (str == "piz" || str == "PIZ")
155 {
156 c = PIZ_COMPRESSION;
157 }
158 else if (str == "pxr24" || str == "PXR24")
159 {
160 c = PXR24_COMPRESSION;
161 }
162 else if (str == "b44" || str == "B44")
163 {
164 c = B44_COMPRESSION;
165 }
166 else
167 {
168 cerr << "Unknown compression method \"" << str << "\"." << endl;
169 exit (1);
170 }
171
172 return c;
173 }
174
175 } // namespace
176
177 int
main(int argc,char ** argv)178 main(int argc, char **argv)
179 {
180 const char *fileName1 = 0;
181 const char *fileName2 = 0;
182 vector<string> transformNames;
183 bool outputXyz = false;
184 bool outputYc = false;
185 bool strict = true;
186 Compression compression = PIZ_COMPRESSION;
187 int numThreads = 0;
188 bool verbose = false;
189
190 //
191 // Parse the command line.
192 //
193
194 if (argc < 2)
195 usageMessage (argv[0], true);
196
197 int i = 1;
198 int j = 1;
199
200 while (i < argc)
201 {
202 if (!strcmp (argv[i], "-C"))
203 {
204 //
205 // Apply a CTL transform
206 //
207
208 if (i > argc - 2)
209 usageMessage (argv[0]);
210
211 transformNames.push_back (argv[i + 1]);
212 i += 2;
213 }
214 else if (!strcmp (argv[i], "-z"))
215 {
216 //
217 // Select compression method
218 //
219
220 if (i > argc - 2)
221 usageMessage (argv[0]);
222
223 compression = getCompression (argv[i + 1]);
224 i += 2;
225 }
226 else if (!strcmp (argv[i], "-xyz"))
227 {
228 //
229 // Output OpenEXR with CIE XYZ primaries
230 //
231
232 outputXyz = true;
233 i += 1;
234 }
235 else if (!strcmp (argv[i], "-yc"))
236 {
237 //
238 // Output OpenEXR in luminance/chroma format
239 //
240
241 outputYc = true;
242 i += 1;
243 }
244 else if (!strcmp (argv[i], "-t"))
245 {
246 //
247 // Set number of threads
248 //
249
250 if (i > argc - 2)
251 usageMessage (argv[0]);
252
253 numThreads = strtol (argv[i + 1], 0, 0);
254
255 if (numThreads < 0)
256 {
257 cerr << "Number of threads cannot be negative." << endl;
258 return 1;
259 }
260
261 i += 2;
262 }
263 else if (!strcmp (argv[i], "-v"))
264 {
265 //
266 // Verbose mode
267 //
268
269 verbose = true;
270 i += 1;
271 }
272 else if (!strcmp (argv[i], "-s"))
273 {
274 //
275 // Less strict DPX header checking
276 //
277
278 strict = false;
279 i += 1;
280 }
281 else if (!strcmp (argv[i], "-h"))
282 {
283 //
284 // Print help message
285 //
286
287 usageMessage (argv[0], true);
288 }
289 else
290 {
291 //
292 // image file name
293 //
294
295 if (j == 1)
296 fileName1 = argv[i];
297 else if (j == 2)
298 fileName2 = argv[i];
299 else
300 usageMessage (argv[0]);
301
302 i += 1;
303 j += 1;
304 }
305 }
306
307 if (fileName1 == 0 || fileName2 == 0)
308 usageMessage (argv[0]);
309
310 //
311 // Do the work
312 //
313
314 int exitStatus = 0;
315
316 try
317 {
318 setGlobalThreadCount (numThreads);
319
320 if (isOpenExrFile (fileName1))
321 {
322 if (transformNames.empty())
323 transformNames.push_back ("transform_EXR_DPX");
324
325 exrToDpx (fileName1,
326 fileName2,
327 transformNames,
328 verbose);
329 }
330 else
331 {
332 if (transformNames.empty())
333 transformNames.push_back ("transform_DPX_EXR");
334
335 dpxToExr (fileName1,
336 fileName2,
337 transformNames,
338 outputXyz,
339 outputYc,
340 compression,
341 strict,
342 verbose);
343 }
344 }
345 catch (const exception &e)
346 {
347 cerr << e.what() << endl;
348 exitStatus = 1;
349 }
350
351 return exitStatus;
352 }
353