1/* exif-content.c
2 *
3 * Copyright  2002,2003 Hans Meine <hans_meine@gmx.net>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA  02110-1301  USA.
19 */
20
21#include "exif.hxx"
22#include <string>
23#include <iostream>
24
25#include <Python.h>
26#include <boost/python.hpp>
27using namespace boost::python;
28
29template<class Wrapper, class Pointer>
30struct WrappedObjectIterator
31{
32	//typedef Wrapper value_type;
33	Pointer *it_, *end_;
34
35	WrappedObjectIterator(Pointer *it, Pointer *end)
36		: it_(it), end_(end)
37	{}
38
39	Wrapper next()
40	{
41		if(it_ == end_)
42		{
43			PyErr_SetString(PyExc_StopIteration, "iterator exhausted");
44			throw_error_already_set();
45		}
46		return Wrapper(*it_++);
47	}
48};
49
50struct PythonEntry : public Exif::Entry
51{
52	PythonEntry() {}
53	PythonEntry(Exif::Entry const &other) : Exif::Entry(other) {}
54
55	object component(long index) const
56	{
57		switch(format())
58		{
59		case EXIF_FORMAT_BYTE:
60			return object(getByte(index));
61		case EXIF_FORMAT_SHORT:
62			return object(getShort(index));
63		case EXIF_FORMAT_LONG:
64			return object(getLong(index));
65		case EXIF_FORMAT_SLONG:
66			return object(getSLong(index));
67		case EXIF_FORMAT_RATIONAL:
68			return object(getRational(index));
69		case EXIF_FORMAT_SRATIONAL:
70			return object(getSRational(index));
71		case EXIF_FORMAT_ASCII:
72			//std::cerr << "returning " << entry_->size << " bytes of data..\n";
73			//std::cerr << " (copied into " << std::string((char *)data, entry_->size).size() << "-character string)\n";
74			return object(std::string((char *)entry_->data, entry_->size));
75		default:
76			break;
77		}
78		return object();
79	}
80
81	object data() const
82	{
83		if((format() == EXIF_FORMAT_ASCII) || (components()==1))
84			return component(0);
85		else
86		{
87			list result;
88			for(unsigned int i=0; i<components(); ++i)
89				result.append(component(i));
90			return result;
91		}
92	}
93
94	template<class Type>
95	Type extractComponent(unsigned int index, object value,
96						  const char *errorString)
97	{
98		extract<Type> extr(value);
99		if(!extr.check())
100		{
101			PyErr_SetString(PyExc_TypeError, errorString);
102			throw_error_already_set();
103		}
104		return extr();
105	}
106
107	void setComponent(unsigned int index, object value)
108	{
109		unsigned char *data= entry_->data
110							 + index * exif_format_get_size(format());
111		ExifByteOrder bo = exif_data_get_byte_order(entry_->parent->parent);
112
113		switch(format())
114		{
115		case EXIF_FORMAT_BYTE:
116			*data= extractComponent<ExifByte>(index, value, "invalid assignment to data: could not convert value to byte format");
117			break;
118		case EXIF_FORMAT_SHORT:
119			exif_set_short(data, bo, extractComponent<ExifShort>(index, value, "invalid assignment to data: could not convert value to short format"));
120			break;
121		case EXIF_FORMAT_LONG:
122			exif_set_long(data, bo, extractComponent<ExifLong>(index, value, "invalid assignment to data: could not convert value to long format"));
123			break;
124		case EXIF_FORMAT_SLONG:
125			exif_set_slong(data, bo, extractComponent<ExifSLong>(index, value, "invalid assignment to data: could not convert value to signed long format"));
126			break;
127		case EXIF_FORMAT_RATIONAL:
128			exif_set_rational(data, bo, extractComponent<ExifRational>(index, value, "invalid assignment to data: could not convert value to rational format (2-tuple expected)"));
129			break;
130		case EXIF_FORMAT_SRATIONAL:
131			exif_set_srational(data, bo, extractComponent<ExifSRational>(index, value, "invalid assignment to data: could not convert value to signed rational format (2-tuple expected)"));
132			break;
133		case EXIF_FORMAT_ASCII: // handled in setData directly
134		case EXIF_FORMAT_UNDEFINED:
135			break;
136		}
137		return;
138	}
139
140	void setData(object data)
141	{
142		if(format() == EXIF_FORMAT_ASCII)
143		{
144			extract<std::string> xstr(data);
145			if(xstr.check())
146			{
147				std::string s= xstr();
148				if(entry_->data)
149					free(entry_->data);
150				entry_->components= s.size();
151				//std::cerr << "assigning " << s.size() << "-character string..\n";
152				entry_->size=
153					exif_format_get_size(format()) * entry_->components;
154				entry_->data= (unsigned char *)malloc(entry_->size);
155				memcpy(entry_->data, s.data(), entry_->size);
156				entry_->data[entry_->size]= 0;
157			}
158			else
159			{
160				PyErr_SetString(PyExc_TypeError,
161								"invalid assignment to data of ASCII format entry: string expected");
162				throw_error_already_set();
163			}
164		}
165		else
166		{
167			if(components()==1)
168				setComponent(0, data);
169			else
170			{
171				extract<list> xlist(data);
172				if(xlist.check())
173				{
174					list l= xlist();
175					for(unsigned i=0; i<components(); ++i)
176						setComponent(i, l[i]);
177				}
178				else
179				{
180					PyErr_SetString(PyExc_TypeError,
181									"invalid assignment to data of entry with more than one component: list expected");
182					throw_error_already_set();
183				}
184			}
185		}
186	}
187};
188
189struct PythonContent : public Exif::Content
190{
191	typedef WrappedObjectIterator<PythonEntry, ExifEntry *> iterator;
192
193	PythonContent() {}
194	PythonContent(Exif::Content const &other) : Exif::Content(other) {}
195
196	PythonEntry entry(object index)
197	{
198		// TODO: use Exif::Content::entry() functions
199
200		extract<ExifTag> xtag(index);
201		if(xtag.check())
202		{
203			ExifTag index= xtag();
204			for(unsigned int i=0; i<size(); i++)
205			{
206				if(content_->entries[i]->tag == index)
207					return Exif::Entry(content_->entries[i]);
208			}
209			PyErr_SetString(PyExc_KeyError,
210							"tag not present in IFD content");
211			throw_error_already_set();
212		}
213		extract<int> xint(index);
214		if(xint.check())
215		{
216			int index= xint();
217			if((index>=0) && (index<(long)size()))
218				return Exif::Entry(content_->entries[index]);
219			if((index<0) && (index>=-(long)size()))
220				return Exif::Entry(content_->entries[size()+index]);
221			PyErr_SetString(PyExc_IndexError,
222							"invalid integer index into IFD content");
223			throw_error_already_set();
224		}
225		PyErr_SetString(PyExc_TypeError,
226						"invalid index into EXIF data (integer or IFD expected)");
227		throw_error_already_set();
228		return Exif::Entry(); // never reached
229	}
230
231	iterator __iter__()
232	{
233		// FIXME: the public API is exif_content_foreach,
234		// relying on memory layout here!
235		return iterator(content_->entries,
236						content_->entries + content_->count);
237	}
238};
239
240struct PythonData : public Exif::Data
241{
242	typedef WrappedObjectIterator<PythonContent, ExifContent *> iterator;
243	bool success_;
244
245	PythonData() {}
246	PythonData(const char *path)
247	: Exif::Data(path, &success_)
248	{
249		if(!success_)
250		{
251			PyErr_SetFromErrno(PyExc_IOError);
252			//PyErr_SetString(PyExc_IOError, "");
253			throw_error_already_set();
254		}
255	}
256	PythonData(const unsigned char *data,
257			   unsigned int size) : Exif::Data(data, size) {}
258	PythonData(Exif::Data const &other) : Exif::Data(other) {}
259
260	PythonContent ifdContent(object index)
261	{
262		extract<ExifIfd> xifd(index);
263		if(xifd.check())
264		{
265			ExifIfd index= xifd();
266			if(index<EXIF_IFD_COUNT)
267				return Exif::Content(data_->ifd[index]);
268			PyErr_SetString(PyExc_IndexError,
269							"invalid IFD index into EXIF data");
270			throw_error_already_set();
271		}
272		extract<int> xint(index);
273		if(xint.check())
274		{
275			int index= xint();
276			if((index>=0) && (index<(long)size()))
277				return Exif::Content(data_->ifd[index]);
278			if((index<0) && (index>=-(long)size()))
279				return Exif::Content(data_->ifd[size()+index]);
280			PyErr_SetString(PyExc_IndexError,
281							"invalid integer index into EXIF data");
282			throw_error_already_set();
283		}
284		PyErr_SetString(PyExc_TypeError,
285						"invalid index into EXIF data (integer or IFD expected)");
286		throw_error_already_set();
287		return Exif::Content(); // never reached
288	}
289
290	iterator __iter__()
291	{
292		return iterator(data_->ifd, data_->ifd + EXIF_IFD_COUNT);
293	}
294};
295
296template<class Rational, class Component>
297struct RationalConverter
298{
299	RationalConverter()
300	{
301		converter::registry::insert(&convertible, &construct,
302									type_id<Rational>());
303	}
304
305    static void* convertible(PyObject* obj)
306    {
307		extract<tuple> xtup(obj);
308		if(xtup.check())
309		{
310			tuple t= xtup();
311			if((t.attr("__len__")() == 2) &&
312			   extract<Component>(t[0]).check() &&
313			   extract<Component>(t[1]).check())
314			{
315				Rational *result = new Rational;
316				result->numerator =   extract<Component>(t[0])();
317				result->denominator = extract<Component>(t[1])();
318				return result;
319			}
320		}
321		return NULL;
322    }
323
324    static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data* data)
325    {
326		Rational const* r =
327			static_cast<Rational*>(data->convertible);
328        void* storage =
329			((converter::rvalue_from_python_storage<Rational>*)data)->storage.bytes;
330        new (storage) Rational();
331		((Rational*)storage)->numerator = r->numerator;
332		((Rational*)storage)->denominator = r->denominator;
333        data->convertible = storage;
334		delete r;
335	}
336
337	static PyObject *convert(Rational r)
338	{
339		tuple t= make_tuple(r.numerator, r.denominator);
340		PyObject *result= t.ptr();
341		Py_INCREF(result);
342		return result;
343	}
344};
345
346BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(entrydumps, Exif::Entry::dump, 0, 1)
347BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(contentdumps, Exif::Content::dump, 0, 1)
348
349BOOST_PYTHON_MODULE(exif)
350{
351	RationalConverter<ExifRational, ExifLong>();
352	RationalConverter<ExifSRational, ExifSLong>();
353	to_python_converter<ExifRational,
354		RationalConverter<ExifRational, ExifLong> >();
355	to_python_converter<ExifSRational,
356		RationalConverter<ExifSRational, ExifSLong> >();
357
358	enum_<ExifByteOrder>("ByteOrder")
359		.value("MOTOROLA", EXIF_BYTE_ORDER_MOTOROLA)
360		.value("INTEL", EXIF_BYTE_ORDER_INTEL);
361
362	def("name", &exif_byte_order_get_name);
363
364	enum_<ExifIfd>("IFD")
365		.value("ZERO", EXIF_IFD_0)
366		.value("ONE", EXIF_IFD_1)
367		.value("EXIF", EXIF_IFD_EXIF)
368		.value("GPS", EXIF_IFD_GPS)
369		.value("INTEROPERABILITY", EXIF_IFD_INTEROPERABILITY);
370	//.value("COUNT", EXIF_IFD_COUNT)
371
372	def("name", &exif_ifd_get_name);
373
374	enum_<ExifFormat>("Format")
375		.value("BYTE", EXIF_FORMAT_BYTE)
376		.value("ASCII", EXIF_FORMAT_ASCII)
377		.value("SHORT", EXIF_FORMAT_SHORT)
378		.value("LONG", EXIF_FORMAT_LONG)
379		.value("RATIONAL", EXIF_FORMAT_RATIONAL)
380		.value("UNDEFINED", EXIF_FORMAT_UNDEFINED)
381		.value("SLONG", EXIF_FORMAT_SLONG)
382		.value("SRATIONAL", EXIF_FORMAT_SRATIONAL);
383
384	def("name", &exif_format_get_name);
385	def("size", &exif_format_get_size);
386
387	enum_<ExifTag>("Tag")
388		.value("INTEROPERABILITY_INDEX", EXIF_TAG_INTEROPERABILITY_INDEX)
389		.value("INTEROPERABILITY_VERSION", EXIF_TAG_INTEROPERABILITY_VERSION)
390		.value("IMAGE_WIDTH", EXIF_TAG_IMAGE_WIDTH)
391		.value("IMAGE_LENGTH", EXIF_TAG_IMAGE_LENGTH)
392		.value("BITS_PER_SAMPLE", EXIF_TAG_BITS_PER_SAMPLE)
393		.value("COMPRESSION", EXIF_TAG_COMPRESSION)
394		.value("PHOTOMETRIC_INTERPRETATION", EXIF_TAG_PHOTOMETRIC_INTERPRETATION)
395		.value("FILL_ORDER", EXIF_TAG_FILL_ORDER)
396		.value("DOCUMENT_NAME", EXIF_TAG_DOCUMENT_NAME)
397		.value("IMAGE_DESCRIPTION", EXIF_TAG_IMAGE_DESCRIPTION)
398		.value("MAKE", EXIF_TAG_MAKE)
399		.value("MODEL", EXIF_TAG_MODEL)
400		.value("STRIP_OFFSETS", EXIF_TAG_STRIP_OFFSETS)
401		.value("ORIENTATION", EXIF_TAG_ORIENTATION)
402		.value("SAMPLES_PER_PIXEL", EXIF_TAG_SAMPLES_PER_PIXEL)
403		.value("ROWS_PER_STRIP", EXIF_TAG_ROWS_PER_STRIP)
404		.value("STRIP_BYTE_COUNTS", EXIF_TAG_STRIP_BYTE_COUNTS)
405		.value("X_RESOLUTION", EXIF_TAG_X_RESOLUTION)
406		.value("Y_RESOLUTION", EXIF_TAG_Y_RESOLUTION)
407		.value("PLANAR_CONFIGURATION", EXIF_TAG_PLANAR_CONFIGURATION)
408		.value("RESOLUTION_UNIT", EXIF_TAG_RESOLUTION_UNIT)
409		.value("TRANSFER_FUNCTION", EXIF_TAG_TRANSFER_FUNCTION)
410		.value("SOFTWARE", EXIF_TAG_SOFTWARE)
411		.value("DATE_TIME", EXIF_TAG_DATE_TIME)
412		.value("ARTIST", EXIF_TAG_ARTIST)
413		.value("WHITE_POINT", EXIF_TAG_WHITE_POINT)
414		.value("PRIMARY_CHROMATICITIES", EXIF_TAG_PRIMARY_CHROMATICITIES)
415		.value("TRANSFER_RANGE", EXIF_TAG_TRANSFER_RANGE)
416		.value("JPEG_PROC", EXIF_TAG_JPEG_PROC)
417		.value("JPEG_INTERCHANGE_FORMAT", EXIF_TAG_JPEG_INTERCHANGE_FORMAT)
418		.value("JPEG_INTERCHANGE_FORMAT_LENGTH", EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH)
419		.value("YCBCR_COEFFICIENTS", EXIF_TAG_YCBCR_COEFFICIENTS)
420		.value("YCBCR_SUB_SAMPLING", EXIF_TAG_YCBCR_SUB_SAMPLING)
421		.value("YCBCR_POSITIONING", EXIF_TAG_YCBCR_POSITIONING)
422		.value("REFERENCE_BLACK_WHITE", EXIF_TAG_REFERENCE_BLACK_WHITE)
423		.value("RELATED_IMAGE_FILE_FORMAT", EXIF_TAG_RELATED_IMAGE_FILE_FORMAT)
424		.value("RELATED_IMAGE_WIDTH", EXIF_TAG_RELATED_IMAGE_WIDTH)
425		.value("RELATED_IMAGE_LENGTH", EXIF_TAG_RELATED_IMAGE_LENGTH)
426		.value("CFA_REPEAT_PATTERN_DIM", EXIF_TAG_CFA_REPEAT_PATTERN_DIM)
427		.value("CFA_PATTERN", EXIF_TAG_CFA_PATTERN)
428		.value("BATTERY_LEVEL", EXIF_TAG_BATTERY_LEVEL)
429		.value("COPYRIGHT", EXIF_TAG_COPYRIGHT)
430		.value("EXPOSURE_TIME", EXIF_TAG_EXPOSURE_TIME)
431		.value("FNUMBER", EXIF_TAG_FNUMBER)
432		.value("IPTC_NAA", EXIF_TAG_IPTC_NAA)
433		.value("EXIF_IFD_POINTER", EXIF_TAG_EXIF_IFD_POINTER)
434		.value("INTER_COLOR_PROFILE", EXIF_TAG_INTER_COLOR_PROFILE)
435		.value("EXPOSURE_PROGRAM", EXIF_TAG_EXPOSURE_PROGRAM)
436		.value("SPECTRAL_SENSITIVITY", EXIF_TAG_SPECTRAL_SENSITIVITY)
437		.value("GPS_INFO_IFD_POINTER", EXIF_TAG_GPS_INFO_IFD_POINTER)
438		.value("ISO_SPEED_RATINGS", EXIF_TAG_ISO_SPEED_RATINGS)
439		.value("OECF", EXIF_TAG_OECF)
440		.value("EXIF_VERSION", EXIF_TAG_EXIF_VERSION)
441		.value("DATE_TIME_ORIGINAL", EXIF_TAG_DATE_TIME_ORIGINAL)
442		.value("DATE_TIME_DIGITIZED", EXIF_TAG_DATE_TIME_DIGITIZED)
443		.value("COMPONENTS_CONFIGURATION", EXIF_TAG_COMPONENTS_CONFIGURATION)
444		.value("COMPRESSED_BITS_PER_PIXEL", EXIF_TAG_COMPRESSED_BITS_PER_PIXEL)
445		.value("SHUTTER_SPEED_VALUE", EXIF_TAG_SHUTTER_SPEED_VALUE)
446		.value("APERTURE_VALUE", EXIF_TAG_APERTURE_VALUE)
447		.value("BRIGHTNESS_VALUE", EXIF_TAG_BRIGHTNESS_VALUE)
448		.value("EXPOSURE_BIAS_VALUE", EXIF_TAG_EXPOSURE_BIAS_VALUE)
449		.value("MAX_APERTURE_VALUE", EXIF_TAG_MAX_APERTURE_VALUE)
450		.value("SUBJECT_DISTANCE", EXIF_TAG_SUBJECT_DISTANCE)
451		.value("METERING_MODE", EXIF_TAG_METERING_MODE)
452		.value("LIGHT_SOURCE", EXIF_TAG_LIGHT_SOURCE)
453		.value("FLASH", EXIF_TAG_FLASH)
454		.value("FOCAL_LENGTH", EXIF_TAG_FOCAL_LENGTH)
455		.value("SUBJECT_AREA", EXIF_TAG_SUBJECT_AREA)
456		.value("MAKER_NOTE", EXIF_TAG_MAKER_NOTE)
457		.value("USER_COMMENT", EXIF_TAG_USER_COMMENT)
458		.value("SUBSEC_TIME", EXIF_TAG_SUBSEC_TIME)
459		.value("SUB_SEC_TIME_ORIGINAL", EXIF_TAG_SUB_SEC_TIME_ORIGINAL)
460		.value("SUB_SEC_TIME_DIGITIZED", EXIF_TAG_SUB_SEC_TIME_DIGITIZED)
461		.value("FLASH_PIX_VERSION", EXIF_TAG_FLASH_PIX_VERSION)
462		.value("COLOR_SPACE", EXIF_TAG_COLOR_SPACE)
463		.value("PIXEL_X_DIMENSION", EXIF_TAG_PIXEL_X_DIMENSION)
464		.value("PIXEL_Y_DIMENSION", EXIF_TAG_PIXEL_Y_DIMENSION)
465		.value("RELATED_SOUND_FILE", EXIF_TAG_RELATED_SOUND_FILE)
466		.value("INTEROPERABILITY_IFD_POINTER", EXIF_TAG_INTEROPERABILITY_IFD_POINTER)
467		.value("FLASH_ENERGY", EXIF_TAG_FLASH_ENERGY)
468		.value("SPATIAL_FREQUENCY_RESPONSE", EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE)
469		.value("FOCAL_PLANE_X_RESOLUTION", EXIF_TAG_FOCAL_PLANE_X_RESOLUTION)
470		.value("FOCAL_PLANE_Y_RESOLUTION", EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION)
471		.value("FOCAL_PLANE_RESOLUTION_UNIT", EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT)
472		.value("SUBJECT_LOCATION", EXIF_TAG_SUBJECT_LOCATION)
473		.value("EXPOSURE_INDEX", EXIF_TAG_EXPOSURE_INDEX)
474		.value("SENSING_METHOD", EXIF_TAG_SENSING_METHOD)
475		.value("FILE_SOURCE", EXIF_TAG_FILE_SOURCE)
476		.value("SCENE_TYPE", EXIF_TAG_SCENE_TYPE)
477		.value("NEW_CFA_PATTERN", EXIF_TAG_NEW_CFA_PATTERN)
478		.value("CUSTOM_RENDERED", EXIF_TAG_CUSTOM_RENDERED)
479		.value("EXPOSURE_MODE", EXIF_TAG_EXPOSURE_MODE)
480		.value("WHITE_BALANCE", EXIF_TAG_WHITE_BALANCE)
481		.value("DIGITAL_ZOOM_RATIO", EXIF_TAG_DIGITAL_ZOOM_RATIO)
482		.value("FOCAL_LENGTH_IN_35MM_FILM", EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM)
483		.value("SCENE_CAPTURE_TYPE", EXIF_TAG_SCENE_CAPTURE_TYPE)
484		.value("GAIN_CONTROL", EXIF_TAG_GAIN_CONTROL)
485		.value("CONTRAST", EXIF_TAG_CONTRAST)
486		.value("SATURATION", EXIF_TAG_SATURATION)
487		.value("SHARPNESS", EXIF_TAG_SHARPNESS)
488		.value("DEVICE_SETTING_DESCRIPTION", EXIF_TAG_DEVICE_SETTING_DESCRIPTION)
489		.value("SUBJECT_DISTANCE_RANGE", EXIF_TAG_SUBJECT_DISTANCE_RANGE)
490		.value("IMAGE_UNIQUE_ID", EXIF_TAG_IMAGE_UNIQUE_ID);
491
492	def("name", &exif_tag_get_name);
493	def("title", &exif_tag_get_title);
494	def("description", &exif_tag_get_description);
495
496	class_<PythonEntry>("Entry")
497		.add_property("tag", &Exif::Entry::tag)
498		.add_property("format", &Exif::Entry::format)
499		.add_property("components", &Exif::Entry::components)
500		.add_property("data", &PythonEntry::data,
501					  &PythonEntry::setData)
502		.def("value", &Exif::Entry::value)
503		.def("briefValue", &Exif::Entry::briefValue)
504		.def("dump", &Exif::Entry::dump);//, entrydumps());
505
506	class_<PythonContent::iterator>("ContentIterator", no_init)
507		.def("next", &PythonContent::iterator::next);
508	class_<PythonContent>("Content")
509		.def("__len__", &Exif::Content::size)
510		.def("__getitem__", &PythonContent::entry)
511		.def("__iter__", &PythonContent::__iter__)
512 		.def("dump", &Exif::Content::dump);//, contentdumps());
513
514	class_<PythonData::iterator>("DataIterator", no_init)
515		.def("next", &PythonData::iterator::next);
516	class_<PythonData>("Data")
517		.def(init<const char *>())
518		.def(init<const unsigned char *, unsigned int>())
519		.def("__len__", &Exif::Data::size)
520		.def("__getitem__", &PythonData::ifdContent)
521		.def("__iter__", &PythonData::__iter__)
522		.def("byteOrder", &Exif::Data::byteOrder)
523		.def("dump", &Exif::Data::dump);
524}
525