• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
27 using namespace boost::python;
28 
29 template<class Wrapper, class Pointer>
30 struct WrappedObjectIterator
31 {
32 	//typedef Wrapper value_type;
33 	Pointer *it_, *end_;
34 
WrappedObjectIteratorWrappedObjectIterator35 	WrappedObjectIterator(Pointer *it, Pointer *end)
36 		: it_(it), end_(end)
37 	{}
38 
nextWrappedObjectIterator39 	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 
50 struct PythonEntry : public Exif::Entry
51 {
PythonEntryPythonEntry52 	PythonEntry() {}
PythonEntryPythonEntry53 	PythonEntry(Exif::Entry const &other) : Exif::Entry(other) {}
54 
componentPythonEntry55 	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 
dataPythonEntry81 	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>
extractComponentPythonEntry95 	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 
setComponentPythonEntry107 	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 
setDataPythonEntry140 	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 
189 struct PythonContent : public Exif::Content
190 {
191 	typedef WrappedObjectIterator<PythonEntry, ExifEntry *> iterator;
192 
PythonContentPythonContent193 	PythonContent() {}
PythonContentPythonContent194 	PythonContent(Exif::Content const &other) : Exif::Content(other) {}
195 
entryPythonContent196 	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 
__iter__PythonContent231 	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 
240 struct PythonData : public Exif::Data
241 {
242 	typedef WrappedObjectIterator<PythonContent, ExifContent *> iterator;
243 	bool success_;
244 
PythonDataPythonData245 	PythonData() {}
PythonDataPythonData246 	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 	}
PythonDataPythonData256 	PythonData(const unsigned char *data,
257 			   unsigned int size) : Exif::Data(data, size) {}
PythonDataPythonData258 	PythonData(Exif::Data const &other) : Exif::Data(other) {}
259 
ifdContentPythonData260 	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 
__iter__PythonData290 	iterator __iter__()
291 	{
292 		return iterator(data_->ifd, data_->ifd + EXIF_IFD_COUNT);
293 	}
294 };
295 
296 template<class Rational, class Component>
297 struct RationalConverter
298 {
RationalConverterRationalConverter299 	RationalConverter()
300 	{
301 		converter::registry::insert(&convertible, &construct,
302 									type_id<Rational>());
303 	}
304 
convertibleRationalConverter305     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 
constructRationalConverter324     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 
convertRationalConverter337 	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 
346 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(entrydumps, Exif::Entry::dump, 0, 1)
347 BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(contentdumps, Exif::Content::dump, 0, 1)
348 
BOOST_PYTHON_MODULE(exif)349 BOOST_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