diff --git a/rtdata/languages/default b/rtdata/languages/default index ed2abf661..0f78a9076 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -863,7 +863,8 @@ TP_HSVEQUALIZER_VAL;V TP_ICM_FILEDLGFILTERANY;Any files TP_ICM_FILEDLGFILTERICM;ICC Profile Files TP_ICM_GAMMABEFOREINPUT;Profile applies Gamma -TP_ICM_INPUTCAMERA;Camera default +TP_ICM_INPUTCAMERA;Camera standard +TP_ICM_INPUTCAMERAICC;Camera standard or ICC TP_ICM_INPUTCUSTOM;Custom TP_ICM_INPUTDLGLABEL;Select Input ICC Profile... TP_ICM_INPUTEMBEDDED;Use Embedded, if possible diff --git a/rtengine/iccstore.cc b/rtengine/iccstore.cc index aa37532de..3a408327a 100644 --- a/rtengine/iccstore.cc +++ b/rtengine/iccstore.cc @@ -174,6 +174,17 @@ cmsHPROFILE ICCStore::getProfile (Glib::ustring name) { return NULL; } +cmsHPROFILE ICCStore::getStdProfile (Glib::ustring name) { + + Glib::Mutex::Lock lock(mutex_); + + + std::map::iterator r = fileStdProfiles.find (name.uppercase()); + if (r==fileProfiles.end()) return NULL; + + return r->second; +} + ProfileContent ICCStore::getContent (Glib::ustring name) { Glib::Mutex::Lock lock(mutex_); @@ -181,24 +192,30 @@ ProfileContent ICCStore::getContent (Glib::ustring name) { return fileProfileContents[name]; } -std::vector ICCStore::parseDir (Glib::ustring pdir) { +// Reads all profiles from the given profiles dir +void ICCStore::init (Glib::ustring usrICCDir, Glib::ustring stdICCDir) { Glib::Mutex::Lock lock(mutex_); - fileProfiles.clear (); - fileProfileContents.clear (); - std::vector result; - if (pdir!="") { + // Load these to different areas, since the short name (e.g. "NIKON D700" may overlap between system/user and RT dir) + loadICCs(usrICCDir, false, fileProfiles, fileProfileContents); + loadICCs(stdICCDir, true, fileStdProfiles, fileStdProfileContents); +} + +void ICCStore::loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map &resultProfileContents) { + resultProfiles.clear (); + resultProfileContents.clear (); + + if (rootDirName!="") { // process directory - Glib::ustring dirname = pdir; + Glib::ustring dirname = rootDirName; Glib::Dir* dir = NULL; try { - if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) - return result; + if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) return; dir = new Glib::Dir (dirname); } catch (Glib::Exception& fe) { - return result; + return; } dirname = dirname + "/"; for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) { @@ -208,15 +225,13 @@ std::vector ICCStore::parseDir (Glib::ustring pdir) { if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) { int lastdot = sname.find_last_of ('.'); if (lastdot!=Glib::ustring::npos && lastdot<=(int)sname.size()-4 && (!sname.casefold().compare (lastdot, 4, ".icm") || !sname.casefold().compare (lastdot, 4, ".icc"))) { -// printf ("processing file %s...\n", fname.c_str()); - Glib::ustring name = sname.substr(0,lastdot); + Glib::ustring name = nameUpper ? sname.substr(0,lastdot).uppercase() : sname.substr(0,lastdot); ProfileContent pc (fname); if (pc.data) { cmsHPROFILE profile = pc.toProfile (); if (profile) { - fileProfiles[name] = profile; - fileProfileContents[name] = pc; - result.push_back (name); + resultProfiles[name] = profile; + resultProfileContents[name] = pc; } } } @@ -224,7 +239,6 @@ std::vector ICCStore::parseDir (Glib::ustring pdir) { } delete dir; } - return result; } // Determine the first monitor default profile of operating system, if selected diff --git a/rtengine/iccstore.h b/rtengine/iccstore.h index 1f0751c99..0086e4e35 100644 --- a/rtengine/iccstore.h +++ b/rtengine/iccstore.h @@ -49,15 +49,21 @@ class ICCStore { std::map wMatrices; std::map iwMatrices; + // these contain profiles from user/system directory (supplied on init) std::map fileProfiles; std::map fileProfileContents; + // these contain standard profiles from RT. keys are all in uppercase + std::map fileStdProfiles; + std::map fileStdProfileContents; + cmsHPROFILE xyz; cmsHPROFILE srgb; Glib::Mutex mutex_; ICCStore (); + void loadICCs(Glib::ustring rootDirName, bool nameUpper, std::map& resultProfiles, std::map &resultProfileContents); public: @@ -74,7 +80,9 @@ class ICCStore { TMatrix workingSpaceInverseMatrix (Glib::ustring name); cmsHPROFILE getProfile (Glib::ustring name); - std::vector parseDir (Glib::ustring pdir); + cmsHPROFILE getStdProfile(Glib::ustring name); + + void init (Glib::ustring usrICCDir, Glib::ustring stdICCDir); ProfileContent getContent (Glib::ustring name); cmsHPROFILE getXYZProfile () { return xyz; } diff --git a/rtengine/init.cc b/rtengine/init.cc index a55615f27..f8ac24b11 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -31,10 +31,10 @@ const Settings* settings; Glib::Mutex* lcmsMutex = NULL; -int init (const Settings* s) { +int init (const Settings* s, Glib::ustring baseDir) { settings = s; - iccStore->parseDir (s->iccDirectory); + iccStore->init (s->iccDirectory, baseDir + "/iccprofiles"); iccStore->findDefaultMonitorProfile(); CurveFactory::init (); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 1c5eb1872..c330fb551 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -420,7 +420,7 @@ void RawImageSource::getImage (ColorTemp ctemp, int tran, Imagefloat* image, Pre // Color correction (only when running on full resolution) if (ri->isBayer() && pp.skip==1) processFalseColorCorrection (image, raw.ccSteps); - colorSpaceConversion (image, cmp, embProfile, camProfile, xyz_cam, defGain); + colorSpaceConversion (image, cmp, embProfile, camProfile, xyz_cam, ((const ImageData*)getMetaData())->getCamera(), defGain); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1563,47 +1563,18 @@ void RawImageSource::processFalseColorCorrection (Imagefloat* im, int steps) { //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +// Converts raw image including ICC input profile to working space - floating point version +void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], std::string camName, double& defgain) { -void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], double& defgain) { - - //camMatrix is cam2xyz = xyz_cam - - if (cmp.input == "(none)") - return; - - - MyTime t1, t2, t3; - - t1.set (); + //MyTime t1, t2, t3; + //t1.set (); cmsHPROFILE in; - cmsHPROFILE out; + if (!findInputProfile(cmp.input, embedded, camName, in)) return; - Glib::ustring inProfile = cmp.input; - - if (inProfile=="(embedded)") { - if (embedded) - in = embedded; - else - in = camprofile; - } - else if (inProfile=="(camera)" || inProfile=="") - in = camprofile; - else { - in = iccStore->getProfile (inProfile); - if (in==NULL) - inProfile = "(camera)"; - } - - - if (inProfile=="(camera)" || inProfile=="" || (inProfile=="(embedded)" && !embedded)) { - // use default profiles supplied by dcraw + if (in==NULL) { + // use default camprofile, supplied by dcraw // in this case we avoid using the slllllooooooowwww lcms - -// out = iccStore->workingSpace (wProfile); -// hTransform = cmsCreateTransform (in, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), out, (FLOAT_SH(1)|COLORSPACE_SH(PT_RGB)|CHANNELS_SH(3)|BYTES_SH(4)|PLANAR_SH(1)), settings->colorimetricIntent, cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT);//cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT); -// cmsDoTransform (hTransform, im->data, im->data, im->planestride/2); -// cmsDeleteTransform(hTransform); TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); float mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; for (int i=0; i<3; i++) @@ -1633,7 +1604,7 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams im->g[h][w] /= 65535.0f ; im->b[h][w] /= 65535.0f ; } - out = iccStore->workingSpace (cmp.working); + cmsHPROFILE out = iccStore->workingSpace (cmp.working); // out = iccStore->workingSpaceGamma (wProfile); lcmsMutex->lock (); @@ -1678,53 +1649,21 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams im->b[h][w] *= 65535.0 ; } } - t3.set (); + + //t3.set (); // printf ("ICM TIME: %d\n", t3.etime(t1)); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], double& defgain) { - - //camMatrix is cam2xyz = xyz_cam - - if (cmp.input == "(none)") - return; - - //MyTime t1, t2, t3; - //t1.set (); +// Converts raw image including ICC input profile to working space - 16bit int version +void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], std::string camName, double& defgain) { cmsHPROFILE in; - cmsHPROFILE out; + if (!findInputProfile(cmp.input, embedded, camName, in)) return; - Glib::ustring inProfile = cmp.input; - - if (inProfile=="(embedded)") { - if (embedded) - in = embedded; - else - in = camprofile; - } - else if (inProfile=="(camera)" || inProfile=="") - in = camprofile; - else { - in = iccStore->getProfile (inProfile); - if (in==NULL) - inProfile = "(camera)"; - } - - - if (inProfile=="(camera)" || inProfile=="" || (inProfile=="(embedded)" && !embedded)) { - -/* out = iccStore->workingSpace (cmp.working); - - lcmsMutex->lock (); - cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, cmsFLAGS_NOCACHE); //cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT);//cmsFLAGS_MATRIXINPUT | cmsFLAGS_MATRIXOUTPUT); - lcmsMutex->unlock (); - - im->ExecCMSTransform(hTransform, settings->LCMSSafeMode); - cmsDeleteTransform(hTransform); -*/ + if (in==NULL) { + // Take camprofile from DCRAW // in this case we avoid using the slllllooooooowwww lcms TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; @@ -1747,7 +1686,7 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); } } else { - out = iccStore->workingSpace (cmp.working); + cmsHPROFILE out = iccStore->workingSpace (cmp.working); // out = iccStore->workingSpaceGamma (wProfile); lcmsMutex->lock (); cmsHTRANSFORM hTransform = cmsCreateTransform (in, TYPE_RGB_16_PLANAR, out, TYPE_RGB_16_PLANAR, settings->colorimetricIntent, @@ -1786,6 +1725,25 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working); // printf ("ICM TIME: %d\n", t3.etime(t1)); } +// Determine RAW input and output profiles. Returns TRUE on success +bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, cmsHPROFILE& in) { + in=NULL; // cam will be taken on NULL + + if (inProfile == "(none)") return false; + + if (inProfile == "(embedded)" && embedded) { + in = embedded; + } else if (inProfile=="(cameraICC)") { + in = iccStore->getStdProfile(camName); + } else if (inProfile!="(camera)" && inProfile!="") { + in = iccStore->getProfile (inProfile); + } + + // "in" might be NULL because of "not found". That's ok, we take the cam profile then + + return true; +} + //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // derived from Dcraw "blend_highlights()" // very effective to reduce (or remove) the magenta, but with levels of grey ! diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 5da8708ad..94ebd994b 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -23,6 +23,7 @@ #include #include #include +#include #define HR_SCALE 2 @@ -59,6 +60,7 @@ class RawImageSource : public ImageSource { private: static LUTf invGrad; // for fast_demosaic static LUTf initInvGrad (); + static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, cmsHPROFILE& in); protected: Glib::Mutex getImageMutex; // locks getImage @@ -154,8 +156,8 @@ class RawImageSource : public ImageSource { void getAutoExpHistogram (LUTu & histogram, int& histcompr); void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw); - static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], double& defgain); - static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], double& defgain); + static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName, double& defgain); + static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName, double& defgain); static void inverse33 (double (*coeff)[3], double (*icoeff)[3]); void boxblur2(float** src, float** dst, int H, int W, int box ); diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 15354737f..4555cd8bb 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -75,6 +75,9 @@ namespace rtengine { virtual std::string getMake () const =0; /** @return the model of the camera */ virtual std::string getModel () const =0; + + std::string getCamera () const { return getMake() + " " + getModel(); } + /** @return the lens on the camera */ virtual std::string getLens () const =0; /** Functions to convert between floating point and string representation of shutter and aperture */ @@ -309,8 +312,8 @@ namespace rtengine { /** * Initializes the RT engine - * @param s is a struct of basic settings */ - int init (const Settings* s); + * @param s is a struct of basic settings, baseDir of RT */ + int init (const Settings* s, Glib::ustring baseDir); /** Cleanup the RT engine (static variables) */ void cleanup (); diff --git a/rtengine/rtetest.cc b/rtengine/rtetest.cc index ab46a4dfb..0b507d560 100644 --- a/rtengine/rtetest.cc +++ b/rtengine/rtetest.cc @@ -47,7 +47,7 @@ int main (int argc, char* argv[]) { s.monitorProfile = ""; Glib::thread_init (); - rtengine::init (s); + rtengine::init (s,""); PListener pl; rtengine::InitialImage* ii; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index 07cb7a0b8..08fa784ba 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -573,7 +573,7 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int } // Full thumbnail processing, second stage if complete profile exists -IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, double& myscale) { +IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName, double& myscale) { // compute WB multipliers ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green); @@ -676,7 +676,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei */ // perform color space transformation if (isRaw) - RawImageSource::colorSpaceConversion16 (resImg, params.icm, embProfile, camProfile, cam2xyz, logDefGain); + RawImageSource::colorSpaceConversion16 (resImg, params.icm, embProfile, camProfile, cam2xyz, camName, logDefGain ); else StdImageSource::colorSpaceConversion16 (resImg, params.icm, embProfile); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index ac189f42e..935095e9d 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -70,7 +70,7 @@ namespace rtengine { static void cleanupGamma (); void init (); - IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale); + IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, double& scale); IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale); int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio); void getDimensions (int& w, int& h, double& scaleFac); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index aff271c9b..7a8b67955 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -49,6 +49,9 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), icamera = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCAMERA"))); pack_start (*icamera, Gtk::PACK_SHRINK, 4); + icameraICC = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCAMERAICC"))); + pack_start (*icameraICC, Gtk::PACK_SHRINK, 4); + ifromfile = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCUSTOM")+":")); Gtk::HBox* ffbox = Gtk::manage (new Gtk::HBox ()); ffbox->pack_start (*ifromfile, Gtk::PACK_SHRINK); @@ -57,6 +60,7 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), pack_start (*ffbox, Gtk::PACK_SHRINK, 4); opts = icamera->get_group(); + icameraICC->set_group (opts); iembedded->set_group (opts); ifromfile->set_group (opts); inone->set_group (opts); @@ -167,6 +171,7 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL), wgamma->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::gpChanged) ); icamera->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); + icameraICC->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); iembedded->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); ifromfile->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) ); igamma->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::profAppGammaChanged) ); @@ -189,13 +194,17 @@ void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) { iembedded->set_active (true); igamma->set_sensitive (false); } + else if ((pp->icm.input == "(cameraICC)") && icameraICC->get_state()!=Gtk::STATE_INSENSITIVE) { + icameraICC->set_active (true); + igamma->set_sensitive (false); + } else if ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()!=Gtk::STATE_INSENSITIVE) { icamera->set_active (true); igamma->set_sensitive (false); } else { ifromfile->set_active (true); - oldip = pp->icm.input.substr(5); + oldip = pp->icm.input.substr(5); // cut of "file:" ipDialog->set_filename (pp->icm.input.substr(5)); igamma->set_sensitive (true); } @@ -253,6 +262,8 @@ void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) { pp->icm.input = "(embedded)"; else if (icamera->get_active ()) pp->icm.input = "(camera)"; + else if (icameraICC->get_active ()) + pp->icm.input = "(cameraICC)"; else { pp->icm.input = "file:"+ipDialog->get_filename (); @@ -344,6 +355,10 @@ void ICMPanel::ipChanged () { profname = "(camera)"; igamma->set_sensitive (false); } + else if (icameraICC->get_active ()) { + profname = "(cameraICC)"; + igamma->set_sensitive (false); + } else { profname = ipDialog->get_filename (); igamma->set_sensitive (true); @@ -400,6 +415,7 @@ void ICMPanel::setRaw (bool raw) { icamera->set_active (raw); iembedded->set_active (!raw); icamera->set_sensitive (raw); + icameraICC->set_sensitive (raw); iembedded->set_sensitive (!raw); enableListener (); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index b508c7cdc..496911399 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -44,6 +44,7 @@ class ICMPanel : public Gtk::VBox, public AdjusterListener, public FoldableToolP Gtk::RadioButton* iembedded; Gtk::RadioButton* icamera; + Gtk::RadioButton* icameraICC; Gtk::RadioButton* ifromfile; Gtk::CheckButton* igamma; Gtk::ComboBoxText* wnames; diff --git a/rtgui/options.cc b/rtgui/options.cc index 126432aff..6598f6fb4 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -712,7 +712,7 @@ void Options::load () { langMgr.load(localeTranslation, new MultiLangMgr(languageTranslation, new MultiLangMgr(defaultTranslation))); - rtengine::init (&options.rtSettings); + rtengine::init (&options.rtSettings, argv0); } void Options::save () { diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 584817759..20ea707dc 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -446,7 +446,7 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro else { // Full thumbnail: apply profile - image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, scale); + image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, scale ); } tpp->getDimensions(lastW,lastH,lastScale); @@ -471,7 +471,7 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro return 0; } - rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, scale); + rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, scale ); tpp->getDimensions(lastW,lastH,lastScale); delete tpp; @@ -555,7 +555,7 @@ void Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaData cfs.timeValid = true; cfs.exifValid = true; cfs.lens = idata->getLens(); - cfs.camera = idata->getMake() + " " + idata->getModel(); + cfs.camera = idata->getCamera(); } else { cfs.lens = "Unknown";