1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4// Digital Ltd. LLC
5//
6// All rights reserved.
7//
8// Redistribution and use in source and binary forms, with or without
9// modification, are permitted provided that the following conditions are
10// met:
11// *       Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13// *       Redistributions in binary form must reproduce the above
14// copyright notice, this list of conditions and the following disclaimer
15// in the documentation and/or other materials provided with the
16// distribution.
17// *       Neither the name of Industrial Light & Magic nor the names of
18// its contributors may be used to endorse or promote products derived
19// from this software without specific prior written permission.
20//
21// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33///////////////////////////////////////////////////////////////////////////
34
35
36//-----------------------------------------------------------------------------
37//
38//	Utility program to print an image file's header
39//
40//-----------------------------------------------------------------------------
41
42#include "OpenEXRConfig.h"
43#include <ImfInputFile.h>
44#include <ImfBoxAttribute.h>
45#include <ImfChannelListAttribute.h>
46#include <ImfChromaticitiesAttribute.h>
47#include <ImfCompressionAttribute.h>
48#include <ImfDoubleAttribute.h>
49#include <ImfEnvmapAttribute.h>
50#include <ImfFloatAttribute.h>
51#include <ImfIntAttribute.h>
52#include <ImfKeyCodeAttribute.h>
53#include <ImfLineOrderAttribute.h>
54#include <ImfMatrixAttribute.h>
55#include <ImfPreviewImageAttribute.h>
56#include <ImfRationalAttribute.h>
57#include <ImfStringAttribute.h>
58#include <ImfTileDescriptionAttribute.h>
59#include <ImfTimeCodeAttribute.h>
60#include <ImfVecAttribute.h>
61#include <ImfVersion.h>
62#include <iostream>
63#include <iomanip>
64
65using namespace Imf;
66using namespace std;
67
68
69void
70printCompression (Compression c)
71{
72    switch (c)
73    {
74      case NO_COMPRESSION:
75	cout << "none";
76	break;
77
78      case RLE_COMPRESSION:
79	cout << "run-length encoding";
80	break;
81
82      case ZIPS_COMPRESSION:
83	cout << "zip, individual scanlines";
84	break;
85
86      case ZIP_COMPRESSION:
87	cout << "zip, multi-scanline blocks";
88	break;
89
90      case PIZ_COMPRESSION:
91	cout << "piz";
92	break;
93
94      case PXR24_COMPRESSION:
95	  cout << "pxr24";
96	  break;
97
98      case B44_COMPRESSION:
99	  cout << "b44";
100	  break;
101
102      case B44A_COMPRESSION:
103	  cout << "b44a";
104	  break;
105
106      default:
107	cout << int (c);
108	break;
109    }
110}
111
112
113void
114printLineOrder (LineOrder lo)
115{
116    switch (lo)
117   {
118      case INCREASING_Y:
119	cout << "increasing y";
120	break;
121
122      case DECREASING_Y:
123	cout << "decreasing y";
124	break;
125
126      case RANDOM_Y:
127	cout << "random y";
128	break;
129
130      default:
131	cout << int (lo);
132	break;
133    };
134}
135
136
137void
138printPixelType (PixelType pt)
139{
140    switch (pt)
141    {
142      case UINT:
143	cout << "32-bit unsigned integer";
144	break;
145
146      case HALF:
147	cout << "16-bit floating-point";
148	break;
149
150      case FLOAT:
151	cout << "32-bit floating-point";
152	break;
153
154      default:
155	cout << "type " << int (pt);
156	break;
157    }
158}
159
160
161void
162printLevelMode (LevelMode lm)
163{
164    switch (lm)
165    {
166      case ONE_LEVEL:
167	cout << "single level";
168	break;
169
170      case MIPMAP_LEVELS:
171	cout << "mip-map";
172	break;
173
174      case RIPMAP_LEVELS:
175	cout << "rip-map";
176	break;
177
178      default:
179	cout << "level mode " << int (lm);
180	break;
181    }
182}
183
184
185void
186printLevelRoundingMode (LevelRoundingMode lm)
187{
188    switch (lm)
189    {
190      case ROUND_DOWN:
191	cout << "down";
192	break;
193
194      case ROUND_UP:
195	cout << "up";
196	break;
197
198      default:
199	cout << "mode " << int (lm);
200	break;
201    }
202}
203
204
205void
206printTimeCode (TimeCode tc)
207{
208    cout << "    "
209	    "time " <<
210	    setfill ('0') <<
211#ifndef HAVE_COMPLETE_IOMANIP
212	    setw (2) << tc.hours() << ":" <<
213	    setw (2) << tc.minutes() << ":" <<
214	    setw (2) << tc.seconds() << ":" <<
215	    setw (2) << tc.frame() << "\n" <<
216#else
217	    setw (2) << right << tc.hours() << ":" <<
218	    setw (2) << right << tc.minutes() << ":" <<
219	    setw (2) << right << tc.seconds() << ":" <<
220	    setw (2) << right << tc.frame() << "\n" <<
221#endif
222	    setfill (' ') <<
223	    "    "
224	    "drop frame " << tc.dropFrame() << ", "
225	    "color frame " << tc.colorFrame() << ", "
226	    "field/phase " << tc.fieldPhase() << "\n"
227	    "    "
228	    "bgf0 " << tc.bgf0() << ", "
229	    "bgf1 " << tc.bgf1() << ", "
230	    "bgf2 " << tc.bgf2() << "\n"
231	    "    "
232	    "user data 0x" << hex << tc.userData() << dec;
233}
234
235
236void
237printEnvmap (Envmap e)
238{
239    switch (e)
240    {
241      case ENVMAP_LATLONG:
242	cout << "latitude-longitude map";
243	break;
244
245      case ENVMAP_CUBE:
246	cout << "cube-face map";
247	break;
248
249      default:
250	cout << "map type " << int (e);
251	break;
252    }
253}
254
255
256void
257printChannelList (const ChannelList &cl)
258{
259    for (ChannelList::ConstIterator i = cl.begin(); i != cl.end(); ++i)
260    {
261	cout << "\n    " << i.name() << ", ";
262
263	printPixelType (i.channel().type);
264
265	cout << ", sampling " <<
266		i.channel().xSampling << " " <<
267		i.channel().ySampling;
268
269	if (i.channel().pLinear)
270	    cout << ", plinear";
271    }
272}
273
274
275void
276printInfo (const char fileName[])
277{
278    InputFile in (fileName);
279    const Header &h = in.header();
280
281    cout << "\n" << fileName <<
282	    (in.isComplete()? "": " (incomplete file)") <<
283	    ":\n\n";
284
285    cout << "file format version: " <<
286	    getVersion (in.version()) << ", "
287	    "flags 0x" <<
288	    setbase (16) << getFlags (in.version()) << setbase (10) << "\n";
289
290    for (Header::ConstIterator i = h.begin(); i != h.end(); ++i)
291    {
292	const Attribute *a = &i.attribute();
293	cout << i.name() << " (type " << a->typeName() << ")";
294
295	if (const Box2iAttribute *ta =
296		dynamic_cast <const Box2iAttribute *> (a))
297	{
298	    cout << ": " << ta->value().min << " - " << ta->value().max;
299	}
300	else if (const Box2fAttribute *ta =
301		dynamic_cast <const Box2fAttribute *> (a))
302	{
303	    cout << ": " << ta->value().min << " - " << ta->value().max;
304	}
305	else if (const ChannelListAttribute *ta =
306		dynamic_cast <const ChannelListAttribute *> (a))
307	{
308	    cout << ":";
309	    printChannelList (ta->value());
310	}
311	else if (const ChromaticitiesAttribute *ta =
312		dynamic_cast <const ChromaticitiesAttribute *> (a))
313	{
314	    cout << ":\n"
315		    "    red   " << ta->value().red << "\n"
316		    "    green " << ta->value().green << "\n"
317		    "    blue  " << ta->value().blue << "\n"
318		    "    white " << ta->value().white;
319	}
320	else if (const CompressionAttribute *ta =
321		dynamic_cast <const CompressionAttribute *> (a))
322	{
323	    cout << ": ";
324	    printCompression (ta->value());
325	}
326	else if (const DoubleAttribute *ta =
327		dynamic_cast <const DoubleAttribute *> (a))
328	{
329	    cout << ": " << ta->value();
330	}
331	else if (const EnvmapAttribute *ta =
332		dynamic_cast <const EnvmapAttribute *> (a))
333	{
334	    cout << ": ";
335	    printEnvmap (ta->value());
336	}
337	else if (const FloatAttribute *ta =
338		dynamic_cast <const FloatAttribute *> (a))
339	{
340	    cout << ": " << ta->value();
341	}
342	else if (const IntAttribute *ta =
343		dynamic_cast <const IntAttribute *> (a))
344	{
345	    cout << ": " << ta->value();
346	}
347	else if (const KeyCodeAttribute *ta =
348		dynamic_cast <const KeyCodeAttribute *> (a))
349	{
350	    cout << ":\n"
351		    "    film manufacturer code " <<
352			    ta->value().filmMfcCode() << "\n"
353		    "    film type code " <<
354			    ta->value().filmType() << "\n"
355		    "    prefix " <<
356			    ta->value().prefix() << "\n"
357		    "    count " <<
358			    ta->value().count() << "\n"
359		    "    perf offset " <<
360			    ta->value().perfOffset() << "\n"
361		    "    perfs per frame " <<
362			    ta->value().perfsPerFrame() << "\n"
363		    "    perfs per count " <<
364			    ta->value().perfsPerCount();
365	}
366	else if (const LineOrderAttribute *ta =
367		dynamic_cast <const LineOrderAttribute *> (a))
368	{
369	    cout << ": ";
370	    printLineOrder (ta->value());
371	}
372	else if (const M33fAttribute *ta =
373		dynamic_cast <const M33fAttribute *> (a))
374	{
375	    cout << ":\n"
376		    "   (" <<
377		    ta->value()[0][0] << " " <<
378		    ta->value()[0][1] << " " <<
379		    ta->value()[0][2] << "\n    " <<
380		    ta->value()[1][0] << " " <<
381		    ta->value()[1][1] << " " <<
382		    ta->value()[1][2] << "\n    " <<
383		    ta->value()[2][0] << " " <<
384		    ta->value()[2][1] << " " <<
385		    ta->value()[2][2] << ")";
386	}
387	else if (const M44fAttribute *ta =
388		dynamic_cast <const M44fAttribute *> (a))
389	{
390	    cout << ":\n"
391		    "   (" <<
392		    ta->value()[0][0] << " " <<
393		    ta->value()[0][1] << " " <<
394		    ta->value()[0][2] << " " <<
395		    ta->value()[0][3] << "\n    " <<
396		    ta->value()[1][0] << " " <<
397		    ta->value()[1][1] << " " <<
398		    ta->value()[1][2] << " " <<
399		    ta->value()[1][3] << "\n    " <<
400		    ta->value()[2][0] << " " <<
401		    ta->value()[2][1] << " " <<
402		    ta->value()[2][2] << " " <<
403		    ta->value()[2][3] << "\n    " <<
404		    ta->value()[3][0] << " " <<
405		    ta->value()[3][1] << " " <<
406		    ta->value()[3][2] << " " <<
407		    ta->value()[3][3] << ")";
408	}
409	else if (const PreviewImageAttribute *ta =
410		dynamic_cast <const PreviewImageAttribute *> (a))
411	{
412	    cout << ": " <<
413		    ta->value().width()  << " by " <<
414		    ta->value().height() << " pixels";
415	}
416	else if (const StringAttribute *ta =
417		dynamic_cast <const StringAttribute *> (a))
418	{
419	    cout << ": \"" << ta->value() << "\"";
420	}
421	else if (const RationalAttribute *ta =
422		dynamic_cast <const RationalAttribute *> (a))
423	{
424	    cout << ": " << ta->value().n << "/" << ta->value().d <<
425		    " (" << double (ta->value()) << ")";
426	}
427	else if (const TileDescriptionAttribute *ta =
428		dynamic_cast <const TileDescriptionAttribute *> (a))
429	{
430	    cout << ":\n    ";
431
432	    printLevelMode (ta->value().mode);
433
434	    cout << "\n    tile size " <<
435		    ta->value().xSize << " by " <<
436		    ta->value().ySize << " pixels";
437
438	    if (ta->value().mode != ONE_LEVEL)
439	    {
440		cout << "\n    level sizes rounded ";
441		printLevelRoundingMode (ta->value().roundingMode);
442	    }
443	}
444	else if (const TimeCodeAttribute *ta =
445		dynamic_cast <const TimeCodeAttribute *> (a))
446	{
447	    cout << ":\n";
448	    printTimeCode (ta->value());
449	}
450	else if (const V2iAttribute *ta =
451		dynamic_cast <const V2iAttribute *> (a))
452	{
453	    cout << ": " << ta->value();
454	}
455	else if (const V2fAttribute *ta =
456		dynamic_cast <const V2fAttribute *> (a))
457	{
458	    cout << ": " << ta->value();
459	}
460	else if (const V3iAttribute *ta =
461		dynamic_cast <const V3iAttribute *> (a))
462	{
463	    cout << ": " << ta->value();
464	}
465	else if (const V3fAttribute *ta =
466		dynamic_cast <const V3fAttribute *> (a))
467	{
468	    cout << ": " << ta->value();
469	}
470
471	cout << '\n';
472    }
473
474    cout << endl;
475}
476
477
478int
479main(int argc, char **argv)
480{
481    if (argc < 2)
482    {
483	std::cerr << "usage: " << argv[0] << " imagefile [imagefile ...]\n";
484	return 1;
485    }
486    else
487    {
488	try
489	{
490	    for (int i = 1; i < argc; ++i)
491		printInfo (argv[i]);
492
493	    return 0;
494	}
495	catch (const std::exception &e)
496	{
497	    std::cerr << e.what() << std::endl;
498	    return 1;
499	}
500    }
501}
502