Enhanced lens info and filter possibilities for Nikon shooters when using manual lenses, Issue 2113
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* RawTherapee is distributed in the hope that it will be useful,
|
* RawTherapee is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* 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 ('.');
|
size_t dotpos = fname.find_last_of ('.');
|
||||||
root = NULL;
|
root = NULL;
|
||||||
iptc = NULL;
|
iptc = NULL;
|
||||||
|
|
||||||
if (ri && (ri->exifBase>=0 || ri->ciffBase>=0)) {
|
if (ri && (ri->exifBase>=0 || ri->ciffBase>=0)) {
|
||||||
FILE* f = safe_g_fopen (fname, "rb");
|
FILE* f = safe_g_fopen (fname, "rb");
|
||||||
if (f) {
|
if (f) {
|
||||||
@@ -47,7 +47,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) {
|
|||||||
root = rtexif::ExifManager::parse (f, ri->exifBase);
|
root = rtexif::ExifManager::parse (f, ri->exifBase);
|
||||||
if (root) {
|
if (root) {
|
||||||
rtexif::Tag* t = root->getTag (0x83BB);
|
rtexif::Tag* t = root->getTag (0x83BB);
|
||||||
if (t)
|
if (t)
|
||||||
iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ());
|
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);
|
fclose (f);
|
||||||
extractInfo ();
|
extractInfo ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((dotpos<fname.size()-3 && !fname.casefold().compare (dotpos, 4, ".jpg")) || (dotpos<fname.size()-4 && !fname.casefold().compare (dotpos, 5, ".jpeg"))) {
|
else if ((dotpos<fname.size()-3 && !fname.casefold().compare (dotpos, 4, ".jpg")) || (dotpos<fname.size()-4 && !fname.casefold().compare (dotpos, 5, ".jpeg"))) {
|
||||||
FILE* f = safe_g_fopen (fname, "rb");
|
FILE* f = safe_g_fopen (fname, "rb");
|
||||||
if (f) {
|
if (f) {
|
||||||
@@ -67,7 +67,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) {
|
|||||||
iptc = iptc_data_new_from_jpeg_file (ff);
|
iptc = iptc_data_new_from_jpeg_file (ff);
|
||||||
fclose (ff);
|
fclose (ff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((dotpos<fname.size()-3 && !fname.casefold().compare (dotpos, 4, ".tif")) || (dotpos<fname.size()-4 && !fname.casefold().compare (dotpos, 5, ".tiff"))) {
|
else if ((dotpos<fname.size()-3 && !fname.casefold().compare (dotpos, 4, ".tif")) || (dotpos<fname.size()-4 && !fname.casefold().compare (dotpos, 5, ".tiff"))) {
|
||||||
FILE* f = safe_g_fopen (fname, "rb");
|
FILE* f = safe_g_fopen (fname, "rb");
|
||||||
if (f) {
|
if (f) {
|
||||||
@@ -76,11 +76,11 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) {
|
|||||||
extractInfo ();
|
extractInfo ();
|
||||||
if (root) {
|
if (root) {
|
||||||
rtexif::Tag* t = root->getTag (0x83BB);
|
rtexif::Tag* t = root->getTag (0x83BB);
|
||||||
if (t)
|
if (t)
|
||||||
iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ());
|
iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
root = new rtexif::TagDirectory ();
|
root = new rtexif::TagDirectory ();
|
||||||
shutter = 0;
|
shutter = 0;
|
||||||
@@ -98,7 +98,7 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) {
|
|||||||
|
|
||||||
void ImageData::extractInfo () {
|
void ImageData::extractInfo () {
|
||||||
|
|
||||||
if (!root)
|
if (!root)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
make = "";
|
make = "";
|
||||||
@@ -113,7 +113,7 @@ void ImageData::extractInfo () {
|
|||||||
iso_speed = 0;
|
iso_speed = 0;
|
||||||
memset (&time, 0, sizeof(time));
|
memset (&time, 0, sizeof(time));
|
||||||
timeStamp = 0;
|
timeStamp = 0;
|
||||||
|
|
||||||
if (root->getTag ("Make")){
|
if (root->getTag ("Make")){
|
||||||
make = root->getTag ("Make")->valueToString ();
|
make = root->getTag ("Make")->valueToString ();
|
||||||
// same dcraw treatment
|
// same dcraw treatment
|
||||||
@@ -154,9 +154,9 @@ void ImageData::extractInfo () {
|
|||||||
rtexif::TagDirectory* exif = NULL;
|
rtexif::TagDirectory* exif = NULL;
|
||||||
if (root->getTag ("Exif"))
|
if (root->getTag ("Exif"))
|
||||||
exif = root->getTag ("Exif")->getDirectory ();
|
exif = root->getTag ("Exif")->getDirectory ();
|
||||||
|
|
||||||
if (exif) {
|
if (exif) {
|
||||||
|
|
||||||
// standard exif tags
|
// standard exif tags
|
||||||
if (exif->getTag ("ShutterSpeedValue"))
|
if (exif->getTag ("ShutterSpeedValue"))
|
||||||
shutter = exif->getTag ("ShutterSpeedValue")->toDouble ();
|
shutter = exif->getTag ("ShutterSpeedValue")->toDouble ();
|
||||||
@@ -177,7 +177,7 @@ void ImageData::extractInfo () {
|
|||||||
int num=-3, denom=-3;
|
int num=-3, denom=-3;
|
||||||
|
|
||||||
// First try, offical EXIF. Set by Adobe on some DNGs
|
// First try, offical EXIF. Set by Adobe on some DNGs
|
||||||
rtexif::Tag* pDst=exif->getTag("SubjectDistance");
|
rtexif::Tag* pDst=exif->getTag("SubjectDistance");
|
||||||
if (pDst) {
|
if (pDst) {
|
||||||
int num, denom;
|
int num, denom;
|
||||||
pDst->toRational(num,denom);
|
pDst->toRational(num,denom);
|
||||||
@@ -188,7 +188,7 @@ void ImageData::extractInfo () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (num!=-3) {
|
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
|
focus_dist=10000; // infinity
|
||||||
else if (denom>0) {
|
else if (denom>0) {
|
||||||
focus_dist=(float)num/denom;
|
focus_dist=(float)num/denom;
|
||||||
@@ -232,6 +232,18 @@ void ImageData::extractInfo () {
|
|||||||
lens = ldata.substr (pos + 7);
|
lens = ldata.substr (pos + 7);
|
||||||
if (lens.compare (0, 7, "Unknown"))
|
if (lens.compare (0, 7, "Unknown"))
|
||||||
lensOk = true;
|
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")) {
|
if (!lensOk && mnote->getTag ("Lens")) {
|
||||||
@@ -255,6 +267,14 @@ void ImageData::extractInfo () {
|
|||||||
else
|
else
|
||||||
str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3];
|
str << "Unknown " << n[0] << "-" << n[1] << "mm F/" << n[2] << "-" << n[3];
|
||||||
lens = str.str();
|
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")) {
|
else if (mnote && !make.compare (0, 5, "Canon")) {
|
||||||
@@ -285,7 +305,7 @@ void ImageData::extractInfo () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mnote && !make.compare (0, 6, "PENTAX")) {
|
else if (mnote && !make.compare (0, 6, "PENTAX")) {
|
||||||
if (mnote->getTag ("LensType"))
|
if (mnote->getTag ("LensType"))
|
||||||
lens = mnote->getTag ("LensType")->valueToString ();
|
lens = mnote->getTag ("LensType")->valueToString ();
|
||||||
|
|
||||||
// Try to get the FocalLength from the LensInfo structure, where length below 10mm will be correctly set
|
// 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 ();
|
focal_len35mm = mnote->getTag ("FocalLengthIn35mmFilm")->toDouble ();
|
||||||
}
|
}
|
||||||
else if (mnote && (!make.compare (0, 4, "SONY") || !make.compare (0, 6, "KONICA"))) {
|
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 ();
|
lens = mnote->getTag ("LensID")->valueToString ();
|
||||||
}
|
}
|
||||||
else if (mnote && !make.compare (0, 7, "OLYMPUS")) {
|
else if (mnote && !make.compare (0, 7, "OLYMPUS")) {
|
||||||
@@ -324,7 +344,7 @@ void ImageData::extractInfo () {
|
|||||||
ImageData::~ImageData () {
|
ImageData::~ImageData () {
|
||||||
|
|
||||||
delete root;
|
delete root;
|
||||||
if (iptc)
|
if (iptc)
|
||||||
iptc_data_free (iptc);
|
iptc_data_free (iptc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +353,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const {
|
|||||||
procparams::IPTCPairs iptcc;
|
procparams::IPTCPairs iptcc;
|
||||||
if (!iptc)
|
if (!iptc)
|
||||||
return iptcc;
|
return iptcc;
|
||||||
|
|
||||||
unsigned char buffer[2100];
|
unsigned char buffer[2100];
|
||||||
for (int i=0; i<16; i++) {
|
for (int i=0; i<16; i++) {
|
||||||
IptcDataSet* ds = iptc_data_get_next_dataset (iptc, NULL, IPTC_RECORD_APP_2, strTags[i].tag);
|
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 ('/');
|
size_t i = s.find_first_of ('/');
|
||||||
if (i==std::string::npos)
|
if (i==std::string::npos)
|
||||||
return atof (s.c_str());
|
return atof (s.c_str());
|
||||||
else
|
else
|
||||||
return atof (s.substr(0,i).c_str()) / atof (s.substr(i+1).c_str());
|
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;
|
return NULL;
|
||||||
|
|
||||||
d = iptc_data_new ();
|
d = iptc_data_new ();
|
||||||
if (!d)
|
if (!d)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
buf = (unsigned char*)iptc_mem_alloc (d->priv->mem, buf_len);
|
buf = (unsigned char*)iptc_mem_alloc (d->priv->mem, buf_len);
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* RawTherapee is distributed in the hope that it will be useful,
|
* RawTherapee is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* 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 } };
|
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');
|
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;
|
std::ostringstream ld;
|
||||||
ld << "Version = " << ver << std::endl;
|
ld << "Version = " << ver << std::endl;
|
||||||
|
|
||||||
int lenstype = t->getParent()->getTag(0x0083)->toInt(0,BYTE);
|
int lenstype = t->getParent()->getTag(0x0083)->toInt(0,BYTE);
|
||||||
|
|
||||||
std::ostringstream lid;
|
std::ostringstream lid;
|
||||||
lid.setf (std::ios_base::hex, std::ios_base::basefield);
|
lid.setf (std::ios_base::hex, std::ios_base::basefield);
|
||||||
lid.setf (std::ios_base::uppercase);
|
lid.setf (std::ios_base::uppercase);
|
||||||
@@ -748,7 +748,7 @@ class NALensDataInterpreter : public Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char buffer[16];
|
unsigned char buffer[16];
|
||||||
if (d100)
|
if (d100)
|
||||||
memcpy (buffer, t->getValue()+6, 7);
|
memcpy (buffer, t->getValue()+6, 7);
|
||||||
else
|
else
|
||||||
memcpy (buffer, t->getValue()+4, 16);
|
memcpy (buffer, t->getValue()+4, 16);
|
||||||
@@ -769,38 +769,70 @@ class NALensDataInterpreter : public Interpreter {
|
|||||||
for (int i=0; i < 16; i++)
|
for (int i=0; i < 16; i++)
|
||||||
buffer[i] ^= (cj += ci * ck++);
|
buffer[i] ^= (cj += ci * ck++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string EffectiveMaxApertureString = "";
|
||||||
if (!d100) {
|
if (!d100) {
|
||||||
|
int EffectiveMaxApertureValue;
|
||||||
if( ver<204 ){
|
if( ver<204 ){
|
||||||
ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl;
|
ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl;
|
||||||
ld << "AFAperture = " << (int) buffer[1] << std::endl;
|
ld << "AFAperture = " << (int) buffer[1] << std::endl;
|
||||||
ld << "FocusPosition = " << (int) buffer[4] << std::endl;
|
ld << "FocusPosition = " << (int) buffer[4] << std::endl;
|
||||||
ld << "FocusDistance = " << (int) buffer[5] << std::endl;
|
ld << "FocusDistance = " << (int) buffer[5] << std::endl;
|
||||||
ld << "FocalLength = " << (int) buffer[6] << std::endl;
|
ld << "FocalLength = " << (int) buffer[6] << std::endl;
|
||||||
ld << "EffectiveMaxAperture = " << (int) buffer[14] << std::endl;
|
EffectiveMaxApertureValue = (int) buffer[14];
|
||||||
}else{
|
}else{
|
||||||
ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl;
|
ld << "ExitPupilPosition = " << (int) buffer[0] << std::endl;
|
||||||
ld << "AFAperture = " << (int) buffer[1] << std::endl;
|
ld << "AFAperture = " << (int) buffer[1] << std::endl;
|
||||||
ld << "FocusPosition = " << (int) buffer[4] << std::endl;
|
ld << "FocusPosition = " << (int) buffer[4] << std::endl;
|
||||||
ld << "FocusDistance = " << (int) buffer[6] << std::endl;
|
ld << "FocusDistance = " << (int) buffer[6] << std::endl;
|
||||||
ld << "FocalLength = " << (int) buffer[7] << 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++)
|
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') << (int)buffer[lidoffs+i] << ' ';
|
||||||
lid << std::setw(2) << std::setfill('0') << lenstype;
|
lid << std::setw(2) << std::setfill('0') << lenstype;
|
||||||
|
|
||||||
std::map<std::string,std::string>::iterator r = lenses.find (lid.str());
|
std::map<std::string,std::string>::iterator r = lenses.find (lid.str());
|
||||||
if (r!=lenses.end())
|
if (r!=lenses.end()){
|
||||||
ld << "Lens = " << r->second;
|
if(r==lenses.begin() && EffectiveMaxApertureString != "") // first entry is for unchipped lenses
|
||||||
|
ld << "Lens = Unknown $FL$mm f/" << EffectiveMaxApertureString;
|
||||||
|
else
|
||||||
|
ld << "Lens = " << r->second;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ld << "Lens = Unknown, ID=" << lid.str();
|
ld << "Lens = Unknown, ID=" << lid.str();
|
||||||
|
|
||||||
return ld.str();
|
return ld.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
NALensDataInterpreter naLensDataInterpreter;
|
NALensDataInterpreter naLensDataInterpreter;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user