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