Merge branch 'dev' into browser-preview-applied-pparams

This commit is contained in:
Lawrence Lee
2023-08-29 22:58:51 -07:00
188 changed files with 12449 additions and 21671 deletions

View File

@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef WIN32
#ifdef _WIN32
#include <windows.h>
#endif
@@ -34,16 +34,78 @@
#include <glibmm/timezone.h>
#include "../rtengine/dynamicprofile.h"
#include "../rtengine/metadata.h"
#include "../rtengine/profilestore.h"
#include "../rtengine/settings.h"
#include "../rtexif/rtexif.h"
#include "guiutils.h"
#include "batchqueue.h"
#include "extprog.h"
#include "md5helper.h"
#include "pathutils.h"
#include "paramsedited.h"
#include "ppversion.h"
#include "procparamchangers.h"
#include "version.h"
namespace {
bool CPBDump(
const Glib::ustring& commFName,
const Glib::ustring& imageFName,
const Glib::ustring& profileFName,
const Glib::ustring& defaultPParams,
const CacheImageData* cfs,
bool flagMode
)
{
const std::unique_ptr<Glib::KeyFile> kf(new Glib::KeyFile);
if (!kf) {
return false;
}
// open the file in write mode
const std::unique_ptr<FILE, decltype(&std::fclose)> f(g_fopen(commFName.c_str (), "wt"), &std::fclose);
if (!f) {
printf ("CPBDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str());
return false;
}
try {
kf->set_string ("RT General", "CachePath", options.cacheBaseDir);
kf->set_string ("RT General", "AppVersion", RTVERSION);
kf->set_integer ("RT General", "ProcParamsVersion", PPVERSION);
kf->set_string ("RT General", "ImageFileName", imageFName);
kf->set_string ("RT General", "OutputProfileFileName", profileFName);
kf->set_string ("RT General", "DefaultProcParams", defaultPParams);
kf->set_boolean ("RT General", "FlaggingMode", flagMode);
kf->set_integer ("Common Data", "FrameCount", cfs->frameCount);
kf->set_integer ("Common Data", "SampleFormat", cfs->sampleFormat);
kf->set_boolean ("Common Data", "IsHDR", cfs->isHDR);
kf->set_boolean ("Common Data", "IsPixelShift", cfs->isPixelShift);
kf->set_double ("Common Data", "FNumber", cfs->fnumber);
kf->set_double ("Common Data", "Shutter", cfs->shutter);
kf->set_double ("Common Data", "FocalLength", cfs->focalLen);
kf->set_integer ("Common Data", "ISO", cfs->iso);
kf->set_string ("Common Data", "Lens", cfs->lens);
kf->set_string ("Common Data", "Make", cfs->camMake);
kf->set_string ("Common Data", "Model", cfs->camModel);
} catch (const Glib::KeyFileError&) {
}
try {
fprintf (f.get(), "%s", kf->to_data().c_str());
} catch (const Glib::KeyFileError&) {
}
return true;
}
} // namespace
using namespace rtengine::procparams;
@@ -86,7 +148,7 @@ Thumbnail::Thumbnail(CacheManager* cm, const Glib::ustring& fname, CacheImageDat
tpp = nullptr;
}
Thumbnail::Thumbnail(CacheManager* cm, const Glib::ustring& fname, const std::string& md5) :
Thumbnail::Thumbnail(CacheManager* cm, const Glib::ustring& fname, const std::string& md5, const std::string &xmpSidecarMd5) :
fname(fname),
cachemgr(cm),
ref(1),
@@ -104,6 +166,7 @@ Thumbnail::Thumbnail(CacheManager* cm, const Glib::ustring& fname, const std::st
cfs.md5 = md5;
cfs.xmpSidecarMd5 = xmpSidecarMd5;
loadProcParams ();
_generateThumbnailImage ();
cfs.recentlySaved = false;
@@ -114,6 +177,11 @@ Thumbnail::Thumbnail(CacheManager* cm, const Glib::ustring& fname, const std::st
tpp = nullptr;
}
Glib::ustring Thumbnail::xmpSidecarPath(const Glib::ustring &imagePath)
{
return rtengine::Exiv2Metadata::xmpSidecarPath(imagePath);
}
void Thumbnail::_generateThumbnailImage ()
{
@@ -163,24 +231,27 @@ void Thumbnail::_generateThumbnailImage ()
// image out of the RAW. Mark as "quick".
// 2. if we don't find that then just grab the real image.
bool quick = false;
rtengine::RawMetaDataLocation ri;
rtengine::eSensorType sensorType = rtengine::ST_NONE;
if ( initial_ && options.internalThumbIfUntouched) {
quick = true;
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, tw, th, 1, TRUE);
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, sensorType, tw, th, 1, TRUE);
}
if ( tpp == nullptr ) {
quick = false;
tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw));
tpp = rtengine::Thumbnail::loadFromRaw (fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw));
}
cfs.sensortype = sensorType;
if (tpp) {
cfs.format = FT_Raw;
cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL;
infoFromImage (fname, std::unique_ptr<rtengine::RawMetaDataLocation>(new rtengine::RawMetaDataLocation(ri)));
infoFromImage (fname);
if (!quick) {
cfs.width = tpp->full_width;
cfs.height = tpp->full_height;
}
}
}
@@ -241,7 +312,6 @@ const ProcParams& Thumbnail::getProcParamsU ()
*/
rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool force, bool flaggingMode)
{
// try to load the last saved parameters from the cache or from the paramfile file
ProcParams* ldprof = nullptr;
@@ -259,52 +329,35 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu
if (!run_cpb) {
if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) {
rtengine::FramesMetaData* imageMetaData;
if (getType() == FT_Raw) {
// Should we ask all frame's MetaData ?
imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr<rtengine::RawMetaDataLocation>(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true);
} else {
// Should we ask all frame's MetaData ?
imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true);
}
PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData, fname);
delete imageMetaData;
int err = pp->pparams->save(outFName);
pp->deleteInstance();
delete pp;
if (!err) {
const auto pp_deleter =
[](PartialProfile* pp)
{
pp->deleteInstance();
delete pp;
};
const std::unique_ptr<const rtengine::FramesMetaData> imageMetaData(rtengine::FramesMetaData::fromFile(fname));
const std::unique_ptr<PartialProfile, decltype(pp_deleter)> pp(
imageMetaData
? ProfileStore::getInstance()->loadDynamicProfile(imageMetaData.get(), fname)
: nullptr,
pp_deleter
);
if (pp && !pp->pparams->save(outFName)) {
loadProcParams();
}
} else if (create && defProf != DEFPROFILE_DYNAMIC) {
const PartialProfile *p = ProfileStore::getInstance()->getProfile(defProf);
const PartialProfile* const p = ProfileStore::getInstance()->getProfile(defProf);
if (p && !p->pparams->save(outFName)) {
loadProcParams();
}
}
} else {
// First generate the communication file, with general values and EXIF metadata
rtengine::FramesMetaData* imageMetaData;
if (getType() == FT_Raw) {
// Should we ask all frame's MetaData ?
imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr<rtengine::RawMetaDataLocation>(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true);
} else {
// Should we ask all frame's MetaData ?
imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true);
}
static int index = 0; // Will act as unique identifier during the session
Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) );
const rtexif::TagDirectory* exifDir = nullptr;
if (imageMetaData && (exifDir = imageMetaData->getRootExifData())) {
exifDir->CPBDump(tmpFileName, fname, outFName,
defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension),
cfs,
flaggingMode);
}
delete imageMetaData;
CPBDump(tmpFileName, fname, outFName,
defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension), cfs, flaggingMode);
// For the filename etc. do NOT use streams, since they are not UTF8 safe
Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\"");
@@ -345,7 +398,7 @@ void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt)
* The result is a complete ProcParams with default values merged with the values
* from the loaded ProcParams (sidecar or cache file).
*/
void Thumbnail::loadProcParams ()
void Thumbnail::loadProcParams()
{
MyMutex::MyLock lock(mutex);
@@ -815,9 +868,14 @@ ThFileType Thumbnail::getType () const
return (ThFileType) cfs.format;
}
int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptr<rtengine::RawMetaDataLocation> rml)
int Thumbnail::infoFromImage (const Glib::ustring& fname)
{
rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, std::move(rml));
return infoFromImage(fname, cfs);
}
int Thumbnail::infoFromImage(const Glib::ustring &fname, CacheImageData &cfs)
{
std::unique_ptr<rtengine::FramesMetaData> idata(rtengine::FramesMetaData::fromFile (fname));
if (!idata) {
return 0;
@@ -878,7 +936,8 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptr<rtengi
cfs.filetype = "";
}
delete idata;
idata->getDimensions(cfs.width, cfs.height);
return deg;
}
@@ -998,6 +1057,10 @@ void Thumbnail::updateCache (bool updatePParams, bool updateCacheImageData)
if (updateCacheImageData) {
cfs.save (getCacheFileName ("data", ".txt"));
}
if (updatePParams && pparamsValid) {
saveMetadata();
}
}
Thumbnail::~Thumbnail ()
@@ -1090,7 +1153,7 @@ void Thumbnail::removeThumbnailListener (ThumbnailListener* tnl)
bool Thumbnail::openDefaultViewer(int destination)
{
#ifdef WIN32
#ifdef _WIN32
Glib::ustring openFName;
if (destination == 1) {
@@ -1176,6 +1239,33 @@ void Thumbnail::getCamWB(double& temp, double& green, rtengine::StandardObserver
}
}
void Thumbnail::saveMetadata()
{
if (options.rtSettings.metadata_xmp_sync != rtengine::Settings::MetadataXmpSync::READ_WRITE) {
return;
}
if (pparams->metadata.exif.empty() && pparams->metadata.iptc.empty()) {
return;
}
auto fn = rtengine::Exiv2Metadata::xmpSidecarPath(fname);
try {
auto xmp = rtengine::Exiv2Metadata::getXmpSidecar(fname);
rtengine::Exiv2Metadata meta;
meta.xmpData() = std::move(xmp);
meta.setExif(pparams->metadata.exif);
meta.setIptc(pparams->metadata.iptc);
meta.saveToXmp(fn);
if (options.rtSettings.verbose) {
std::cout << "saved edited metadata for " << fname << " to "
<< fn << std::endl;
}
} catch (std::exception &exc) {
std::cerr << "ERROR saving metadata for " << fname << " to " << fn
<< ": " << exc.what() << std::endl;
}
}
void Thumbnail::getSpotWB(int x, int y, int rect, double& temp, double& green)
{
if (tpp) {