1 #include "ImageAttributes.hh"
2 #include <Base/Common/W32Compat.hh>
4 #include <Base/Debug/DebugSimple.hh>
5 #include <Base/Debug/Error.hh>
6 #include <Base/Common/FileHandling.hh>
21 #define METER_PER_INCH 0.0254
36 static TagInfo tag_table[] = {
37 { 0x100, (
char *)
"ImageWidth"},
38 { 0x101, (
char *)
"ImageLength"},
39 { 0x102, (
char *)
"BitsPerSample"},
40 { 0x103, (
char *)
"Compression"},
41 { 0x106, (
char *)
"PhotometricInterpretation"},
42 { 0x10a, (
char *)
"FillOrder"},
43 { 0x10d, (
char *)
"DocumentName"},
44 { 0x10e, (
char *)
"ImageDescription"},
45 { 0x10f, (
char *)
"Make"},
46 { 0x110, (
char *)
"Model"},
47 { 0x111, (
char *)
"StripOffsets"},
48 { 0x112, (
char *)
"Orientation"},
49 { 0x115, (
char *)
"SamplesPerPixel"},
50 { 0x116, (
char *)
"RowsPerStrip"},
51 { 0x117, (
char *)
"StripByteCounts"},
52 { 0x11a, (
char *)
"XResolution"},
53 { 0x11b, (
char *)
"YResolution"},
54 { 0x11c, (
char *)
"PlanarConfiguration"},
55 { 0x128, (
char *)
"ResolutionUnit"},
56 { 0x12d, (
char *)
"TransferFunction"},
57 { 0x131, (
char *)
"Software"},
58 { 0x132, (
char *)
"DateTime"},
59 { 0x13b, (
char *)
"Artist"},
60 { 0x13e, (
char *)
"WhitePoint"},
61 { 0x13f, (
char *)
"PrimaryChromaticities"},
62 { 0x156, (
char *)
"TransferRange"},
63 { 0x200, (
char *)
"JPEGProc"},
64 { 0x201, (
char *)
"JPEGInterchangeFormat"},
65 { 0x202, (
char *)
"JPEGInterchangeFormatLength"},
66 { 0x211, (
char *)
"YCbCrCoefficients"},
67 { 0x212, (
char *)
"YCbCrSubSampling"},
68 { 0x213, (
char *)
"YCbCrPositioning"},
69 { 0x214, (
char *)
"ReferenceBlackWhite"},
70 { 0x1000, (
char *)
"RelatedImageFileFormat"},
71 { 0x1001, (
char *)
"RelatedImageLength"},
72 { 0x1002, (
char *)
"RelatedImageWidth"},
73 { 0x828d, (
char *)
"CFARepeatPatternDim"},
74 { 0x828e, (
char *)
"CFAPattern"},
75 { 0x828f, (
char *)
"BatteryLevel"},
76 { 0x8298, (
char *)
"Copyright"},
77 { 0x829a, (
char *)
"ExposureTime"},
78 { 0x829d, (
char *)
"FNumber"},
79 { 0x83Bb, (
char *)
"IPTC/NAA"},
80 { 0x8769, (
char *)
"ExifOffset"},
81 { 0x8773, (
char *)
"InterColorProfile"},
82 { 0x8822, (
char *)
"ExposureProgram"},
83 { 0x8824, (
char *)
"SpectralSensitivity"},
84 { 0x8825, (
char *)
"GPSInfo"},
85 { 0x8827, (
char *)
"ISOSpeedRatings"},
86 { 0x8828, (
char *)
"OECF"},
87 { 0x8829, (
char *)
"Interlace"},
88 { 0x882a, (
char *)
"TimeZoneOffset"},
89 { 0x882b, (
char *)
"SelfTimerMode"},
90 { 0x9000, (
char *)
"ExifVersion"},
91 { 0x9003, (
char *)
"DateTimeOriginal"},
92 { 0x9004, (
char *)
"DateTimeDigitized"},
93 { 0x9101, (
char *)
"ComponentsConfiguration"},
94 { 0x9102, (
char *)
"CompressedBitsPerPixel"},
95 { 0x9201, (
char *)
"ShutterSpeedValue"},
96 { 0x9202, (
char *)
"ApertureValue"},
97 { 0x9203, (
char *)
"BrightnessValue"},
98 { 0x9204, (
char *)
"ExposureBiasValue"},
99 { 0x9205, (
char *)
"MaxApertureValue"},
100 { 0x9206, (
char *)
"SubjectDistance"},
101 { 0x9207, (
char *)
"MeteringMode"},
102 { 0x9208, (
char *)
"LightSrc"},
103 { 0x9209, (
char *)
"Flash"},
104 { 0x920a, (
char *)
"FocalLength"},
105 { 0x920b, (
char *)
"FlashEnergy"},
106 { 0x920c, (
char *)
"SpatialFrequencyResponse"},
107 { 0x920d, (
char *)
"Noise"},
108 { 0x9211, (
char *)
"ImageNumber"},
109 { 0x9212, (
char *)
"SecurityClassification"},
110 { 0x9213, (
char *)
"ImageHistory"},
111 { 0x9214, (
char *)
"SubjectLocation"},
112 { 0x9215, (
char *)
"ExposureIndex"},
113 { 0x9216, (
char *)
"TIFF/EPStandardID"},
114 { 0x927c, (
char *)
"MakerNote"},
115 { 0x9286, (
char *)
"UserComment"},
116 { 0x9290, (
char *)
"SubSecTime"},
117 { 0x9291, (
char *)
"SubSecTimeOriginal"},
118 { 0x9292, (
char *)
"SubSecTimeDigitized"},
119 { 0xA000, (
char *)
"FlashPixVersion"},
120 { 0xA001, (
char *)
"ColorSpace"},
121 { 0xA002, (
char *)
"ExifImageWidth"},
122 { 0xA003, (
char *)
"ExifImageLength"},
123 { 0xA005, (
char *)
"InteroperabilityOffset"},
124 { 0xA20b, (
char *)
"FlashEnergy"},
125 { 0xA20c, (
char *)
"SpatialFrequencyResponse"},
126 { 0xA20e, (
char *)
"FocalPlaneXResolution"},
127 { 0xA20f, (
char *)
"FocalPlaneYResolution"},
128 { 0xA210, (
char *)
"FocalPlaneResolutionUnit"},
129 { 0xA214, (
char *)
"SubjectLocation"},
130 { 0xA215, (
char *)
"ExposureIndex"},
131 { 0xA217, (
char *)
"SensingMethod"},
132 { 0xA300, (
char *)
"FileSource"},
133 { 0xA301, (
char *)
"SceneType"},
134 { 0xA302, (
char *)
"CFAPattern"},
135 { 0x0000, (
char *) NULL}
148 void ImageAttributes::InitExifTags(){
152 const unsigned int nTags=
sizeof(tag_table) /
sizeof( __typeof__( *tag_table ));
155 const unsigned int nTags = 99;
159 for (
unsigned int i=0; i<nTags; i++){
160 if ((tag_table[i].tag!=0x0) && (tag_table[i].description!=NULL)){
162 this->push_back(
ExifTag(tag_table[i].tag,
163 tag_table[i].description) );
169 int ImageAttributes::Read(
const std::string & filename){
170 return ReadMagickPP(filename);
175 int ImageAttributes::ReadMagickPP(
const std::string & filename){
179 #ifndef BIAS_HAVE_IMAGEMAGICKLIB
180 BIASERR(
"BIAS_HAVE_IMAGEMAGICKLIB not defined. Please recompile BIAS with USE_IMAGEMAGICK enabled to load "<<filename);
186 Magick::InitializeMagick(NULL);
191 return ReadMagickPP(img);
192 }
catch ( Magick::Exception &error_ ) {
193 BIASERR(
"Getting Image attributes from "<<filename<<
" with Magick++ failed."<<endl
194 <<
" Caught exception: "<<endl
195 <<
" "<<error_.what()<<endl );
198 BIASERR(
"Getting Image attributes from "<<filename<<
" with Magick++ failed."<<endl
199 <<
" Caught unspecied (...) exception."<<endl);
206 #ifdef BIAS_HAVE_IMAGEMAGICKLIB
207 int ImageAttributes::ReadMagickPP(Magick::Image & img){
209 ImageAttributes::iterator it;
212 unsigned int index = 0;
213 for (it=this->begin(); it!=this->end(); it++, index++){
216 val=img.attribute(name);
217 if (it->GoodValue( val )){
219 mapValidTags_[it->name]=index;
226 }
catch ( Magick::Exception &error_ ) {
227 BIASERR(
"Getting Image attributes from Magick::Image with Magick++ failed."<<endl
228 <<
" Caught exception: "<<endl
229 <<
" "<<error_.what()<<endl );
232 BIASERR(
"Getting Image attributes from Magick::Image with Magick++ failed."<<endl
233 <<
" Caught unspecified (...) exception."<<endl );
236 return BIAS_IMAGEATTRIBUTES_SUCCESS;
241 std::ostream& ImageAttributes::Print(std::ostream& os,
242 const bool printAll)
const
244 os<<
"ImageAttributes: size="<<this->size()<<endl;
245 ImageAttributes::const_iterator it=this->begin();
246 for (it=this->begin(); it!=(this->end()); it++){
247 if (printAll || it->GoodValue(it->value) ) {
260 return attr.
Print(os);
264 bool ImageAttributes::GetString_(
const string& key,
string& value) {
265 map<string, unsigned int>::iterator it;
266 if ((it = mapValidTags_.find(key))==mapValidTags_.end()) {
267 BIASDOUT(D_EXIF,
"failed to find "<<key);
270 value = (*this)[it->second].value;
271 BIASDOUT(D_EXIF,
"Found "<<key<<
"="<<value);
275 bool ImageAttributes::GetRational_(
const string& key,
double& value) {
277 if (!GetString_(key, thevalue))
return false;
278 string::size_type slashpos = thevalue.find(
'/');
279 string second, first = thevalue.substr(0, slashpos);
280 if (slashpos>=0 && slashpos<(string::size_type)thevalue.size()-1)
281 second = thevalue.substr(slashpos+1,thevalue.size()-1);
282 double dfirst = atof(first.c_str());
283 double dsecond = atof(second.c_str());
284 value = dfirst/dsecond;
288 bool ImageAttributes::GetShort_(
const string& key,
int& value){
296 if (!GetString_(key,thevalue))
return false;
297 value = numeric_limits<int>::max();
298 value = atoi(thevalue.c_str());
299 if (value==numeric_limits<int>::max())
return false;
304 int ImageAttributes::GetFocalLengthMeter(
double &fm) {
305 if (!GetRational_(
"FocalLength",fm))
return -1;
308 BIASDOUT(D_EXIF,
"focal length in meter is "<<fm);
313 int ImageAttributes::GetFocalLengthXPixel(
double &fp) {
314 int res = GetFocalLengthMeter(fp);
315 if (res<0)
return res;
317 res = GetPixelSizeXMeter(pixelsize);
318 if (res<0)
return res;
320 BIASDOUT(D_EXIF,
"FocalLengthXPixel is "<<fp);
324 int ImageAttributes::GetFocalLengthYPixel(
double &fp) {
325 int res = GetFocalLengthMeter(fp);
326 if (res<0)
return res;
328 res = GetPixelSizeYMeter(pixelsize);
329 if (res<0)
return res;
331 BIASDOUT(D_EXIF,
"FocalLengthYPixel is "<<fp);
335 int ImageAttributes::GetPixelSizeXMeter(
double &p) {
336 if (!GetRational_(
"FocalPlaneXResolution", p))
return -1;
337 BIASDOUT(D_EXIF,
"FocalPlaneXResolution is "<<p);
339 if (!GetShort_(
"FocalPlaneResolutionUnit", unit))
return -1;
342 p = METER_PER_INCH / p;
355 int ImageAttributes::GetPixelSizeYMeter(
double &p) {
356 if (!GetRational_(
"FocalPlaneYResolution", p))
return -1;
357 BIASDOUT(D_EXIF,
"FocalPlaneYResolution is "<<p);
359 if (!GetShort_(
"FocalPlaneResolutionUnit", unit))
return -1;
365 p = METER_PER_INCH / p;
378 int ImageAttributes::GetFieldOfViewDegree(
double &x,
double& y) {
381 if (GetImageDimensions(width, height)!=0)
return -1;
382 if (GetFocalLengthXPixel(fp)<0)
return -2;
383 x = 180.0/M_PI *2.0*atan(
double(width)/(2.0*fp));
384 if (GetFocalLengthYPixel(fp)<0)
return -3;
385 y = 180.0/M_PI *2.0*atan(
double(height)/(2.0*fp));
391 int ImageAttributes::GetImageDimensions(
int& width,
int& height) {
392 if (!GetShort_(
"ImageWidth", width)) {
393 if (!GetShort_(
"ExifImageWidth", width)) {
396 if (!GetShort_(
"ExifImageLength", height)) {
401 if (!GetShort_(
"ImageLength", height))
return -1;
406 int ImageAttributes::GetPrincipalPoint(
double& x,
double& y) {
408 if (GetImageDimensions(width, height)!=0)
return -1;
409 x = double(width-1)/2.0;
410 y = double(height-1)/2.0;
414 int ImageAttributes::GetHardwareName(
string& Make,
string& Model){
418 if (!GetString_(
"Make",Make)) res -= 1;
419 if (!GetString_(
"Model",Model)) res -= 2;
424 std::string ImageAttributes::GetIdentifier()
427 if (GetString_(
"Make",tmp) )
id += tmp;
428 else id +=
"Unknown";
430 if (GetString_(
"Model",tmp) )
id += tmp;
431 else id +=
"Unknown";
433 GetFocalLengthMeter(focalmeter);
435 oss<<focalmeter*1000;
436 id +=
" "+oss.str()+
"mm";
helper class containing EXIF Tag info and its's value.
std::ostream & operator<<(std::ostream &os, const Array2D< T > &arg)
static std::string Extension(const std::string &fullname)
Get file extension (without dot!) from given path and filename.
contains all atribute info and values of e.g. a file.
std::ostream & Print(std::ostream &os=std::cout, const bool printAll=false) const
print the content of this to os