From 5c631343fd0258e69a1e47196703c53d37e2a144 Mon Sep 17 00:00:00 2001 From: Ingo Date: Tue, 10 Dec 2013 20:54:44 +0100 Subject: [PATCH] Enhanced lens info and filter possibilities for Nikon shooters when using manual lenses, Issue 2113 --- rtengine/imagedata.cc | 58 ++++++++++++++++++++++++++------------- rtexif/nikonattribs.cc | 62 ++++++++++++++++++++++++++++++++---------- 2 files changed, 86 insertions(+), 34 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index b3b454ae2..1f7c7d2bb 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -39,7 +39,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) { size_t dotpos = fname.find_last_of ('.'); root = NULL; iptc = NULL; - + if (ri && (ri->exifBase>=0 || ri->ciffBase>=0)) { FILE* f = safe_g_fopen (fname, "rb"); if (f) { @@ -47,7 +47,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) { root = rtexif::ExifManager::parse (f, ri->exifBase); if (root) { rtexif::Tag* t = root->getTag (0x83BB); - if (t) + if (t) iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); } } @@ -56,7 +56,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) { fclose (f); extractInfo (); } - } + } else if ((dotposgetTag (0x83BB); - if (t) + if (t) iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); } } - } + } else { root = new rtexif::TagDirectory (); shutter = 0; @@ -98,7 +98,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) { void ImageData::extractInfo () { - if (!root) + if (!root) return; make = ""; @@ -113,7 +113,7 @@ void ImageData::extractInfo () { iso_speed = 0; memset (&time, 0, sizeof(time)); timeStamp = 0; - + if (root->getTag ("Make")){ make = root->getTag ("Make")->valueToString (); // same dcraw treatment @@ -154,9 +154,9 @@ void ImageData::extractInfo () { rtexif::TagDirectory* exif = NULL; if (root->getTag ("Exif")) exif = root->getTag ("Exif")->getDirectory (); - + if (exif) { - + // standard exif tags if (exif->getTag ("ShutterSpeedValue")) shutter = exif->getTag ("ShutterSpeedValue")->toDouble (); @@ -177,7 +177,7 @@ void ImageData::extractInfo () { int num=-3, denom=-3; // First try, offical EXIF. Set by Adobe on some DNGs - rtexif::Tag* pDst=exif->getTag("SubjectDistance"); + rtexif::Tag* pDst=exif->getTag("SubjectDistance"); if (pDst) { int num, denom; pDst->toRational(num,denom); @@ -188,7 +188,7 @@ void ImageData::extractInfo () { } if (num!=-3) { - if ((denom==1 && num>=10000) || num<0 || denom<0) + if ((denom==1 && num>=10000) || num<0 || denom<0) focus_dist=10000; // infinity else if (denom>0) { focus_dist=(float)num/denom; @@ -232,6 +232,18 @@ void ImageData::extractInfo () { lens = ldata.substr (pos + 7); if (lens.compare (0, 7, "Unknown")) lensOk = true; + else { + int pos = lens.find("$FL$"); // is there a placeholder for focallength? + if(pos != Glib::ustring::npos) { // then fill in focallength + lens = lens.replace(pos,4,exif->getTag ("FocalLength")->valueToString ()); + if(mnote->getTag ("LensType")) { + std::string ltype = mnote->getTag ("LensType")->valueToString (); + if(ltype.find("MF = Yes")!=Glib::ustring::npos) // check, whether it's a MF lens, should be always + lens = lens.replace(0,7,"MF"); + lensOk = true; + } + } + } } } if (!lensOk && mnote->getTag ("Lens")) { @@ -255,6 +267,14 @@ void ImageData::extractInfo () { else str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3]; lens = str.str(); + // Look whether it's MF or AF + if(mnote->getTag ("LensType")) { + std::string ltype = mnote->getTag ("LensType")->valueToString (); + if(ltype.find("MF = Yes")!=Glib::ustring::npos) // check, whether it's a MF lens + lens = lens.replace(0,7,"MF"); // replace 'Unknwon' with 'MF' + else + lens = lens.replace(0,7,"AF"); // replace 'Unknwon' with 'AF' + } } } else if (mnote && !make.compare (0, 5, "Canon")) { @@ -285,7 +305,7 @@ void ImageData::extractInfo () { } } else if (mnote && !make.compare (0, 6, "PENTAX")) { - if (mnote->getTag ("LensType")) + if (mnote->getTag ("LensType")) lens = mnote->getTag ("LensType")->valueToString (); // Try to get the FocalLength from the LensInfo structure, where length below 10mm will be correctly set @@ -301,7 +321,7 @@ void ImageData::extractInfo () { focal_len35mm = mnote->getTag ("FocalLengthIn35mmFilm")->toDouble (); } else if (mnote && (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA"))) { - if (mnote->getTag ("LensID")) + if (mnote->getTag ("LensID")) lens = mnote->getTag ("LensID")->valueToString (); } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { @@ -324,7 +344,7 @@ void ImageData::extractInfo () { ImageData::~ImageData () { delete root; - if (iptc) + if (iptc) iptc_data_free (iptc); } @@ -333,7 +353,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const { procparams::IPTCPairs iptcc; if (!iptc) return iptcc; - + unsigned char buffer[2100]; for (int i=0; i<16; i++) { IptcDataSet* ds = iptc_data_get_next_dataset (iptc, NULL, IPTC_RECORD_APP_2, strTags[i].tag); @@ -406,7 +426,7 @@ double ImageMetaData::shutterFromString (std::string s) { size_t i = s.find_first_of ('/'); if (i==std::string::npos) return atof (s.c_str()); - else + else return atof (s.substr(0,i).c_str()) / atof (s.substr(i+1).c_str()); } @@ -441,7 +461,7 @@ iptc_data_new_from_jpeg_file (FILE *infile) return NULL; d = iptc_data_new (); - if (!d) + if (!d) return NULL; buf = (unsigned char*)iptc_mem_alloc (d->priv->mem, buf_len); diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc index 2bf8ab250..c3fe42e69 100644 --- a/rtexif/nikonattribs.cc +++ b/rtexif/nikonattribs.cc @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -722,12 +722,12 @@ class NALensDataInterpreter : public Interpreter { 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } }; int ver = (t->toInt (0, BYTE) - '0') * 1000 + (t->toInt (1, BYTE) - '0') * 100 + (t->toInt (2, BYTE) - '0') * 10 + (t->toInt (3, BYTE) - '0'); - + std::ostringstream ld; ld << "Version = " << ver << std::endl; - + int lenstype = t->getParent()->getTag(0x0083)->toInt(0,BYTE); - + std::ostringstream lid; lid.setf (std::ios_base::hex, std::ios_base::basefield); lid.setf (std::ios_base::uppercase); @@ -748,7 +748,7 @@ class NALensDataInterpreter : public Interpreter { } unsigned char buffer[16]; - if (d100) + if (d100) memcpy (buffer, t->getValue()+6, 7); else memcpy (buffer, t->getValue()+4, 16); @@ -769,38 +769,70 @@ class NALensDataInterpreter : public Interpreter { for (int i=0; i < 16; i++) buffer[i] ^= (cj += ci * ck++); } - + + std::string EffectiveMaxApertureString = ""; if (!d100) { + int EffectiveMaxApertureValue; if( ver<204 ){ ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl; ld << "AFAperture = " << (int) buffer[1] << std::endl; ld << "FocusPosition = " << (int) buffer[4] << std::endl; ld << "FocusDistance = " << (int) buffer[5] << std::endl; ld << "FocalLength = " << (int) buffer[6] << std::endl; - ld << "EffectiveMaxAperture = " << (int) buffer[14] << std::endl; + EffectiveMaxApertureValue = (int) buffer[14]; }else{ ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl; ld << "AFAperture = " << (int) buffer[1] << std::endl; ld << "FocusPosition = " << (int) buffer[4] << std::endl; ld << "FocusDistance = " << (int) buffer[6] << std::endl; ld << "FocalLength = " << (int) buffer[7] << std::endl; - ld << "EffectiveMaxAperture = " << (int) buffer[15] << std::endl; + EffectiveMaxApertureValue = (int) buffer[15]; } + switch (EffectiveMaxApertureValue) { + case 0x8: EffectiveMaxApertureString = "1.2";break; + case 0xc: EffectiveMaxApertureString = "1.4";break; + case 0x14: EffectiveMaxApertureString = "1.8";break; + case 0x18: EffectiveMaxApertureString = "2.0";break; + case 0x20: EffectiveMaxApertureString = "2.5";break; + case 0x24: EffectiveMaxApertureString = "2.8";break; + case 0x2a: EffectiveMaxApertureString = "3.3";break; + case 0x2c: EffectiveMaxApertureString = "3.5";break; + case 0x30: EffectiveMaxApertureString = "4.0";break; + case 0x34: EffectiveMaxApertureString = "4.5";break; + case 0x38: EffectiveMaxApertureString = "5.0";break; + case 0x3c: EffectiveMaxApertureString = "5.6";break; + case 0x40: EffectiveMaxApertureString = "6.3";break; + case 0x44: EffectiveMaxApertureString = "7.1";break; + case 0x48: EffectiveMaxApertureString = "8.0";break; + case 0x4e: EffectiveMaxApertureString = "9.5";break; + case 0x54: EffectiveMaxApertureString = "11.0";break; + case 0x5a: EffectiveMaxApertureString = "13.0";break; + case 0x5e: EffectiveMaxApertureString = "15.0";break; + case 0x60: EffectiveMaxApertureString = "16.0";break; + case 0x66: EffectiveMaxApertureString = "19.0";break; + case 0x6c: EffectiveMaxApertureString = "22.0";break; + default : EffectiveMaxApertureString = ""; + } + ld << "EffectiveMaxAperture = " << EffectiveMaxApertureString << std::endl; } - + for (int i=0; i<7; i++) lid << std::setw(2) << std::setfill('0') << (int)buffer[lidoffs+i] << ' '; - lid << std::setw(2) << std::setfill('0') << lenstype; - + lid << std::setw(2) << std::setfill('0') << lenstype; + std::map::iterator r = lenses.find (lid.str()); - if (r!=lenses.end()) - ld << "Lens = " << r->second; + if (r!=lenses.end()){ + if(r==lenses.begin() && EffectiveMaxApertureString != "") // first entry is for unchipped lenses + ld << "Lens = Unknown $FL$mm f/" << EffectiveMaxApertureString; + else + ld << "Lens = " << r->second; + } else ld << "Lens = Unknown, ID=" << lid.str(); - + return ld.str(); } - + }; NALensDataInterpreter naLensDataInterpreter;