PICCANTE  0.4
The hottest HDR imaging library!
exif.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_IO_EXIF
19 #define PIC_IO_EXIF
20 
21 #include <stdio.h>
22 #include <string>
23 
24 #include "../base.hpp"
25 
26 #include "../util/math.hpp"
27 
28 namespace pic {
29 
36 unsigned int twoByteToValue(unsigned char data[2], bool bMotorola)
37 {
38  if(bMotorola) {
39  return (data[0] << 8) + (data[1]);
40  } else {
41  return (data[1] << 8) + (data[0]);
42  }
43 }
44 
51 unsigned int fourByteToValue(unsigned char data[4], bool bMotorola)
52 {
53  if(bMotorola) {
54  return (data[0] << 24) + (data[1] << 16) +
55  (data[2] << 8) + (data[3]);
56  } else {
57  return (data[3] << 24) + (data[2] << 16) +
58  (data[1] << 8) + (data[0]);
59  }
60 }
61 
69 bool checkTag(unsigned char tag[2], unsigned short tag_r, bool bMotorola)
70 {
71  unsigned char tag_ref[2];
72  tag_ref[0] = (tag_r >> 8) & 0x00ff;
73  tag_ref[1] = tag_r & 0x00ff;
74 
75  bool bRet = false;
76  if(bMotorola) {
77  bRet = (tag[0] == tag_ref[0]) && (tag[1] == tag_ref[1]);
78  } else {
79  bRet = (tag[1] == tag_ref[0]) && (tag[0] == tag_ref[1]);
80  }
81 
82  return bRet;
83 }
84 
91 int getTagID(unsigned char tag[2], bool bMotorola)
92 {
93  if(checkTag(tag, 0x829a, bMotorola)) {
94  return 0;
95  }
96 
97  if(checkTag(tag, 0x829d, bMotorola)) {
98  return 1;
99  }
100 
101  if(checkTag(tag, 0x8827, bMotorola)) {
102  return 2;
103  }
104 
105  if(checkTag(tag, 0x9202, bMotorola)) {
106  return 3;
107  }
108 
109  if(checkTag(tag, 0x920a, bMotorola)) {
110  return 4;
111  }
112 
113  return -1;
114 }
115 
121 int getBytesForComponents(int value)
122 {
123  switch(value)
124  {
125  case 1: {
126  return 1;
127  } break;
128 
129  case 2: {
130  return 1;
131  } break;
132 
133  case 3: {
134  return 2;
135  } break;
136 
137  case 4: {
138  return 4;
139  } break;
140 
141  case 5: {
142  return 8;
143  } break;
144 
145  case 6: {
146  return 1;
147  } break;
148 
149  case 7: {
150  return 1;
151  } break;
152 
153  case 8: {
154  return 2;
155  } break;
156 
157  case 9: {
158  return 4;
159  } break;
160 
161  case 10: {
162  return 8;
163  } break;
164 
165  case 11: {
166  return 4;
167  } break;
168 
169  case 12: {
170  return 8;
171  } break;
172 
173  default: {
174  return -1;
175  }
176 
177  }
178 }
179 
186 std::string readString(FILE *file, int length)
187 {
188  char *tmp = new char[length];
189  fread(tmp, 1, length, file);
190  std::string str(tmp);
191 
192  delete[] tmp;
193 
194  return str;
195 }
196 
202 std::string readStringFromUChar(unsigned char *data, int length)
203 {
204  std::string str;
205 
206  for(int i = 0; i < length; i++) {
207  str += (char) data[i];
208  }
209 
210  return str;
211 }
212 
219 float readUnsignedRational(FILE *file, bool bMotorola)
220 {
221  unsigned char val0[4];
222  fread(val0, 1, 4, file);
223 
224  unsigned char val1[4];
225  fread(val1, 1, 4, file);
226 
227  auto num = fourByteToValue(val0, bMotorola);
228  auto denum = fourByteToValue(val1, bMotorola);
229 
230  return float(num) / float(denum);
231 }
232 
233 struct EXIFInfo
234 {
236  float fNumber;
237  float aperture;
238  float iso;
240 
241  std::string camera_maker;
242 };
243 
250 bool readEXIF(std::string name, EXIFInfo &info)
251 {
252  FILE *file = fopen(name.c_str(), "rb");
253 
254  unsigned char buf[2];
255  fread(buf, 1, 2, file);
256 
257  if(!checkTag(buf, 0xffd8, true)) {
258  return false;
259  }
260 
261  unsigned char buf2[2];
262  int length = 0;
263 
264  bool bFound = false;
265  while(!feof(file)) {
266  fread(buf2, 1, 2, file);
267  //printf("%x%x\n", buf2[0], buf2[1]);
268 
269  unsigned char len[2];
270  fread(&len, 1, 2, file);
271 
272  //printf("LEN: %x %x\n", len[0], len[1]);
273  length = (len[0] << 8) + (len[1]);
274 
275  if(checkTag(buf2, 0xffe1, true)) {
276  bFound = true;
277  break;
278  }
279 
280  fseek(file, length - 2, SEEK_CUR);
281  }
282 
283  if(!bFound) {
284  fclose(file);
285  return false;
286  }
287 
288  //EXIF header
289 
290  unsigned char buf6[6];
291  fread(buf6, 1, 6, file);
292 
293  if(buf6[0] != 0x45 || buf6[1] != 0x78 ||
294  buf6[2] != 0x69 || buf6[3] != 0x66 ||
295  buf6[4] != 0x00 || buf6[5] != 0x00) {
296  fclose(file);
297  return false;
298  }
299 
300  //TIFF header
301  fpos_t pos;
302  fgetpos(file, &pos);
303 
304  //is it Motorala mode?
305  fread(buf2, 1, 2, file);
306  bool bMotorola = (buf2[0] == 0x4d) && (buf2[1] == 0x4d);
307 
308  fread(buf2, 1, 2, file);
309  bool bCheck = false;
310 
311  if(!checkTag(buf2, 0x002a, bMotorola)) {
312  fclose(file);
313  return false;
314  }
315 
316  unsigned char buf4[4];
317  fread(buf4, 1, 4, file); //this is the offset
318 
319  if(bMotorola) {
320  bCheck = (buf4[0] == 0x00) && (buf4[1] == 0x00) &&
321  (buf4[2] == 0x00) && (buf4[3] == 0x08);
322  } else {
323  bCheck = (buf4[0] == 0x08) && (buf4[1] == 0x00) &&
324  (buf4[2] == 0x00) && (buf4[3] == 0x00);
325  }
326 
327  if(!bCheck) {
328  fclose(file);
329  return false;
330  }
331 
332  //IFD0: Image file directory
333  fread(buf2, 1, 2, file);
334 
335  int nIFD = twoByteToValue(buf2, bMotorola);
336 
337  //printf("nIFD: %d\n", nIFD);
338 
339  unsigned int offset = 0;
340  for(int i = 0; i < nIFD; i++) {
341  unsigned char tag[2];
342  fread(tag, 1, 2, file); //TAG
343 
344  unsigned char data_format[2];
345  fread(data_format, 1, 2, file); //dataformat
346 
347  unsigned char num_components[4];
348  fread(num_components, 1, 4, file); //number of components
349 
350  unsigned char data[4];
351  fread(data, 1, 4, file); //data or offset to data
352 
353  //maker
354  if(checkTag(tag, 0x010f, bMotorola)) {
355 
356  int df = twoByteToValue(data_format, bMotorola);
357  int nc = fourByteToValue(num_components, bMotorola);
358 
359  int total_data_byte = getBytesForComponents(df) * nc;
360 
361  if(total_data_byte > 4) {
362  int offset = fourByteToValue(data, bMotorola);
363 
364  fpos_t tmp_pos;
365  fgetpos(file, &tmp_pos);
366  fseek(file, offset, SEEK_CUR);
367  info.camera_maker = readString(file, nc);
368  fsetpos(file, &tmp_pos);
369 
370  } else {
371  info.camera_maker = readStringFromUChar(data, nc);
372  }
373  }
374 
375  if(checkTag(tag, 0x8769, bMotorola)) {
376  offset = fourByteToValue(data, bMotorola);
377  }
378  }
379 
380  unsigned char next_IFD[4];
381  fread(next_IFD, 1, 4, file);
382  int offset_next_IFD = fourByteToValue(next_IFD, bMotorola);
383  //printf("OFFSET: %d\n", offset_next_IFD);
384 
385  if(offset > 0) {
386  fsetpos(file, &pos);
387  fseek(file, offset, SEEK_CUR);
388  //NOTE: this works but gives warnings --> fseek(file, pos + offset, SEEK_SET);
389  }
390 
391  //
392  // IFD 1
393  //
394 
395  fread(buf2, 1, 2, file);
396 
397  nIFD = twoByteToValue(buf2, bMotorola);
398 
399  for(int i = 0; i < nIFD; i++) {
400  unsigned char tag[2];
401 
402  fread(tag, 1, 2, file); //TAG
403 
404  unsigned char data_format[2];
405  fread(data_format, 1, 2, file); //dataformat
406 
407  unsigned char num_components[4];
408  fread(num_components, 1, 4, file); //number of components
409 
410  unsigned char data[4];
411  fread(data, 1, 4, file); //data or offset to data
412 
413  int df = twoByteToValue(data_format, bMotorola);
414  int nc = fourByteToValue(num_components, bMotorola);
415  int total_data_byte = getBytesForComponents(df) * nc;
416 
417  int id = getTagID(tag, bMotorola);
418 
419  float data_value = 0;
420  if(total_data_byte > 4) {
421  int offset = fourByteToValue(data, bMotorola);
422 
423  fpos_t tmp_pos;
424  fgetpos(file, &tmp_pos);
425 
426  fsetpos(file, &pos);
427  fseek(file, offset, SEEK_CUR);
428  //fseek(file, pos + offset, SEEK_SET);
429 
430  switch(df) {
431  case 5: {
432  data_value = readUnsignedRational(file, bMotorola);
433  } break;
434  }
435  //unsigned rational
436 
437  fsetpos(file, &tmp_pos);
438  //fseek(file, tmp_pos, SEEK_SET);
439  } else {
440  switch(df) {
441  case 3: {
442  data_value = float(twoByteToValue(data, bMotorola));
443  } break;
444  }
445  }
446 
447  switch(id) {
448  case 0:
449  {
450  info.exposureTime = data_value;
451  } break;
452 
453  case 1:
454  {
455  info.fNumber = data_value;
456 
457  } break;
458 
459  case 2:
460  {
461  info.iso = data_value;
462 
463  } break;
464 
465  case 3:
466  {
467  info.aperture = data_value;
468 
469  } break;
470 
471  case 4:
472  {
473  info.focal_length = data_value;
474  } break;
475 
476  default:
477  {
478 
479  } break;
480 
481  }
482  }
483 
484  #ifdef PIC_DEBUG
485  printf("%f %f %f\n", info.iso, info.exposureTime, info.fNumber);
486  #endif
487 
488  fclose(file);
489 
490  return true;
491 }
492 
493 } // end namespace pic
494 
495 #endif /* PIC_IO_VOL_HPP */
496 
unsigned int twoByteToValue(unsigned char data[2], bool bMotorola)
twoByteToValue
Definition: exif.hpp:36
std::string readString(FILE *file, int length)
readString
Definition: exif.hpp:186
float aperture
Definition: exif.hpp:237
float exposureTime
Definition: exif.hpp:235
float iso
Definition: exif.hpp:238
unsigned int fourByteToValue(unsigned char data[4], bool bMotorola)
fourByteToValue
Definition: exif.hpp:51
Definition: exif.hpp:233
float focal_length
Definition: exif.hpp:239
std::string readStringFromUChar(unsigned char *data, int length)
readStringFromUChar
Definition: exif.hpp:202
bool readEXIF(std::string name, EXIFInfo &info)
readEXIF
Definition: exif.hpp:250
int getBytesForComponents(int value)
getBytesForComponents
Definition: exif.hpp:121
int getTagID(unsigned char tag[2], bool bMotorola)
getTagID
Definition: exif.hpp:91
float fNumber
Definition: exif.hpp:236
Definition: bilateral_separation.hpp:25
std::string camera_maker
Definition: exif.hpp:241
float readUnsignedRational(FILE *file, bool bMotorola)
readUnsignedRational
Definition: exif.hpp:219
bool checkTag(unsigned char tag[2], unsigned short tag_r, bool bMotorola)
checkTag
Definition: exif.hpp:69