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