From f23be9345cbd45e51b64675438637024ad22f9a2 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Tue, 8 Aug 2017 23:42:05 +0200 Subject: [PATCH 01/27] Add multi-frame handling. - Exif of all frames are displayed in the Editor's Exif tab (without separator) - isHDR and isPixelShift is added to the data files stored in cache - In the Editor panel, the QuickInfo frame display the HDR and PixelShift information, as well as the number of frame and bit-depth for HDR image - the number of frame is provided by dcraw. If not set, it is provided by the Exif's main IFD count - the PixelShift information (for Pentax as of now) is provided by looking at the Exif informations - the HDR information is provided by the Exif information of the first frame for Pentax raw files, or by the bitspersample, sampleformat and compression tags for other files TODO: add icons to the thumbnails to tag HDR and PixelShift files. --- rtdata/languages/Francais | 8 + rtdata/languages/default | 8 + rtengine/dcp.cc | 3 +- rtengine/dfmanager.cc | 7 +- rtengine/dynamicprofile.cc | 2 +- rtengine/dynamicprofile.h | 2 +- rtengine/ffmanager.cc | 7 +- rtengine/imagedata.cc | 309 +++++++++++---- rtengine/imagedata.h | 176 ++++++++- rtengine/imageformat.h | 54 +++ rtengine/imageio.h | 26 +- rtengine/imagesource.h | 18 +- rtengine/profilestore.cc | 2 +- rtengine/profilestore.h | 2 +- rtengine/rawimage.h | 2 +- rtengine/rawimagesource.cc | 7 +- rtengine/rawimagesource.h | 4 +- rtengine/rawmetadatalocation.h | 10 +- rtengine/rtengine.h | 71 ++-- rtengine/stdimagesource.cc | 2 +- rtengine/stdimagesource.h | 4 +- rtexif/pentaxattribs.cc | 1 + rtexif/rtexif.cc | 137 +++++-- rtexif/rtexif.h | 47 ++- rtexif/stdattribs.cc | 2 + rtgui/cacheimagedata.cc | 20 +- rtgui/cacheimagedata.h | 4 + rtgui/dynamicprofilepanel.cc | 4 +- rtgui/editorpanel.cc | 21 +- rtgui/exifpanel.cc | 21 +- rtgui/exifpanel.h | 4 +- rtgui/filebrowser.cc | 4 +- rtgui/filecatalog.cc | 2 + rtgui/filterpanel.cc | 12 +- rtgui/icmpanel.cc | 2 +- rtgui/icmpanel.h | 2 +- rtgui/inspector.cc | 2 +- rtgui/iptcpanel.cc | 2 +- rtgui/iptcpanel.h | 2 +- rtgui/lensprofile.cc | 2 +- rtgui/lensprofile.h | 2 +- rtgui/thumbnail.cc | 61 +-- rtgui/toolpanelcoord.cc | 8 +- tools/source_icons/scalable/HDR-thumbnail.svg | 355 ++++++++++++++++++ .../scalable/PixeShift-thumbnail.svg | 353 +++++++++++++++++ 45 files changed, 1529 insertions(+), 265 deletions(-) create mode 100644 rtengine/imageformat.h create mode 100644 tools/source_icons/scalable/HDR-thumbnail.svg create mode 100644 tools/source_icons/scalable/PixeShift-thumbnail.svg diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 65cf503eb..34a9a75a2 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -1155,8 +1155,16 @@ PROGRESSBAR_SAVEPNG;Enregistrement du fichier PNG... PROGRESSBAR_SAVETIFF;Enregistrement du fichier TIFF... PROGRESSBAR_SNAPSHOT_ADDED;Signet ajouté PROGRESSDLG_PROFILECHANGEDINBROWSER;Profil modifié dans le navigateur +QINFO_HDR;HDR / %1 image(s) QINFO_ISO;ISO QINFO_NOEXIF;Données EXIF non disponibles. +QINFO_PIXELSHIFT;PixelShift / %1 images +SAMPLEFORMAT_0;Format de donnée inconnu +SAMPLEFORMAT_1;8 bits non signé +SAMPLEFORMAT_2;16 bits non signé +SAMPLEFORMAT_4;LogLuv 24 bits +SAMPLEFORMAT_8;LogLuv 32 bits +SAMPLEFORMAT_16;32 bits à virgule flottante SAVEDLG_AUTOSUFFIX;Ajouter automatiquement un suffixe si le fichier existe déjà SAVEDLG_FILEFORMAT;Format de fichier SAVEDLG_FORCEFORMATOPTS;Forcer les options d'enregistrement diff --git a/rtdata/languages/default b/rtdata/languages/default index 5f1b4666c..f8d54154c 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1157,8 +1157,16 @@ PROGRESSBAR_SAVEPNG;Saving PNG file... PROGRESSBAR_SAVETIFF;Saving TIFF file... PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +QINFO_HDR;HDR / %1 frame(s) QINFO_ISO;ISO QINFO_NOEXIF;Exif data not available. +QINFO_PIXELSHIFT;PixelShift / %1 frame(s) +SAMPLEFORMAT_0;Unknown data format +SAMPLEFORMAT_1;Unsigned 8 bits +SAMPLEFORMAT_2;Unsigned 16 bits +SAMPLEFORMAT_4;LogLuv 24 bits +SAMPLEFORMAT_8;LogLuv 32 bits +SAMPLEFORMAT_16;32 bits floating point SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists SAVEDLG_FILEFORMAT;File format SAVEDLG_FORCEFORMATOPTS;Force saving options diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 43aa98480..ee0cf3462 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -696,7 +696,8 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : return; } - std::unique_ptr tagDir(ExifManager::parseTIFF(file, false)); + ExifManager exifManager(file, nullptr, true); + std::unique_ptr tagDir(exifManager.parseTIFF(false)); Tag* tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_1)); light_source_1 = diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index bc35b3c71..68123d9b4 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -382,11 +382,8 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool) return &(iter->second); } - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); + RawMetaDataLocation rml(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen()); + FramesData idata(filename, &rml, true); /* Files are added in the map, divided by same maker/model,ISO and shutter*/ std::string key( dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed()) ); iter = dfList.find( key ); diff --git a/rtengine/dynamicprofile.cc b/rtengine/dynamicprofile.cc index 5ac408da5..1afc04446 100644 --- a/rtengine/dynamicprofile.cc +++ b/rtengine/dynamicprofile.cc @@ -72,7 +72,7 @@ bool DynamicProfileRule::operator< (const DynamicProfileRule &other) const } -bool DynamicProfileRule::matches (const rtengine::ImageMetaData *im) const +bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im) const { return (iso (im->getISOSpeed()) && fnumber (im->getFNumber()) diff --git a/rtengine/dynamicprofile.h b/rtengine/dynamicprofile.h index cfe46d9ba..4e6bbbba9 100644 --- a/rtengine/dynamicprofile.h +++ b/rtengine/dynamicprofile.h @@ -48,7 +48,7 @@ public: }; DynamicProfileRule(); - bool matches (const rtengine::ImageMetaData *im) const; + bool matches (const rtengine::FramesMetaData *im) const; bool operator< (const DynamicProfileRule &other) const; int serial_number; diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index 87ae98905..6acdc1b0a 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -338,11 +338,8 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) return &(iter->second); } - RawMetaDataLocation rml; - rml.exifBase = ri.get_exifBase(); - rml.ciffBase = ri.get_ciffBase(); - rml.ciffLength = ri.get_ciffLen(); - ImageData idata(filename, &rml); + RawMetaDataLocation rml(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen()); + FramesData idata(filename, &rml, true); /* Files are added in the map, divided by same maker/model,lens and aperture*/ std::string key( ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()) ); iter = ffList.find( key ); diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 5faa6175e..289fc4a25 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -18,6 +18,7 @@ */ #include #include +#include #include "imagedata.h" #include "iptcpairs.h" @@ -40,57 +41,25 @@ Glib::ustring to_utf8 (const std::string& str) } -ImageMetaData* ImageMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml) +FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml, bool firstFrameOnly) { - - return new ImageData (fname, rml); + return new FramesData (fname, rml, firstFrameOnly); } -ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed(0), aperture(0.), shutter(0.) +FrameData::FrameData () + : root(nullptr), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), + shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), lens("Unknown"), + sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) { memset (&time, 0, sizeof(time)); - root = nullptr; - iptc = nullptr; +} - if (ri && (ri->exifBase >= 0 || ri->ciffBase >= 0)) { - FILE* f = g_fopen (fname.c_str (), "rb"); - - if (f) { - if (ri->exifBase >= 0) { - root = rtexif::ExifManager::parse (f, ri->exifBase); - - if (root) { - rtexif::Tag* t = root->getTag (0x83BB); - - if (t) { - iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); - } - } - } else if (ri->ciffBase >= 0) { - root = rtexif::ExifManager::parseCIFF (f, ri->ciffBase, ri->ciffLength); - } - - fclose (f); - extractInfo (); - } - } else if (hasJpegExtension(fname)) { - FILE* f = g_fopen (fname.c_str (), "rb"); - - if (f) { - root = rtexif::ExifManager::parseJPEG (f); - extractInfo (); - fclose (f); - FILE* ff = g_fopen (fname.c_str (), "rb"); - iptc = iptc_data_new_from_jpeg_file (ff); - fclose (ff); - } - } else if (hasTiffExtension(fname)) { - FILE* f = g_fopen (fname.c_str (), "rb"); - - if (f) { - root = rtexif::ExifManager::parseTIFF (f); - fclose (f); - extractInfo (); +RawFrameData::RawFrameData (rtexif::ExifManager &exifManager) +{ + bool rootCreated = false; + if (exifManager.f && exifManager.rml) { + if (exifManager.rml->exifBase >= 0) { + root = exifManager.parse (); if (root) { rtexif::Tag* t = root->getTag (0x83BB); @@ -98,23 +67,59 @@ ImageData::ImageData (Glib::ustring fname, RawMetaDataLocation* ri) : iso_speed( if (t) { iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); } + extractInfo (); + rootCreated = true; } + } else if (exifManager.rml->ciffBase >= 0) { + root = exifManager.parseCIFF (); + extractInfo (); + rootCreated = true; } - } else { + } + if (!rootCreated) { root = new rtexif::TagDirectory (); - shutter = 0; - aperture = 0; - iso_speed = 0; - lens = "Unknown"; - make = "Unknown"; - model = "Unknown"; - orientation = "Unknown"; - expcomp = 0; - focal_len = 0; } } -void ImageData::extractInfo () +JpegFrameData::JpegFrameData (rtexif::ExifManager &exifManager) +{ + bool rootCreated = false; + if (exifManager.f) { + root = exifManager.parseJPEG (); + if (root) { + extractInfo (); + rootCreated = true; + } + rewind (exifManager.f); // Not sure this is necessary + iptc = iptc_data_new_from_jpeg_file (exifManager.f); + } + if (!rootCreated) { + root = new rtexif::TagDirectory (); + } +} + +TiffFrameData::TiffFrameData (rtexif::ExifManager &exifManager) +{ + bool rootCreated = false; + if (exifManager.f) { + root = exifManager.parseTIFF (); + extractInfo (); + + if (root) { + rtexif::Tag* t = root->getTag (0x83BB); + + if (t) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + } + rootCreated = true; + } + } + if (!rootCreated) { + root = new rtexif::TagDirectory (); + } +} + +void FrameData::extractInfo () { if (!root) { @@ -206,8 +211,13 @@ void ImageData::extractInfo () orientation = root->getTag ("Orientation")->valueToString (); } - rtexif::TagDirectory* exif = nullptr; + rtexif::Tag* mnoteTag = root->findTag("MakerNote"); + rtexif::TagDirectory* mnote = nullptr; + if (mnoteTag) { + mnote = mnoteTag->getDirectory(); + } + rtexif::TagDirectory* exif = nullptr; if (root->getTag ("Exif")) { exif = root->getTag ("Exif")->getDirectory (); } @@ -313,12 +323,10 @@ void ImageData::extractInfo () } if (lens == "Unknown") { - rtexif::Tag* mnoteTag = root->findTag("MakerNote"); - if (mnoteTag) { - rtexif::TagDirectory* mnote = mnoteTag->getDirectory(); + if (mnote) { - if (mnote && !make.compare (0, 5, "NIKON")) { + if (!make.compare (0, 5, "NIKON")) { // ISO at max value supported, check manufacturer specific if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* isoTag = mnote->getTagP("ISOInfo/ISO"); @@ -406,7 +414,7 @@ void ImageData::extractInfo () } } } - } else if (mnote && !make.compare (0, 5, "Canon")) { + } else if (!make.compare (0, 5, "Canon")) { // ISO at max value supported, check manufacturer specific if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* baseIsoTag = mnote->getTagP("CanonShotInfo/BaseISO"); @@ -440,7 +448,7 @@ void ImageData::extractInfo () } } } - } else if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { + } else if (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX"))) { // ISO at max value supported, check manufacturer specific if (iso_speed == 65535 || iso_speed == 0) { rtexif::Tag* baseIsoTag = mnote->getTag("ISO"); @@ -475,7 +483,7 @@ void ImageData::extractInfo () if (mnote->getTag ("LensID")) { lens = mnote->getTag ("LensID")->valueToString (); } - } else if (mnote && !make.compare (0, 7, "OLYMPUS")) { + } else if (!make.compare (0, 7, "OLYMPUS")) { if (mnote->getTag ("Equipment")) { rtexif::TagDirectory* eq = mnote->getTag ("Equipment")->getDirectory (); @@ -504,9 +512,111 @@ void ImageData::extractInfo () } } } + + + // ----------------------- Special file type detection (HDR, PixelShift) ------------------------ + + + uint16 bitspersample = 0, samplesperpixel = 0, sampleformat = 0, photometric = 0, compression = 0; + rtexif::Tag* bps = root->findTag("BitsPerSample"); + rtexif::Tag* spp = root->findTag("SamplesPerPixel"); + rtexif::Tag* sf = root->findTag("SampleFormat"); + rtexif::Tag* pi = root->findTag("PhotometricInterpretation"); + rtexif::Tag* c = root->findTag("Compression"); + + if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { + rtexif::Tag* hdr = mnote->findTag("HDR"); + if (hdr) { + if (hdr->toInt() > 0 && hdr->toInt(2) > 0) { + isHDR = true; + } + } else { + rtexif::Tag* dm = mnote->findTag("DriveMode"); + if (dm) { + char buffer[60]; + dm->toString(buffer, 3); + buffer[3] = 0; + if (!strcmp(buffer, "HDR")) { + isHDR = true; + } + } + } + + if (!isHDR) { + rtexif::Tag* q = mnote->findTag("Quality"); + if (q && q->toInt() == 7) { + isPixelShift = true; + } + } + } + + sampleFormat = IIOSF_UNKNOWN; + + if (!sf) + /* + * WARNING: This is a dirty hack! + * We assume that files which doesn't contain the TIFFTAG_SAMPLEFORMAT tag + * (which is the case with uncompressed TIFFs produced by RT!) are RGB files, + * but that may be not true. --- Hombre + */ + { + sampleformat = SAMPLEFORMAT_UINT; + } else { + sampleformat = sf->toInt(); + } + + if ((!bps & !spp) || !pi) { + return; + } + + samplesperpixel = spp->toInt(); + bitspersample = bps->toInt(); + + photometric = pi->toInt(); + if (photometric == PHOTOMETRIC_LOGLUV) { + if (!c) { + compression = COMPRESSION_NONE; + } else { + compression = c->toInt(); + } + } + + if (photometric == PHOTOMETRIC_RGB || photometric == PHOTOMETRIC_MINISBLACK) { + if ((samplesperpixel == 1 || samplesperpixel == 3 || samplesperpixel == 4) && sampleformat == SAMPLEFORMAT_UINT) { + if (bitspersample == 8) { + sampleFormat = IIOSF_UNSIGNED_CHAR; + } + + if (bitspersample == 16) { + sampleFormat = IIOSF_UNSIGNED_SHORT; + } + } else if (samplesperpixel == 3 && sampleformat == SAMPLEFORMAT_IEEEFP) { + /* + * Not yet supported + * + if (bitspersample==16) { + sampleFormat = IIOSF_HALF; + }*/ + if ((samplesperpixel == 3 || samplesperpixel == 4) && bitspersample == 32) { + sampleFormat = IIOSF_FLOAT; + isHDR = true; + } + } + } else if (photometric == PHOTOMETRIC_CFA) { + // Assuming Bayer or X-Trans raw file deliver 10, 12 14 or 16 bits uint, which is the case as of now + sampleFormat = IIOSF_UNSIGNED_SHORT; + } else if (samplesperpixel == 3 && photometric == PHOTOMETRIC_LOGLUV) { + if (compression == COMPRESSION_SGILOG24) { + sampleFormat = IIOSF_LOGLUV24; + isHDR = true; + } else if (compression == COMPRESSION_SGILOG) { + sampleFormat = IIOSF_LOGLUV32; + isHDR = true; + } + } } -ImageData::~ImageData () +FrameData::~FrameData () { delete root; @@ -516,7 +626,7 @@ ImageData::~ImageData () } } -const procparams::IPTCPairs ImageData::getIPTCData () const +const procparams::IPTCPairs FrameData::getIPTCData () const { procparams::IPTCPairs iptcc; @@ -565,7 +675,7 @@ const procparams::IPTCPairs ImageData::getIPTCData () const //------inherited functions--------------// -std::string ImageMetaData::apertureToString (double aperture) +std::string FramesMetaData::apertureToString (double aperture) { char buffer[256]; @@ -573,7 +683,7 @@ std::string ImageMetaData::apertureToString (double aperture) return buffer; } -std::string ImageMetaData::shutterToString (double shutter) +std::string FramesMetaData::shutterToString (double shutter) { char buffer[256]; @@ -587,7 +697,7 @@ std::string ImageMetaData::shutterToString (double shutter) return buffer; } -std::string ImageMetaData::expcompToString (double expcomp, bool maskZeroexpcomp) +std::string FramesMetaData::expcompToString (double expcomp, bool maskZeroexpcomp) { char buffer[256]; @@ -605,7 +715,7 @@ std::string ImageMetaData::expcompToString (double expcomp, bool maskZeroexpcomp } } -double ImageMetaData::shutterFromString (std::string s) +double FramesMetaData::shutterFromString (std::string s) { size_t i = s.find_first_of ('/'); @@ -617,7 +727,7 @@ double ImageMetaData::shutterFromString (std::string s) } } -double ImageMetaData::apertureFromString (std::string s) +double FramesMetaData::apertureFromString (std::string s) { return atof (s.c_str()); @@ -685,3 +795,60 @@ failure: } } + +FramesData::FramesData (Glib::ustring fname, RawMetaDataLocation* rml, bool firstFrameOnly, bool loadAll) : dcrawFrameCount (0) +{ + if (rml && (rml->exifBase >= 0 || rml->ciffBase >= 0)) { + FILE* f = g_fopen (fname.c_str (), "rb"); + + if (f) { + rtexif::ExifManager exifManager (f, rml, firstFrameOnly); + + if (rml->exifBase >= 0) { + FrameData *idata = new RawFrameData (exifManager); + frames.push_back(idata); + if (rml && !firstFrameOnly) { + while (exifManager.getNextIFDOffset ()) { + int nextIFD = exifManager.getNextIFDOffset (); + exifManager.setIFDOffset (nextIFD); + idata = new RawFrameData (exifManager); + frames.push_back(idata); + } + } + } + fclose (f); + } + } else if (hasJpegExtension(fname)) { + FILE* f = g_fopen (fname.c_str (), "rb"); + + if (f) { + rtexif::ExifManager exifManager (f, rml, true); + FrameData *idata = new JpegFrameData (exifManager); + frames.push_back(idata); + fclose (f); + } + } else if (hasTiffExtension(fname)) { + FILE* f = g_fopen (fname.c_str (), "rb"); + + if (f) { + rtexif::ExifManager exifManager (f, rml, firstFrameOnly); + FrameData *idata = new TiffFrameData (exifManager); + frames.push_back(idata); + if (rml && !firstFrameOnly) { + while (exifManager.getNextIFDOffset ()) { + exifManager.setIFDOffset (exifManager.getNextIFDOffset ()); + idata = new TiffFrameData (exifManager); + frames.push_back(idata); + } + } + fclose (f); + } + } +} + +FramesData::~FramesData () +{ + for (auto currFrame : frames) { + delete currFrame; + } +} diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index f28a49a2f..da5b337cb 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -31,7 +31,7 @@ namespace rtengine { -class ImageData : public ImageMetaData +class FrameData { protected: @@ -49,13 +49,34 @@ protected: std::string make, model, serial; std::string orientation; std::string lens; + IIOSampleFormat sampleFormat; + + // each frame has the knowledge of "being an" + // or "being part of an" HDR or PS image + bool isPixelShift; + int isHDR; // Number of frame void extractInfo (); public: - ImageData (Glib::ustring fname, RawMetaDataLocation* rml = nullptr); - virtual ~ImageData (); + FrameData (); + FrameData (rtexif::ExifManager &exifManager); + virtual ~FrameData (); + + bool getPixelShift () const + { + return isPixelShift; + } + int getHDR () const + { + return isHDR; + } + + IIOSampleFormat getSampleFormat () const + { + return sampleFormat; + } const rtexif::TagDirectory* getExifData () const { @@ -128,5 +149,154 @@ public: return orientation; } }; + +class RawFrameData : public FrameData +{ +public: + RawFrameData (rtexif::ExifManager &exifManager); +}; + +class JpegFrameData : public FrameData +{ +public: + JpegFrameData (rtexif::ExifManager &exifManager); +}; + +class TiffFrameData : public FrameData +{ +public: + TiffFrameData (rtexif::ExifManager &exifManager); +}; + +class FramesData : public FramesMetaData { +private: + std::vector frames; + int dcrawFrameCount; + +public: + FramesData (Glib::ustring fname, RawMetaDataLocation* rml = nullptr, bool firstFrameOnly = false, bool loadAll = false); + ~FramesData (); + + void setDCRawFrameCount (int frameCount) + { + dcrawFrameCount = frameCount; + } + + int getFrameCount () const + { + return dcrawFrameCount ? dcrawFrameCount : frames.size(); + } + FrameData *getFrameData (int frame) const + { + return frames.at(frame); + } + + bool getPixelShift (int frame = 0) const + { + // So far only Pentax provide multi-frame HDR file. + // Only the first frame contains the HDR tag + // If more brand have to be supported, this rule may need + // to evolve + + //return frames.at(frame)->getPixelShift (); + return frames.at(0)->getPixelShift (); + } + int getHDR (int frame = 0) const + { + // So far only Pentax provide multi-frame HDR file. + // Only the first frame contains the HDR tag + // If more brand have to be supported, this rule may need + // to evolve + + //return frames.at(frame)->getPixelShift (); + if (frames.size()) { + return frames.at(frame)->getHDR (); + } else { + return 0; + } + } + + IIOSampleFormat getSampleFormat (int frame = 0) const + { + return frames.at(frame)->getSampleFormat (); + } + + const rtexif::TagDirectory* getExifData (int frame = 0) const + { + return frames.at(frame)->getExifData (); + } + const procparams::IPTCPairs getIPTCData (int frame = 0) const + { + return frames.at(frame)->getIPTCData (); + } + + bool hasExif (int frame = 0) const + { + return frames.at(frame)->hasExif (); + } + bool hasIPTC (int frame = 0) const + { + return frames.at(frame)->hasIPTC (); + } + + struct tm getDateTime (int frame = 0) const { + return frames.at(frame)->getDateTime (); + } + time_t getDateTimeAsTS(int frame = 0) const + { + return frames.at(frame)->getDateTimeAsTS (); + } + int getISOSpeed (int frame = 0) const + { + return frames.at(frame)->getISOSpeed (); + } + double getFNumber (int frame = 0) const + { + return frames.at(frame)->getFNumber (); + } + double getFocalLen (int frame = 0) const + { + return frames.at(frame)->getFocalLen (); + } + double getFocalLen35mm (int frame = 0) const + { + return frames.at(frame)->getFocalLen35mm (); + } + float getFocusDist (int frame = 0) const + { + return frames.at(frame)->getFocusDist (); + } + double getShutterSpeed (int frame = 0) const + { + return frames.at(frame)->getShutterSpeed (); + } + double getExpComp (int frame = 0) const + { + return frames.at(frame)->getExpComp (); + } + std::string getMake (int frame = 0) const + { + return frames.at(frame)->getMake (); + } + std::string getModel (int frame = 0) const + { + return frames.at(frame)->getModel (); + } + std::string getLens (int frame = 0) const + { + return frames.at(frame)->getLens (); + } + std::string getSerialNumber (int frame = 0) const + { + return frames.at(frame)->getSerialNumber (); + } + std::string getOrientation (int frame = 0) const + { + return frames.at(frame)->getOrientation (); + } + +}; + + } #endif diff --git a/rtengine/imageformat.h b/rtengine/imageformat.h new file mode 100644 index 000000000..b34f701b7 --- /dev/null +++ b/rtengine/imageformat.h @@ -0,0 +1,54 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 20017 Jean-Christophe Frisch + * + * RawTherapee is free software: you can redistribute it and/or modify + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _IMAGEFORMAT_ +#define _IMAGEFORMAT_ + +namespace rtengine +{ + +//NB: Update the associated strings in languages files when updating the following enum +// Look for "SAMPLEFORMAT_" +typedef enum IIO_Sample_Format { + IIOSF_UNKNOWN = 0, // Unknown or Unsupported file type; Has to remain 0 + //IIOSF_SIGNED_INT , // Not yet supported + IIOSF_UNSIGNED_CHAR = 1 << 0, + IIOSF_UNSIGNED_SHORT = 1 << 1, + //IIOSF_HALF , // OpenEXR & NVidia's Half Float, not yet supported + IIOSF_LOGLUV24 = 1 << 2, + IIOSF_LOGLUV32 = 1 << 3, + IIOSF_FLOAT = 1 << 4 +} IIOSampleFormat; + +typedef enum IIO_Sample_Arrangement { + IIOSA_UNKNOWN, // Unknown or Unsupported file type + IIOSA_CHUNKY, + IIOSA_PLANAR +} IIOSampleArrangement; + +typedef enum SensorType { + ST_NONE, // use this value if the image is already demosaiced (i.e. not a raw file) + ST_BAYER, + ST_FUJI_XTRANS, + ST_FOVEON, + //ST_FUJI_EXR +} eSensorType; + +} + +#endif diff --git a/rtengine/imageio.h b/rtengine/imageio.h index 1fbeb6e2d..372f42380 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -29,6 +29,7 @@ #define IMIO_CANNOTWRITEFILE 7 #include "rtengine.h" +#include "imageformat.h" #include #include "procparams.h" #include @@ -43,31 +44,6 @@ namespace rtengine class ProgressListener; class Imagefloat; -typedef enum IIO_Sample_Format { - IIOSF_UNKNOWN = 0, // Unknown or Unsupported file type; Has to remain 0 - //IIOSF_SIGNED_INT , // Not yet supported - IIOSF_UNSIGNED_CHAR = 1 << 0, - IIOSF_UNSIGNED_SHORT = 1 << 1, - //IIOSF_HALF , // OpenEXR & NVidia's Half Float, not yet supported - IIOSF_LOGLUV24 = 1 << 2, - IIOSF_LOGLUV32 = 1 << 3, - IIOSF_FLOAT = 1 << 4 -} IIOSampleFormat; - -typedef enum IIO_Sample_Arrangement { - IIOSA_UNKNOWN, // Unknown or Unsupported file type - IIOSA_CHUNKY, - IIOSA_PLANAR -} IIOSampleArrangement; - -typedef enum SensorType { - ST_NONE, // use this value if the image is already demosaiced (i.e. not a raw file) - ST_BAYER, - ST_FUJI_XTRANS, - ST_FOVEON, - //ST_FUJI_EXR -} eSensorType; - class ImageIO : virtual public ImageDatas { diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 0eec1325a..02f0ec550 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -57,7 +57,7 @@ protected: double redAWBMul, greenAWBMul, blueAWBMul; // local copy of the multipliers, to avoid recomputing the values cmsHPROFILE embProfile; Glib::ustring fileName; - ImageData* idata; + FramesData* idata; ImageMatrices imatrices; double dirpyrdenoiseExpComp; @@ -76,12 +76,12 @@ public: virtual void flushRGB () {}; virtual void HLRecovery_Global (ToneCurveParams hrp) {}; virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; - virtual void MSR(LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; + virtual void MSR (LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; - virtual bool IsrgbSourceModified() const = 0; // tracks whether cached rgb output of demosaic has been modified + virtual bool IsrgbSourceModified () const = 0; // tracks whether cached rgb output of demosaic has been modified - virtual void setCurrentFrame(unsigned int frameNum) = 0; - virtual int getFrameCount() = 0; + virtual void setCurrentFrame (unsigned int frameNum) = 0; + virtual int getFrameCount () = 0; // use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat* @@ -107,10 +107,10 @@ public: return 0; } - virtual ImageData* getImageData () = 0; + virtual FrameData* getImageData (int frameNum) = 0; virtual ImageMatrices* getImageMatrices () = 0; - virtual bool isRAW() const = 0; - virtual DCPProfile* getDCP(const ColorManagementParams &cmp, ColorTemp &wb, DCPProfile::ApplyState &as) + virtual bool isRAW () const = 0; + virtual DCPProfile* getDCP (const ColorManagementParams &cmp, ColorTemp &wb, DCPProfile::ApplyState &as) { return nullptr; }; @@ -150,7 +150,7 @@ public: { return embProfile; } - virtual const ImageMetaData* getMetaData () + virtual const FramesMetaData* getMetaData () { return idata; } diff --git a/rtengine/profilestore.cc b/rtengine/profilestore.cc index c713d6b5c..4d06b6f6b 100644 --- a/rtengine/profilestore.cc +++ b/rtengine/profilestore.cc @@ -498,7 +498,7 @@ void ProfileStore::dumpFolderList() printf ("\n"); } -PartialProfile *ProfileStore::loadDynamicProfile (const ImageMetaData *im) +PartialProfile *ProfileStore::loadDynamicProfile (const FramesMetaData *im) { if (storeState == STORESTATE_NOTINITIALIZED) { parseProfilesOnce(); diff --git a/rtengine/profilestore.h b/rtengine/profilestore.h index 372dbfc3b..4949517da 100644 --- a/rtengine/profilestore.h +++ b/rtengine/profilestore.h @@ -195,7 +195,7 @@ public: void addListener (ProfileStoreListener *listener); void removeListener (ProfileStoreListener *listener); - rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::ImageMetaData *im); + rtengine::procparams::PartialProfile* loadDynamicProfile (const rtengine::FramesMetaData *im); void dumpFolderList(); }; diff --git a/rtengine/rawimage.h b/rtengine/rawimage.h index 62752b59c..33580c6de 100644 --- a/rtengine/rawimage.h +++ b/rtengine/rawimage.h @@ -22,7 +22,7 @@ #include #include "dcraw.h" -#include "imageio.h" +#include "imageformat.h" #include "noncopyable.h" namespace rtengine diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 148d17ee9..6641cf51e 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -913,7 +913,7 @@ DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, ColorTemp & { DCPProfile *dcpProf = nullptr; cmsHPROFILE dummy; - findInputProfile(cmp.input, nullptr, (static_cast(getMetaData()))->getCamera(), &dcpProf, dummy); + findInputProfile(cmp.input, nullptr, (static_cast(getMetaData()))->getCamera(), &dcpProf, dummy); if (dcpProf == nullptr) { if (settings->verbose) { @@ -929,7 +929,7 @@ DCPProfile *RawImageSource::getDCP(const ColorManagementParams &cmp, ColorTemp & void RawImageSource::convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb) { double pre_mul[3] = { ri->get_pre_mul(0), ri->get_pre_mul(1), ri->get_pre_mul(2) }; - colorSpaceConversion (image, cmp, wb, pre_mul, embProfile, camProfile, imatrices.xyz_cam, (static_cast(getMetaData()))->getCamera()); + colorSpaceConversion (image, cmp, wb, pre_mul, embProfile, camProfile, imatrices.xyz_cam, (static_cast(getMetaData()))->getCamera()); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1703,7 +1703,8 @@ int RawImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) rml.exifBase = ri->get_exifBase(); rml.ciffBase = ri->get_ciffBase(); rml.ciffLength = ri->get_ciffLen(); - idata = new ImageData (fname, &rml); + idata = new FramesData (fname, &rml); + idata->setDCRawFrameCount (numFrames); green(W, H); red(W, H); diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index bc2589408..21db71a72 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -166,9 +166,9 @@ public: return ri->get_rotateDegree(); } - ImageData* getImageData () + FrameData* getImageData (int frameNum) { - return idata; + return idata->getFrameData (frameNum); } ImageMatrices* getImageMatrices () { diff --git a/rtengine/rawmetadatalocation.h b/rtengine/rawmetadatalocation.h index d029d2a13..40ac6cc3e 100644 --- a/rtengine/rawmetadatalocation.h +++ b/rtengine/rawmetadatalocation.h @@ -22,11 +22,19 @@ namespace rtengine { -struct RawMetaDataLocation { +class RawMetaDataLocation { + +public: int exifBase; int ciffBase; int ciffLength; + + RawMetaDataLocation () : exifBase(-1), ciffBase(-1), ciffLength(-1) {} + RawMetaDataLocation (int exifBase) : exifBase(exifBase), ciffBase(-1), ciffLength(-1) {} + RawMetaDataLocation (int ciffBase, int ciffLength) : exifBase(-1), ciffBase(ciffBase), ciffLength(ciffLength) {} + RawMetaDataLocation (int exifBase, int ciffBase, int ciffLength) : exifBase(exifBase), ciffBase(ciffBase), ciffLength(ciffLength) {} }; + } #endif diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 6ab12c026..e72f6fbfd 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -19,6 +19,7 @@ #ifndef _RTENGINE_ #define _RTENGINE_ +#include "imageformat.h" #include "rt_math.h" #include "procparams.h" #include "procevents.h" @@ -49,57 +50,68 @@ class IImage16; class IImagefloat; /** - * This class represents provides functions to obtain exif and IPTC metadata information - * from the image file + * This class provides functions to obtain exif and IPTC metadata information + * from any of the sub-frame of an image file */ -class ImageMetaData +class FramesMetaData { public: + /** @return Returns the number of frame contained in the file based on Metadata */ + virtual int getFrameCount () const = 0; + /** Checks the availability of exif metadata tags. * @return Returns true if image contains exif metadata tags */ - virtual bool hasExif () const = 0; + virtual bool hasExif (int frame = 0) const = 0; /** Returns the directory of exif metadata tags. * @return The directory of exif metadata tags */ - virtual const rtexif::TagDirectory* getExifData () const = 0; + virtual const rtexif::TagDirectory* getExifData (int frame = 0) const = 0; /** Checks the availability of IPTC tags. * @return Returns true if image contains IPTC tags */ - virtual bool hasIPTC () const = 0; + virtual bool hasIPTC (int frame = 0) const = 0; /** Returns the directory of IPTC tags. * @return The directory of IPTC tags */ - virtual const procparams::IPTCPairs getIPTCData () const = 0; + virtual const procparams::IPTCPairs getIPTCData (int frame = 0) const = 0; /** @return a struct containing the date and time of the image */ - virtual struct tm getDateTime () const = 0; + virtual struct tm getDateTime (int frame = 0) const = 0; /** @return a timestamp containing the date and time of the image */ - virtual time_t getDateTimeAsTS() const = 0; + virtual time_t getDateTimeAsTS(int frame = 0) const = 0; /** @return the ISO of the image */ - virtual int getISOSpeed () const = 0; + virtual int getISOSpeed (int frame = 0) const = 0; /** @return the F number of the image */ - virtual double getFNumber () const = 0; + virtual double getFNumber (int frame = 0) const = 0; /** @return the focal length used at the exposure */ - virtual double getFocalLen () const = 0; + virtual double getFocalLen (int frame = 0) const = 0; /** @return the focal length in 35mm used at the exposure */ - virtual double getFocalLen35mm () const = 0; + virtual double getFocalLen35mm (int frame = 0) const = 0; /** @return the focus distance in meters, 0=unknown, 10000=infinity */ - virtual float getFocusDist () const = 0; + virtual float getFocusDist (int frame = 0) const = 0; /** @return the shutter speed */ - virtual double getShutterSpeed () const = 0; + virtual double getShutterSpeed (int frame = 0) const = 0; /** @return the exposure compensation */ - virtual double getExpComp () const = 0; + virtual double getExpComp (int frame = 0) const = 0; /** @return the maker of the camera */ - virtual std::string getMake () const = 0; + virtual std::string getMake (int frame = 0) const = 0; /** @return the model of the camera */ - virtual std::string getModel () const = 0; + virtual std::string getModel (int frame = 0) const = 0; - std::string getCamera () const + std::string getCamera (int frame = 0) const { - return getMake() + " " + getModel(); + return getMake(frame) + " " + getModel(frame); } /** @return the lens on the camera */ - virtual std::string getLens () const = 0; + virtual std::string getLens (int frame = 0) const = 0; /** @return the orientation of the image */ - virtual std::string getOrientation () const = 0; + virtual std::string getOrientation (int frame = 0) const = 0; + + /** @return true if the file is a PixelShift shot (Pentax bodies) */ + virtual bool getPixelShift (int frame = 0) const = 0; + /** @return 0: not ah HDR file ; 1: single shot HDR (e.g. 32 bit float DNG file or Log compressed) ; >1: multi-frame HDR file */ + virtual int getHDR (int frame = 0) const = 0; + /** @return the sample format based on MetaData */ + virtual IIOSampleFormat getSampleFormat (int frame = 0) const = 0; + /** Functions to convert between floating point and string representation of shutter and aperture */ static std::string apertureToString (double aperture); /** Functions to convert between floating point and string representation of shutter and aperture */ @@ -111,14 +123,15 @@ public: /** Functions to convert between floating point and string representation of exposure compensation */ static std::string expcompToString (double expcomp, bool maskZeroexpcomp); - virtual ~ImageMetaData () {} + virtual ~FramesMetaData () {} /** Reads metadata from file. * @param fname is the name of the file - * @param rml is a struct containing information about metadata location. Use it only for raw files. In case - * of jpgs and tiffs pass a NULL pointer. + * @param rml is a struct containing information about metadata location of the first frame. + * Use it only for raw files. In caseof jpgs and tiffs pass a NULL pointer. + * @param firstFrameOnly must be true to get the MetaData of the first frame only, e.g. for a PixelShift file. * @return The metadata */ - static ImageMetaData* fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml); + static FramesMetaData* fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml, bool firstFrameOnly = false); }; /** This listener interface is used to indicate the progress of time consuming operations */ @@ -157,9 +170,9 @@ public: /** Returns the embedded icc profile of the image. * @return The handle of the embedded profile */ virtual cmsHPROFILE getEmbeddedProfile () = 0; - /** Returns a class providing access to the exif and iptc metadata tags of the image. - * @return An instance of the ImageMetaData class */ - virtual const ImageMetaData* getMetaData () = 0; + /** Returns a class providing access to the exif and iptc metadata tags of all frames of the image. + * @return An instance of the FramesMetaData class */ + virtual const FramesMetaData* getMetaData () = 0; /** This is a function used for internal purposes only. */ virtual ImageSource* getImageSource () = 0; /** This class has manual reference counting. You have to call this function each time to make a new reference to an instance. */ diff --git a/rtengine/stdimagesource.cc b/rtengine/stdimagesource.cc index 87f25a497..d4e6a62f1 100644 --- a/rtengine/stdimagesource.cc +++ b/rtengine/stdimagesource.cc @@ -158,7 +158,7 @@ int StdImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) embProfile = img->getEmbeddedProfile (); - idata = new ImageData (fname); + idata = new FramesData (fname); if (idata->hasExif()) { int deg = 0; diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 330c08244..2e845e3f3 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -68,9 +68,9 @@ public: void getFullSize (int& w, int& h, int tr = TR_NONE); void getSize (const PreviewProps &pp, int& w, int& h); - ImageData* getImageData () + FrameData* getImageData (int frameNum) { - return idata; + return idata->getFrameData (frameNum); } ImageIO* getImageIO () { diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index 2c52a0c88..e9a7a3544 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -1228,6 +1228,7 @@ public: choices[2] = "HDR 1"; choices[3] = "HDR 2"; choices[4] = "HDR 3"; + choices[5] = "Advanced"; choices1[0] = "Auto-align Off"; choices1[1] = "Auto-align On"; diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index c12f5f782..7c508892a 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -19,6 +19,7 @@ * along with RawTherapee. If not, see . */ #include +#include #include #include #include @@ -289,6 +290,8 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring 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_integer ("Common Data", "IsHDR", cfs->isHDR); + kf->set_boolean ("Common Data", "IsPixelShift", cfs->isPixelShift); kf->set_string ("Common Data", "Lens", cfs->lens); kf->set_string ("Common Data", "Make", cfs->camMake); kf->set_string ("Common Data", "Model", cfs->camModel); @@ -849,7 +852,11 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) } if (tag == 0x002e) { // location of the embedded preview image in raw files of Panasonic cameras - TagDirectory* previewdir = ExifManager::parseJPEG (f, ftell (f)); // try to parse the exif data from the preview image + TagDirectory* previewdir; + { + ExifManager exifManager(f, 0, true); + previewdir = exifManager.parseJPEG (ftell (f)); // try to parse the exif data from the preview image + } if (previewdir) { if (previewdir->getTag ("Exif")) { @@ -1894,7 +1901,7 @@ const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field) } -TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) +TagDirectory* ExifManager::parseCIFF () { TagDirectory* root = new TagDirectory (nullptr, ifdAttribs, INTEL); @@ -1904,12 +1911,12 @@ TagDirectory* ExifManager::parseCIFF (FILE* f, int base, int length) mn->initMakerNote (IFD, canonAttribs); root->addTag (exif); exif->getDirectory()->addTag (mn); - parseCIFF (f, base, length, root); + parseCIFF (rml->ciffLength, root); root->sort (); return root; } -Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name) +Tag* ExifManager::saveCIFFMNTag (TagDirectory* root, int len, const char* name) { int s = ftell (f); if(s >= 0) { @@ -1927,15 +1934,22 @@ Tag* ExifManager::saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const cha } } -void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) +void ExifManager::parseCIFF (int length, TagDirectory* root) { + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return; + } + char buffer[1024]; Tag* t; - fseek (f, base + length - 4, SEEK_SET); + fseek (f, rml->ciffBase + length - 4, SEEK_SET); - int dirStart = get4 (f, INTEL) + base; + int dirStart = get4 (f, INTEL) + rml->ciffBase; fseek (f, dirStart, SEEK_SET); int numOfTags = get2 (f, INTEL); @@ -1960,10 +1974,12 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) int nextPos = ftell (f) + 4; // seek to the location of the value - fseek (f, base + get4 (f, INTEL), SEEK_SET); + fseek (f, rml->ciffBase + get4 (f, INTEL), SEEK_SET); if ((((type >> 8) + 8) | 8) == 0x38) { - parseCIFF (f, ftell (f), len, root); // Parse a sub-table + rtengine::RawMetaDataLocation rml2(ftell (f), len); + ExifManager exifManager(f, &rml2, true); + exifManager.parseCIFF (len, root); // Parse a sub-table } if (type == 0x0810) { @@ -1994,8 +2010,9 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) } + ExifManager exifManager(f, 0, true); if (type == 0x102d) { - Tag* t = saveCIFFMNTag (f, root, len, "CanonCameraSettings"); + Tag* t = exifManager.saveCIFFMNTag (root, len, "CanonCameraSettings"); int mm = t->toInt (34, SHORT); Tag* nt = new Tag (exif, lookupAttrib (exifAttribs, "MeteringMode")); @@ -2074,31 +2091,31 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root) } if (type == 0x1029) { - saveCIFFMNTag (f, root, len, "CanonFocalLength"); + exifManager.saveCIFFMNTag (root, len, "CanonFocalLength"); } if (type == 0x1031) { - saveCIFFMNTag (f, root, len, "SensorInfo"); + exifManager.saveCIFFMNTag (root, len, "SensorInfo"); } if (type == 0x1033) { - saveCIFFMNTag (f, root, len, "CustomFunctions"); + exifManager.saveCIFFMNTag (root, len, "CustomFunctions"); } if (type == 0x1038) { - saveCIFFMNTag (f, root, len, "CanonAFInfo"); + exifManager.saveCIFFMNTag (root, len, "CanonAFInfo"); } if (type == 0x1093) { - saveCIFFMNTag (f, root, len, "CanonFileInfo"); + exifManager.saveCIFFMNTag (root, len, "CanonFileInfo"); } if (type == 0x10a9) { - saveCIFFMNTag (f, root, len, "ColorBalance"); + exifManager.saveCIFFMNTag (root, len, "ColorBalance"); } if (type == 0x102a) { - saveCIFFMNTag (f, root, len, "CanonShotInfo"); + exifManager.saveCIFFMNTag (root, len, "CanonShotInfo"); iso = pow (2, (get4 (f, INTEL), get2 (f, INTEL)) / 32.0 - 4) * 50; aperture = (get2 (f, INTEL), (short)get2 (f, INTEL)) / 32.0f; @@ -2530,22 +2547,47 @@ parse_leafdata (TagDirectory* root, ByteOrder order) } } -TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) +TagDirectory* ExifManager::parse (bool skipIgnored) { + int ifd = IFDOffset; + + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return nullptr; + } setlocale (LC_NUMERIC, "C"); // to set decimal point in sscanf - // read tiff header - fseek (f, base, SEEK_SET); - unsigned short bo; - fread (&bo, 1, 2, f); - ByteOrder order = (ByteOrder) ((int)bo); - get2 (f, order); - int firstifd = get4 (f, order); + + if (order == ByteOrder::UNKNOWN) { + // read tiff header + fseek (f, rml->exifBase, SEEK_SET); + unsigned short bo; + fread (&bo, 1, 2, f); + order = (ByteOrder) ((int)bo); + get2 (f, order); + if (!ifd) { + ifd = get4 (f, order); + } + } + + return parseIFD (ifd, skipIgnored); +} + +TagDirectory* ExifManager::parseIFD (int ifdOffset, bool skipIgnored) +{ + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return nullptr; + } // seek to IFD0 - fseek (f, base + firstifd, SEEK_SET); + fseek (f, rml->exifBase + ifdOffset, SEEK_SET); // first read the IFD directory - TagDirectory* root = new TagDirectory (nullptr, f, base, ifdAttribs, order, skipIgnored); + TagDirectory* root = new TagDirectory (nullptr, f, rml->exifBase, ifdAttribs, order, skipIgnored); // fix ISO issue with nikon and panasonic cameras Tag* make = root->getTag ("Make"); @@ -2580,8 +2622,8 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) if (make && !strncmp ((char*)make->getValue(), "Kodak", 5)) { if (!exif) { // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir - fseek (f, base + firstifd, SEEK_SET); - TagDirectory* exifdir = new TagDirectory (nullptr, f, base, exifAttribs, order, true); + fseek (f, rml->exifBase + ifdOffset, SEEK_SET); + TagDirectory* exifdir = new TagDirectory (nullptr, f, rml->exifBase, exifAttribs, order, true); exif = new Tag (root, root->getAttrib ("Exif")); exif->initSubDir (exifdir); @@ -2777,13 +2819,20 @@ TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) } } -// root->printAll (); + nextIFDOffset = get4 (f, order); + //root->printAll (); return root; } -TagDirectory* ExifManager::parseJPEG (FILE* f, int offset) +TagDirectory* ExifManager::parseJPEG (int offset) { + if (!f) { + #ifndef NDEBUG + std::cerr << "ERROR : no file opened !" << std::endl; + #endif + return nullptr; + } if(!fseek (f, offset, SEEK_SET)) { unsigned char c; @@ -2805,7 +2854,20 @@ TagDirectory* ExifManager::parseJPEG (FILE* f, int offset) if (!memcmp (idbuff + 2, exifid, 6)) { // Exif info found tiffbase = ftell (f); - return parse (f, tiffbase); + + // We need a RawMetaDataLocation to put the 'tiffbase' value + bool rmlCreated = false; + if (!rml) { + rml = new rtengine::RawMetaDataLocation (0); + rmlCreated = true; + } + rml->exifBase = tiffbase; + TagDirectory* tagDir = parse (); + if (rmlCreated) { + delete rml; + rml = nullptr; + } + return tagDir; } } } @@ -2815,10 +2877,17 @@ TagDirectory* ExifManager::parseJPEG (FILE* f, int offset) return nullptr; } -TagDirectory* ExifManager::parseTIFF (FILE* f, bool skipIgnored) +TagDirectory* ExifManager::parseTIFF (bool skipIgnored) { - return parse (f, 0, skipIgnored); + if (!rml) { + rml = new rtengine::RawMetaDataLocation(0); + TagDirectory* tagDir = parse (skipIgnored); + delete rml; + return tagDir; + } else { + return parse (skipIgnored); + } } std::vector ExifManager::getDefaultTIFFTags (TagDirectory* forthis) diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 0167ef445..c476e3dc9 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -31,6 +31,7 @@ #include "../rtengine/procparams.h" #include "../rtengine/noncopyable.h" +#include "../rtengine/rawmetadatalocation.h" class CacheImageData; @@ -46,7 +47,7 @@ enum ActionCode { AC_INVALID = 100, // invalid state }; -enum ByteOrder {INTEL = 0x4949, MOTOROLA = 0x4D4D}; +enum ByteOrder {UNKNOWN = 0, INTEL = 0x4949, MOTOROLA = 0x4D4D}; #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ const enum ByteOrder HOSTORDER = INTEL; #else @@ -99,10 +100,10 @@ class TagDirectory { protected: - std::vector tags; // tags in the directory - const TagAttrib* attribs; // descriptor table to decode the tags - ByteOrder order; // byte order - TagDirectory* parent; // parent directory (NULL if root) + std::vector tags; // tags in the directory + const TagAttrib* attribs; // descriptor table to decode the tags + ByteOrder order; // byte order + TagDirectory* parent; // parent directory (NULL if root) static Glib::ustring getDumpKey (int tagID, const Glib::ustring &tagName); public: @@ -309,13 +310,37 @@ public: class ExifManager { - static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name); + Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name); + TagDirectory* parseIFD (int ifdOffset, bool skipIgnored); + public: - static TagDirectory* parse (FILE*f, int base, bool skipIgnored = true); - static TagDirectory* parseJPEG (FILE*f, int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail - static TagDirectory* parseTIFF (FILE*f, bool skipIgnored = true); - static TagDirectory* parseCIFF (FILE* f, int base, int length); - static void parseCIFF (FILE* f, int base, int length, TagDirectory* root); + FILE* f; + rtengine::RawMetaDataLocation *rml; + ByteOrder order; + bool onlyFirst; // Only first IFD + unsigned int IFDOffset; + unsigned int nextIFDOffset; + + ExifManager (FILE* fHandle, rtengine::RawMetaDataLocation *rml, bool onlyFirstIFD) + : f(fHandle), rml(rml), order(UNKNOWN), onlyFirst(onlyFirstIFD), + IFDOffset(0), nextIFDOffset(0) {} + + void setIFDOffset(unsigned int offset) + { + IFDOffset = offset; + } + + unsigned int getNextIFDOffset() + { + return nextIFDOffset; + } + + // The following functions parse only one IFD at a time and store the "next IFD offset" + TagDirectory* parse (bool skipIgnored = true); + TagDirectory* parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail + TagDirectory* parseTIFF (bool skipIgnored = true); + TagDirectory* parseCIFF (); + void parseCIFF (int length, TagDirectory* root); /// @brief Get default tag for TIFF /// @param forthis The byte order will be taken from the given directory. diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index 514dd5215..f59fa9b36 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -539,6 +539,7 @@ const TagAttrib exifAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter}, {0, AC_WRITE, 0, nullptr, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter}, @@ -777,6 +778,7 @@ const TagAttrib ifdAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x013E, AUTO, "WhitePoint", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter}, {0, AC_WRITE, 0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter}, diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 34983d46a..e1a3eaba3 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -24,9 +24,9 @@ CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), - timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), - redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) + timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), + fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (0), isPixelShift (false), + sampleFormat(rtengine::IIOSF_UNKNOWN), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) { } @@ -138,6 +138,14 @@ int CacheImageData::load (const Glib::ustring& fname) iso = keyFile.get_integer ("ExifInfo", "ISO"); } + if (keyFile.has_key ("ExifInfo", "IsHDR")) { + isHDR = keyFile.get_integer ("ExifInfo", "IsHDR"); + } + + if (keyFile.has_key ("ExifInfo", "IsPixelShift")) { + isPixelShift = keyFile.get_boolean ("ExifInfo", "IsPixelShift"); + } + if (keyFile.has_key ("ExifInfo", "ExpComp")) { expcomp = keyFile.get_string ("ExifInfo", "ExpComp"); } @@ -160,6 +168,9 @@ int CacheImageData::load (const Glib::ustring& fname) if (keyFile.has_key ("FileInfo", "Filetype")) { filetype = keyFile.get_string ("FileInfo", "Filetype"); } + if (keyFile.has_key ("FileInfo", "SampleFormat")) { + sampleFormat = (rtengine::IIO_Sample_Format)keyFile.get_integer ("FileInfo", "SampleFormat"); + } } if (format == FT_Raw && keyFile.has_group ("ExtraRawInfo")) { @@ -235,6 +246,8 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_double ("ExifInfo", "FocalLen35mm", focalLen35mm); keyFile.set_double ("ExifInfo", "FocusDist", focusDist); keyFile.set_integer ("ExifInfo", "ISO", iso); + keyFile.set_integer ("ExifInfo", "IsHDR", isHDR); + keyFile.set_boolean ("ExifInfo", "IsPixelShift", isPixelShift); keyFile.set_string ("ExifInfo", "ExpComp", expcomp); } @@ -242,6 +255,7 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_string ("ExifInfo", "CameraMake", camMake); keyFile.set_string ("ExifInfo", "CameraModel", camModel); keyFile.set_string ("FileInfo", "Filetype", filetype); + keyFile.set_integer ("FileInfo", "SampleFormat", sampleFormat); if (format == FT_Raw) { keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType); diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index f655bd88b..548633168 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -21,6 +21,7 @@ #include #include "options.h" +#include "../rtengine/imageformat.h" class CacheImageData { @@ -51,6 +52,9 @@ public: double focalLen, focalLen35mm; float focusDist; unsigned iso; + int isHDR; // null if no HDR, otherwise provide the number of frame for this HDR file + bool isPixelShift; + rtengine::IIO_Sample_Format sampleFormat; Glib::ustring lens; Glib::ustring camMake; Glib::ustring camModel; diff --git a/rtgui/dynamicprofilepanel.cc b/rtgui/dynamicprofilepanel.cc index db3a19ed0..c8a8a1644 100644 --- a/rtgui/dynamicprofilepanel.cc +++ b/rtgui/dynamicprofilepanel.cc @@ -405,7 +405,7 @@ void DynamicProfilePanel::render_fnumber ( RENDER_RANGE_ (double, fnumber, [] (double f) { return std::string ("f/") + - rtengine::ImageMetaData::apertureToString (f); + rtengine::FramesMetaData::apertureToString (f); }); } @@ -421,7 +421,7 @@ void DynamicProfilePanel::render_shutterspeed ( Gtk::CellRenderer *cell, const Gtk::TreeModel::iterator &iter) { RENDER_RANGE_ (double, shutterspeed, - rtengine::ImageMetaData::shutterToString); + rtengine::FramesMetaData::shutterToString); } diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 389c16a4e..1566f3c07 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1268,13 +1268,14 @@ void EditorPanel::info_toggled () Glib::ustring infoString2; //2-nd line Glib::ustring infoString3; //3-rd line Glib::ustring infoString4; //4-th line + Glib::ustring infoString5; //5-th line Glib::ustring expcomp; if (!ipc || !openThm) { return; } - const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData(); if (idata && idata->hasExif()) { infoString1 = Glib::ustring::compose ("%1 + %2", @@ -1305,6 +1306,24 @@ void EditorPanel::info_toggled () infoString4 = Glib::ustring::compose ("%1 MP (%2x%3)", Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), ww, hh); infoString = Glib::ustring::compose ("%1\n%2\n%3\n%4", infoString1, infoString2, infoString3, infoString4); + + //adding special characteristics + bool isHDR = idata->getHDR(); + bool isPixelShift = idata->getPixelShift(); + int numFrames = idata->getFrameCount(); + if (isHDR) { + infoString5 = Glib::ustring::compose (M("QINFO_HDR"), numFrames); + if (numFrames == 1) { + int sampleFormat = idata->getSampleFormat(); + infoString5 = Glib::ustring::compose ("%1 / %2", infoString5, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat))); + } + } else if (isPixelShift) { + infoString5 = Glib::ustring::compose (M("QINFO_PIXELSHIFT"), numFrames); + } + if (!infoString5.empty()) { + infoString = Glib::ustring::compose ("%1\n%2", infoString, infoString5); + } + } else { infoString = M ("QINFO_NOEXIF"); } diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 34cb2c064..370a29c77 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -177,15 +177,28 @@ void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pe defChangeList = defParams->exif; } -void ExifPanel::setImageData (const ImageMetaData* id) +void ExifPanel::setImageData (const FramesMetaData* id) { idata = id; exifTreeModel->clear (); - if (id && id->getExifData ()) { -// id->getExifData ()->printAll (); - addDirectory (id->getExifData (), exifTreeModel->children()); + if (id) { + //bool first = true; + // HOMBRE: Should we only display the current frame's Exifs ? + for (int frameNum = 0; frameNum < id->getFrameCount (); ++frameNum) { + if ( id->getExifData (frameNum)) { + /* + if (!first) { + Gtk::Separator *sep = Gtk::manage (new Gtk::Separator); + sep->set_orientation(Gtk::ORIENTATION_HORIZONTAL); + first = false; + } + */ + //id->getExifData ()->printAll (); + addDirectory (id->getExifData (frameNum), exifTreeModel->children()); + } + } } } diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index 6244c1a4f..db1fc8649 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -26,7 +26,7 @@ class ExifPanel : public Gtk::VBox, public ToolPanel { private: - const rtengine::ImageMetaData* idata; + const rtengine::FramesMetaData* idata; rtengine::procparams::ExifPairs changeList; rtengine::procparams::ExifPairs defChangeList; bool recursiveOp; @@ -91,7 +91,7 @@ public: void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setImageData (const rtengine::ImageMetaData* id); + void setImageData (const rtengine::FramesMetaData* id); void exifSelectionChanged (); void removePressed (); diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 10d4809ed..ff49b5ce3 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -1539,8 +1539,8 @@ bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) // true -> entry && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0); return - (!filter.exifFilter.filterShutter || (rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2)) - && (!filter.exifFilter.filterFNumber || (rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom - tol2 && rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo + tol2)) + (!filter.exifFilter.filterShutter || (rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom - tol2 && rtengine::FramesMetaData::shutterFromString(rtengine::FramesMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo + tol2)) + && (!filter.exifFilter.filterFNumber || (rtengine::FramesMetaData::apertureFromString(rtengine::FramesMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom - tol2 && rtengine::FramesMetaData::apertureFromString(rtengine::FramesMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo + tol2)) && (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom - tol && cfs->focalLen <= filter.exifFilter.focalTo + tol)) && (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo)) && (!filter.exifFilter.filterExpComp || filter.exifFilter.expcomp.count(cfs->expcomp) > 0) diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index eafe32fcd..a2088b9e2 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -770,6 +770,8 @@ void FileCatalog::previewReady (int dir_id, FileBrowserEntry* fdn) if (cfs->focalLen > dirEFS.focalTo) { dirEFS.focalTo = cfs->focalLen; } + + //TODO: ass filters for HDR and PixelShift files } dirEFS.filetypes.insert (cfs->filetype); diff --git a/rtgui/filterpanel.cc b/rtgui/filterpanel.cc index a8691c1b3..5f8fa2781 100644 --- a/rtgui/filterpanel.cc +++ b/rtgui/filterpanel.cc @@ -171,15 +171,15 @@ void FilterPanel::setFilter (ExifFilterSettings& defefs, bool updateLists) } // enaFNumber->set_active (curefs.filterFNumber); - fnumberFrom->set_text (ImageMetaData::apertureToString (defefs.fnumberFrom)); + fnumberFrom->set_text (FramesMetaData::apertureToString (defefs.fnumberFrom)); curefs.fnumberFrom = defefs.fnumberFrom; - fnumberTo->set_text (ImageMetaData::apertureToString (defefs.fnumberTo)); + fnumberTo->set_text (FramesMetaData::apertureToString (defefs.fnumberTo)); curefs.fnumberTo = defefs.fnumberTo; // enaShutter->set_active (curefs.filterShutter); - shutterFrom->set_text (ImageMetaData::shutterToString (defefs.shutterFrom)); + shutterFrom->set_text (FramesMetaData::shutterToString (defefs.shutterFrom)); curefs.shutterFrom = defefs.shutterFrom; - shutterTo->set_text (ImageMetaData::shutterToString (defefs.shutterTo)); + shutterTo->set_text (FramesMetaData::shutterToString (defefs.shutterTo)); curefs.shutterTo = defefs.shutterTo; // enaISO->set_active (curefs.filterISO); @@ -315,8 +315,8 @@ ExifFilterSettings FilterPanel::getFilter () efs.focalTo = atof (focalTo->get_text().c_str()); efs.isoFrom = atoi (isoFrom->get_text().c_str()); efs.isoTo = atoi (isoTo->get_text().c_str()); - efs.shutterFrom = ImageMetaData::shutterFromString (shutterFrom->get_text()); - efs.shutterTo = ImageMetaData::shutterFromString (shutterTo->get_text()); + efs.shutterFrom = FramesMetaData::shutterFromString (shutterFrom->get_text()); + efs.shutterTo = FramesMetaData::shutterFromString (shutterTo->get_text()); efs.filterFNumber = enaFNumber->get_active (); efs.filterShutter = enaShutter->get_active (); diff --git a/rtgui/icmpanel.cc b/rtgui/icmpanel.cc index 1bb1c23a3..e026243be 100644 --- a/rtgui/icmpanel.cc +++ b/rtgui/icmpanel.cc @@ -958,7 +958,7 @@ void ICMPanel::oBPCChanged () } } -void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) +void ICMPanel::setRawMeta (bool raw, const rtengine::FramesData* pMeta) { disableListener (); diff --git a/rtgui/icmpanel.h b/rtgui/icmpanel.h index 35017bed4..f8c762b0e 100644 --- a/rtgui/icmpanel.h +++ b/rtgui/icmpanel.h @@ -122,7 +122,7 @@ public: void applyBaselineExposureOffsetChanged(); void applyHueSatMapChanged(); - void setRawMeta (bool raw, const rtengine::ImageData* pMeta); + void setRawMeta (bool raw, const rtengine::FramesData* pMeta); void saveReferencePressed (); void setICMPanelListener (ICMPanelListener* ipl) diff --git a/rtgui/inspector.cc b/rtgui/inspector.cc index 8af99b2ab..4084e300f 100644 --- a/rtgui/inspector.cc +++ b/rtgui/inspector.cc @@ -59,7 +59,7 @@ InspectorBuffer::~InspectorBuffer() { //int InspectorBuffer::infoFromImage (const Glib::ustring& fname) //{ // -// rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, nullptr); +// rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, nullptr, true); // // if (!idata) { // return 0; diff --git a/rtgui/iptcpanel.cc b/rtgui/iptcpanel.cc index 5ee533e2c..cd0fe4050 100644 --- a/rtgui/iptcpanel.cc +++ b/rtgui/iptcpanel.cc @@ -434,7 +434,7 @@ void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pe defChangeList = defParams->iptc; } -void IPTCPanel::setImageData (const ImageMetaData* id) +void IPTCPanel::setImageData (const FramesMetaData* id) { if (id) { diff --git a/rtgui/iptcpanel.h b/rtgui/iptcpanel.h index 63309cc27..b216cf638 100644 --- a/rtgui/iptcpanel.h +++ b/rtgui/iptcpanel.h @@ -75,7 +75,7 @@ public: void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); - void setImageData (const rtengine::ImageMetaData* id); + void setImageData (const rtengine::FramesMetaData* id); void notifyListener (); diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0855ef03f..991ad0416 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -110,7 +110,7 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa conUseDist.block(false); } -void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta) +void LensProfilePanel::setRawMeta(bool raw, const rtengine::FramesMetaData* pMeta) { if (!raw || pMeta->getFocusDist() <= 0) { disableListener(); diff --git a/rtgui/lensprofile.h b/rtgui/lensprofile.h index 9543721a0..4ccc4acf7 100644 --- a/rtgui/lensprofile.h +++ b/rtgui/lensprofile.h @@ -47,7 +47,7 @@ public: void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setRawMeta (bool raw, const rtengine::ImageMetaData* pMeta); + void setRawMeta (bool raw, const rtengine::FramesMetaData* pMeta); void onLCPFileChanged (); void onLCPFileReset (); diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 9db7c69b6..320424bf1 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -227,14 +227,17 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (!run_cpb) { if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { - rtengine::ImageMetaData* imageMetaData; + rtengine::FramesMetaData* imageMetaData; if (getType() == FT_Raw) { rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); - imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, &metaData, true); } else { - imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); } PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData); + delete imageMetaData; int err = pp->pparams->save(outFName); pp->deleteInstance(); delete pp; @@ -249,13 +252,15 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu } } else { // First generate the communication file, with general values and EXIF metadata - rtengine::ImageMetaData* imageMetaData; + rtengine::FramesMetaData* imageMetaData; if (getType() == FT_Raw) { rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); - imageMetaData = rtengine::ImageMetaData::fromFile (fname, &metaData); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, &metaData, true); } else { - imageMetaData = rtengine::ImageMetaData::fromFile (fname, nullptr); + // Should we ask all frame's MetaData ? + imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); } Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) ); @@ -268,6 +273,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu cfs, flaggingMode); } + delete imageMetaData; // For the filename etc. do NOT use streams, since they are not UTF8 safe Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\""); @@ -284,8 +290,6 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu } g_remove (tmpFileName.c_str ()); - - delete imageMetaData; } if (returnParams && hasProcParams()) { @@ -645,7 +649,7 @@ void Thumbnail::generateExifDateTimeStrings () return; } - exifString = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", Glib::ustring(rtengine::ImageData::apertureToString(cfs.fnumber)), Glib::ustring(rtengine::ImageData::shutterToString(cfs.shutter)), M("QINFO_ISO"), cfs.iso, Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), cfs.focalLen)); + exifString = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", Glib::ustring(rtengine::FramesData::apertureToString(cfs.fnumber)), Glib::ustring(rtengine::FramesData::shutterToString(cfs.shutter)), M("QINFO_ISO"), cfs.iso, Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2), cfs.focalLen)); if (options.fbShowExpComp && cfs.expcomp != "0.00" && cfs.expcomp != "") { // don't show exposure compensation if it is 0.00EV;old cache iles do not have ExpComp, so value will not be displayed. exifString = Glib::ustring::compose ("%1 %2EV", exifString, cfs.expcomp); // append exposure compensation to exifString @@ -712,7 +716,7 @@ ThFileType Thumbnail::getType () int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml) { - rtengine::ImageMetaData* idata = rtengine::ImageMetaData::fromFile (fname, rml); + rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, rml); if (!idata) { return 0; @@ -723,24 +727,27 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataL cfs.exifValid = false; if (idata->hasExif()) { - cfs.shutter = idata->getShutterSpeed (); - cfs.fnumber = idata->getFNumber (); - cfs.focalLen = idata->getFocalLen (); + cfs.shutter = idata->getShutterSpeed (); + cfs.fnumber = idata->getFNumber (); + cfs.focalLen = idata->getFocalLen (); cfs.focalLen35mm = idata->getFocalLen35mm (); - cfs.focusDist = idata->getFocusDist (); - cfs.iso = idata->getISOSpeed (); - cfs.expcomp = idata->expcompToString (idata->getExpComp(), false); // do not mask Zero expcomp - cfs.year = 1900 + idata->getDateTime().tm_year; - cfs.month = idata->getDateTime().tm_mon + 1; - cfs.day = idata->getDateTime().tm_mday; - cfs.hour = idata->getDateTime().tm_hour; - cfs.min = idata->getDateTime().tm_min; - cfs.sec = idata->getDateTime().tm_sec; - cfs.timeValid = true; - cfs.exifValid = true; - cfs.lens = idata->getLens(); - cfs.camMake = idata->getMake(); - cfs.camModel = idata->getModel(); + cfs.focusDist = idata->getFocusDist (); + cfs.iso = idata->getISOSpeed (); + cfs.expcomp = idata->expcompToString (idata->getExpComp(), false); // do not mask Zero expcomp + cfs.isHDR = idata->getHDR (); + cfs.isPixelShift = idata->getPixelShift (); + cfs.sampleFormat = idata->getSampleFormat (); + cfs.year = 1900 + idata->getDateTime().tm_year; + cfs.month = idata->getDateTime().tm_mon + 1; + cfs.day = idata->getDateTime().tm_mday; + cfs.hour = idata->getDateTime().tm_hour; + cfs.min = idata->getDateTime().tm_min; + cfs.sec = idata->getDateTime().tm_sec; + cfs.timeValid = true; + cfs.exifValid = true; + cfs.lens = idata->getLens(); + cfs.camMake = idata->getMake(); + cfs.camModel = idata->getModel(); if (idata->getOrientation() == "Rotate 90 CW") { deg = 90; diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index b06463eff..8fde5a1de 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -510,7 +510,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool toneCurve->enableListener (); if (ipc) { - const rtengine::ImageMetaData* pMetaData = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData* pMetaData = ipc->getInitialImage()->getMetaData(); exifpanel->setImageData (pMetaData); iptcpanel->setImageData (pMetaData); @@ -528,7 +528,7 @@ void ToolPanelCoordinator::initImage (rtengine::StagedImageProcessor* ipc_, bool ipc->setImageTypeListener (this); flatfield->setShortcutPath(Glib::path_get_dirname(ipc->getInitialImage()->getFileName())); - icm->setRawMeta (raw, (const rtengine::ImageData*)pMetaData); + icm->setRawMeta (raw, (const rtengine::FramesData*)pMetaData); lensProf->setRawMeta (raw, pMetaData); } @@ -677,7 +677,7 @@ rtengine::RawImage* ToolPanelCoordinator::getDF() return nullptr; } - const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData *imd = ipc->getInitialImage()->getMetaData(); if(imd) { int iso = imd->getISOSpeed(); @@ -698,7 +698,7 @@ rtengine::RawImage* ToolPanelCoordinator::getFF() return nullptr; } - const rtengine::ImageMetaData *imd = ipc->getInitialImage()->getMetaData(); + const rtengine::FramesMetaData *imd = ipc->getInitialImage()->getMetaData(); if(imd) { // int iso = imd->getISOSpeed(); temporarilly removed because unused diff --git a/tools/source_icons/scalable/HDR-thumbnail.svg b/tools/source_icons/scalable/HDR-thumbnail.svg new file mode 100644 index 000000000..2b6d1a4bc --- /dev/null +++ b/tools/source_icons/scalable/HDR-thumbnail.svg @@ -0,0 +1,355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/tools/source_icons/scalable/PixeShift-thumbnail.svg b/tools/source_icons/scalable/PixeShift-thumbnail.svg new file mode 100644 index 000000000..9e50ba9c1 --- /dev/null +++ b/tools/source_icons/scalable/PixeShift-thumbnail.svg @@ -0,0 +1,353 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + From 1a296b763f0b3f032a7115e9cfb112918d3b9851 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Thu, 10 Aug 2017 00:50:26 +0200 Subject: [PATCH 02/27] Correction as discussed in commit review (see also issue #4008) --- rtdata/languages/Francais | 4 +- rtdata/languages/default | 4 +- rtengine/imagedata.cc | 206 +++++++++++++++++++++++++++- rtengine/imagedata.h | 251 +++++++--------------------------- rtengine/imageformat.h | 2 +- rtengine/imagesource.h | 2 +- rtengine/improccoordinator.cc | 4 +- rtengine/rawimagesource.h | 2 +- rtengine/rtengine.h | 46 +++---- rtengine/stdimagesource.h | 2 +- rtexif/rtexif.cc | 8 +- rtexif/rtexif.h | 4 +- rtgui/cacheimagedata.cc | 4 +- rtgui/cacheimagedata.h | 2 +- rtgui/editorpanel.cc | 40 +++--- rtgui/exifpanel.cc | 2 +- 16 files changed, 310 insertions(+), 273 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 34a9a75a2..de6b6e44e 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -1155,10 +1155,10 @@ PROGRESSBAR_SAVEPNG;Enregistrement du fichier PNG... PROGRESSBAR_SAVETIFF;Enregistrement du fichier TIFF... PROGRESSBAR_SNAPSHOT_ADDED;Signet ajouté PROGRESSDLG_PROFILECHANGEDINBROWSER;Profil modifié dans le navigateur -QINFO_HDR;HDR / %1 image(s) +QINFO_HDR;HDR / %2 image(s) QINFO_ISO;ISO QINFO_NOEXIF;Données EXIF non disponibles. -QINFO_PIXELSHIFT;PixelShift / %1 images +QINFO_PIXELSHIFT;PixelShift / %2 images SAMPLEFORMAT_0;Format de donnée inconnu SAMPLEFORMAT_1;8 bits non signé SAMPLEFORMAT_2;16 bits non signé diff --git a/rtdata/languages/default b/rtdata/languages/default index f8d54154c..f90a8b1f2 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1157,10 +1157,10 @@ PROGRESSBAR_SAVEPNG;Saving PNG file... PROGRESSBAR_SAVETIFF;Saving TIFF file... PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser -QINFO_HDR;HDR / %1 frame(s) +QINFO_HDR;HDR / %2 frame(s) QINFO_ISO;ISO QINFO_NOEXIF;Exif data not available. -QINFO_PIXELSHIFT;PixelShift / %1 frame(s) +QINFO_PIXELSHIFT;PixelShift / %2 frame(s) SAMPLEFORMAT_0;Unknown data format SAMPLEFORMAT_1;Unsigned 8 bits SAMPLEFORMAT_2;Unsigned 16 bits diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 289fc4a25..9c27ddd50 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -626,7 +626,7 @@ FrameData::~FrameData () } } -const procparams::IPTCPairs FrameData::getIPTCData () const +procparams::IPTCPairs FrameData::getIPTCData () const { procparams::IPTCPairs iptcc; @@ -672,6 +672,210 @@ const procparams::IPTCPairs FrameData::getIPTCData () const return iptcc; } + +bool FrameData::getPixelShift () const +{ + return isPixelShift; +} +bool FrameData::getHDR () const +{ + return isHDR; +} +IIOSampleFormat FrameData::getSampleFormat () const +{ + return sampleFormat; +} +rtexif::TagDirectory* FrameData::getExifData () const +{ + return root; +} +bool FrameData::hasExif () const +{ + return root && root->getCount(); +} +bool FrameData::hasIPTC () const +{ + return iptc; +} +tm FrameData::getDateTime () const +{ + return time; +} +time_t FrameData::getDateTimeAsTS () const +{ + return timeStamp; +} +int FrameData::getISOSpeed () const +{ + return iso_speed; +} +double FrameData::getFNumber () const +{ + return aperture; +} +double FrameData::getFocalLen () const +{ + return focal_len; +} +double FrameData::getFocalLen35mm () const +{ + return focal_len35mm; +} +float FrameData::getFocusDist () const +{ + return focus_dist; +} +double FrameData::getShutterSpeed () const +{ + return shutter; +} +double FrameData::getExpComp () const +{ + return expcomp; +} +std::string FrameData::getMake () const +{ + return make; +} +std::string FrameData::getModel () const +{ + return model; +} +std::string FrameData::getLens () const +{ + return lens; +} +std::string FrameData::getSerialNumber () const +{ + return serial; +} +std::string FrameData::getOrientation () const +{ + return orientation; +} + + + +void FramesData::setDCRawFrameCount (unsigned int frameCount) +{ + dcrawFrameCount = frameCount; +} + +unsigned int FramesData::getFrameCount () const +{ + return dcrawFrameCount ? dcrawFrameCount : frames.size(); +} +FrameData *FramesData::getFrameData (int frame) const +{ + return frames.at(frame); +} + +bool FramesData::getPixelShift (unsigned int frame) const +{ + // So far only Pentax provide multi-frame HDR file. + // Only the first frame contains the HDR tag + // If more brand have to be supported, this rule may need + // to evolve + + //return frames.at(frame)->getPixelShift (); + return frames.at(0)->getPixelShift (); +} +bool FramesData::getHDR (unsigned int frame) const +{ + // So far only Pentax provide multi-frame HDR file. + // Only the first frame contains the HDR tag + // If more brand have to be supported, this rule may need + // to evolve + + //return frames.at(frame)->getHDR (); + if (frames.size()) { + return frames.at(0)->getHDR (); + } else { + return 0; + } +} + +IIOSampleFormat FramesData::getSampleFormat (unsigned int frame) const +{ + return frames.at(frame)->getSampleFormat (); +} + +rtexif::TagDirectory* FramesData::getExifData (unsigned int frame) const +{ + return frames.at(frame)->getExifData (); +} +procparams::IPTCPairs FramesData::getIPTCData (unsigned int frame) const +{ + return frames.at(frame)->getIPTCData (); +} + +bool FramesData::hasExif (unsigned int frame) const +{ + return frames.at(frame)->hasExif (); +} +bool FramesData::hasIPTC (unsigned int frame) const +{ + return frames.at(frame)->hasIPTC (); +} + +tm FramesData::getDateTime (unsigned int frame) const +{ + return frames.at(frame)->getDateTime (); +} +time_t FramesData::getDateTimeAsTS(unsigned int frame) const +{ + return frames.at(frame)->getDateTimeAsTS (); +} +int FramesData::getISOSpeed (unsigned int frame) const +{ + return frames.at(frame)->getISOSpeed (); +} +double FramesData::getFNumber (unsigned int frame) const +{ + return frames.at(frame)->getFNumber (); +} +double FramesData::getFocalLen (unsigned int frame) const +{ + return frames.at(frame)->getFocalLen (); +} +double FramesData::getFocalLen35mm (unsigned int frame) const +{ + return frames.at(frame)->getFocalLen35mm (); +} +float FramesData::getFocusDist (unsigned int frame) const +{ + return frames.at(frame)->getFocusDist (); +} +double FramesData::getShutterSpeed (unsigned int frame) const +{ + return frames.at(frame)->getShutterSpeed (); +} +double FramesData::getExpComp (unsigned int frame) const +{ + return frames.at(frame)->getExpComp (); +} +std::string FramesData::getMake (unsigned int frame) const +{ + return frames.at(frame)->getMake (); +} +std::string FramesData::getModel (unsigned int frame) const +{ + return frames.at(frame)->getModel (); +} +std::string FramesData::getLens (unsigned int frame) const +{ + return frames.at(frame)->getLens (); +} +std::string FramesData::getSerialNumber (unsigned int frame) const +{ + return frames.at(frame)->getSerialNumber (); +} +std::string FramesData::getOrientation (unsigned int frame) const +{ + return frames.at(frame)->getOrientation (); +} + + //------inherited functions--------------// diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index da5b337cb..7474ecab7 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -54,7 +54,7 @@ protected: // each frame has the knowledge of "being an" // or "being part of an" HDR or PS image bool isPixelShift; - int isHDR; // Number of frame + bool isHDR; void extractInfo (); @@ -64,90 +64,27 @@ public: FrameData (rtexif::ExifManager &exifManager); virtual ~FrameData (); - bool getPixelShift () const - { - return isPixelShift; - } - int getHDR () const - { - return isHDR; - } - - IIOSampleFormat getSampleFormat () const - { - return sampleFormat; - } - - const rtexif::TagDirectory* getExifData () const - { - return root; - } - const procparams::IPTCPairs getIPTCData () const; - - bool hasExif () const - { - return root && root->getCount(); - } - bool hasIPTC () const - { - return iptc; - } - - struct tm getDateTime () const { - return time; - } - time_t getDateTimeAsTS() const - { - return timeStamp; - } - int getISOSpeed () const - { - return iso_speed; - } - double getFNumber () const - { - return aperture; - } - double getFocalLen () const - { - return focal_len; - } - double getFocalLen35mm () const - { - return focal_len35mm; - } - float getFocusDist () const - { - return focus_dist; - } - double getShutterSpeed () const - { - return shutter; - } - double getExpComp () const - { - return expcomp; - } - std::string getMake () const - { - return make; - } - std::string getModel () const - { - return model; - } - std::string getLens () const - { - return lens; - } - std::string getSerialNumber () const - { - return serial; - } - std::string getOrientation () const - { - return orientation; - } + bool getPixelShift () const; + bool getHDR () const; + IIOSampleFormat getSampleFormat () const; + rtexif::TagDirectory* getExifData () const; + procparams::IPTCPairs getIPTCData () const; + bool hasExif () const; + bool hasIPTC () const; + tm getDateTime () const; + time_t getDateTimeAsTS () const; + int getISOSpeed () const; + double getFNumber () const; + double getFocalLen () const; + double getFocalLen35mm () const; + float getFocusDist () const; + double getShutterSpeed () const; + double getExpComp () const; + std::string getMake () const; + std::string getModel () const; + std::string getLens () const; + std::string getSerialNumber () const; + std::string getOrientation () const; }; class RawFrameData : public FrameData @@ -171,130 +108,36 @@ public: class FramesData : public FramesMetaData { private: std::vector frames; - int dcrawFrameCount; + unsigned int dcrawFrameCount; public: FramesData (Glib::ustring fname, RawMetaDataLocation* rml = nullptr, bool firstFrameOnly = false, bool loadAll = false); ~FramesData (); - void setDCRawFrameCount (int frameCount) - { - dcrawFrameCount = frameCount; - } - - int getFrameCount () const - { - return dcrawFrameCount ? dcrawFrameCount : frames.size(); - } - FrameData *getFrameData (int frame) const - { - return frames.at(frame); - } - - bool getPixelShift (int frame = 0) const - { - // So far only Pentax provide multi-frame HDR file. - // Only the first frame contains the HDR tag - // If more brand have to be supported, this rule may need - // to evolve - - //return frames.at(frame)->getPixelShift (); - return frames.at(0)->getPixelShift (); - } - int getHDR (int frame = 0) const - { - // So far only Pentax provide multi-frame HDR file. - // Only the first frame contains the HDR tag - // If more brand have to be supported, this rule may need - // to evolve - - //return frames.at(frame)->getPixelShift (); - if (frames.size()) { - return frames.at(frame)->getHDR (); - } else { - return 0; - } - } - - IIOSampleFormat getSampleFormat (int frame = 0) const - { - return frames.at(frame)->getSampleFormat (); - } - - const rtexif::TagDirectory* getExifData (int frame = 0) const - { - return frames.at(frame)->getExifData (); - } - const procparams::IPTCPairs getIPTCData (int frame = 0) const - { - return frames.at(frame)->getIPTCData (); - } - - bool hasExif (int frame = 0) const - { - return frames.at(frame)->hasExif (); - } - bool hasIPTC (int frame = 0) const - { - return frames.at(frame)->hasIPTC (); - } - - struct tm getDateTime (int frame = 0) const { - return frames.at(frame)->getDateTime (); - } - time_t getDateTimeAsTS(int frame = 0) const - { - return frames.at(frame)->getDateTimeAsTS (); - } - int getISOSpeed (int frame = 0) const - { - return frames.at(frame)->getISOSpeed (); - } - double getFNumber (int frame = 0) const - { - return frames.at(frame)->getFNumber (); - } - double getFocalLen (int frame = 0) const - { - return frames.at(frame)->getFocalLen (); - } - double getFocalLen35mm (int frame = 0) const - { - return frames.at(frame)->getFocalLen35mm (); - } - float getFocusDist (int frame = 0) const - { - return frames.at(frame)->getFocusDist (); - } - double getShutterSpeed (int frame = 0) const - { - return frames.at(frame)->getShutterSpeed (); - } - double getExpComp (int frame = 0) const - { - return frames.at(frame)->getExpComp (); - } - std::string getMake (int frame = 0) const - { - return frames.at(frame)->getMake (); - } - std::string getModel (int frame = 0) const - { - return frames.at(frame)->getModel (); - } - std::string getLens (int frame = 0) const - { - return frames.at(frame)->getLens (); - } - std::string getSerialNumber (int frame = 0) const - { - return frames.at(frame)->getSerialNumber (); - } - std::string getOrientation (int frame = 0) const - { - return frames.at(frame)->getOrientation (); - } - + void setDCRawFrameCount (unsigned int frameCount); + unsigned int getFrameCount () const; + FrameData *getFrameData (int frame) const; + bool getPixelShift (unsigned int frame = 0) const; + bool getHDR (unsigned int frame = 0) const; + IIOSampleFormat getSampleFormat (unsigned int frame = 0) const; + rtexif::TagDirectory* getExifData (unsigned int frame = 0) const; + procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const; + bool hasExif (unsigned int frame = 0) const; + bool hasIPTC (unsigned int frame = 0) const; + tm getDateTime (unsigned int frame = 0) const; + time_t getDateTimeAsTS (unsigned int frame = 0) const; + int getISOSpeed (unsigned int frame = 0) const; + double getFNumber (unsigned int frame = 0) const; + double getFocalLen (unsigned int frame = 0) const; + double getFocalLen35mm (unsigned int frame = 0) const; + float getFocusDist (unsigned int frame = 0) const; + double getShutterSpeed (unsigned int frame = 0) const; + double getExpComp (unsigned int frame = 0) const; + std::string getMake (unsigned int frame = 0) const; + std::string getModel (unsigned int frame = 0) const; + std::string getLens (unsigned int frame = 0) const; + std::string getSerialNumber (unsigned int frame = 0) const; + std::string getOrientation (unsigned int frame = 0) const; }; diff --git a/rtengine/imageformat.h b/rtengine/imageformat.h index b34f701b7..2c9bb480d 100644 --- a/rtengine/imageformat.h +++ b/rtengine/imageformat.h @@ -1,7 +1,7 @@ /* * This file is part of RawTherapee. * - * Copyright (c) 20017 Jean-Christophe Frisch + * Copyright (c) 2017 Jean-Christophe Frisch * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 02f0ec550..e7aa9d1a5 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -78,7 +78,7 @@ public: virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; virtual void MSR (LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; - virtual bool IsrgbSourceModified () const = 0; // tracks whether cached rgb output of demosaic has been modified + virtual bool IsRGBSourceModified () const = 0; // tracks whether cached rgb output of demosaic has been modified virtual void setCurrentFrame (unsigned int frameNum) = 0; virtual int getFrameCount () = 0; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index e7a611f0b..2758ca889 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -220,8 +220,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if ( (todo & M_RAW) || (!highDetailRawComputed && highDetailNeeded) - || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->IsrgbSourceModified()) - || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->IsrgbSourceModified())) { + || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->IsRGBSourceModified()) + || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->IsRGBSourceModified())) { if (settings->verbose) { if (imgsrc->getSensorType() == ST_BAYER) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 21db71a72..77f277cbf 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -128,7 +128,7 @@ public: void refinement_lassus (int PassCount); void refinement(int PassCount); - bool IsrgbSourceModified() const + bool IsRGBSourceModified() const { return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified } diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index e72f6fbfd..8e6e8430d 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -58,59 +58,59 @@ class FramesMetaData public: /** @return Returns the number of frame contained in the file based on Metadata */ - virtual int getFrameCount () const = 0; + virtual unsigned int getFrameCount () const = 0; /** Checks the availability of exif metadata tags. * @return Returns true if image contains exif metadata tags */ - virtual bool hasExif (int frame = 0) const = 0; + virtual bool hasExif (unsigned int frame = 0) const = 0; /** Returns the directory of exif metadata tags. * @return The directory of exif metadata tags */ - virtual const rtexif::TagDirectory* getExifData (int frame = 0) const = 0; + virtual rtexif::TagDirectory* getExifData (unsigned int frame = 0) const = 0; /** Checks the availability of IPTC tags. * @return Returns true if image contains IPTC tags */ - virtual bool hasIPTC (int frame = 0) const = 0; + virtual bool hasIPTC (unsigned int frame = 0) const = 0; /** Returns the directory of IPTC tags. * @return The directory of IPTC tags */ - virtual const procparams::IPTCPairs getIPTCData (int frame = 0) const = 0; + virtual procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const = 0; /** @return a struct containing the date and time of the image */ - virtual struct tm getDateTime (int frame = 0) const = 0; + virtual tm getDateTime (unsigned int frame = 0) const = 0; /** @return a timestamp containing the date and time of the image */ - virtual time_t getDateTimeAsTS(int frame = 0) const = 0; + virtual time_t getDateTimeAsTS(unsigned int frame = 0) const = 0; /** @return the ISO of the image */ - virtual int getISOSpeed (int frame = 0) const = 0; + virtual int getISOSpeed (unsigned int frame = 0) const = 0; /** @return the F number of the image */ - virtual double getFNumber (int frame = 0) const = 0; + virtual double getFNumber (unsigned int frame = 0) const = 0; /** @return the focal length used at the exposure */ - virtual double getFocalLen (int frame = 0) const = 0; + virtual double getFocalLen (unsigned int frame = 0) const = 0; /** @return the focal length in 35mm used at the exposure */ - virtual double getFocalLen35mm (int frame = 0) const = 0; + virtual double getFocalLen35mm (unsigned int frame = 0) const = 0; /** @return the focus distance in meters, 0=unknown, 10000=infinity */ - virtual float getFocusDist (int frame = 0) const = 0; + virtual float getFocusDist (unsigned int frame = 0) const = 0; /** @return the shutter speed */ - virtual double getShutterSpeed (int frame = 0) const = 0; + virtual double getShutterSpeed (unsigned int frame = 0) const = 0; /** @return the exposure compensation */ - virtual double getExpComp (int frame = 0) const = 0; + virtual double getExpComp (unsigned int frame = 0) const = 0; /** @return the maker of the camera */ - virtual std::string getMake (int frame = 0) const = 0; + virtual std::string getMake (unsigned int frame = 0) const = 0; /** @return the model of the camera */ - virtual std::string getModel (int frame = 0) const = 0; + virtual std::string getModel (unsigned int frame = 0) const = 0; - std::string getCamera (int frame = 0) const + std::string getCamera (unsigned int frame = 0) const { return getMake(frame) + " " + getModel(frame); } /** @return the lens on the camera */ - virtual std::string getLens (int frame = 0) const = 0; + virtual std::string getLens (unsigned int frame = 0) const = 0; /** @return the orientation of the image */ - virtual std::string getOrientation (int frame = 0) const = 0; + virtual std::string getOrientation (unsigned int frame = 0) const = 0; /** @return true if the file is a PixelShift shot (Pentax bodies) */ - virtual bool getPixelShift (int frame = 0) const = 0; + virtual bool getPixelShift (unsigned int frame = 0) const = 0; /** @return 0: not ah HDR file ; 1: single shot HDR (e.g. 32 bit float DNG file or Log compressed) ; >1: multi-frame HDR file */ - virtual int getHDR (int frame = 0) const = 0; + virtual bool getHDR (unsigned int frame = 0) const = 0; /** @return the sample format based on MetaData */ - virtual IIOSampleFormat getSampleFormat (int frame = 0) const = 0; + virtual IIOSampleFormat getSampleFormat (unsigned int frame = 0) const = 0; /** Functions to convert between floating point and string representation of shutter and aperture */ static std::string apertureToString (double aperture); @@ -123,7 +123,7 @@ public: /** Functions to convert between floating point and string representation of exposure compensation */ static std::string expcompToString (double expcomp, bool maskZeroexpcomp); - virtual ~FramesMetaData () {} + virtual ~FramesMetaData () = default; /** Reads metadata from file. * @param fname is the name of the file diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 2e845e3f3..6759e4739 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -93,7 +93,7 @@ public: void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h) static void colorSpaceConversion (Imagefloat* im, const ColorManagementParams &cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); - bool IsrgbSourceModified() const + bool IsRGBSourceModified() const { return rgbSourceModified; } diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 7c508892a..b242c2cbd 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -290,7 +290,7 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring 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_integer ("Common Data", "IsHDR", cfs->isHDR); + kf->set_boolean ("Common Data", "IsHDR", cfs->isHDR); kf->set_boolean ("Common Data", "IsPixelShift", cfs->isPixelShift); kf->set_string ("Common Data", "Lens", cfs->lens); kf->set_string ("Common Data", "Make", cfs->camMake); @@ -2881,10 +2881,8 @@ TagDirectory* ExifManager::parseTIFF (bool skipIgnored) { if (!rml) { - rml = new rtengine::RawMetaDataLocation(0); - TagDirectory* tagDir = parse (skipIgnored); - delete rml; - return tagDir; + std::unique_ptr rml(new rtengine::RawMetaDataLocation(0)); + return parse (skipIgnored); } else { return parse (skipIgnored); } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index c476e3dc9..5821c58f5 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -49,7 +49,7 @@ enum ActionCode { }; enum ByteOrder {UNKNOWN = 0, INTEL = 0x4949, MOTOROLA = 0x4D4D}; #if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__ -const enum ByteOrder HOSTORDER = INTEL; +const ByteOrder HOSTORDER = INTEL; #else const enum ByteOrder HOSTORDER = MOTOROLA; #endif @@ -312,6 +312,7 @@ class ExifManager Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name); TagDirectory* parseIFD (int ifdOffset, bool skipIgnored); + void parseCIFF (int length, TagDirectory* root); public: FILE* f; @@ -340,7 +341,6 @@ public: TagDirectory* parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail TagDirectory* parseTIFF (bool skipIgnored = true); TagDirectory* parseCIFF (); - void parseCIFF (int length, TagDirectory* root); /// @brief Get default tag for TIFF /// @param forthis The byte order will be taken from the given directory. diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index e1a3eaba3..5726b041d 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -25,7 +25,7 @@ CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (0), isPixelShift (false), + fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (false), isPixelShift (false), sampleFormat(rtengine::IIOSF_UNKNOWN), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) { } @@ -246,7 +246,7 @@ int CacheImageData::save (const Glib::ustring& fname) keyFile.set_double ("ExifInfo", "FocalLen35mm", focalLen35mm); keyFile.set_double ("ExifInfo", "FocusDist", focusDist); keyFile.set_integer ("ExifInfo", "ISO", iso); - keyFile.set_integer ("ExifInfo", "IsHDR", isHDR); + keyFile.set_boolean ("ExifInfo", "IsHDR", isHDR); keyFile.set_boolean ("ExifInfo", "IsPixelShift", isPixelShift); keyFile.set_string ("ExifInfo", "ExpComp", expcomp); } diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 548633168..1934442d1 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -52,7 +52,7 @@ public: double focalLen, focalLen35mm; float focusDist; unsigned iso; - int isHDR; // null if no HDR, otherwise provide the number of frame for this HDR file + bool isHDR; bool isPixelShift; rtengine::IIO_Sample_Format sampleFormat; Glib::ustring lens; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 1566f3c07..c1760c1ff 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1264,11 +1264,6 @@ void EditorPanel::info_toggled () { Glib::ustring infoString; - Glib::ustring infoString1; //1-st line - Glib::ustring infoString2; //2-nd line - Glib::ustring infoString3; //3-rd line - Glib::ustring infoString4; //4-th line - Glib::ustring infoString5; //5-th line Glib::ustring expcomp; if (!ipc || !openThm) { @@ -1278,11 +1273,9 @@ void EditorPanel::info_toggled () const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData(); if (idata && idata->hasExif()) { - infoString1 = Glib::ustring::compose ("%1 + %2", + infoString = Glib::ustring::compose ("%1 + %2\nf/%3 %4s %5%6 %7mm", Glib::ustring (idata->getMake() + " " + idata->getModel()), - Glib::ustring (idata->getLens())); - - infoString2 = Glib::ustring::compose ("f/%1 %2s %3%4 %5mm", + Glib::ustring (idata->getLens()), Glib::ustring (idata->apertureToString (idata->getFNumber())), Glib::ustring (idata->shutterToString (idata->getShutterSpeed())), M ("QINFO_ISO"), idata->getISOSpeed(), @@ -1290,40 +1283,39 @@ void EditorPanel::info_toggled () expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(), true)); // maskZeroexpcomp - if (expcomp != "") { - infoString2 = Glib::ustring::compose ("%1 %2EV", - infoString2, + if (!expcomp.empty ()) { + infoString = Glib::ustring::compose ("%1 %2EV", + infoString, expcomp /*Glib::ustring(idata->expcompToString(idata->getExpComp()))*/); } - infoString3 = Glib::ustring::compose ("%1%2", + infoString = Glib::ustring::compose ("%1\n%2%3", + infoString, escapeHtmlChars (Glib::path_get_dirname (openThm->getFileName())) + G_DIR_SEPARATOR_S, escapeHtmlChars (Glib::path_get_basename (openThm->getFileName())) ); int ww = ipc->getFullWidth(); int hh = ipc->getFullHeight(); //megapixels - infoString4 = Glib::ustring::compose ("%1 MP (%2x%3)", Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), ww, hh); - - infoString = Glib::ustring::compose ("%1\n%2\n%3\n%4", infoString1, infoString2, infoString3, infoString4); + infoString = Glib::ustring::compose ("%1\n%2 MP (%2x%3)", + infoString, + Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), + ww, hh); //adding special characteristics bool isHDR = idata->getHDR(); bool isPixelShift = idata->getPixelShift(); - int numFrames = idata->getFrameCount(); + unsigned int numFrames = idata->getFrameCount(); if (isHDR) { - infoString5 = Glib::ustring::compose (M("QINFO_HDR"), numFrames); + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames); if (numFrames == 1) { int sampleFormat = idata->getSampleFormat(); - infoString5 = Glib::ustring::compose ("%1 / %2", infoString5, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat))); + infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat))); } } else if (isPixelShift) { - infoString5 = Glib::ustring::compose (M("QINFO_PIXELSHIFT"), numFrames); + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames); + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_PIXELSHIFT"), infoString, numFrames); } - if (!infoString5.empty()) { - infoString = Glib::ustring::compose ("%1\n%2", infoString, infoString5); - } - } else { infoString = M ("QINFO_NOEXIF"); } diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 370a29c77..1f5b7d999 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -186,7 +186,7 @@ void ExifPanel::setImageData (const FramesMetaData* id) if (id) { //bool first = true; // HOMBRE: Should we only display the current frame's Exifs ? - for (int frameNum = 0; frameNum < id->getFrameCount (); ++frameNum) { + for (unsigned int frameNum = 0; frameNum < id->getFrameCount (); ++frameNum) { if ( id->getExifData (frameNum)) { /* if (!first) { From d5e4980c08af68bf06cf40091ce17b4817064013 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Sat, 12 Aug 2017 19:21:29 +0200 Subject: [PATCH 03/27] Adding Floessie's patch to use std::unique_ptr (issue #4008) --- rtengine/dfmanager.cc | 3 +-- rtengine/ffmanager.cc | 3 +-- rtengine/imagedata.cc | 23 +++++++++++++-------- rtengine/imagedata.h | 13 ++++++++---- rtengine/rawimagesource.cc | 9 +++----- rtengine/rtengine.h | 2 +- rtexif/rtexif.cc | 42 ++++++++++++++++++++++---------------- rtexif/rtexif.h | 22 +++++++++++--------- rtgui/thumbnail.cc | 13 +++++------- rtgui/thumbnail.h | 2 +- 10 files changed, 71 insertions(+), 61 deletions(-) diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc index 68123d9b4..1ce43637d 100644 --- a/rtengine/dfmanager.cc +++ b/rtengine/dfmanager.cc @@ -382,8 +382,7 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool) return &(iter->second); } - RawMetaDataLocation rml(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen()); - FramesData idata(filename, &rml, true); + FramesData idata(filename, std::unique_ptr(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true); /* Files are added in the map, divided by same maker/model,ISO and shutter*/ std::string key( dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed()) ); iter = dfList.find( key ); diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc index 6acdc1b0a..8f8d928c1 100644 --- a/rtengine/ffmanager.cc +++ b/rtengine/ffmanager.cc @@ -338,8 +338,7 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool) return &(iter->second); } - RawMetaDataLocation rml(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen()); - FramesData idata(filename, &rml, true); + FramesData idata(filename, std::unique_ptr(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true); /* Files are added in the map, divided by same maker/model,lens and aperture*/ std::string key( ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()) ); iter = ffList.find( key ); diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 9c27ddd50..66cd3874b 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -41,9 +41,9 @@ Glib::ustring to_utf8 (const std::string& str) } -FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml, bool firstFrameOnly) +FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly) { - return new FramesData (fname, rml, firstFrameOnly); + return new FramesData (fname, std::move(rml), firstFrameOnly); } FrameData::FrameData () @@ -1000,18 +1000,20 @@ failure: } -FramesData::FramesData (Glib::ustring fname, RawMetaDataLocation* rml, bool firstFrameOnly, bool loadAll) : dcrawFrameCount (0) +FramesData::FramesData (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly, bool loadAll) : + dcrawFrameCount (0) { if (rml && (rml->exifBase >= 0 || rml->ciffBase >= 0)) { FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { - rtexif::ExifManager exifManager (f, rml, firstFrameOnly); + const bool has_rml_exif_base = rml->exifBase >= 0; + rtexif::ExifManager exifManager (f, std::move(rml), firstFrameOnly); - if (rml->exifBase >= 0) { + if (has_rml_exif_base) { FrameData *idata = new RawFrameData (exifManager); frames.push_back(idata); - if (rml && !firstFrameOnly) { + if (!firstFrameOnly) { while (exifManager.getNextIFDOffset ()) { int nextIFD = exifManager.getNextIFDOffset (); exifManager.setIFDOffset (nextIFD); @@ -1026,7 +1028,8 @@ FramesData::FramesData (Glib::ustring fname, RawMetaDataLocation* rml, bool firs FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { - rtexif::ExifManager exifManager (f, rml, true); + rtexif::ExifManager exifManager (f, std::move(rml), true); + FrameData *idata = new JpegFrameData (exifManager); frames.push_back(idata); fclose (f); @@ -1035,10 +1038,12 @@ FramesData::FramesData (Glib::ustring fname, RawMetaDataLocation* rml, bool firs FILE* f = g_fopen (fname.c_str (), "rb"); if (f) { - rtexif::ExifManager exifManager (f, rml, firstFrameOnly); + const bool has_rml = static_cast(rml); + rtexif::ExifManager exifManager (f, std::move(rml), firstFrameOnly); + FrameData *idata = new TiffFrameData (exifManager); frames.push_back(idata); - if (rml && !firstFrameOnly) { + if (has_rml && !firstFrameOnly) { while (exifManager.getNextIFDOffset ()) { exifManager.setIFDOffset (exifManager.getNextIFDOffset ()); idata = new TiffFrameData (exifManager); diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 7474ecab7..f8ba685c1 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -20,12 +20,17 @@ #define __IMAGEDATA_H__ #include -#include "rawimage.h" +#include #include + #include -#include "../rtexif/rtexif.h" -#include "procparams.h" + #include + +#include "../rtexif/rtexif.h" + +#include "procparams.h" +#include "rawimage.h" #include "rtengine.h" namespace rtengine @@ -111,7 +116,7 @@ private: unsigned int dcrawFrameCount; public: - FramesData (Glib::ustring fname, RawMetaDataLocation* rml = nullptr, bool firstFrameOnly = false, bool loadAll = false); + FramesData (const Glib::ustring& fname, std::unique_ptr rml = nullptr, bool firstFrameOnly = false, bool loadAll = false); ~FramesData (); void setDCRawFrameCount (unsigned int frameCount); diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 6641cf51e..0cbb393d7 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1698,12 +1698,9 @@ int RawImageSource::load (const Glib::ustring &fname, int imageNum, bool batch) } - //Load complete Exif informations - RawMetaDataLocation rml; - rml.exifBase = ri->get_exifBase(); - rml.ciffBase = ri->get_ciffBase(); - rml.ciffLength = ri->get_ciffLen(); - idata = new FramesData (fname, &rml); + // Load complete Exif informations + std::unique_ptr rml(new RawMetaDataLocation (ri->get_exifBase(), ri->get_ciffBase(), ri->get_ciffLen())); + idata = new FramesData (fname, std::move(rml)); idata->setDCRawFrameCount (numFrames); green(W, H); diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 8e6e8430d..8f5a490d6 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -131,7 +131,7 @@ public: * Use it only for raw files. In caseof jpgs and tiffs pass a NULL pointer. * @param firstFrameOnly must be true to get the MetaData of the first frame only, e.g. for a PixelShift file. * @return The metadata */ - static FramesMetaData* fromFile (const Glib::ustring& fname, RawMetaDataLocation* rml, bool firstFrameOnly = false); + static FramesMetaData* fromFile (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly = false); }; /** This listener interface is used to indicate the progress of time consuming operations */ diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index b242c2cbd..441d017d4 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -852,11 +852,11 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) } if (tag == 0x002e) { // location of the embedded preview image in raw files of Panasonic cameras - TagDirectory* previewdir; - { - ExifManager exifManager(f, 0, true); - previewdir = exifManager.parseJPEG (ftell (f)); // try to parse the exif data from the preview image - } + const TagDirectory* const previewdir = + [&f]() + { + return ExifManager(f, nullptr, true).parseJPEG(ftell(f)); // try to parse the exif data from the preview image + }(); if (previewdir) { if (previewdir->getTag ("Exif")) { @@ -1977,9 +1977,16 @@ void ExifManager::parseCIFF (int length, TagDirectory* root) fseek (f, rml->ciffBase + get4 (f, INTEL), SEEK_SET); if ((((type >> 8) + 8) | 8) == 0x38) { - rtengine::RawMetaDataLocation rml2(ftell (f), len); - ExifManager exifManager(f, &rml2, true); - exifManager.parseCIFF (len, root); // Parse a sub-table + ExifManager( + f, + std::unique_ptr( + new rtengine::RawMetaDataLocation( + ftell(f), + len + ) + ), + true + ).parseCIFF(len, root); // Parse a sub-table } if (type == 0x0810) { @@ -2010,7 +2017,7 @@ void ExifManager::parseCIFF (int length, TagDirectory* root) } - ExifManager exifManager(f, 0, true); + ExifManager exifManager(f, nullptr, true); if (type == 0x102d) { Tag* t = exifManager.saveCIFFMNTag (root, len, "CanonCameraSettings"); int mm = t->toInt (34, SHORT); @@ -2856,16 +2863,14 @@ TagDirectory* ExifManager::parseJPEG (int offset) tiffbase = ftell (f); // We need a RawMetaDataLocation to put the 'tiffbase' value - bool rmlCreated = false; - if (!rml) { - rml = new rtengine::RawMetaDataLocation (0); - rmlCreated = true; + const bool rmlCreated = !rml; + if (rmlCreated) { + rml.reset(new rtengine::RawMetaDataLocation(0)); } rml->exifBase = tiffbase; TagDirectory* tagDir = parse (); if (rmlCreated) { - delete rml; - rml = nullptr; + rml.reset(); } return tagDir; } @@ -2879,10 +2884,11 @@ TagDirectory* ExifManager::parseJPEG (int offset) TagDirectory* ExifManager::parseTIFF (bool skipIgnored) { - if (!rml) { - std::unique_ptr rml(new rtengine::RawMetaDataLocation(0)); - return parse (skipIgnored); + rml.reset(new rtengine::RawMetaDataLocation(0)); + TagDirectory* const res = parse(skipIgnored); + rml.reset(); + return res; } else { return parse (skipIgnored); } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 5821c58f5..bc9495187 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -19,14 +19,16 @@ #ifndef _MEXIF3_ #define _MEXIF3_ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include "../rtengine/procparams.h" @@ -316,14 +318,14 @@ class ExifManager public: FILE* f; - rtengine::RawMetaDataLocation *rml; + std::unique_ptr rml; ByteOrder order; bool onlyFirst; // Only first IFD unsigned int IFDOffset; unsigned int nextIFDOffset; - ExifManager (FILE* fHandle, rtengine::RawMetaDataLocation *rml, bool onlyFirstIFD) - : f(fHandle), rml(rml), order(UNKNOWN), onlyFirst(onlyFirstIFD), + ExifManager (FILE* fHandle, std::unique_ptr _rml, bool onlyFirstIFD) + : f(fHandle), rml(std::move(_rml)), order(UNKNOWN), onlyFirst(onlyFirstIFD), IFDOffset(0), nextIFDOffset(0) {} void setIFDOffset(unsigned int offset) diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 320424bf1..283f80bed 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -145,7 +145,7 @@ void Thumbnail::_generateThumbnailImage () if (tpp) { cfs.format = FT_Raw; cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; - infoFromImage (fname, &ri); + infoFromImage (fname, std::unique_ptr(new rtengine::RawMetaDataLocation(ri))); } } @@ -229,9 +229,8 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { rtengine::FramesMetaData* imageMetaData; if (getType() == FT_Raw) { - rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); // Should we ask all frame's MetaData ? - imageMetaData = rtengine::FramesMetaData::fromFile (fname, &metaData, true); + imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true); } else { // Should we ask all frame's MetaData ? imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); @@ -255,9 +254,8 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu rtengine::FramesMetaData* imageMetaData; if (getType() == FT_Raw) { - rtengine::RawMetaDataLocation metaData = rtengine::Thumbnail::loadMetaDataFromRaw(fname); // Should we ask all frame's MetaData ? - imageMetaData = rtengine::FramesMetaData::fromFile (fname, &metaData, true); + imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true); } else { // Should we ask all frame's MetaData ? imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true); @@ -713,10 +711,9 @@ ThFileType Thumbnail::getType () return (ThFileType) cfs.format; } -int Thumbnail::infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml) +int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptr rml) { - - rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, rml); + rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, std::move(rml)); if (!idata) { return 0; diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index eb9e38f7f..70bd60790 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -70,7 +70,7 @@ class Thumbnail void _loadThumbnail (bool firstTrial = true); void _saveThumbnail (); void _generateThumbnailImage (); - int infoFromImage (const Glib::ustring& fname, rtengine::RawMetaDataLocation* rml = nullptr); + int infoFromImage (const Glib::ustring& fname, std::unique_ptr rml = nullptr); void loadThumbnail (bool firstTrial = true); void generateExifDateTimeStrings (); From 86dac147c64cd91a2b13426ca15ea4701e502aca Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Sun, 13 Aug 2017 18:13:39 +0200 Subject: [PATCH 04/27] Adding icons on thumbnails and solving a bug in cacheimagedata.cc See issue #4008. The bug in cacheimagedata.cc was preventing correct cached thumbnail loading, asking for a full processing at each loading of the directory. --- rtdata/images/Dark/actions/HDR-thumbnail.png | Bin 0 -> 706 bytes .../Dark/actions/PixelShift-thumbnail.png | Bin 0 -> 479 bytes rtdata/images/Light/actions/HDR-thumbnail.png | Bin 0 -> 706 bytes .../Light/actions/PixelShift-thumbnail.png | Bin 0 -> 479 bytes rtengine/imagesource.h | 2 +- rtengine/improccoordinator.cc | 4 +- rtengine/rawimagesource.h | 2 +- rtengine/stdimagesource.h | 2 +- rtgui/cacheimagedata.cc | 2 +- rtgui/filebrowserentry.cc | 24 +++++++++ rtgui/filebrowserentry.h | 3 ++ rtgui/thumbbrowserentrybase.cc | 23 ++++++++- rtgui/thumbbrowserentrybase.h | 2 + rtgui/thumbnail.cc | 9 ++++ rtgui/thumbnail.h | 2 + .../source_icons/scalable/HDR-thumbnail.file | 1 + tools/source_icons/scalable/HDR-thumbnail.svg | 47 ++++++++---------- .../scalable/PixelShift-thumbnail.file | 1 + ...thumbnail.svg => PixelShift-thumbnail.svg} | 24 ++++----- 19 files changed, 104 insertions(+), 44 deletions(-) create mode 100644 rtdata/images/Dark/actions/HDR-thumbnail.png create mode 100644 rtdata/images/Dark/actions/PixelShift-thumbnail.png create mode 100644 rtdata/images/Light/actions/HDR-thumbnail.png create mode 100644 rtdata/images/Light/actions/PixelShift-thumbnail.png create mode 100644 tools/source_icons/scalable/HDR-thumbnail.file create mode 100644 tools/source_icons/scalable/PixelShift-thumbnail.file rename tools/source_icons/scalable/{PixeShift-thumbnail.svg => PixelShift-thumbnail.svg} (76%) diff --git a/rtdata/images/Dark/actions/HDR-thumbnail.png b/rtdata/images/Dark/actions/HDR-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..182e603e84574c7e9df97699e530b9c40cbadd72 GIT binary patch literal 706 zcmV;z0zLhSP)bCA!s3DXD6tYg`|jSf`uSAji4zK1i{>^Y|d-+qL}tMu*J?SGxHq|>jC1I zBL>j#_x*T0{`Y?m3&XINOePJ0oO2yX>UO&_#>g0>v$Hcv((&=Jj4_&6&N(^fI(#S_4Lv_U*GE$K_xF;d zQmG_BnM_8Kl+9+NH(yVwRFWi>%jKch*eb zZ!{W`q@$ywD0g>vr2#XGVDO!^+wIEpJOMg6Igupo@9zsx zEEd!2>#K^zq5v%{Ea>s^QMFo4i9|wxwzjr(d3hO8UteFVP$&pcKA)GQpGLa4xcFhB z?d|PvCYqn0A1Zw=m(%m}b7Z2)$w>_c1D&3p3Xtb{dU$yFDQ~CK!CFf)nZy_aKp2Kt zYgt=c?VKidMt56A&{JRZMn+fMwC zK^TU=9mn|qkfcvZS}vC|#zf`&zJef-B%MwtH5v`MuB&V|D`Si%lZhmKK2t?TolZwz z&8TeK)^@v<=XtSNx7&@3>{ra)ZU;cER%5+hKhX(-fWzScK)>JTcsw$lPN~=HZ!sgH zOeP~hrBX@0??;;#i-jD=iQcJHN~6(8UwV&rxm;rCmSw5e>q(MkvzhYw{M&rL-$zEy zzp((u<1x8hj!LD1=XtbREsDh=o6Uy#d``RF2H<+V#-j}e0|82>(+a~-uX0^CMq4Np zbid!@M7P@wV+`eT8OyR>x6o`hS*=!_&u5a!B-Lt_;c!SI@%QvBKtFMi*7L`|t3NL& V0bQ5A|H1$O002ovPDHLkV1oYB%Qyf4 literal 0 HcmV?d00001 diff --git a/rtdata/images/Light/actions/HDR-thumbnail.png b/rtdata/images/Light/actions/HDR-thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..182e603e84574c7e9df97699e530b9c40cbadd72 GIT binary patch literal 706 zcmV;z0zLhSP)bCA!s3DXD6tYg`|jSf`uSAji4zK1i{>^Y|d-+qL}tMu*J?SGxHq|>jC1I zBL>j#_x*T0{`Y?m3&XINOePJ0oO2yX>UO&_#>g0>v$Hcv((&=Jj4_&6&N(^fI(#S_4Lv_U*GE$K_xF;d zQmG_BnM_8Kl+9+NH(yVwRFWi>%jKch*eb zZ!{W`q@$ywD0g>vr2#XGVDO!^+wIEpJOMg6Igupo@9zsx zEEd!2>#K^zq5v%{Ea>s^QMFo4i9|wxwzjr(d3hO8UteFVP$&pcKA)GQpGLa4xcFhB z?d|PvCYqn0A1Zw=m(%m}b7Z2)$w>_c1D&3p3Xtb{dU$yFDQ~CK!CFf)nZy_aKp2Kt zYgt=c?VKidMt56A&{JRZMn+fMwC zK^TU=9mn|qkfcvZS}vC|#zf`&zJef-B%MwtH5v`MuB&V|D`Si%lZhmKK2t?TolZwz z&8TeK)^@v<=XtSNx7&@3>{ra)ZU;cER%5+hKhX(-fWzScK)>JTcsw$lPN~=HZ!sgH zOeP~hrBX@0??;;#i-jD=iQcJHN~6(8UwV&rxm;rCmSw5e>q(MkvzhYw{M&rL-$zEy zzp((u<1x8hj!LD1=XtbREsDh=o6Uy#d``RF2H<+V#-j}e0|82>(+a~-uX0^CMq4Np zbid!@M7P@wV+`eT8OyR>x6o`hS*=!_&u5a!B-Lt_;c!SI@%QvBKtFMi*7L`|t3NL& V0bQ5A|H1$O002ovPDHLkV1oYB%Qyf4 literal 0 HcmV?d00001 diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index e7aa9d1a5..2a67c367a 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -78,7 +78,7 @@ public: virtual void HLRecovery_inpaint (float** red, float** green, float** blue) {}; virtual void MSR (LabImage* lab, LUTf & mapcurve, bool &mapcontlutili, int width, int height, int skip, RetinexParams deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax) {}; - virtual bool IsRGBSourceModified () const = 0; // tracks whether cached rgb output of demosaic has been modified + virtual bool isRGBSourceModified () const = 0; // tracks whether cached rgb output of demosaic has been modified virtual void setCurrentFrame (unsigned int frameNum) = 0; virtual int getFrameCount () = 0; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 2758ca889..9cc11b59f 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -220,8 +220,8 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) if ( (todo & M_RAW) || (!highDetailRawComputed && highDetailNeeded) - || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->IsRGBSourceModified()) - || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->IsRGBSourceModified())) { + || ( params.toneCurve.hrenabled && params.toneCurve.method != "Color" && imgsrc->isRGBSourceModified()) + || (!params.toneCurve.hrenabled && params.toneCurve.method == "Color" && imgsrc->isRGBSourceModified())) { if (settings->verbose) { if (imgsrc->getSensorType() == ST_BAYER) { diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index 77f277cbf..3e76efd54 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -128,7 +128,7 @@ public: void refinement_lassus (int PassCount); void refinement(int PassCount); - bool IsRGBSourceModified() const + bool isRGBSourceModified() const { return rgbSourceModified; // tracks whether cached rgb output of demosaic has been modified } diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index 6759e4739..cdb0b14fc 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -93,7 +93,7 @@ public: void convertColorSpace(Imagefloat* image, const ColorManagementParams &cmp, const ColorTemp &wb);// RAWParams raw will not be used for non-raw files (see imagesource.h) static void colorSpaceConversion (Imagefloat* im, const ColorManagementParams &cmp, cmsHPROFILE embedded, IIOSampleFormat sampleFormat); - bool IsRGBSourceModified() const + bool isRGBSourceModified() const { return rgbSourceModified; } diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 5726b041d..d53ca6bb1 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -139,7 +139,7 @@ int CacheImageData::load (const Glib::ustring& fname) } if (keyFile.has_key ("ExifInfo", "IsHDR")) { - isHDR = keyFile.get_integer ("ExifInfo", "IsHDR"); + isHDR = keyFile.get_boolean ("ExifInfo", "IsHDR"); } if (keyFile.has_key ("ExifInfo", "IsPixelShift")) { diff --git a/rtgui/filebrowserentry.cc b/rtgui/filebrowserentry.cc index d76870788..c3adae3aa 100644 --- a/rtgui/filebrowserentry.cc +++ b/rtgui/filebrowserentry.cc @@ -36,6 +36,8 @@ bool FileBrowserEntry::iconsLoaded(false); Glib::RefPtr FileBrowserEntry::editedIcon; Glib::RefPtr FileBrowserEntry::recentlySavedIcon; Glib::RefPtr FileBrowserEntry::enqueuedIcon; +Glib::RefPtr FileBrowserEntry::hdr; +Glib::RefPtr FileBrowserEntry::ps; FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) : ThumbBrowserEntryBase (fname), wasInside(false), iatlistener(nullptr), press_x(0), press_y(0), action_x(0), action_y(0), rot_deg(0.0), landscape(true), cropgl(nullptr), state(SNormal), crop_custom_ratio(0.f) @@ -57,6 +59,8 @@ FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname) editedIcon = RTImage::createFromFile ("edited.png"); recentlySavedIcon = RTImage::createFromFile ("recent-save.png"); enqueuedIcon = RTImage::createFromFile ("processing.png"); + hdr = RTImage::createFromFile ("HDR-thumbnail.png"); + ps = RTImage::createFromFile ("PixelShift-thumbnail.png"); iconsLoaded = true; } @@ -137,6 +141,26 @@ std::vector > FileBrowserEntry::getIconsOnImageArea () return ret; } +std::vector > FileBrowserEntry::getSpecificityIconsOnImageArea () +{ + + std::vector > ret; + + if (!thumbnail) { + return ret; + } + + if (thumbnail->isHDR() && hdr) { + ret.push_back (hdr); + } + + if (thumbnail->isPixelShift() && ps) { + ret.push_back (ps); + } + + return ret; +} + void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr c) { if(scale != 1.0 && cropParams.enabled) { // somewhere in pipeline customBackBufferUpdate is called when scale == 1.0, which is nonsense for a thumb diff --git a/rtgui/filebrowserentry.h b/rtgui/filebrowserentry.h index 4c3d519ab..423128ddb 100644 --- a/rtgui/filebrowserentry.h +++ b/rtgui/filebrowserentry.h @@ -70,6 +70,8 @@ public: static Glib::RefPtr editedIcon; static Glib::RefPtr recentlySavedIcon; static Glib::RefPtr enqueuedIcon; + static Glib::RefPtr hdr; + static Glib::RefPtr ps; FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname); ~FileBrowserEntry (); @@ -87,6 +89,7 @@ public: void calcThumbnailSize (); virtual std::vector > getIconsOnImageArea (); + virtual std::vector > getSpecificityIconsOnImageArea (); virtual void getIconSize (int& w, int& h); // thumbnaillistener interface diff --git a/rtgui/thumbbrowserentrybase.cc b/rtgui/thumbbrowserentrybase.cc index ff7e58d49..0cb53d0c2 100644 --- a/rtgui/thumbbrowserentrybase.cc +++ b/rtgui/thumbbrowserentrybase.cc @@ -160,6 +160,7 @@ void ThumbBrowserEntryBase::updateBackBuffer () // draw icons onto the thumbnail area bbIcons = getIconsOnImageArea (); + bbSpecificityIcons = getSpecificityIconsOnImageArea (); int infow, infoh; getTextSizes (infow, infoh); @@ -224,6 +225,19 @@ void ThumbBrowserEntryBase::updateBackBuffer () } } + if (!bbSpecificityIcons.empty()) { + int igap = 2; + int istartx2 = prex + prew - 1 + igap; + int istarty2 = prey + preh - igap - 1; + + for (size_t i = 0; i < bbSpecificityIcons.size(); ++i) { + istartx2 -= bbSpecificityIcons[i]->get_width() - igap; + Gdk::Cairo::set_source_pixbuf(cc, bbSpecificityIcons[i], istartx2, istarty2 - bbSpecificityIcons[i]->get_height()); + cc->rectangle(istartx2, istarty2 - bbSpecificityIcons[i]->get_height(), bbSpecificityIcons[i]->get_width(), bbSpecificityIcons[i]->get_height()); + cc->fill(); + } + } + if ( ( (parent->getLocation() != ThumbBrowserBase::THLOC_EDITOR && options.showFileNames) || (parent->getLocation() == ThumbBrowserBase::THLOC_EDITOR && options.filmStripShowFileNames)) && withFilename > WFNAME_NONE) { @@ -512,7 +526,9 @@ void ThumbBrowserEntryBase::draw (Cairo::RefPtr cc) } if (!backBuffer || selected != bbSelected || framed != bbFramed || preview != bbPreview - || exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons || backBuffer->isDirty()) { + || exp_width != bbWidth || exp_height != bbHeight || getIconsOnImageArea () != bbIcons + || getSpecificityIconsOnImageArea() != bbSpecificityIcons || backBuffer->isDirty()) + { updateBackBuffer (); } @@ -592,6 +608,11 @@ std::vector > ThumbBrowserEntryBase::getIconsOnImageAr return std::vector >(); } +std::vector > ThumbBrowserEntryBase::getSpecificityIconsOnImageArea() +{ + return std::vector >(); +} + void ThumbBrowserEntryBase::getIconSize(int& w, int& h) { w = 0; diff --git a/rtgui/thumbbrowserentrybase.h b/rtgui/thumbbrowserentrybase.h index f4779faa1..0ebf597e2 100644 --- a/rtgui/thumbbrowserentrybase.h +++ b/rtgui/thumbbrowserentrybase.h @@ -80,6 +80,7 @@ protected: bool bbSelected, bbFramed; guint8* bbPreview; std::vector > bbIcons; + std::vector > bbSpecificityIcons; CursorShape cursor_type; void drawFrame (Cairo::RefPtr cr, const Gdk::RGBA& bg, const Gdk::RGBA& fg); @@ -185,6 +186,7 @@ public: virtual void drawProgressBar (Glib::RefPtr win, const Gdk::RGBA& foregr, const Gdk::RGBA& backgr, int x, int w, int y, int h) {} virtual std::vector > getIconsOnImageArea (); + virtual std::vector > getSpecificityIconsOnImageArea (); virtual void getIconSize (int& w, int& h); virtual bool motionNotify (int x, int y); diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 283f80bed..4bc5bcdb9 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -499,6 +499,15 @@ bool Thumbnail::isEnqueued () return enqueueNumber > 0; } +bool Thumbnail::isPixelShift () +{ + return cfs.isPixelShift; +} +bool Thumbnail::isHDR () +{ + return cfs.isHDR; +} + void Thumbnail::increaseRef () { MyMutex::MyLock lock(mutex); diff --git a/rtgui/thumbnail.h b/rtgui/thumbnail.h index 70bd60790..3ef094d6b 100644 --- a/rtgui/thumbnail.h +++ b/rtgui/thumbnail.h @@ -107,6 +107,8 @@ public: void imageEnqueued (); void imageRemovedFromQueue (); bool isEnqueued (); + bool isPixelShift (); + bool isHDR (); // unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); diff --git a/tools/source_icons/scalable/HDR-thumbnail.file b/tools/source_icons/scalable/HDR-thumbnail.file new file mode 100644 index 000000000..59f729498 --- /dev/null +++ b/tools/source_icons/scalable/HDR-thumbnail.file @@ -0,0 +1 @@ +HDR-thumbnail.png,w29,actions diff --git a/tools/source_icons/scalable/HDR-thumbnail.svg b/tools/source_icons/scalable/HDR-thumbnail.svg index 2b6d1a4bc..ef070f380 100644 --- a/tools/source_icons/scalable/HDR-thumbnail.svg +++ b/tools/source_icons/scalable/HDR-thumbnail.svg @@ -14,7 +14,7 @@ height="896.78442" id="svg2" sodipodi:version="0.32" - inkscape:version="0.91 r13725" + inkscape:version="0.92.1 r15371" sodipodi:docname="HDR-thumbnail.svg" inkscape:export-filename="/home/philippe/devel/rawtherapee/icons/NewIcons/processing.png" inkscape:export-xdpi="1.8" @@ -281,22 +281,22 @@ - - - - - + + + diff --git a/tools/source_icons/scalable/PixelShift-thumbnail.file b/tools/source_icons/scalable/PixelShift-thumbnail.file new file mode 100644 index 000000000..a62809a4d --- /dev/null +++ b/tools/source_icons/scalable/PixelShift-thumbnail.file @@ -0,0 +1 @@ +PixelShift-thumbnail.png,w18,actions diff --git a/tools/source_icons/scalable/PixeShift-thumbnail.svg b/tools/source_icons/scalable/PixelShift-thumbnail.svg similarity index 76% rename from tools/source_icons/scalable/PixeShift-thumbnail.svg rename to tools/source_icons/scalable/PixelShift-thumbnail.svg index 9e50ba9c1..b606b24f8 100644 --- a/tools/source_icons/scalable/PixeShift-thumbnail.svg +++ b/tools/source_icons/scalable/PixelShift-thumbnail.svg @@ -14,8 +14,8 @@ height="896.78442" id="svg2" sodipodi:version="0.32" - inkscape:version="0.91 r13725" - sodipodi:docname="PixeShift-thumbnail.svg" + inkscape:version="0.92.1 r15371" + sodipodi:docname="PixelShift-thumbnail.svg" inkscape:export-filename="/home/philippe/devel/rawtherapee/icons/NewIcons/processing.png" inkscape:export-xdpi="1.8" inkscape:export-ydpi="1.8" @@ -281,22 +281,22 @@ From a056493e9a4160d74b16bad61fe2b4c500d3c4a3 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Tue, 15 Aug 2017 16:25:56 +0200 Subject: [PATCH 05/27] Bug fix (see #4008) --- rtengine/imagedata.cc | 58 ++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 66cd3874b..aaa959c2e 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -767,7 +767,7 @@ unsigned int FramesData::getFrameCount () const } FrameData *FramesData::getFrameData (int frame) const { - return frames.at(frame); + return frames.empty() ? nullptr : frames.at(frame); } bool FramesData::getPixelShift (unsigned int frame) const @@ -778,7 +778,7 @@ bool FramesData::getPixelShift (unsigned int frame) const // to evolve //return frames.at(frame)->getPixelShift (); - return frames.at(0)->getPixelShift (); + return frames.empty() ? false : frames.at(0)->getPixelShift (); } bool FramesData::getHDR (unsigned int frame) const { @@ -788,91 +788,97 @@ bool FramesData::getHDR (unsigned int frame) const // to evolve //return frames.at(frame)->getHDR (); - if (frames.size()) { - return frames.at(0)->getHDR (); - } else { - return 0; - } + return frames.empty() ? false : frames.at(0)->getHDR (); } IIOSampleFormat FramesData::getSampleFormat (unsigned int frame) const { - return frames.at(frame)->getSampleFormat (); + return frames.empty() ? IIOSF_UNKNOWN : frames.at(frame)->getSampleFormat (); } rtexif::TagDirectory* FramesData::getExifData (unsigned int frame) const { - return frames.at(frame)->getExifData (); + return frames.empty() ? nullptr : frames.at(frame)->getExifData (); } procparams::IPTCPairs FramesData::getIPTCData (unsigned int frame) const { - return frames.at(frame)->getIPTCData (); + if (frames.empty()) { + procparams::IPTCPairs emptyPairs; + return emptyPairs; + } else { + return frames.at(frame)->getIPTCData (); + } } bool FramesData::hasExif (unsigned int frame) const { - return frames.at(frame)->hasExif (); + return frames.empty() ? false : frames.at(frame)->hasExif (); } bool FramesData::hasIPTC (unsigned int frame) const { - return frames.at(frame)->hasIPTC (); + return frames.empty() ? false : frames.at(frame)->hasIPTC (); } tm FramesData::getDateTime (unsigned int frame) const { - return frames.at(frame)->getDateTime (); + if (frames.empty()) { + tm emptytm = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + return emptytm; + } else { + return frames.at(frame)->getDateTime (); + } } time_t FramesData::getDateTimeAsTS(unsigned int frame) const { - return frames.at(frame)->getDateTimeAsTS (); + return frames.empty() ? 0 : frames.at(frame)->getDateTimeAsTS (); } int FramesData::getISOSpeed (unsigned int frame) const { - return frames.at(frame)->getISOSpeed (); + return frames.empty() ? 0 : frames.at(frame)->getISOSpeed (); } double FramesData::getFNumber (unsigned int frame) const { - return frames.at(frame)->getFNumber (); + return frames.empty() ? 0. : frames.at(frame)->getFNumber (); } double FramesData::getFocalLen (unsigned int frame) const { - return frames.at(frame)->getFocalLen (); + return frames.empty() ? 0. : frames.at(frame)->getFocalLen (); } double FramesData::getFocalLen35mm (unsigned int frame) const { - return frames.at(frame)->getFocalLen35mm (); + return frames.empty() ? 0. : frames.at(frame)->getFocalLen35mm (); } float FramesData::getFocusDist (unsigned int frame) const { - return frames.at(frame)->getFocusDist (); + return frames.empty() ? 0.f : frames.at(frame)->getFocusDist (); } double FramesData::getShutterSpeed (unsigned int frame) const { - return frames.at(frame)->getShutterSpeed (); + return frames.empty() ? 0. : frames.at(frame)->getShutterSpeed (); } double FramesData::getExpComp (unsigned int frame) const { - return frames.at(frame)->getExpComp (); + return frames.empty() ? 0. : frames.at(frame)->getExpComp (); } std::string FramesData::getMake (unsigned int frame) const { - return frames.at(frame)->getMake (); + return frames.empty() ? std::string() : frames.at(frame)->getMake (); } std::string FramesData::getModel (unsigned int frame) const { - return frames.at(frame)->getModel (); + return frames.empty() ? std::string() : frames.at(frame)->getModel (); } std::string FramesData::getLens (unsigned int frame) const { - return frames.at(frame)->getLens (); + return frames.empty() ? std::string() : frames.at(frame)->getLens (); } std::string FramesData::getSerialNumber (unsigned int frame) const { - return frames.at(frame)->getSerialNumber (); + return frames.empty() ? std::string() : frames.at(frame)->getSerialNumber (); } std::string FramesData::getOrientation (unsigned int frame) const { - return frames.at(frame)->getOrientation (); + return frames.empty() ? std::string() : frames.at(frame)->getOrientation (); } From ae19b6485a2078cb9e431089ce5f7680e1f3d265 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Sun, 20 Aug 2017 22:51:06 +0200 Subject: [PATCH 06/27] Adding separators between frames in ExifPanel (see #4008) --- rtgui/exifpanel.cc | 32 +++++++++++++++++++++++--------- rtgui/exifpanel.h | 3 +++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 1f5b7d999..133c3a9ed 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -45,6 +45,11 @@ ExifPanel::ExifPanel () : idata(nullptr) exifTreeModel = Gtk::TreeStore::create(exifColumns); exifTree->set_model (exifTreeModel); + exifTree->set_grid_lines(Gtk::TREE_VIEW_GRID_LINES_NONE); + exifTree->set_row_separator_func( + [&](const Glib::RefPtr& model, const Gtk::TreeModel::iterator& row) + { return row->get_value (exifColumns.isSeparator); } + ); delicon = RTImage::createFromFile ("gtk-close.png"); keepicon = RTImage::createFromFile ("gtk-apply.png"); @@ -184,18 +189,12 @@ void ExifPanel::setImageData (const FramesMetaData* id) exifTreeModel->clear (); if (id) { - //bool first = true; - // HOMBRE: Should we only display the current frame's Exifs ? for (unsigned int frameNum = 0; frameNum < id->getFrameCount (); ++frameNum) { if ( id->getExifData (frameNum)) { - /* - if (!first) { - Gtk::Separator *sep = Gtk::manage (new Gtk::Separator); - sep->set_orientation(Gtk::ORIENTATION_HORIZONTAL); - first = false; - } - */ //id->getExifData ()->printAll (); + if (frameNum > 0) { + addSeparator(); + } addDirectory (id->getExifData (frameNum), exifTreeModel->children()); } } @@ -233,6 +232,21 @@ Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root return row.children(); } +Gtk::TreeModel::Children ExifPanel::addSeparator () +{ + + Gtk::TreeModel::Row row = *(exifTreeModel->append(exifTreeModel->children())); + row[exifColumns.action] = rtexif::ActionCode::AC_INVALID; + row[exifColumns.editable] = false; + row[exifColumns.edited] = false; + row[exifColumns.field_nopango] = ""; + row[exifColumns.value_nopango] = ""; + row[exifColumns.orig_value] = ""; + row[exifColumns.isSeparator] = true; + + return row.children(); +} + void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root) { diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index db1fc8649..d86e82af8 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -43,6 +43,7 @@ private: Gtk::TreeModelColumn action; Gtk::TreeModelColumn editable; Gtk::TreeModelColumn edited; + Gtk::TreeModelColumn isSeparator; ExifColumns() { @@ -55,6 +56,7 @@ private: add(value_nopango); add(editable); add(orig_value); + add(isSeparator); } }; Glib::RefPtr delicon; @@ -76,6 +78,7 @@ private: void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value); void updateChangeList (Gtk::TreeModel::Children root, std::string prefix); void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root); + Gtk::TreeModel::Children addSeparator (); Glib::ustring getSelection (bool onlyifeditable = false); Glib::ustring getSelectedValue (); void updateChangeList (); From ee0bff4124a7dcadaab4cb262cec88fc8c058941 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Sat, 16 Sep 2017 22:30:07 +0200 Subject: [PATCH 07/27] Updated frame handling with any type of hierarchy (see #4008) Images can now be detected in nested IFDs or as root IFDs. --- rtengine/dcp.cc | 3 +- rtengine/imagedata.cc | 360 +++++++++++---------- rtengine/imagedata.h | 32 +- rtengine/rtengine.h | 11 +- rtengine/simpleprocess.cc | 4 +- rtexif/canonattribs.cc | 17 + rtexif/rtexif.cc | 660 +++++++++++++++++++++++--------------- rtexif/rtexif.h | 59 ++-- rtgui/editorpanel.cc | 3 +- rtgui/exifpanel.cc | 10 +- rtgui/thumbnail.cc | 2 +- 11 files changed, 667 insertions(+), 494 deletions(-) diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index ee0cf3462..f9cdd1c73 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -697,7 +697,8 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : } ExifManager exifManager(file, nullptr, true); - std::unique_ptr tagDir(exifManager.parseTIFF(false)); + exifManager.parseTIFF(false); + std::unique_ptr tagDir(exifManager.roots.at(0)); Tag* tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_1)); light_source_1 = diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index aaa959c2e..4be057685 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -46,86 +46,25 @@ FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, std::uniqu return new FramesData (fname, std::move(rml), firstFrameOnly); } -FrameData::FrameData () - : root(nullptr), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), +FrameData::FrameData (rtexif::TagDirectory* frameRootDir) + : frameRootDir(frameRootDir), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), lens("Unknown"), sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) { memset (&time, 0, sizeof(time)); -} -RawFrameData::RawFrameData (rtexif::ExifManager &exifManager) -{ - bool rootCreated = false; - if (exifManager.f && exifManager.rml) { - if (exifManager.rml->exifBase >= 0) { - root = exifManager.parse (); - - if (root) { - rtexif::Tag* t = root->getTag (0x83BB); - - if (t) { - iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); - } - extractInfo (); - rootCreated = true; - } - } else if (exifManager.rml->ciffBase >= 0) { - root = exifManager.parseCIFF (); - extractInfo (); - rootCreated = true; - } - } - if (!rootCreated) { - root = new rtexif::TagDirectory (); - } -} - -JpegFrameData::JpegFrameData (rtexif::ExifManager &exifManager) -{ - bool rootCreated = false; - if (exifManager.f) { - root = exifManager.parseJPEG (); - if (root) { - extractInfo (); - rootCreated = true; - } - rewind (exifManager.f); // Not sure this is necessary - iptc = iptc_data_new_from_jpeg_file (exifManager.f); - } - if (!rootCreated) { - root = new rtexif::TagDirectory (); - } -} - -TiffFrameData::TiffFrameData (rtexif::ExifManager &exifManager) -{ - bool rootCreated = false; - if (exifManager.f) { - root = exifManager.parseTIFF (); - extractInfo (); - - if (root) { - rtexif::Tag* t = root->getTag (0x83BB); - - if (t) { - iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); - } - rootCreated = true; - } - } - if (!rootCreated) { - root = new rtexif::TagDirectory (); - } + extractInfo(); } void FrameData::extractInfo () { - if (!root) { + if (!frameRootDir) { return; } + rtexif::Tag* tag; + memset(&time, 0, sizeof(time)); timeStamp = 0; iso_speed = 0; @@ -141,8 +80,9 @@ void FrameData::extractInfo () orientation.clear(); lens.clear(); - if (root->getTag("Make")) { - make = root->getTag ("Make")->valueToString(); + tag = frameRootDir->findTagUpward("Make"); + if (tag) { + make = tag->valueToString(); // Same dcraw treatment for (const auto& corp : { "Canon", @@ -174,8 +114,9 @@ void FrameData::extractInfo () make.erase(make.find_last_not_of(' ') + 1); } - if (root->getTag("Model")) { - model = root->getTag("Model")->valueToString(); + tag = frameRootDir->findTagUpward("Model"); + if (tag) { + model = tag->valueToString(); } if (!model.empty()) { @@ -207,66 +148,68 @@ void FrameData::extractInfo () model = "Unknown"; } - if (root->getTag ("Orientation")) { - orientation = root->getTag ("Orientation")->valueToString (); + tag = frameRootDir->findTagUpward("Orientation"); + if (tag) { + orientation = tag->valueToString (); } - rtexif::Tag* mnoteTag = root->findTag("MakerNote"); + tag = frameRootDir->findTagUpward("MakerNote"); rtexif::TagDirectory* mnote = nullptr; - if (mnoteTag) { - mnote = mnoteTag->getDirectory(); + if (tag) { + mnote = tag->getDirectory(); } rtexif::TagDirectory* exif = nullptr; - if (root->getTag ("Exif")) { - exif = root->getTag ("Exif")->getDirectory (); + tag = frameRootDir->findTagUpward("Exif"); + if (tag) { + exif = tag->getDirectory (); } if (exif) { // standard exif tags - if (exif->getTag ("ShutterSpeedValue")) { - shutter = exif->getTag ("ShutterSpeedValue")->toDouble (); + if ((tag = exif->getTag ("ShutterSpeedValue"))) { + shutter = tag->toDouble (); } - if (exif->getTag ("ExposureTime")) { - shutter = exif->getTag ("ExposureTime")->toDouble (); + if ((tag = exif->getTag ("ExposureTime"))) { + shutter = tag->toDouble (); } - if (exif->getTag ("ApertureValue")) { - aperture = exif->getTag ("ApertureValue")->toDouble (); + if ((tag = exif->getTag ("ApertureValue"))) { + aperture = tag->toDouble (); } - if (exif->getTag ("FNumber")) { - aperture = exif->getTag ("FNumber")->toDouble (); + if ((tag = exif->getTag ("FNumber"))) { + aperture = tag->toDouble (); } - if (exif->getTag ("ExposureBiasValue")) { - expcomp = exif->getTag ("ExposureBiasValue")->toDouble (); + if ((tag = exif->getTag ("ExposureBiasValue"))) { + expcomp = tag->toDouble (); } - if (exif->getTag ("FocalLength")) { - focal_len = exif->getTag ("FocalLength")->toDouble (); + if ((tag = exif->getTag ("FocalLength"))) { + focal_len = tag->toDouble (); } - if (exif->getTag ("FocalLengthIn35mmFilm")) { - focal_len35mm = exif->getTag ("FocalLengthIn35mmFilm")->toDouble (); + if ((tag = exif->getTag ("FocalLengthIn35mmFilm"))) { + focal_len35mm = tag->toDouble (); } // Focus distance from EXIF or XMP. MakerNote ones are scattered and partly encrypted int num = -3, denom = -3; // First try, offical EXIF. Set by Adobe on some DNGs - rtexif::Tag* pDst = exif->getTag("SubjectDistance"); + tag = exif->getTag("SubjectDistance"); - if (pDst) { + if (tag) { int num, denom; - pDst->toRational(num, denom); + tag->toRational(num, denom); } else { // Second try, XMP data char sXMPVal[64]; - if (root->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { + if (frameRootDir->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { sscanf(sXMPVal, "%d/%d", &num, &denom); } } @@ -279,12 +222,12 @@ void FrameData::extractInfo () } } - if (exif->getTag ("ISOSpeedRatings")) { - iso_speed = exif->getTag ("ISOSpeedRatings")->toDouble (); + if ((tag = exif->getTag ("ISOSpeedRatings"))) { + iso_speed = tag->toDouble (); } - if (exif->getTag ("DateTimeOriginal")) { - if (sscanf ((const char*)exif->getTag("DateTimeOriginal")->getValue(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { + if ((tag = exif->getTag ("DateTimeOriginal"))) { + if (sscanf ((const char*)tag->getValue(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { time.tm_year -= 1900; time.tm_mon -= 1; time.tm_isdst = -1; @@ -292,14 +235,14 @@ void FrameData::extractInfo () } } - rtexif::Tag *snTag = exif->findTag ("SerialNumber"); + tag = exif->findTag ("SerialNumber"); - if(!snTag) { - snTag = exif->findTag ("InternalSerialNumber"); + if(!tag) { + tag = exif->findTag ("InternalSerialNumber"); } - if ( snTag ) { - serial = snTag->valueToString(); + if (tag) { + serial = tag->valueToString(); } // guess lens... @@ -513,16 +456,21 @@ void FrameData::extractInfo () } } + rtexif::Tag* t = frameRootDir->getTag(0x83BB); + if (t) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + } + // ----------------------- Special file type detection (HDR, PixelShift) ------------------------ - uint16 bitspersample = 0, samplesperpixel = 0, sampleformat = 0, photometric = 0, compression = 0; - rtexif::Tag* bps = root->findTag("BitsPerSample"); - rtexif::Tag* spp = root->findTag("SamplesPerPixel"); - rtexif::Tag* sf = root->findTag("SampleFormat"); - rtexif::Tag* pi = root->findTag("PhotometricInterpretation"); - rtexif::Tag* c = root->findTag("Compression"); + uint16 bitspersample = 0, sampleformat = 0, photometric = 0, compression = 0; + rtexif::Tag* bps = frameRootDir->findTag("BitsPerSample"); + rtexif::Tag* spp = frameRootDir->findTag("SamplesPerPixel"); + rtexif::Tag* sf = frameRootDir->findTag("SampleFormat"); + rtexif::Tag* pi = frameRootDir->findTag("PhotometricInterpretation"); + rtexif::Tag* c = frameRootDir->findTag("Compression"); if (mnote && (!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { rtexif::Tag* hdr = mnote->findTag("HDR"); @@ -569,7 +517,6 @@ void FrameData::extractInfo () return; } - samplesperpixel = spp->toInt(); bitspersample = bps->toInt(); photometric = pi->toInt(); @@ -582,30 +529,37 @@ void FrameData::extractInfo () } if (photometric == PHOTOMETRIC_RGB || photometric == PHOTOMETRIC_MINISBLACK) { - if ((samplesperpixel == 1 || samplesperpixel == 3 || samplesperpixel == 4) && sampleformat == SAMPLEFORMAT_UINT) { + if (sampleformat == SAMPLEFORMAT_INT || sampleformat == SAMPLEFORMAT_UINT) { if (bitspersample == 8) { sampleFormat = IIOSF_UNSIGNED_CHAR; - } - - if (bitspersample == 16) { + } else if (bitspersample <= 16) { sampleFormat = IIOSF_UNSIGNED_SHORT; } - } else if (samplesperpixel == 3 && sampleformat == SAMPLEFORMAT_IEEEFP) { + } else if (sampleformat == SAMPLEFORMAT_IEEEFP) { /* * Not yet supported * if (bitspersample==16) { sampleFormat = IIOSF_HALF; + isHDR = true; }*/ - if ((samplesperpixel == 3 || samplesperpixel == 4) && bitspersample == 32) { + if (bitspersample == 32) { sampleFormat = IIOSF_FLOAT; isHDR = true; } } } else if (photometric == PHOTOMETRIC_CFA) { - // Assuming Bayer or X-Trans raw file deliver 10, 12 14 or 16 bits uint, which is the case as of now - sampleFormat = IIOSF_UNSIGNED_SHORT; - } else if (samplesperpixel == 3 && photometric == PHOTOMETRIC_LOGLUV) { + if (sampleformat == SAMPLEFORMAT_IEEEFP) { + sampleFormat = IIOSF_FLOAT; + isHDR = true; + } else if (sampleformat == SAMPLEFORMAT_INT || sampleformat == SAMPLEFORMAT_UINT) { + if (bitspersample == 8) { // shouldn't occur... + sampleFormat = IIOSF_UNSIGNED_CHAR; + } else if (bitspersample <= 16) { + sampleFormat = IIOSF_UNSIGNED_SHORT; + } + } + } else if (photometric == PHOTOMETRIC_LOGLUV) { if (compression == COMPRESSION_SGILOG24) { sampleFormat = IIOSF_LOGLUV24; isHDR = true; @@ -619,26 +573,29 @@ void FrameData::extractInfo () FrameData::~FrameData () { - delete root; - if (iptc) { iptc_data_free (iptc); } } procparams::IPTCPairs FrameData::getIPTCData () const +{ + return getIPTCData(iptc); +} + +procparams::IPTCPairs FrameData::getIPTCData (IptcData* iptc_) { procparams::IPTCPairs iptcc; - if (!iptc) { + if (!iptc_) { return iptcc; } unsigned char buffer[2100]; for (int i = 0; i < 16; i++) { - IptcDataSet* ds = iptc_data_get_next_dataset (iptc, nullptr, IPTC_RECORD_APP_2, strTags[i].tag); + IptcDataSet* ds = iptc_data_get_next_dataset (iptc_, nullptr, IPTC_RECORD_APP_2, strTags[i].tag); if (ds) { iptc_dataset_get_data (ds, buffer, 2100); @@ -653,7 +610,7 @@ procparams::IPTCPairs FrameData::getIPTCData () const IptcDataSet* ds = nullptr; std::vector keywords; - while ((ds = iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS))) { + while ((ds = iptc_data_get_next_dataset (iptc_, ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS))) { iptc_dataset_get_data (ds, buffer, 2100); keywords.push_back (to_utf8((char*)buffer)); } @@ -662,7 +619,7 @@ procparams::IPTCPairs FrameData::getIPTCData () const ds = nullptr; std::vector suppCategories; - while ((ds = iptc_data_get_next_dataset (iptc, ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY))) { + while ((ds = iptc_data_get_next_dataset (iptc_, ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY))) { iptc_dataset_get_data (ds, buffer, 2100); suppCategories.push_back (to_utf8((char*)buffer)); iptc_dataset_unref (ds); @@ -687,11 +644,11 @@ IIOSampleFormat FrameData::getSampleFormat () const } rtexif::TagDirectory* FrameData::getExifData () const { - return root; + return frameRootDir; } bool FrameData::hasExif () const { - return root && root->getCount(); + return frameRootDir && frameRootDir->getCount(); } bool FrameData::hasIPTC () const { @@ -761,13 +718,19 @@ void FramesData::setDCRawFrameCount (unsigned int frameCount) dcrawFrameCount = frameCount; } +unsigned int FramesData::getRootCount () const +{ + return roots.size(); +} + unsigned int FramesData::getFrameCount () const { return dcrawFrameCount ? dcrawFrameCount : frames.size(); } + FrameData *FramesData::getFrameData (int frame) const { - return frames.empty() ? nullptr : frames.at(frame); + return frames.empty() || frame >= frames.size() ? nullptr : frames.at(frame); } bool FramesData::getPixelShift (unsigned int frame) const @@ -778,7 +741,7 @@ bool FramesData::getPixelShift (unsigned int frame) const // to evolve //return frames.at(frame)->getPixelShift (); - return frames.empty() ? false : frames.at(0)->getPixelShift (); + return frames.empty() || frame >= frames.size() ? false : frames.at(0)->getPixelShift (); } bool FramesData::getHDR (unsigned int frame) const { @@ -788,40 +751,50 @@ bool FramesData::getHDR (unsigned int frame) const // to evolve //return frames.at(frame)->getHDR (); - return frames.empty() ? false : frames.at(0)->getHDR (); + return frames.empty() || frame >= frames.size() ? false : frames.at(0)->getHDR (); } IIOSampleFormat FramesData::getSampleFormat (unsigned int frame) const { - return frames.empty() ? IIOSF_UNKNOWN : frames.at(frame)->getSampleFormat (); + return frames.empty() || frame >= frames.size() ? IIOSF_UNKNOWN : frames.at(frame)->getSampleFormat (); } -rtexif::TagDirectory* FramesData::getExifData (unsigned int frame) const +rtexif::TagDirectory* FramesData::getFrameExifData (unsigned int frame) const { - return frames.empty() ? nullptr : frames.at(frame)->getExifData (); + return frames.empty() || frame >= frames.size() ? nullptr : frames.at(frame)->getExifData (); } + +rtexif::TagDirectory* FramesData::getRootExifData (unsigned int root) const +{ + return roots.empty() || root >= roots.size() ? nullptr : roots.at(root); +} + procparams::IPTCPairs FramesData::getIPTCData (unsigned int frame) const { - if (frames.empty()) { - procparams::IPTCPairs emptyPairs; - return emptyPairs; + if (frame < frames.size() && frames.at(frame)->hasIPTC()) { + return frames.at(frame)->getIPTCData(); } else { - return frames.at(frame)->getIPTCData (); + if (iptc) { + return FrameData::getIPTCData(iptc); + } else { + procparams::IPTCPairs emptyPairs; + return emptyPairs; + } } } bool FramesData::hasExif (unsigned int frame) const { - return frames.empty() ? false : frames.at(frame)->hasExif (); + return frames.empty() || frame >= frames.size() ? false : frames.at(frame)->hasExif (); } bool FramesData::hasIPTC (unsigned int frame) const { - return frames.empty() ? false : frames.at(frame)->hasIPTC (); + return frames.empty() || frame >= frames.size() ? false : frames.at(frame)->hasIPTC (); } tm FramesData::getDateTime (unsigned int frame) const { - if (frames.empty()) { + if (frames.empty() || frame >= frames.size() ) { tm emptytm = {0, 0, 0, 0, 0, 0, 0, 0, 0}; return emptytm; } else { @@ -830,55 +803,55 @@ tm FramesData::getDateTime (unsigned int frame) const } time_t FramesData::getDateTimeAsTS(unsigned int frame) const { - return frames.empty() ? 0 : frames.at(frame)->getDateTimeAsTS (); + return frames.empty() || frame >= frames.size() ? 0 : frames.at(frame)->getDateTimeAsTS (); } int FramesData::getISOSpeed (unsigned int frame) const { - return frames.empty() ? 0 : frames.at(frame)->getISOSpeed (); + return frames.empty() || frame >= frames.size() ? 0 : frames.at(frame)->getISOSpeed (); } double FramesData::getFNumber (unsigned int frame) const { - return frames.empty() ? 0. : frames.at(frame)->getFNumber (); + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getFNumber (); } double FramesData::getFocalLen (unsigned int frame) const { - return frames.empty() ? 0. : frames.at(frame)->getFocalLen (); + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getFocalLen (); } double FramesData::getFocalLen35mm (unsigned int frame) const { - return frames.empty() ? 0. : frames.at(frame)->getFocalLen35mm (); + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getFocalLen35mm (); } float FramesData::getFocusDist (unsigned int frame) const { - return frames.empty() ? 0.f : frames.at(frame)->getFocusDist (); + return frames.empty() || frame >= frames.size() ? 0.f : frames.at(frame)->getFocusDist (); } double FramesData::getShutterSpeed (unsigned int frame) const { - return frames.empty() ? 0. : frames.at(frame)->getShutterSpeed (); + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getShutterSpeed (); } double FramesData::getExpComp (unsigned int frame) const { - return frames.empty() ? 0. : frames.at(frame)->getExpComp (); + return frames.empty() || frame >= frames.size() ? 0. : frames.at(frame)->getExpComp (); } std::string FramesData::getMake (unsigned int frame) const { - return frames.empty() ? std::string() : frames.at(frame)->getMake (); + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getMake (); } std::string FramesData::getModel (unsigned int frame) const { - return frames.empty() ? std::string() : frames.at(frame)->getModel (); + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getModel (); } std::string FramesData::getLens (unsigned int frame) const { - return frames.empty() ? std::string() : frames.at(frame)->getLens (); + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getLens (); } std::string FramesData::getSerialNumber (unsigned int frame) const { - return frames.empty() ? std::string() : frames.at(frame)->getSerialNumber (); + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getSerialNumber (); } std::string FramesData::getOrientation (unsigned int frame) const { - return frames.empty() ? std::string() : frames.at(frame)->getOrientation (); + return frames.empty() || frame >= frames.size() ? std::string() : frames.at(frame)->getOrientation (); } @@ -1007,7 +980,7 @@ failure: } FramesData::FramesData (const Glib::ustring& fname, std::unique_ptr rml, bool firstFrameOnly, bool loadAll) : - dcrawFrameCount (0) + iptc(nullptr), dcrawFrameCount (0) { if (rml && (rml->exifBase >= 0 || rml->ciffBase >= 0)) { FILE* f = g_fopen (fname.c_str (), "rb"); @@ -1017,14 +990,30 @@ FramesData::FramesData (const Glib::ustring& fname, std::unique_ptrexifBase >= 0) { + exifManager.parseRaw (); + + } else if (exifManager.rml->ciffBase >= 0) { + exifManager.parseCIFF (); + } + } + + // copying roots + roots = exifManager.roots; + + // creating FrameData + for (auto currFrame : exifManager.frames) { + FrameData* fd = new FrameData(currFrame); + + frames.push_back(fd); + } + for (auto currRoot : roots) { + rtexif::Tag* t = currRoot->getTag(0x83BB); + + if (t && !iptc) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + break; } } } @@ -1035,25 +1024,38 @@ FramesData::FramesData (const Glib::ustring& fname, std::unique_ptr(rml); rtexif::ExifManager exifManager (f, std::move(rml), firstFrameOnly); - FrameData *idata = new TiffFrameData (exifManager); - frames.push_back(idata); - if (has_rml && !firstFrameOnly) { - while (exifManager.getNextIFDOffset ()) { - exifManager.setIFDOffset (exifManager.getNextIFDOffset ()); - idata = new TiffFrameData (exifManager); - frames.push_back(idata); + exifManager.parseTIFF(); + + // creating FrameData + for (auto currFrame : exifManager.frames) { + FrameData* fd = new FrameData(currFrame); + + frames.push_back(fd); + } + for (auto currRoot : roots) { + rtexif::Tag* t = currRoot->getTag(0x83BB); + + if (t && !iptc) { + iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); + break; } } fclose (f); @@ -1063,7 +1065,11 @@ FramesData::FramesData (const Glib::ustring& fname, std::unique_ptr frames; + // root IFD in the file + std::vector roots; + IptcData* iptc; unsigned int dcrawFrameCount; public: @@ -120,12 +106,14 @@ public: ~FramesData (); void setDCRawFrameCount (unsigned int frameCount); + unsigned int getRootCount () const; unsigned int getFrameCount () const; FrameData *getFrameData (int frame) const; bool getPixelShift (unsigned int frame = 0) const; bool getHDR (unsigned int frame = 0) const; IIOSampleFormat getSampleFormat (unsigned int frame = 0) const; - rtexif::TagDirectory* getExifData (unsigned int frame = 0) const; + rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const; + rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const; procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const; bool hasExif (unsigned int frame = 0) const; bool hasIPTC (unsigned int frame = 0) const; diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 8f5a490d6..235ed2764 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -57,6 +57,8 @@ class FramesMetaData { public: + /** @return Returns the number of root Metadata */ + virtual unsigned int getRootCount () const = 0; /** @return Returns the number of frame contained in the file based on Metadata */ virtual unsigned int getFrameCount () const = 0; @@ -64,8 +66,13 @@ public: * @return Returns true if image contains exif metadata tags */ virtual bool hasExif (unsigned int frame = 0) const = 0; /** Returns the directory of exif metadata tags. + * @param root root number in the metadata tree * @return The directory of exif metadata tags */ - virtual rtexif::TagDirectory* getExifData (unsigned int frame = 0) const = 0; + virtual rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const = 0; + /** Returns the directory of exif metadata tags. + * @param frame frame number in the metadata tree + * @return The directory of exif metadata tags */ + virtual rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const = 0; /** Checks the availability of IPTC tags. * @return Returns true if image contains IPTC tags */ virtual bool hasIPTC (unsigned int frame = 0) const = 0; @@ -107,7 +114,7 @@ public: /** @return true if the file is a PixelShift shot (Pentax bodies) */ virtual bool getPixelShift (unsigned int frame = 0) const = 0; - /** @return 0: not ah HDR file ; 1: single shot HDR (e.g. 32 bit float DNG file or Log compressed) ; >1: multi-frame HDR file */ + /** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */ virtual bool getHDR (unsigned int frame = 0) const = 0; /** @return the sample format based on MetaData */ virtual IIOSampleFormat getSampleFormat (unsigned int frame = 0) const = 0; diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 2c5d5a10e..44425c380 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1277,9 +1277,9 @@ private: } if (tunnelMetaData) { - readyImg->setMetadata (ii->getMetaData()->getExifData ()); + readyImg->setMetadata (ii->getMetaData()->getRootExifData ()); } else { - readyImg->setMetadata (ii->getMetaData()->getExifData (), params.exif, params.iptc); + readyImg->setMetadata (ii->getMetaData()->getRootExifData (), params.exif, params.iptc); } diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc index 01b00dd53..eaea38378 100644 --- a/rtexif/canonattribs.cc +++ b/rtexif/canonattribs.cc @@ -1068,6 +1068,22 @@ public: }; CAFocalPlaneInterpreter caFocalPlaneInterpreter; +class RawImageSegmentationInterpreter : public Interpreter +{ +public: + virtual std::string toString (Tag* t) + { + int segmentNumber = t->toInt(0, SHORT); + int segmentWidth = t->toInt(2, SHORT); + int lastSegmentWidth = t->toInt(4, SHORT); + + char buffer[32]; + sprintf (buffer, "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth); + return buffer; + } +}; +RawImageSegmentationInterpreter rawImageSegmentationInterpreter; + class CAExposureTimeInterpreter : public Interpreter { public: @@ -1995,6 +2011,7 @@ const TagAttrib canonAttribs[] = { {1, AC_WRITE, 0, nullptr, 0x4005, AUTO, "UnknownBlock2", &stdInterpreter}, {1, AC_WRITE, 0, nullptr, 0x4008, AUTO, "BlackLevel", &stdInterpreter}, {1, AC_WRITE, 0, canonMicroAdjustAttrib, 0x4013, AUTO, "AFMicroAdj", &stdInterpreter}, + {1, AC_WRITE, 0, nullptr, 0xc640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter}, { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 441d017d4..c5aa44670 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -45,8 +46,6 @@ Interpreter stdInterpreter; // this class is a collection (an array) of tags //----------------------------------------------------------------------------- -#define TAG_SUBFILETYPE 0x00fe - TagDirectory::TagDirectory () : attribs (ifdAttribs), order (HOSTORDER), parent (nullptr) {} @@ -79,7 +78,7 @@ TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* int id = newTag->getID(); // detect and possibly ignore tags of directories belonging to the embedded thumbnail image - if (attribs == ifdAttribs && id == TAG_SUBFILETYPE && newTag->toInt() != 0) { + if (attribs == ifdAttribs && id == TIFFTAG_SUBFILETYPE && newTag->toInt() != 0) { thumbdescr = true; } @@ -208,11 +207,14 @@ void TagDirectory::printAll (unsigned int level) const for (size_t i = 0; i < tags.size(); i++) { std::string name = tags[i]->nameToString (); + TagDirectory* currTagDir; if (tags[i]->isDirectory()) { - for (int j = 0; tags[i]->getDirectory (j); j++) { + for (int j = 0; (currTagDir = tags[i]->getDirectory (j)) != nullptr; j++) { printf ("%s+-- DIRECTORY %s[%d]:\n", prefixStr, name.c_str(), j); - tags[i]->getDirectory (j)->printAll (level + 1); + currTagDir->printAll (level + 1); } + } else { + printf ("%s- %s\n", prefixStr, name.c_str()); } } } @@ -448,22 +450,14 @@ Tag* TagDirectory::getTagP (const char* name) const return nullptr; } -Tag* TagDirectory::findTag (const char* name) const +Tag* TagDirectory::findTag (const char* name, bool lookUpward) const { - if (attribs) { - for (int i = 0; attribs[i].ignore != -1; i++) - if (!strcmp (attribs[i].name, name)) { - Tag* t = getTag (attribs[i].ID); - - if (t) { - return t; - } else { - break; - } - } + Tag* t = getTag(name); + if (t) { + return t; } - for (size_t i = 0; i < tags.size(); i++) + for (size_t i = 0; i < tags.size(); i++) { if (tags[i]->isDirectory()) { TagDirectory *dir = tags[i]->getDirectory(); Tag* t = dir->findTag (name); @@ -472,10 +466,97 @@ Tag* TagDirectory::findTag (const char* name) const return t; } } + } + + if (lookUpward && parent) { + Tag* t = parent->findTagUpward(name); + + if (t) { + return t; + } + } return nullptr; } +std::vector TagDirectory::findTags (int ID) +{ + + std::vector tagList; + + //assuming that an entry can only exist once + Tag* t = getTag(ID); + if (t) { + tagList.push_back(t); + } + + for (auto tag : tags) { + if (tag->isDirectory()) { + TagDirectory *dir = tag->getDirectory(); + std::vector subTagList = dir->findTags (ID); + + if (!subTagList.empty()) { + // concatenating the 2 vectors + // not really optimal in a memory efficiency pov + for (auto tag2 : subTagList) { + tagList.push_back(tag2); + } + } + } + } + + return tagList; +} + +std::vector TagDirectory::findTags (const char* name) +{ + + std::vector tagList; + + //assuming that an entry can only exist once + Tag* t = getTag(name); + if (t) { + tagList.push_back(t); + } + + for (auto tag : tags) { + if (tag->isDirectory()) { + TagDirectory *dir = tag->getDirectory(); + std::vector subTagList = dir->findTags (name); + + if (!subTagList.empty()) { + // concatenating the 2 vectors + // not really optimal in a memory efficiency pov + for (auto tag2 : subTagList) { + tagList.push_back(tag2); + } + } + } + } + + return tagList; +} + + +Tag* TagDirectory::findTagUpward (const char* name) const +{ + Tag* t = getTag(name); + if (t) { + return t; + } + + if (parent) { + Tag* t = parent->findTagUpward(name); + + if (t) { + return t; + } + } + + return nullptr; +} + + // Searches a simple value, as either attribute or element // only for simple values, not for entries with special chars or free text bool TagDirectory::getXMPTagValue (const char* name, char* value) const @@ -852,13 +933,11 @@ Tag::Tag (TagDirectory* p, FILE* f, int base) } if (tag == 0x002e) { // location of the embedded preview image in raw files of Panasonic cameras - const TagDirectory* const previewdir = - [&f]() - { - return ExifManager(f, nullptr, true).parseJPEG(ftell(f)); // try to parse the exif data from the preview image - }(); + ExifManager eManager(f, nullptr, true); + eManager.parseJPEG(ftell(f)); // try to parse the exif data from the preview image - if (previewdir) { + if (eManager.roots.size()) { + const TagDirectory* const previewdir = eManager.roots.at(0); if (previewdir->getTag ("Exif")) { if (previewdir->getTag ("Make")) { if (previewdir->getTag ("Make")->valueToString() == "Panasonic") { // "make" is not yet available here, so get it from the preview tags to assure we're doing the right thing @@ -1358,7 +1437,7 @@ void Tag::fromString (const char* v, int size) } } -int Tag::toInt (int ofs, TagType astype) +int Tag::toInt (int ofs, TagType astype) const { if (attrib) { return attrib->interpreter->toInt (this, ofs, astype); @@ -1409,7 +1488,7 @@ int Tag::toInt (int ofs, TagType astype) return 0; } -double Tag::toDouble (int ofs) +double Tag::toDouble (int ofs) const { if (attrib) { return attrib->interpreter->toDouble (this, ofs); @@ -1900,8 +1979,12 @@ const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field) return nullptr; } +void ExifManager::setIFDOffset(unsigned int offset) +{ + IFDOffset = offset; +} -TagDirectory* ExifManager::parseCIFF () +void ExifManager::parseCIFF () { TagDirectory* root = new TagDirectory (nullptr, ifdAttribs, INTEL); @@ -1913,7 +1996,6 @@ TagDirectory* ExifManager::parseCIFF () exif->getDirectory()->addTag (mn); parseCIFF (rml->ciffLength, root); root->sort (); - return root; } Tag* ExifManager::saveCIFFMNTag (TagDirectory* root, int len, const char* name) @@ -2217,6 +2299,12 @@ void ExifManager::parseCIFF (int length, TagDirectory* root) t->initString (buffer); root->addTag (t); } + + if (root->getTag("RawImageSegmentation")) { // Canon CR2 files + frames.push_back(root); + } + roots.push_back(root); + } static void @@ -2554,15 +2642,24 @@ parse_leafdata (TagDirectory* root, ByteOrder order) } } -TagDirectory* ExifManager::parse (bool skipIgnored) +void ExifManager::parseRaw (bool skipIgnored) { + parse(true, skipIgnored); +} + +void ExifManager::parseStd (bool skipIgnored) { + parse(false, skipIgnored); +} + +// return a root TagDirectory +void ExifManager::parse (bool isRaw, bool skipIgnored) { - int ifd = IFDOffset; + int ifdOffset = IFDOffset; if (!f) { #ifndef NDEBUG std::cerr << "ERROR : no file opened !" << std::endl; #endif - return nullptr; + return; } setlocale (LC_NUMERIC, "C"); // to set decimal point in sscanf @@ -2573,39 +2670,38 @@ TagDirectory* ExifManager::parse (bool skipIgnored) fread (&bo, 1, 2, f); order = (ByteOrder) ((int)bo); get2 (f, order); - if (!ifd) { - ifd = get4 (f, order); + if (!ifdOffset) { + ifdOffset = get4 (f, order); } } - return parseIFD (ifd, skipIgnored); -} + do { + // seek to IFD + fseek (f, rml->exifBase + ifdOffset, SEEK_SET); -TagDirectory* ExifManager::parseIFD (int ifdOffset, bool skipIgnored) -{ - if (!f) { - #ifndef NDEBUG - std::cerr << "ERROR : no file opened !" << std::endl; - #endif - return nullptr; - } + // first read the IFD directory + TagDirectory* root = new TagDirectory (nullptr, f, rml->exifBase, ifdAttribs, order, skipIgnored); - // seek to IFD0 - fseek (f, rml->exifBase + ifdOffset, SEEK_SET); + // fix ISO issue with nikon and panasonic cameras + Tag* make = root->getTag ("Make"); + Tag* exif = root->getTag ("Exif"); - // first read the IFD directory - TagDirectory* root = new TagDirectory (nullptr, f, rml->exifBase, ifdAttribs, order, skipIgnored); + if (exif && !exif->getDirectory()->getTag ("ISOSpeedRatings")) { + if (make && !strncmp ((char*)make->getValue(), "NIKON", 5)) { + Tag* mn = exif->getDirectory()->getTag ("MakerNote"); - // fix ISO issue with nikon and panasonic cameras - Tag* make = root->getTag ("Make"); - Tag* exif = root->getTag ("Exif"); + if (mn) { + Tag* iso = mn->getDirectory()->getTag ("ISOSpeed"); - if (exif && !exif->getDirectory()->getTag ("ISOSpeedRatings")) { - if (make && !strncmp ((char*)make->getValue(), "NIKON", 5)) { - Tag* mn = exif->getDirectory()->getTag ("MakerNote"); - - if (mn) { - Tag* iso = mn->getDirectory()->getTag ("ISOSpeed"); + if (iso) { + std::string isov = iso->valueToString (); + Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); + niso->initInt (atoi (isov.c_str()), SHORT); + exif->getDirectory()->addTagFront (niso); + } + } + } else if (make && (!strncmp ((char*)make->getValue(), "Panasonic", 9) || !strncmp ((char*)make->getValue(), "LEICA", 5))) { + Tag* iso = root->getTag ("PanaISO"); if (iso) { std::string isov = iso->valueToString (); @@ -2614,231 +2710,284 @@ TagDirectory* ExifManager::parseIFD (int ifdOffset, bool skipIgnored) exif->getDirectory()->addTagFront (niso); } } - } else if (make && (!strncmp ((char*)make->getValue(), "Panasonic", 9) || !strncmp ((char*)make->getValue(), "LEICA", 5))) { - Tag* iso = root->getTag ("PanaISO"); - - if (iso) { - std::string isov = iso->valueToString (); - Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); - niso->initInt (atoi (isov.c_str()), SHORT); - exif->getDirectory()->addTagFront (niso); - } } - } - if (make && !strncmp ((char*)make->getValue(), "Kodak", 5)) { - if (!exif) { - // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir - fseek (f, rml->exifBase + ifdOffset, SEEK_SET); - TagDirectory* exifdir = new TagDirectory (nullptr, f, rml->exifBase, exifAttribs, order, true); + if (make && !strncmp ((char*)make->getValue(), "Kodak", 5)) { + if (!exif) { + // old Kodak cameras may have exif tags in IFD0, reparse and create an exif subdir + fseek (f, rml->exifBase + ifdOffset, SEEK_SET); + TagDirectory* exifdir = new TagDirectory (nullptr, f, rml->exifBase, exifAttribs, order, true); - exif = new Tag (root, root->getAttrib ("Exif")); - exif->initSubDir (exifdir); - root->addTagFront (exif); + exif = new Tag (root, root->getAttrib ("Exif")); + exif->initSubDir (exifdir); + root->addTagFront (exif); - if (!exif->getDirectory()->getTag ("ISOSpeedRatings") && exif->getDirectory()->getTag ("ExposureIndex")) { - Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); - niso->initInt (exif->getDirectory()->getTag ("ExposureIndex")->toInt(), SHORT); - exif->getDirectory()->addTagFront (niso); + if (!exif->getDirectory()->getTag ("ISOSpeedRatings") && exif->getDirectory()->getTag ("ExposureIndex")) { + Tag* niso = new Tag (exif->getDirectory(), exif->getDirectory()->getAttrib ("ISOSpeedRatings")); + niso->initInt (exif->getDirectory()->getTag ("ExposureIndex")->toInt(), SHORT); + exif->getDirectory()->addTagFront (niso); + } + } + + Tag *kodakIFD = root->getTag ("KodakIFD"); + + if (kodakIFD && kodakIFD->getDirectory()->getTag ("TextualInfo")) { + parseKodakIfdTextualInfo (kodakIFD->getDirectory()->getTag ("TextualInfo"), exif); } } - Tag *kodakIFD = root->getTag ("KodakIFD"); + parse_leafdata (root, order); - if (kodakIFD && kodakIFD->getDirectory()->getTag ("TextualInfo")) { - parseKodakIfdTextualInfo (kodakIFD->getDirectory()->getTag ("TextualInfo"), exif); - } - } + if (make && !strncmp ((char*)make->getValue(), "Hasselblad", 10)) { + /* + Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly + different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through + Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and + Phocus-generated DNGs. - parse_leafdata (root, order); + FFF usually has a sane model name in Model (and is used as reference for what we shall + call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for + all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body. + V-mount backs may have the model name of the V body instead of the back model. Etc... + as said it's a mess. - if (make && !strncmp ((char*)make->getValue(), "Hasselblad", 10)) { - /* - Figuring out the Hasselblad model is a mess. Hasselblad raw data comes in four slightly - different containers, 3FR (directly from CF card), FFF (same as 3FR but filtered through - Phocus, calibration data applied and a bit different tags), Adobe-generated DNGs and - Phocus-generated DNGs. + This code is supposed to handle all raw containers and end up with the same model + regardless of container. - FFF usually has a sane model name in Model (and is used as reference for what we shall - call the different Hasselblad models), but 3FR only says like "Hasselblad H3D" for - all H3D models, or "Flash Sync" if the back has been used on a mechanical camera body. - V-mount backs may have the model name of the V body instead of the back model. Etc... - as said it's a mess. + We don't differ between single shot and multi-shot models, and probably there's no use + of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that + tethered. In single-shot mode they should be exactly the same as the single-shot models. + */ + Tag *subd = root->getTag (0x14a); + Tag *iw = (subd) ? subd->getDirectory()->getTag ("ImageWidth") : nullptr; + int sensorWidth = (iw) ? iw->toInt() : 0; + Tag* tmodel = root->getTag ("Model"); + const char *model = (tmodel) ? (const char *)tmodel->getValue() : ""; - This code is supposed to handle all raw containers and end up with the same model - regardless of container. + if (strstr (model, "Hasselblad ") == model) { + model += 11; + } else { + // if HxD is used in flash sync mode for example, we need to fetch model from this tag + Tag* tmodel3 = root->getTag ("UniqueCameraModel"); + const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - We don't differ between single shot and multi-shot models, and probably there's no use - of doing so. You need Hasselblad's own software to shoot multi-shot and can only do that - tethered. In single-shot mode they should be exactly the same as the single-shot models. - */ - Tag *subd = root->getTag (0x14a); - Tag *iw = (subd) ? subd->getDirectory()->getTag ("ImageWidth") : nullptr; - int sensorWidth = (iw) ? iw->toInt() : 0; - Tag* tmodel = root->getTag ("Model"); - const char *model = (tmodel) ? (const char *)tmodel->getValue() : ""; + if (strstr (model3, "Hasselblad ") == model3) { + model = model3 + 11; + } + } - if (strstr (model, "Hasselblad ") == model) { - model += 11; - } else { - // if HxD is used in flash sync mode for example, we need to fetch model from this tag + // FIXME: due to lack of test files this Hasselblad model identification is not 100% complete + // This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models + + if (!strcmp (model, "H3D")) { + // We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a + // H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance + // to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50 + // H3D-50 although Hasselblad never released such a model. + switch (sensorWidth) { + case 4096: + tmodel->initString ("H3D-22"); + break; + + case 6542: + tmodel->initString ("H3D-31"); + break; + + case 7262: + tmodel->initString ("H3D-39"); + break; + + case 8282: + tmodel->initString ("H3DII-50"); + break; + } + } else if (!strcmp (model, "H4D")) { + switch (sensorWidth) { + case 6542: + tmodel->initString ("H4D-31"); + break; + + case 7410: + tmodel->initString ("H4D-40"); + break; + + case 8282: + tmodel->initString ("H4D-50"); + break; + + case 9044: + tmodel->initString ("H4D-60"); + break; + } + } else if (!strcmp (model, "H5D")) { + switch (sensorWidth) { + case 7410: + tmodel->initString ("H5D-40"); + break; + + case 8282: + tmodel->initString ("H5D-50"); + break; + + case 8374: + tmodel->initString ("H5D-50c"); + break; + + case 9044: + tmodel->initString ("H5D-60"); + break; + } + } else if (!strcmp (model, "CFV")) { + switch (sensorWidth) { + case 7262: + tmodel->initString ("CFV-39"); + break; + + case 8282: + tmodel->initString ("CFV-50"); + break; + + case 8374: + tmodel->initString ("CFV-50c"); + break; + } + } + + // and a few special cases Tag* tmodel3 = root->getTag ("UniqueCameraModel"); const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; if (strstr (model3, "Hasselblad ") == model3) { - model = model3 + 11; - } - } - - // FIXME: due to lack of test files this Hasselblad model identification is not 100% complete - // This needs checking out: CFV-39/CFV-50 3FR, H3DII vs H3D, old CF/CFH models - - if (!strcmp (model, "H3D")) { - // We can't differ between H3D and H3DII for the 22, 31 and 39 models. There's was no H3D-50 so we know that is a - // H3DII-50. At the time of writing I have no test files for the H3D vs H3DII models, so there still may be a chance - // to differ between them. AFAIK Adobe's DNG converter don't differ between them, and actually call the H3DII-50 - // H3D-50 although Hasselblad never released such a model. - switch (sensorWidth) { - case 4096: - tmodel->initString ("H3D-22"); - break; - - case 6542: - tmodel->initString ("H3D-31"); - break; - - case 7262: - tmodel->initString ("H3D-39"); - break; - - case 8282: - tmodel->initString ("H3DII-50"); - break; - } - } else if (!strcmp (model, "H4D")) { - switch (sensorWidth) { - case 6542: - tmodel->initString ("H4D-31"); - break; - - case 7410: - tmodel->initString ("H4D-40"); - break; - - case 8282: - tmodel->initString ("H4D-50"); - break; - - case 9044: - tmodel->initString ("H4D-60"); - break; - } - } else if (!strcmp (model, "H5D")) { - switch (sensorWidth) { - case 7410: - tmodel->initString ("H5D-40"); - break; - - case 8282: - tmodel->initString ("H5D-50"); - break; - - case 8374: - tmodel->initString ("H5D-50c"); - break; - - case 9044: - tmodel->initString ("H5D-60"); - break; - } - } else if (!strcmp (model, "CFV")) { - switch (sensorWidth) { - case 7262: - tmodel->initString ("CFV-39"); - break; - - case 8282: - tmodel->initString ("CFV-50"); - break; - - case 8374: - tmodel->initString ("CFV-50c"); - break; - } - } - - // and a few special cases - Tag* tmodel3 = root->getTag ("UniqueCameraModel"); - const char *model3 = (tmodel3) ? (const char *)tmodel3->getValue() : ""; - - if (strstr (model3, "Hasselblad ") == model3) { - model3 = model3 + 11; - } - - if (!strcmp (model3, "ixpressCF132")) { - tmodel->initString ("CF-22"); - } else if (!strcmp (model3, "Hasselblad96")) { - tmodel->initString ("CFV"); // popularly called CFV-16, but the official name is CFV - } else if (!strcmp (model3, "Hasselblad234")) { - tmodel->initString ("CFV-39"); - } else if (sensorWidth == 4090) { - tmodel->initString ("V96C"); - } - - // and yet some, this is for Adobe-generated DNG files - Tag* tmodel4 = root->getTag ("LocalizedCameraModel"); - - if (tmodel4) { - const char *model4 = (const char *)tmodel4->getValue(); - - if (strstr (model4, "Hasselblad ") == model4) { - model4 = model4 + 11; + model3 = model3 + 11; } - if (!strcmp (model4, "ixpressCF132-22")) { + if (!strcmp (model3, "ixpressCF132")) { tmodel->initString ("CF-22"); - } else if (!strcmp (model4, "Hasselblad96-16")) { - tmodel->initString ("CFV"); - } else if (!strcmp (model4, "Hasselblad234-39")) { + } else if (!strcmp (model3, "Hasselblad96")) { + tmodel->initString ("CFV"); // popularly called CFV-16, but the official name is CFV + } else if (!strcmp (model3, "Hasselblad234")) { tmodel->initString ("CFV-39"); - } else if (!strcmp (model4, "H3D-50")) { - // Adobe names H3DII-50 incorrectly as H3D-50 - tmodel->initString ("H3DII-50"); - } else if (strstr (model4, "H3D-") == model4 || strstr (model4, "H4D-") == model4 || strstr (model4, "H5D-") == model4) { - tmodel->initString (model4); - } - } - } - - if (!root->getTag ("Orientation")) { - if (make && !strncmp ((char*)make->getValue(), "Phase One", 9)) { - int orientation = 0; - Tag *iw = root->getTag ("ImageWidth"); - - if (iw) { - // from dcraw, derive orientation from image width - orientation = "0653"[iw->toInt() & 3] - '0'; + } else if (sensorWidth == 4090) { + tmodel->initString ("V96C"); } - Tag *t = new Tag (root, root->getAttrib ("Orientation")); - t->initInt (orientation, SHORT); - root->addTagFront (t); + // and yet some, this is for Adobe-generated DNG files + Tag* tmodel4 = root->getTag ("LocalizedCameraModel"); + + if (tmodel4) { + const char *model4 = (const char *)tmodel4->getValue(); + + if (strstr (model4, "Hasselblad ") == model4) { + model4 = model4 + 11; + } + + if (!strcmp (model4, "ixpressCF132-22")) { + tmodel->initString ("CF-22"); + } else if (!strcmp (model4, "Hasselblad96-16")) { + tmodel->initString ("CFV"); + } else if (!strcmp (model4, "Hasselblad234-39")) { + tmodel->initString ("CFV-39"); + } else if (!strcmp (model4, "H3D-50")) { + // Adobe names H3DII-50 incorrectly as H3D-50 + tmodel->initString ("H3DII-50"); + } else if (strstr (model4, "H3D-") == model4 || strstr (model4, "H4D-") == model4 || strstr (model4, "H5D-") == model4) { + tmodel->initString (model4); + } + } } + + if (!root->getTag ("Orientation")) { + if (make && !strncmp ((char*)make->getValue(), "Phase One", 9)) { + int orientation = 0; + Tag *iw = root->getTag ("ImageWidth"); + + if (iw) { + // from dcraw, derive orientation from image width + orientation = "0653"[iw->toInt() & 3] - '0'; + } + + Tag *t = new Tag (root, root->getAttrib ("Orientation")); + t->initInt (orientation, SHORT); + root->addTagFront (t); + } + } + + // --- detecting image root IFD based on SubFileType, or if not provided, on PhotometricInterpretation + + bool frameRootDetected = false; + std::vector sftTagList = root->findTags(TIFFTAG_SUBFILETYPE); + + if (!sftTagList.empty()) { + for (auto sft : sftTagList) { + int sftVal = sft->toInt(); + if (sftVal == (isRaw ? 0 : 2)) { + frames.push_back(sft->getParent()); + frameRootDetected = true; + + //printf("\n--------------- FRAME -----------------------------\n\n"); + //sft->getParent()->printAll (); + } + } + } + + if(!frameRootDetected) { + sftTagList = root->findTags(TIFFTAG_OSUBFILETYPE); + if (!sftTagList.empty()) { + for (auto sft : sftTagList) { + int sftVal = sft->toInt(); + if (sftVal == OFILETYPE_IMAGE) { + frames.push_back(sft->getParent()); + frameRootDetected = true; + + //printf("\n--------------- FRAME -----------------------------\n\n"); + //sft->getParent()->printAll (); + } + } + } + } + + if(!frameRootDetected) { + std::vector piTagList = root->findTags("PhotometricInterpretation"); + if (!piTagList.empty()) { + for (auto pi : piTagList) { + int piVal = pi->toInt(); + if (piVal == (isRaw ? 32803 : 2)) { + frames.push_back(pi->getParent()); + //frameRootDetected = true; not used afterward + + //printf("\n--------------- FRAME -----------------------------\n\n"); + //pi->getParent()->printAll (); + } + } + } + } + + // --- getting next sibling root + + ifdOffset = get4 (f, order); + + roots.push_back(root); + + //printf("\n~~~~~~~~~ ROOT ~~~~~~~~~~~~~~~~~~~~~~~~\n\n"); + //root->printAll (); + + } while (ifdOffset && !onlyFirst); + + // Security check : if there's at least one root, there must be at least one image. + // If the following occurs, then image detection above has failed or it's an unsupported file type. + // Yet the result of this should be valid. + if (!roots.empty() && frames.empty()) { + frames.push_back(roots.at(0)); } - - nextIFDOffset = get4 (f, order); - - //root->printAll (); - return root; } -TagDirectory* ExifManager::parseJPEG (int offset) +void ExifManager::parseJPEG (int offset) { if (!f) { #ifndef NDEBUG std::cerr << "ERROR : no file opened !" << std::endl; #endif - return nullptr; + return; } if(!fseek (f, offset, SEEK_SET)) { @@ -2856,7 +3005,7 @@ TagDirectory* ExifManager::parseJPEG (int offset) if (fread (&c, 1, 1, f) && c == 0xe1) { // APP1 marker found if (fread (idbuff, 1, 8, f) < 8) { - return nullptr; + return; } if (!memcmp (idbuff + 2, exifid, 6)) { // Exif info found @@ -2868,29 +3017,26 @@ TagDirectory* ExifManager::parseJPEG (int offset) rml.reset(new rtengine::RawMetaDataLocation(0)); } rml->exifBase = tiffbase; - TagDirectory* tagDir = parse (); + parse (false); if (rmlCreated) { rml.reset(); } - return tagDir; + return; } } } } } - - return nullptr; } -TagDirectory* ExifManager::parseTIFF (bool skipIgnored) +void ExifManager::parseTIFF (bool skipIgnored) { if (!rml) { rml.reset(new rtengine::RawMetaDataLocation(0)); - TagDirectory* const res = parse(skipIgnored); + parse(false, skipIgnored); rml.reset(); - return res; } else { - return parse (skipIgnored); + parse (false,skipIgnored); } } diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index bc9495187..bd2d82977 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -128,16 +128,31 @@ public: return tags.size (); } const TagAttrib* getAttrib (int id); - const TagAttrib* getAttrib (const char* name); // Find a Tag by scanning the whole tag tree and stopping at the first occurrence - const TagAttrib* getAttribP (const char* name); // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + // Find a Tag by scanning the whole tag tree and stopping at the first occurrence + const TagAttrib* getAttrib (const char* name); + // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + const TagAttrib* getAttribP (const char* name); const TagAttrib* getAttribTable() { return attribs; } - Tag* getTag (const char* name) const; // Find a Tag by scanning the whole tag tree and stopping at the first occurrence - Tag* getTagP (const char* name) const; // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + // Find a Tag by scanning the whole tag tree and stopping at the first occurrence + Tag* getTag (const char* name) const; + // Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength") + Tag* getTagP (const char* name) const; Tag* getTag (int ID) const; - virtual Tag* findTag (const char* name) const; + + // Try to get the Tag in the current directory and in subdirectories + // if lookUpward = true, it will scan the parents TagDirectory up to the root one, + // but w/o looking into their subdirs + virtual Tag* findTag (const char* name, bool lookUpward = false) const; + // Find a all Tags with the given name by scanning the whole tag tree + std::vector findTags (const char* name); + // Find a all Tags with the given ID by scanning the whole tag tree + std::vector findTags (int ID); + // Try to get the Tag in the current directory and in parent directories + // (won't look into subdirs) + virtual Tag* findTagUpward (const char* name) const; bool getXMPTagValue (const char* name, char* value) const; void keepTag (int ID); @@ -263,9 +278,9 @@ public: } // read/write value - int toInt (int ofs = 0, TagType astype = INVALID); + int toInt (int ofs = 0, TagType astype = INVALID) const; void fromInt (int v); - double toDouble (int ofs = 0); + double toDouble (int ofs = 0) const; double *toDoubleArray (int ofs = 0); void toRational (int& num, int& denom, int ofs = 0); void toString (char* buffer, int ofs = 0); @@ -313,8 +328,8 @@ class ExifManager { Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name); - TagDirectory* parseIFD (int ifdOffset, bool skipIgnored); void parseCIFF (int length, TagDirectory* root); + void parse (bool isRaw, bool skipIgnored = true); public: FILE* f; @@ -322,27 +337,21 @@ public: ByteOrder order; bool onlyFirst; // Only first IFD unsigned int IFDOffset; - unsigned int nextIFDOffset; + std::vector roots; + std::vector frames; ExifManager (FILE* fHandle, std::unique_ptr _rml, bool onlyFirstIFD) : f(fHandle), rml(std::move(_rml)), order(UNKNOWN), onlyFirst(onlyFirstIFD), - IFDOffset(0), nextIFDOffset(0) {} + IFDOffset(0) {} - void setIFDOffset(unsigned int offset) - { - IFDOffset = offset; - } + void setIFDOffset(unsigned int offset); - unsigned int getNextIFDOffset() - { - return nextIFDOffset; - } - // The following functions parse only one IFD at a time and store the "next IFD offset" - TagDirectory* parse (bool skipIgnored = true); - TagDirectory* parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail - TagDirectory* parseTIFF (bool skipIgnored = true); - TagDirectory* parseCIFF (); + void parseRaw (bool skipIgnored = true); + void parseStd (bool skipIgnored = true); + void parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail + void parseTIFF (bool skipIgnored = true); + void parseCIFF (); /// @brief Get default tag for TIFF /// @param forthis The byte order will be taken from the given directory. @@ -379,7 +388,7 @@ public: } } // Get the value as a double - virtual double toDouble (Tag* t, int ofs = 0) + virtual double toDouble (const Tag* t, int ofs = 0) { double ud, dd; @@ -420,7 +429,7 @@ public: } } // Get the value as an int - virtual int toInt (Tag* t, int ofs = 0, TagType astype = INVALID) + virtual int toInt (const Tag* t, int ofs = 0, TagType astype = INVALID) { int a; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index bb5e77b42..25e37514e 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1297,7 +1297,7 @@ void EditorPanel::info_toggled () int ww = ipc->getFullWidth(); int hh = ipc->getFullHeight(); //megapixels - infoString = Glib::ustring::compose ("%1\n%2 MP (%2x%3)", + infoString = Glib::ustring::compose ("%1\n%2 MP (%3x%4)", infoString, Glib::ustring::format (std::setw (4), std::fixed, std::setprecision (1), (float)ww * hh / 1000000), ww, hh); @@ -1313,7 +1313,6 @@ void EditorPanel::info_toggled () infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat))); } } else if (isPixelShift) { - infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames); infoString = Glib::ustring::compose ("%1\n" + M("QINFO_PIXELSHIFT"), infoString, numFrames); } } else { diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 133c3a9ed..9e10b75fa 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -189,13 +189,13 @@ void ExifPanel::setImageData (const FramesMetaData* id) exifTreeModel->clear (); if (id) { - for (unsigned int frameNum = 0; frameNum < id->getFrameCount (); ++frameNum) { - if ( id->getExifData (frameNum)) { - //id->getExifData ()->printAll (); - if (frameNum > 0) { + for (unsigned int rootNum = 0; rootNum < id->getRootCount (); ++rootNum) { + if ( id->getRootExifData (rootNum)) { + //id->getRootExifData ()->printAll (); + if (rootNum > 0) { addSeparator(); } - addDirectory (id->getExifData (frameNum), exifTreeModel->children()); + addDirectory (id->getRootExifData (rootNum), exifTreeModel->children()); } } } diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 4bc5bcdb9..fbe8fc7be 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -265,7 +265,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const rtexif::TagDirectory* exifDir = nullptr; - if (imageMetaData && (exifDir = imageMetaData->getExifData())) { + 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, From 17c7ec684d4085fcb31a8c453e8f223a1aa1d8db Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Sun, 17 Sep 2017 23:05:34 +0200 Subject: [PATCH 08/27] PixelShift detection for PEF files was broken (see #4008) --- rtengine/imagedata.cc | 23 +++++++++++ rtengine/imagedata.h | 15 +++----- rtexif/rtexif.cc | 89 +++++++++++++++++++++++++++---------------- rtexif/rtexif.h | 14 +++---- 4 files changed, 92 insertions(+), 49 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 4be057685..3d9c3276a 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -23,6 +23,8 @@ #include "imagedata.h" #include "iptcpairs.h" +#define PRINT_HDR_PS_DETECTION 0 + using namespace rtengine; extern "C" IptcData *iptc_data_new_from_jpeg_file (FILE* infile); @@ -477,6 +479,9 @@ void FrameData::extractInfo () if (hdr) { if (hdr->toInt() > 0 && hdr->toInt(2) > 0) { isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> \"HDR\" tag found\n"); +#endif } } else { rtexif::Tag* dm = mnote->findTag("DriveMode"); @@ -486,6 +491,9 @@ void FrameData::extractInfo () buffer[3] = 0; if (!strcmp(buffer, "HDR")) { isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> DriveMode = \"HDR\"\n"); +#endif } } } @@ -494,6 +502,9 @@ void FrameData::extractInfo () rtexif::Tag* q = mnote->findTag("Quality"); if (q && q->toInt() == 7) { isPixelShift = true; +#if PRINT_HDR_PS_DETECTION + printf("PixelShift detected ! -> \"Quality\" = 7\n"); +#endif } } } @@ -546,12 +557,18 @@ void FrameData::extractInfo () if (bitspersample == 32) { sampleFormat = IIOSF_FLOAT; isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif } } } else if (photometric == PHOTOMETRIC_CFA) { if (sampleformat == SAMPLEFORMAT_IEEEFP) { sampleFormat = IIOSF_FLOAT; isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif } else if (sampleformat == SAMPLEFORMAT_INT || sampleformat == SAMPLEFORMAT_UINT) { if (bitspersample == 8) { // shouldn't occur... sampleFormat = IIOSF_UNSIGNED_CHAR; @@ -563,9 +580,15 @@ void FrameData::extractInfo () if (compression == COMPRESSION_SGILOG24) { sampleFormat = IIOSF_LOGLUV24; isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif } else if (compression == COMPRESSION_SGILOG) { sampleFormat = IIOSF_LOGLUV32; isHDR = true; +#if PRINT_HDR_PS_DETECTION + printf("HDR detected ! -> sampleFormat = %d\n", sampleFormat); +#endif } } } diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 4850e9f60..07119e5f0 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -20,17 +20,12 @@ #define __IMAGEDATA_H__ #include -#include -#include - -#include - -#include - -#include "../rtexif/rtexif.h" - -#include "procparams.h" #include "rawimage.h" +#include +#include +#include "../rtexif/rtexif.h" +#include "procparams.h" +#include #include "rtengine.h" namespace rtengine diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index c5aa44670..c6ffabec9 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -35,6 +35,9 @@ #include "../rtgui/version.h" #include "../rtgui/ppversion.h" +// see end of ExifManager::parse(bool, bool) +#define PRINT_METADATA_TREE 0 + using namespace std; namespace rtexif @@ -288,12 +291,14 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring 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_boolean ("Common Data", "IsHDR", cfs->isHDR); - kf->set_boolean ("Common Data", "IsPixelShift", cfs->isPixelShift); kf->set_string ("Common Data", "Lens", cfs->lens); kf->set_string ("Common Data", "Make", cfs->camMake); kf->set_string ("Common Data", "Model", cfs->camModel); @@ -457,13 +462,18 @@ Tag* TagDirectory::findTag (const char* name, bool lookUpward) const return t; } - for (size_t i = 0; i < tags.size(); i++) { - if (tags[i]->isDirectory()) { - TagDirectory *dir = tags[i]->getDirectory(); - Tag* t = dir->findTag (name); + for (auto tag : tags) { + if (tag->isDirectory()) { + TagDirectory *dir; + int i = 0; + while ((dir = tag->getDirectory(i)) != nullptr) { + TagDirectory *dir = tag->getDirectory(); + Tag* t = dir->findTag (name); - if (t) { - return t; + if (t) { + return t; + } + ++i; } } } @@ -492,15 +502,19 @@ std::vector TagDirectory::findTags (int ID) for (auto tag : tags) { if (tag->isDirectory()) { - TagDirectory *dir = tag->getDirectory(); - std::vector subTagList = dir->findTags (ID); + TagDirectory *dir; + int i = 0; + while ((dir = tag->getDirectory(i)) != nullptr) { + std::vector subTagList = dir->findTags (ID); - if (!subTagList.empty()) { - // concatenating the 2 vectors - // not really optimal in a memory efficiency pov - for (auto tag2 : subTagList) { - tagList.push_back(tag2); + if (!subTagList.empty()) { + // concatenating the 2 vectors + // not really optimal in a memory efficiency pov + for (auto tag2 : subTagList) { + tagList.push_back(tag2); + } } + ++i; } } } @@ -521,15 +535,19 @@ std::vector TagDirectory::findTags (const char* name) for (auto tag : tags) { if (tag->isDirectory()) { - TagDirectory *dir = tag->getDirectory(); - std::vector subTagList = dir->findTags (name); + TagDirectory *dir; + int i = 0; + while ((dir = tag->getDirectory(i)) != nullptr) { + std::vector subTagList = dir->findTags (name); - if (!subTagList.empty()) { - // concatenating the 2 vectors - // not really optimal in a memory efficiency pov - for (auto tag2 : subTagList) { - tagList.push_back(tag2); + if (!subTagList.empty()) { + // concatenating the 2 vectors + // not really optimal in a memory efficiency pov, but adding 10 items should be a maximum + for (auto tag2 : subTagList) { + tagList.push_back(tag2); + } } + ++i; } } } @@ -540,7 +558,7 @@ std::vector TagDirectory::findTags (const char* name) Tag* TagDirectory::findTagUpward (const char* name) const { - Tag* t = getTag(name); + Tag* t = findTag(name); if (t) { return t; } @@ -2650,7 +2668,6 @@ void ExifManager::parseStd (bool skipIgnored) { parse(false, skipIgnored); } -// return a root TagDirectory void ExifManager::parse (bool isRaw, bool skipIgnored) { int ifdOffset = IFDOffset; @@ -2924,8 +2941,10 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) frames.push_back(sft->getParent()); frameRootDetected = true; - //printf("\n--------------- FRAME -----------------------------\n\n"); - //sft->getParent()->printAll (); +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (SUBFILETYPE) ---------------\n\n"); + sft->getParent()->printAll (); +#endif } } } @@ -2939,8 +2958,10 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) frames.push_back(sft->getParent()); frameRootDetected = true; - //printf("\n--------------- FRAME -----------------------------\n\n"); - //sft->getParent()->printAll (); +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (OSUBFILETYPE) ---------------\n\n"); + sft->getParent()->printAll (); +#endif } } } @@ -2955,8 +2976,10 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) frames.push_back(pi->getParent()); //frameRootDetected = true; not used afterward - //printf("\n--------------- FRAME -----------------------------\n\n"); - //pi->getParent()->printAll (); +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (PHOTOMETRIC) ---------------\n\n"); + pi->getParent()->printAll (); +#endif } } } @@ -2968,8 +2991,10 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) roots.push_back(root); - //printf("\n~~~~~~~~~ ROOT ~~~~~~~~~~~~~~~~~~~~~~~~\n\n"); - //root->printAll (); +#if PRINT_METADATA_TREE + printf("\n~~~~~~~~~ ROOT ~~~~~~~~~~~~~~~~~~~~~~~~\n\n"); + root->printAll (); +#endif } while (ifdOffset && !onlyFirst); diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index bd2d82977..666c3a552 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -19,15 +19,15 @@ #ifndef _MEXIF3_ #define _MEXIF3_ -#include #include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include #include From 6c988e94d4bfa1c4b2cc5eb665f3b32efdc41a95 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Mon, 18 Sep 2017 21:30:42 +0200 Subject: [PATCH 09/27] FileBrowser now detects the 2 frames from DualPixel Canon files The QuickInfo frame from the EditorPanel now display the number of frame contained in the image file if > 1 See #4008 --- rtdata/languages/Francais | 1 + rtdata/languages/default | 1 + rtexif/canonattribs.cc | 17 ---------------- rtexif/rtexif.cc | 42 ++++++++++++++++++++++++++------------- rtexif/stdattribs.cc | 33 ++++++++++++++++++++++-------- rtgui/editorpanel.cc | 2 ++ 6 files changed, 57 insertions(+), 39 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index e2d2faea6..b45b41e02 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -1153,6 +1153,7 @@ PROGRESSBAR_SAVEPNG;Enregistrement du fichier PNG... PROGRESSBAR_SAVETIFF;Enregistrement du fichier TIFF... PROGRESSBAR_SNAPSHOT_ADDED;Signet ajouté PROGRESSDLG_PROFILECHANGEDINBROWSER;Profil modifié dans le navigateur +QINFO_FRAMECOUNT;%2 images QINFO_HDR;HDR / %2 image(s) QINFO_ISO;ISO QINFO_NOEXIF;Données EXIF non disponibles. diff --git a/rtdata/languages/default b/rtdata/languages/default index ffb6ce194..1f1bb98e0 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1176,6 +1176,7 @@ PROGRESSBAR_SAVEPNG;Saving PNG file... PROGRESSBAR_SAVETIFF;Saving TIFF file... PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +QINFO_FRAMECOUNT;%2 frames QINFO_HDR;HDR / %2 frame(s) QINFO_ISO;ISO QINFO_NOEXIF;Exif data not available. diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc index eaea38378..01b00dd53 100644 --- a/rtexif/canonattribs.cc +++ b/rtexif/canonattribs.cc @@ -1068,22 +1068,6 @@ public: }; CAFocalPlaneInterpreter caFocalPlaneInterpreter; -class RawImageSegmentationInterpreter : public Interpreter -{ -public: - virtual std::string toString (Tag* t) - { - int segmentNumber = t->toInt(0, SHORT); - int segmentWidth = t->toInt(2, SHORT); - int lastSegmentWidth = t->toInt(4, SHORT); - - char buffer[32]; - sprintf (buffer, "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth); - return buffer; - } -}; -RawImageSegmentationInterpreter rawImageSegmentationInterpreter; - class CAExposureTimeInterpreter : public Interpreter { public: @@ -2011,7 +1995,6 @@ const TagAttrib canonAttribs[] = { {1, AC_WRITE, 0, nullptr, 0x4005, AUTO, "UnknownBlock2", &stdInterpreter}, {1, AC_WRITE, 0, nullptr, 0x4008, AUTO, "BlackLevel", &stdInterpreter}, {1, AC_WRITE, 0, canonMicroAdjustAttrib, 0x4013, AUTO, "AFMicroAdj", &stdInterpreter}, - {1, AC_WRITE, 0, nullptr, 0xc640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter}, { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index c6ffabec9..3494d12e8 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -2318,9 +2318,6 @@ void ExifManager::parseCIFF (int length, TagDirectory* root) root->addTag (t); } - if (root->getTag("RawImageSegmentation")) { // Canon CR2 files - frames.push_back(root); - } roots.push_back(root); } @@ -2932,25 +2929,42 @@ void ExifManager::parse (bool isRaw, bool skipIgnored) // --- detecting image root IFD based on SubFileType, or if not provided, on PhotometricInterpretation bool frameRootDetected = false; - std::vector sftTagList = root->findTags(TIFFTAG_SUBFILETYPE); - if (!sftTagList.empty()) { - for (auto sft : sftTagList) { - int sftVal = sft->toInt(); - if (sftVal == (isRaw ? 0 : 2)) { - frames.push_back(sft->getParent()); + if(!frameRootDetected) { + std::vector risTagList = root->findTags("RawImageSegmentation"); + if (!risTagList.empty()) { + for (auto ris : risTagList) { + frames.push_back(ris->getParent()); frameRootDetected = true; -#if PRINT_METADATA_TREE - printf("\n--------------- FRAME (SUBFILETYPE) ---------------\n\n"); - sft->getParent()->printAll (); -#endif + #if PRINT_METADATA_TREE + printf("\n--------------- FRAME (RAWIMAGESEGMENTATION) ---------------\n\n"); + ris->getParent()->printAll (); + #endif } } } if(!frameRootDetected) { - sftTagList = root->findTags(TIFFTAG_OSUBFILETYPE); + std::vector sftTagList = root->findTags(TIFFTAG_SUBFILETYPE); + if (!sftTagList.empty()) { + for (auto sft : sftTagList) { + int sftVal = sft->toInt(); + if (sftVal == (isRaw ? 0 : 2)) { + frames.push_back(sft->getParent()); + frameRootDetected = true; + +#if PRINT_METADATA_TREE + printf("\n--------------- FRAME (SUBFILETYPE) ---------------\n\n"); + sft->getParent()->printAll (); +#endif + } + } + } + } + + if(!frameRootDetected) { + std::vector sftTagList = root->findTags(TIFFTAG_OSUBFILETYPE); if (!sftTagList.empty()) { for (auto sft : sftTagList) { int sftVal = sft->toInt(); diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index f59fa9b36..bacd6ffef 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -534,6 +534,22 @@ public: }; UTF8BinInterpreter utf8BinInterpreter; +class RawImageSegmentationInterpreter : public Interpreter +{ +public: + virtual std::string toString (Tag* t) + { + int segmentNumber = t->toInt(0, SHORT); + int segmentWidth = t->toInt(2, SHORT); + int lastSegmentWidth = t->toInt(4, SHORT); + + char buffer[32]; + sprintf (buffer, "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth); + return buffer; + } +}; +RawImageSegmentationInterpreter rawImageSegmentationInterpreter; + const TagAttrib exifAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, @@ -644,9 +660,9 @@ const TagAttrib exifAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC68D, AUTO, "ActiveArea", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC68F, AUTO, "AsShotICCProfile", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC68F, AUTO, "AsShotICCProfile", & ???}, {0, AC_WRITE, 0, nullptr, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC691, AUTO, "CurrentICCProfile", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC691, AUTO, "CurrentICCProfile", & ???}, {0, AC_WRITE, 0, nullptr, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter}, @@ -671,13 +687,13 @@ const TagAttrib exifAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC71E, AUTO, "SubTileBlockSize", & ???}, -// {0, AC_WRITE, 0, 0, 0xC71F, AUTO, "RowInterleaveFactor", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC71E, AUTO, "SubTileBlockSize", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC71F, AUTO, "RowInterleaveFactor", & ???}, {0, AC_WRITE, 0, nullptr, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter}, -// {0, AC_WRITE, 0, 0, 0xC740, AUTO, "OpcodeList1", & ???}, -// {0, AC_WRITE, 0, 0, 0xC741, AUTO, "OpcodeList2", & ???}, -// {0, AC_WRITE, 0, 0, 0xC74E, AUTO, "OpcodeList3", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC740, AUTO, "OpcodeList1", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC741, AUTO, "OpcodeList2", & ???}, +// {0, AC_WRITE, 0, nullptr, 0xC74E, AUTO, "OpcodeList3", & ???}, {0, AC_WRITE, 0, nullptr, 0xC761, AUTO, "NoiseProfile", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC763, AUTO, "TimeCodes", &stdInterpreter}, {0, AC_WRITE, 0, nullptr, 0xC764, AUTO, "FrameRate", &stdInterpreter}, @@ -754,6 +770,7 @@ const TagAttrib iopAttribs[] = { const TagAttrib ifdAttribs[] = { {0, AC_SYSTEM, 0, nullptr, 0x0017, AUTO, "PanaISO", &stdInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter}, @@ -809,9 +826,9 @@ const TagAttrib ifdAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData + {0, AC_DONTWRITE, 0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter}, {0, AC_WRITE, 0, nullptr, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0xc761, AUTO, "NoiseProfile", &stdInterpreter}, - {0, AC_SYSTEM, 0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter}, { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} }; } diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 1604384a5..d858ab9d7 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1356,6 +1356,8 @@ void EditorPanel::info_toggled () } } else if (isPixelShift) { infoString = Glib::ustring::compose ("%1\n" + M("QINFO_PIXELSHIFT"), infoString, numFrames); + } else if (numFrames > 1) { + infoString = Glib::ustring::compose ("%1\n" + M("QINFO_FRAMECOUNT"), infoString, numFrames); } } else { infoString = M ("QINFO_NOEXIF"); From 77a86f5d1e238e01416955a0855103eb8d823a24 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Tue, 19 Sep 2017 01:07:25 +0200 Subject: [PATCH 10/27] Bugfix: wrong interpreter called due to invalid overriding (#4008) --- rtexif/canonattribs.cc | 4 ++-- rtexif/nikonattribs.cc | 4 ++-- rtexif/pentaxattribs.cc | 22 +++++++++++----------- rtexif/sonyminoltaattribs.cc | 20 ++++++++++---------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/rtexif/canonattribs.cc b/rtexif/canonattribs.cc index 01b00dd53..8998c653a 100644 --- a/rtexif/canonattribs.cc +++ b/rtexif/canonattribs.cc @@ -1102,7 +1102,7 @@ public: sprintf (buffer, "%d", a); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = Interpreter::toInt (t, ofs); @@ -1113,7 +1113,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { int a = Interpreter::toInt (t, ofs, astype); diff --git a/rtexif/nikonattribs.cc b/rtexif/nikonattribs.cc index bf4fc5a6b..c977d076e 100644 --- a/rtexif/nikonattribs.cc +++ b/rtexif/nikonattribs.cc @@ -55,7 +55,7 @@ public: sprintf (buffer, "%d", a); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->getValue()[ofs]; @@ -66,7 +66,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { int a = t->getValue()[ofs]; diff --git a/rtexif/pentaxattribs.cc b/rtexif/pentaxattribs.cc index e9a7a3544..109ea0e78 100644 --- a/rtexif/pentaxattribs.cc +++ b/rtexif/pentaxattribs.cc @@ -1335,7 +1335,7 @@ public: sprintf (buffer, "%d", a ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a; @@ -1366,7 +1366,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { double a = double (t->toInt (0, LONG)); @@ -1396,7 +1396,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (ofs, BYTE); float b = float (10 * int (a >> 2)) * pow (4.f, float (int (a & 0x03) - 2)); @@ -1422,7 +1422,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return 100.*exp (double (a - 32) * log (2.) / 8.); @@ -1453,7 +1453,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); a &= 0x7F; @@ -1479,7 +1479,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return double (a - 64) / 8.; @@ -1499,7 +1499,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, SBYTE); return double (a) / 8.; @@ -1519,7 +1519,7 @@ public: sprintf (buffer, "%.1f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return exp ((double (a) - 68.) * log (2.) / 16.); @@ -1539,7 +1539,7 @@ public: sprintf (buffer, "%.6f", v ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE); return 24.*exp (- (double (a) - 32.) * log (2.) / 8.); @@ -1559,7 +1559,7 @@ public: sprintf (buffer, "%.1f", double (int (pow (2.0, double (mina + 10) / 4.0) + 0.2))); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = t->toInt (0, BYTE) & 0x0F; return double (int (pow (2.0, double (a + 10) / 4.0) + 0.2)); @@ -1579,7 +1579,7 @@ public: sprintf (buffer, "%.1f", double (int (pow (2.0, double (maxa) / 4.0) + 0.2)) ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { int a = ( t->toInt (0, BYTE) & 0xF0) >> 4; return double (int (pow (2.0, double (a) / 4.0) + 0.2)); diff --git a/rtexif/sonyminoltaattribs.cc b/rtexif/sonyminoltaattribs.cc index 7195bf8e5..738b33d50 100644 --- a/rtexif/sonyminoltaattribs.cc +++ b/rtexif/sonyminoltaattribs.cc @@ -2010,7 +2010,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT TagType astype = t->getType(); @@ -2029,7 +2029,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT int a = 0; @@ -2070,7 +2070,7 @@ public: return "n/a"; } } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT TagType astype = t->getType(); @@ -2089,7 +2089,7 @@ public: return 0.; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT int a = 0; @@ -2130,7 +2130,7 @@ public: return "Auto"; } } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { // Get the value; Depending on the camera model, this parameter can be a BYTE or a SHORT int a = 0; @@ -2166,7 +2166,7 @@ public: sprintf (buffer, "%.2f", a ); return buffer; } - virtual double toDouble (Tag* t, int ofs) + virtual double toDouble (const Tag* t, int ofs) { // Get the value int a = t->getValue()[ofs]; @@ -2186,7 +2186,7 @@ public: sprintf (buffer, "%d", t->getValue()[0] - 20); return buffer; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { return t->getValue()[0] - 20; } @@ -2207,7 +2207,7 @@ public: return "Off"; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { return (t->getValue()[0] & 0x80) == 0x80 ? 1 : 0; } @@ -2225,7 +2225,7 @@ public: sprintf (buffer, "%d", t->getValue()[0] & 0x7f); return buffer; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { return t->getValue()[0] & 0x7f; } @@ -2281,7 +2281,7 @@ public: sprintf (buffer, "%d", t->toInt()); return buffer; } - virtual int toInt (Tag* t, int ofs, TagType astype) + virtual int toInt (const Tag* t, int ofs, TagType astype) { int a = 0; From 615dfcbb6cc0b458c52767cec5b4e3dabab8b6fd Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Fri, 22 Sep 2017 00:35:10 +0200 Subject: [PATCH 11/27] Added "Show all" button in Exif panel + astylized exifpanel.cc/.h See #4008 --- rtdata/languages/Francais | 1 + rtexif/stdattribs.cc | 2 +- rtgui/exifpanel.cc | 264 +++++++++++++++++++++----------------- rtgui/exifpanel.h | 61 ++++----- rtgui/options.cc | 6 + rtgui/options.h | 1 + 6 files changed, 189 insertions(+), 146 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index b45b41e02..16e774aa7 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -68,6 +68,7 @@ EXIFPANEL_RESET;Réinitialiser EXIFPANEL_RESETALL;Réinitialiser tout EXIFPANEL_RESETALLHINT;Réinitialise tous les tags à leur valeur initiale EXIFPANEL_RESETHINT;Réinitialise les données sélectionnées à la valeur initiale +EXIFPANEL_SHOWALL;Voir tout EXIFPANEL_SUBDIRECTORY;Sous-répertoire EXPORT_BYPASS;Étapes de traitement à ignorer EXPORT_BYPASS_ALL;Sélectionner / Désélectionner tout diff --git a/rtexif/stdattribs.cc b/rtexif/stdattribs.cc index bacd6ffef..a7e3fe00f 100644 --- a/rtexif/stdattribs.cc +++ b/rtexif/stdattribs.cc @@ -826,7 +826,7 @@ const TagAttrib ifdAttribs[] = { {0, AC_WRITE, 0, nullptr, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter}, {0, AC_SYSTEM, 0, nullptr, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData - {0, AC_DONTWRITE, 0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter}, + {0, AC_SYSTEM, 0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter}, {0, AC_WRITE, 0, nullptr, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter}, {0, AC_DONTWRITE, 0, nullptr, 0xc761, AUTO, "NoiseProfile", &stdInterpreter}, { -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr} diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 9e10b75fa..874c6b6e2 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -25,49 +25,50 @@ using namespace rtengine; using namespace rtengine::procparams; using namespace rtexif; -ExifPanel::ExifPanel () : idata(nullptr) +ExifPanel::ExifPanel () : idata (nullptr) { recursiveOp = true; - exifTree = Gtk::manage(new Gtk::TreeView()); - scrolledWindow = Gtk::manage(new Gtk::ScrolledWindow()); + exifTree = Gtk::manage (new Gtk::TreeView()); + scrolledWindow = Gtk::manage (new Gtk::ScrolledWindow()); - exifTree->set_headers_visible(false); - exifTree->set_rules_hint(false); - exifTree->set_reorderable(false); - exifTree->set_enable_search(true); + exifTree->set_headers_visible (false); + exifTree->set_rules_hint (false); + exifTree->set_reorderable (false); + exifTree->set_enable_search (true); exifTree->get_selection()->set_mode (Gtk::SELECTION_MULTIPLE); - scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE); - scrolledWindow->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); - scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT); - scrolledWindow->add(*exifTree); + scrolledWindow->set_shadow_type (Gtk::SHADOW_NONE); + scrolledWindow->set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); + scrolledWindow->property_window_placement().set_value (Gtk::CORNER_TOP_LEFT); + scrolledWindow->add (*exifTree); - exifTreeModel = Gtk::TreeStore::create(exifColumns); + exifTreeModel = Gtk::TreeStore::create (exifColumns); exifTree->set_model (exifTreeModel); - exifTree->set_grid_lines(Gtk::TREE_VIEW_GRID_LINES_NONE); - exifTree->set_row_separator_func( - [&](const Glib::RefPtr& model, const Gtk::TreeModel::iterator& row) - { return row->get_value (exifColumns.isSeparator); } + exifTree->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_NONE); + exifTree->set_row_separator_func ( + [&] (const Glib::RefPtr& model, const Gtk::TreeModel::iterator & row) { + return row->get_value (exifColumns.isSeparator); + } ); delicon = RTImage::createFromFile ("gtk-close.png"); keepicon = RTImage::createFromFile ("gtk-apply.png"); editicon = RTImage::createFromFile ("gtk-add.png"); - Gtk::TreeView::Column *viewcol = Gtk::manage(new Gtk::TreeView::Column ("Field Name")); - Gtk::CellRendererPixbuf* render_pb = Gtk::manage(new Gtk::CellRendererPixbuf ()); - Gtk::CellRendererText *render_txt = Gtk::manage(new Gtk::CellRendererText()); + Gtk::TreeView::Column *viewcol = Gtk::manage (new Gtk::TreeView::Column ("Field Name")); + Gtk::CellRendererPixbuf* render_pb = Gtk::manage (new Gtk::CellRendererPixbuf ()); + Gtk::CellRendererText *render_txt = Gtk::manage (new Gtk::CellRendererText()); render_txt->property_ellipsize() = Pango::ELLIPSIZE_END; viewcol->pack_start (*render_pb, false); viewcol->pack_start (*render_txt, true); viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon); viewcol->add_attribute (*render_txt, "markup", exifColumns.field); - viewcol->set_expand(true); + viewcol->set_expand (true); viewcol->set_resizable (true); - viewcol->set_fixed_width(35); - viewcol->set_min_width(35); - viewcol->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE); + viewcol->set_fixed_width (35); + viewcol->set_min_width (35); + viewcol->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE); render_pb->property_ypad() = 0; render_txt->property_ypad() = 0; @@ -76,16 +77,16 @@ ExifPanel::ExifPanel () : idata(nullptr) exifTree->append_column (*viewcol); - Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value")); - Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText()); + Gtk::TreeView::Column *viewcolv = Gtk::manage (new Gtk::TreeView::Column ("Value")); + Gtk::CellRendererText *render_txtv = Gtk::manage (new Gtk::CellRendererText()); render_txtv->property_ellipsize() = Pango::ELLIPSIZE_END; viewcolv->pack_start (*render_txtv, true); viewcolv->add_attribute (*render_txtv, "markup", exifColumns.value); - viewcolv->set_expand(true); + viewcolv->set_expand (true); viewcolv->set_resizable (true); - viewcol->set_fixed_width(35); - viewcolv->set_min_width(35); - viewcolv->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE); + viewcol->set_fixed_width (35); + viewcolv->set_min_width (35); + viewcolv->set_sizing (Gtk::TREE_VIEW_COLUMN_AUTOSIZE); render_txtv->property_ypad() = 0; @@ -93,61 +94,68 @@ ExifPanel::ExifPanel () : idata(nullptr) pack_start (*scrolledWindow); - Gtk::Grid* buttons1 = Gtk::manage(new Gtk::Grid()); - buttons1->set_row_homogeneous(true); - buttons1->set_column_homogeneous(true); - setExpandAlignProperties(buttons1, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - Gtk::Grid* buttons2 = Gtk::manage(new Gtk::Grid()); - buttons2->set_row_homogeneous(true); - buttons2->set_column_homogeneous(true); - setExpandAlignProperties(buttons2, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + Gtk::Grid* buttons1 = Gtk::manage (new Gtk::Grid()); + buttons1->set_row_homogeneous (true); + buttons1->set_column_homogeneous (true); + setExpandAlignProperties (buttons1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); + Gtk::Grid* buttons2 = Gtk::manage (new Gtk::Grid()); + buttons2->set_row_homogeneous (true); + buttons2->set_column_homogeneous (true); + setExpandAlignProperties (buttons2, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER); - remove = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_REMOVE") - remove->set_image (*Gtk::manage(new Gtk::Image (delicon))); - remove->set_tooltip_text (M("EXIFPANEL_REMOVEHINT")); - remove->get_style_context()->add_class("Left"); - setExpandAlignProperties(remove, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to(*remove, Gtk::POS_LEFT, 1, 1); + remove = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_REMOVE") + remove->set_image (*Gtk::manage (new Gtk::Image (delicon))); + remove->set_tooltip_text (M ("EXIFPANEL_REMOVEHINT")); + remove->get_style_context()->add_class ("Left"); + setExpandAlignProperties (remove, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to (*remove, Gtk::POS_LEFT, 1, 1); - keep = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_KEEP") - keep->set_image (*Gtk::manage(new Gtk::Image (keepicon))); - keep->set_tooltip_text (M("EXIFPANEL_KEEPHINT")); - keep->get_style_context()->add_class("MiddleH"); - setExpandAlignProperties(keep, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to(*keep, Gtk::POS_RIGHT, 1, 1); + keep = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_KEEP") + keep->set_image (*Gtk::manage (new Gtk::Image (keepicon))); + keep->set_tooltip_text (M ("EXIFPANEL_KEEPHINT")); + keep->get_style_context()->add_class ("MiddleH"); + setExpandAlignProperties (keep, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to (*keep, Gtk::POS_RIGHT, 1, 1); - add = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_ADDEDIT") - add->set_image (*Gtk::manage(new Gtk::Image (editicon))); - add->set_tooltip_text (M("EXIFPANEL_ADDEDITHINT")); - add->get_style_context()->add_class("Right"); - setExpandAlignProperties(add, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons1->attach_next_to(*add, Gtk::POS_RIGHT, 1, 1); + add = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_ADDEDIT") + add->set_image (*Gtk::manage (new Gtk::Image (editicon))); + add->set_tooltip_text (M ("EXIFPANEL_ADDEDITHINT")); + add->get_style_context()->add_class ("Right"); + setExpandAlignProperties (add, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons1->attach_next_to (*add, Gtk::POS_RIGHT, 1, 1); - reset = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_RESET") - reset->set_image (*Gtk::manage(new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); - reset->set_tooltip_text (M("EXIFPANEL_RESETHINT")); - reset->get_style_context()->add_class("Left"); - setExpandAlignProperties(reset, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons2->attach_next_to(*reset, Gtk::POS_LEFT, 1, 1); + showAll = Gtk::manage (new Gtk::ToggleButton (M ("EXIFPANEL_SHOWALL"))); + //add->set_tooltip_text (M("EXIFPANEL_SHOWALL")); + setExpandAlignProperties (showAll, false, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + showAll->set_active (options.lastShowAllExif); + buttons2->attach_next_to (*showAll, Gtk::POS_LEFT, 1, 1); - resetAll = Gtk::manage(new Gtk::Button ()); // M("EXIFPANEL_RESETALL") - resetAll->set_image (*Gtk::manage(new RTImage ("gtk-undoall-ltr.png", "gtk-undoall-rtl.png"))); - resetAll->set_tooltip_text (M("EXIFPANEL_RESETALLHINT")); - resetAll->get_style_context()->add_class("Right"); - setExpandAlignProperties(resetAll, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); - buttons2->attach_next_to(*resetAll, Gtk::POS_RIGHT, 1, 1); + reset = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESET") + reset->set_image (*Gtk::manage (new RTImage ("gtk-undo-ltr.png", "gtk-undo-rtl.png"))); + reset->set_tooltip_text (M ("EXIFPANEL_RESETHINT")); + reset->get_style_context()->add_class ("Left"); + setExpandAlignProperties (reset, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons2->attach_next_to (*reset, Gtk::POS_RIGHT, 1, 1); + + resetAll = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESETALL") + resetAll->set_image (*Gtk::manage (new RTImage ("gtk-undoall-ltr.png", "gtk-undoall-rtl.png"))); + resetAll->set_tooltip_text (M ("EXIFPANEL_RESETALLHINT")); + resetAll->get_style_context()->add_class ("Right"); + setExpandAlignProperties (resetAll, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL); + buttons2->attach_next_to (*resetAll, Gtk::POS_RIGHT, 1, 1); pack_end (*buttons2, Gtk::PACK_SHRINK); pack_end (*buttons1, Gtk::PACK_SHRINK); - exifTree->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &ExifPanel::exifSelectionChanged)); - exifTree->signal_row_activated().connect(sigc::mem_fun(*this, &ExifPanel::row_activated)); + exifTree->get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ExifPanel::exifSelectionChanged)); + exifTree->signal_row_activated().connect (sigc::mem_fun (*this, &ExifPanel::row_activated)); - remove->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::removePressed) ); - keep->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::keepPressed) ); - reset->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetPressed) ); - resetAll->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetAllPressed) ); - add->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::addPressed) ); + remove->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::removePressed) ); + keep->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::keepPressed) ); + reset->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetPressed) ); + resetAll->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetAllPressed) ); + add->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::addPressed) ); + showAll->signal_toggled().connect ( sigc::mem_fun (*this, &ExifPanel::showAlltoggled) ); show_all (); } @@ -188,14 +196,10 @@ void ExifPanel::setImageData (const FramesMetaData* id) idata = id; exifTreeModel->clear (); - if (id) { + if (idata) { for (unsigned int rootNum = 0; rootNum < id->getRootCount (); ++rootNum) { if ( id->getRootExifData (rootNum)) { - //id->getRootExifData ()->printAll (); - if (rootNum > 0) { - addSeparator(); - } - addDirectory (id->getRootExifData (rootNum), exifTreeModel->children()); + addDirectory (id->getRootExifData (rootNum), exifTreeModel->children(), rootNum > 0); } } } @@ -204,7 +208,7 @@ void ExifPanel::setImageData (const FramesMetaData* id) Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable) { - Gtk::TreeModel::Row row = *(exifTreeModel->append(root)); + Gtk::TreeModel::Row row = * (exifTreeModel->append (root)); row[exifColumns.action] = action; row[exifColumns.editable] = editable; row[exifColumns.edited] = false; @@ -219,14 +223,14 @@ Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root } if (editable) { - row[exifColumns.field] = Glib::ustring("") + escapeHtmlChars(field) + ""; - row[exifColumns.value] = Glib::ustring("") + escapeHtmlChars(value) + ""; + row[exifColumns.field] = Glib::ustring ("") + escapeHtmlChars (field) + ""; + row[exifColumns.value] = Glib::ustring ("") + escapeHtmlChars (value) + ""; } else if (action == AC_SYSTEM) { - row[exifColumns.field] = Glib::ustring("") + escapeHtmlChars(field) + ""; - row[exifColumns.value] = Glib::ustring("") + escapeHtmlChars(value) + ""; + row[exifColumns.field] = Glib::ustring ("") + escapeHtmlChars (field) + ""; + row[exifColumns.value] = Glib::ustring ("") + escapeHtmlChars (value) + ""; } else { - row[exifColumns.field] = escapeHtmlChars(field); - row[exifColumns.value] = escapeHtmlChars(value); + row[exifColumns.field] = escapeHtmlChars (field); + row[exifColumns.value] = escapeHtmlChars (value); } return row.children(); @@ -235,7 +239,7 @@ Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root Gtk::TreeModel::Children ExifPanel::addSeparator () { - Gtk::TreeModel::Row row = *(exifTreeModel->append(exifTreeModel->children())); + Gtk::TreeModel::Row row = * (exifTreeModel->append (exifTreeModel->children())); row[exifColumns.action] = rtexif::ActionCode::AC_INVALID; row[exifColumns.editable] = false; row[exifColumns.edited] = false; @@ -247,23 +251,45 @@ Gtk::TreeModel::Children ExifPanel::addSeparator () return row.children(); } -void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root) +void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator) { - for (int i = 0; i < dir->getCount(); i++) { - Tag* t = (const_cast(dir))->getTagByIndex (i); + for (int i = 0; i < dir->getCount(); ++i) { + Tag* t = (const_cast (dir))->getTagByIndex (i); - if (t->getAttrib() && t->getAttrib()->action == AC_SYSTEM) { + bool hasContent = false; + + if (checkForSeparator && i == 0) { + for (int j = 0; j < dir->getCount(); ++j) { + Tag* t2 = (const_cast (dir))->getTagByIndex (j); + const TagAttrib* currAttrib = t->getAttrib(); + + if (currAttrib && ((options.lastShowAllExif) || (!options.lastShowAllExif && currAttrib->action != AC_SYSTEM))) { + addSeparator(); + hasContent = true; + break; + } + } + } else { + hasContent = true; + } + + if (!hasContent) { + return; + } + + const TagAttrib* currAttrib = t->getAttrib(); + + if (!options.lastShowAllExif && currAttrib && currAttrib->action == AC_SYSTEM) { continue; } if (t->isDirectory()) - for (int j = 0; t->getDirectory(j); j++) { - Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M("EXIFPANEL_SUBDIRECTORY"), t->getAttrib() ? t->getAttrib()->action : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); - addDirectory (t->getDirectory(j), ch); - } - else { - addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? (t->getOwnMemory() ? t->getAttrib()->action : AC_SYSTEM) : AC_DONTWRITE, t->getAttrib() && t->getAttrib()->editable); + for (int j = 0; t->getDirectory (j); j++) { + Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M ("EXIFPANEL_SUBDIRECTORY"), currAttrib ? currAttrib->action : AC_DONTWRITE, currAttrib && currAttrib->editable); + addDirectory (t->getDirectory (j), ch); + } else { + addTag (root, t->nameToString (), t->valueToString (), currAttrib ? (t->getOwnMemory() ? currAttrib->action : AC_SYSTEM) : AC_DONTWRITE, currAttrib && currAttrib->editable); } } } @@ -289,11 +315,11 @@ void ExifPanel::exifSelectionChanged () remove->set_sensitive (1); keep->set_sensitive (1); reset->set_sensitive (1); - } else if (iter->get_value(exifColumns.icon) == delicon) { + } else if (iter->get_value (exifColumns.icon) == delicon) { remove->set_sensitive (0); keep->set_sensitive (1); reset->set_sensitive (1); - } else if (iter->get_value(exifColumns.icon) == keepicon || iter->get_value(exifColumns.icon) == editicon) { + } else if (iter->get_value (exifColumns.icon) == keepicon || iter->get_value (exifColumns.icon) == editicon) { keep->set_sensitive (0); remove->set_sensitive (1); reset->set_sensitive (1); @@ -398,8 +424,8 @@ Gtk::TreeModel::iterator ExifPanel::resetIt (Gtk::TreeModel::iterator iter) } if (iter->get_value (exifColumns.edited)) { - iter->set_value (exifColumns.value, Glib::ustring("") + iter->get_value(exifColumns.orig_value) + ""); - iter->set_value (exifColumns.value_nopango, iter->get_value(exifColumns.orig_value)); + iter->set_value (exifColumns.value, Glib::ustring ("") + iter->get_value (exifColumns.orig_value) + ""); + iter->set_value (exifColumns.value_nopango, iter->get_value (exifColumns.orig_value)); iter->set_value (exifColumns.edited, false); } @@ -442,14 +468,14 @@ void ExifPanel::resetAllPressed () void ExifPanel::addPressed () { - Gtk::Dialog* dialog = new Gtk::Dialog (M("EXIFPANEL_ADDTAGDLG_TITLE"), *((Gtk::Window*)get_toplevel()), true); + Gtk::Dialog* dialog = new Gtk::Dialog (M ("EXIFPANEL_ADDTAGDLG_TITLE"), * ((Gtk::Window*)get_toplevel()), true); dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); dialog->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); Gtk::HBox* hb1 = new Gtk::HBox (); Gtk::HBox* hb2 = new Gtk::HBox (); - Gtk::Label* tlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":"); + Gtk::Label* tlabel = new Gtk::Label (M ("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":"); MyComboBoxText* tcombo = new MyComboBoxText (); tcombo->append ("Artist"); @@ -460,7 +486,7 @@ void ExifPanel::addPressed () hb1->pack_start (*tlabel, Gtk::PACK_SHRINK, 4); hb1->pack_start (*tcombo); - Gtk::Label* vlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_ENTERVALUE") + ":"); + Gtk::Label* vlabel = new Gtk::Label (M ("EXIFPANEL_ADDTAGDLG_ENTERVALUE") + ":"); Gtk::Entry* ventry = new Gtk::Entry (); hb2->pack_start (*vlabel, Gtk::PACK_SHRINK, 4); hb2->pack_start (*ventry); @@ -506,6 +532,12 @@ void ExifPanel::addPressed () delete hb2; } +void ExifPanel::showAlltoggled () +{ + options.lastShowAllExif = showAll->get_active(); + setImageData (idata); +} + void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value) { @@ -520,29 +552,30 @@ void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib } if (iter == root.end() && value != "#keep" && value != "#delete") { - iter = exifTreeModel->append(root); + iter = exifTreeModel->append (root); iter->set_value (exifColumns.field_nopango, fseg); iter->set_value (exifColumns.action, AC_INVALID); if (dp == Glib::ustring::npos) { - iter->set_value (exifColumns.value, Glib::ustring("") + value + ""); + iter->set_value (exifColumns.value, Glib::ustring ("") + value + ""); iter->set_value (exifColumns.value_nopango, value); iter->set_value (exifColumns.orig_value, value); - iter->set_value (exifColumns.field, Glib::ustring("") + fseg + ""); + iter->set_value (exifColumns.field, Glib::ustring ("") + fseg + ""); iter->set_value (exifColumns.edited, true); iter->set_value (exifColumns.editable, true); iter->set_value (exifColumns.icon, editicon); } else { - iter->set_value (exifColumns.value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); - iter->set_value (exifColumns.value_nopango, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); + iter->set_value (exifColumns.value, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY"))); + iter->set_value (exifColumns.value_nopango, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY"))); iter->set_value (exifColumns.field, fseg); iter->set_value (exifColumns.icon, keepicon); - iter->set_value (exifColumns.orig_value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY"))); + iter->set_value (exifColumns.orig_value, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY"))); } } - if (iter == root.end()) + if (iter == root.end()) { return; + } if (dp == Glib::ustring::npos) { if (value == "#keep" && iter->get_value (exifColumns.action) != AC_SYSTEM) { @@ -550,7 +583,7 @@ void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib } else if (value == "#delete" && iter->get_value (exifColumns.action) != AC_SYSTEM) { iter->set_value (exifColumns.icon, delicon); } else { - iter->set_value (exifColumns.value, Glib::ustring("") + value + ""); + iter->set_value (exifColumns.value, Glib::ustring ("") + value + ""); iter->set_value (exifColumns.value_nopango, value); iter->set_value (exifColumns.edited, true); iter->set_value (exifColumns.icon, editicon); @@ -664,8 +697,7 @@ void ExifPanel::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewCo exifTree->collapse_row (path); } else { exifTree->expand_row (path, false); - } - else if (iter->get_value (exifColumns.editable)) { + } else if (iter->get_value (exifColumns.editable)) { addPressed (); } } @@ -676,6 +708,6 @@ void ExifPanel::notifyListener () { if (listener) { - listener->panelChanged (EvExif, M("HISTORY_CHANGED")); + listener->panelChanged (EvExif, M ("HISTORY_CHANGED")); } } diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index d86e82af8..b9d76f25d 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -47,16 +47,16 @@ private: ExifColumns() { - add(field); - add(value); - add(icon); - add(action); - add(edited); - add(field_nopango); - add(value_nopango); - add(editable); - add(orig_value); - add(isSeparator); + add (field); + add (value); + add (icon); + add (action); + add (edited); + add (field_nopango); + add (value_nopango); + add (editable); + add (orig_value); + add (isSeparator); } }; Glib::RefPtr delicon; @@ -73,38 +73,41 @@ private: Gtk::Button* add; Gtk::Button* reset; Gtk::Button* resetAll; + Gtk::ToggleButton* showAll; - Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable); + Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable); void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value); void updateChangeList (Gtk::TreeModel::Children root, std::string prefix); - void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root); - Gtk::TreeModel::Children addSeparator (); + void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator = false); + Gtk::TreeModel::Children addSeparator(); Glib::ustring getSelection (bool onlyifeditable = false); - Glib::ustring getSelectedValue (); - void updateChangeList (); - void applyChangeList (); - void keepIt (Gtk::TreeModel::iterator iter); - void delIt (Gtk::TreeModel::iterator iter); + Glib::ustring getSelectedValue(); + void updateChangeList(); + void applyChangeList(); + void keepIt (Gtk::TreeModel::iterator iter); + void delIt (Gtk::TreeModel::iterator iter); Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter); + void removePressed(); + void keepPressed(); + void resetPressed(); + void resetAllPressed(); + void addPressed(); + void showAlltoggled(); + public: ExifPanel (); - virtual ~ExifPanel (); + virtual ~ExifPanel(); - void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); - void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); - void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); + void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited = nullptr); + void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited = nullptr); + void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited = nullptr); void setImageData (const rtengine::FramesMetaData* id); - void exifSelectionChanged (); - void removePressed (); - void keepPressed (); - void resetPressed (); - void resetAllPressed (); - void addPressed (); + void exifSelectionChanged(); void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); - void notifyListener (); + void notifyListener(); }; diff --git a/rtgui/options.cc b/rtgui/options.cc index 38be51931..53c4ffb4a 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -354,6 +354,7 @@ void Options::setDefaults () CPFontFamily = "default"; CPFontSize = 8; lastScale = 5; + lastShowAllExif = false; panAccelFactor = 5; rememberZoomAndPan = true; lastCropSize = 1; @@ -1390,6 +1391,10 @@ void Options::readFromFile (Glib::ustring fname) lastScale = keyFile.get_integer ("GUI", "LastPreviewScale"); } + if (keyFile.has_key ("GUI", "LastShowAllExif")) { + lastShowAllExif = keyFile.get_boolean ("GUI", "LastShowAllExif"); + } + if (keyFile.has_key ("GUI", "PanAccelFactor")) { panAccelFactor = keyFile.get_integer ("GUI", "PanAccelFactor"); } @@ -2105,6 +2110,7 @@ void Options::saveToFile (Glib::ustring fname) keyFile.set_string ("GUI", "CPFontFamily", CPFontFamily); keyFile.set_integer ("GUI", "CPFontSize", CPFontSize); keyFile.set_integer ("GUI", "LastPreviewScale", lastScale); + keyFile.set_boolean ("GUI", "LastShowAllExif", lastShowAllExif); keyFile.set_integer ("GUI", "PanAccelFactor", panAccelFactor); keyFile.set_boolean ("GUI", "RememberZoomAndPan", rememberZoomAndPan); keyFile.set_integer ("GUI", "LastCropSize", lastCropSize); diff --git a/rtgui/options.h b/rtgui/options.h index 291a45d47..5bf77fa65 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -168,6 +168,7 @@ public: int dirBrowserHeight; int preferencesWidth; int preferencesHeight; + bool lastShowAllExif; int lastScale; int panAccelFactor; int lastCropSize; From 08075106038f1831769ac9ce8b82e4abe0936dca Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Tue, 26 Sep 2017 21:42:59 +0200 Subject: [PATCH 12/27] Bigfix: CR2 files couldn't find the metadata for display (see #4008) --- rtdata/languages/default | 1 + rtengine/imagedata.cc | 40 ++++++++++++++++++++++------------------ rtengine/imagedata.h | 4 +--- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 1f1bb98e0..bbf0ff5f9 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -71,6 +71,7 @@ EXIFPANEL_RESET;Reset EXIFPANEL_RESETALL;Reset All EXIFPANEL_RESETALLHINT;Reset all tags to their original values. EXIFPANEL_RESETHINT;Reset the selected tags to their original values. +EXIFPANEL_SHOWALL;Show all EXIFPANEL_SUBDIRECTORY;Subdirectory EXPORT_BYPASS;Processing steps to bypass EXPORT_BYPASS_ALL;Select / Unselect All diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 3d9c3276a..5e5e40c79 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -48,24 +48,19 @@ FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname, std::uniqu return new FramesData (fname, std::move(rml), firstFrameOnly); } -FrameData::FrameData (rtexif::TagDirectory* frameRootDir) - : frameRootDir(frameRootDir), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), +FrameData::FrameData (rtexif::TagDirectory* frameRootDir_, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir) + : frameRootDir(frameRootDir_), iptc(nullptr), time(), timeStamp(), iso_speed(0), aperture(0.), focal_len(0.), focal_len35mm(0.), focus_dist(0.f), shutter(0.), expcomp(0.), make("Unknown"), model("Unknown"), orientation("Unknown"), lens("Unknown"), sampleFormat(IIOSF_UNKNOWN), isPixelShift(false), isHDR(false) { memset (&time, 0, sizeof(time)); - extractInfo(); -} - -void FrameData::extractInfo () -{ - if (!frameRootDir) { return; } rtexif::Tag* tag; + rtexif::TagDirectory* newFrameRootDir = frameRootDir; memset(&time, 0, sizeof(time)); timeStamp = 0; @@ -82,7 +77,16 @@ void FrameData::extractInfo () orientation.clear(); lens.clear(); - tag = frameRootDir->findTagUpward("Make"); + tag = newFrameRootDir->findTag("Make"); + if (!tag) { + newFrameRootDir = rootDir; + tag = newFrameRootDir->findTag("Make"); + if (!tag) { + // For some raw files (like Canon's CR2 files), the metadata are contained in the first root directory + newFrameRootDir = firstRootDir; + tag = newFrameRootDir->findTag("Make"); + } + } if (tag) { make = tag->valueToString(); // Same dcraw treatment @@ -116,7 +120,7 @@ void FrameData::extractInfo () make.erase(make.find_last_not_of(' ') + 1); } - tag = frameRootDir->findTagUpward("Model"); + tag = newFrameRootDir->findTagUpward("Model"); if (tag) { model = tag->valueToString(); } @@ -150,19 +154,19 @@ void FrameData::extractInfo () model = "Unknown"; } - tag = frameRootDir->findTagUpward("Orientation"); + tag = newFrameRootDir->findTagUpward("Orientation"); if (tag) { orientation = tag->valueToString (); } - tag = frameRootDir->findTagUpward("MakerNote"); + tag = newFrameRootDir->findTagUpward("MakerNote"); rtexif::TagDirectory* mnote = nullptr; if (tag) { mnote = tag->getDirectory(); } rtexif::TagDirectory* exif = nullptr; - tag = frameRootDir->findTagUpward("Exif"); + tag = newFrameRootDir->findTagUpward("Exif"); if (tag) { exif = tag->getDirectory (); } @@ -211,7 +215,7 @@ void FrameData::extractInfo () // Second try, XMP data char sXMPVal[64]; - if (frameRootDir->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { + if (newFrameRootDir->getXMPTagValue("aux:ApproximateFocusDistance", sXMPVal)) { sscanf(sXMPVal, "%d/%d", &num, &denom); } } @@ -458,7 +462,7 @@ void FrameData::extractInfo () } } - rtexif::Tag* t = frameRootDir->getTag(0x83BB); + rtexif::Tag* t = newFrameRootDir->getTag(0x83BB); if (t) { iptc = iptc_data_new_from_data ((unsigned char*)t->getValue (), (unsigned)t->getValueSize ()); } @@ -1027,7 +1031,7 @@ FramesData::FramesData (const Glib::ustring& fname, std::unique_ptrgetRoot(), roots.at(0)); frames.push_back(fd); } @@ -1051,7 +1055,7 @@ FramesData::FramesData (const Glib::ustring& fname, std::unique_ptrgetRoot(), roots.at(0)); frames.push_back(fd); } rewind (exifManager.f); // Not sure this is necessary @@ -1069,7 +1073,7 @@ FramesData::FramesData (const Glib::ustring& fname, std::unique_ptrgetRoot(), roots.at(0)); frames.push_back(fd); } diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 07119e5f0..b9a7a2e70 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -56,11 +56,9 @@ protected: bool isPixelShift; bool isHDR; - void extractInfo (); - public: - FrameData (rtexif::TagDirectory* frameRootDir); + FrameData (rtexif::TagDirectory* frameRootDir, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir); virtual ~FrameData (); bool getPixelShift () const; From e97c7cad2c18c3e8dc9686e863888fd78d114a0f Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Thu, 28 Sep 2017 00:25:23 +0200 Subject: [PATCH 13/27] Bugfix: when 'off', "Show all" only shew the first frame The QuickInfo panel now reflect the selected subframe's metadata See #4008 --- rtgui/editorpanel.cc | 24 ++++++++++++++++-------- rtgui/editorpanel.h | 2 ++ rtgui/exifpanel.cc | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index d858ab9d7..52adf1da4 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -484,7 +484,12 @@ public: }; EditorPanel::EditorPanel (FilePanel* filePanel) - : catalogPane (nullptr), realized (false), tbBeforeLock (nullptr), iHistoryShow (nullptr), iHistoryHide (nullptr), iTopPanel_1_Show (nullptr), iTopPanel_1_Hide (nullptr), iRightPanel_1_Show (nullptr), iRightPanel_1_Hide (nullptr), iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr), beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr), beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false) + : catalogPane (nullptr), realized (false), tbBeforeLock (nullptr), iHistoryShow (nullptr), iHistoryHide (nullptr), + iTopPanel_1_Show (nullptr), iTopPanel_1_Hide (nullptr), iRightPanel_1_Show (nullptr), iRightPanel_1_Hide (nullptr), + iBeforeLockON (nullptr), iBeforeLockOFF (nullptr), previewHandler (nullptr), beforePreviewHandler (nullptr), + beforeIarea (nullptr), beforeBox (nullptr), afterBox (nullptr), beforeLabel (nullptr), afterLabel (nullptr), + beforeHeaderBox (nullptr), afterHeaderBox (nullptr), parent (nullptr), parentWindow (nullptr), openThm (nullptr), + selectedFrame(0), isrc (nullptr), ipc (nullptr), beforeIpc (nullptr), err (0), isProcessing (false) { epih = new EditorPanelIdleHelper; @@ -1137,6 +1142,9 @@ void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, r // if (ev!=EvPhotoLoaded) // saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); + + selectedFrame = params->raw.bayersensor.imageNum; + info_toggled(); } void EditorPanel::setProgressState (bool inProcessing) @@ -1314,16 +1322,16 @@ void EditorPanel::info_toggled () const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData(); - if (idata && idata->hasExif()) { + if (idata && idata->hasExif(selectedFrame)) { infoString = Glib::ustring::compose ("%1 + %2\nf/%3 %4s %5%6 %7mm", Glib::ustring (idata->getMake() + " " + idata->getModel()), Glib::ustring (idata->getLens()), - Glib::ustring (idata->apertureToString (idata->getFNumber())), - Glib::ustring (idata->shutterToString (idata->getShutterSpeed())), - M ("QINFO_ISO"), idata->getISOSpeed(), - Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen())); + Glib::ustring (idata->apertureToString (idata->getFNumber(selectedFrame))), + Glib::ustring (idata->shutterToString (idata->getShutterSpeed(selectedFrame))), + M ("QINFO_ISO"), idata->getISOSpeed(selectedFrame), + Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen(selectedFrame))); - expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(), true)); // maskZeroexpcomp + expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(selectedFrame), true)); // maskZeroexpcomp if (!expcomp.empty ()) { infoString = Glib::ustring::compose ("%1 %2EV", @@ -1351,7 +1359,7 @@ void EditorPanel::info_toggled () if (isHDR) { infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames); if (numFrames == 1) { - int sampleFormat = idata->getSampleFormat(); + int sampleFormat = idata->getSampleFormat(selectedFrame); infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat))); } } else if (isPixelShift) { diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 9c063661a..5beb9ee7d 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -212,6 +212,8 @@ private: Thumbnail* openThm; // may get invalid on external delete event Glib::ustring fname; // must be saved separately + int selectedFrame; + rtengine::InitialImage* isrc; rtengine::StagedImageProcessor* ipc; rtengine::StagedImageProcessor* beforeIpc; // for the before-after view diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 874c6b6e2..0e7875815 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -262,7 +262,7 @@ void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children if (checkForSeparator && i == 0) { for (int j = 0; j < dir->getCount(); ++j) { Tag* t2 = (const_cast (dir))->getTagByIndex (j); - const TagAttrib* currAttrib = t->getAttrib(); + const TagAttrib* currAttrib = t2->getAttrib(); if (currAttrib && ((options.lastShowAllExif) || (!options.lastShowAllExif && currAttrib->action != AC_SYSTEM))) { addSeparator(); From bb874bcce765b5b786afaaf50e09276232e7f544 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Wed, 4 Oct 2017 23:27:08 +0200 Subject: [PATCH 14/27] Bigfix (see #4008) : - CIECam now gets the shot's setting of the selected frame - 'UserComment' metadata now correctly handled - RT prepared to handle XTrans multiframe - SensorType now set in the cache/data files --- rtengine/imagedata.cc | 35 +++++++++++++++++++++++++++++++++++ rtengine/imagedata.h | 1 + rtengine/improccoordinator.cc | 19 +++++++++++++++---- rtengine/improcfun.cc | 5 +++-- rtengine/previewimage.cc | 3 ++- rtengine/rtengine.h | 8 +++++++- rtengine/rtthumbnail.cc | 20 +++++++++++++++----- rtengine/rtthumbnail.h | 6 +++--- rtengine/simpleprocess.cc | 19 ++++++++++++++----- rtexif/rtexif.cc | 32 ++++++++++++++++++++++++++++++-- rtexif/rtexif.h | 21 +++++++++++---------- rtgui/cacheimagedata.cc | 9 +++++++-- rtgui/cacheimagedata.h | 2 ++ rtgui/editorpanel.cc | 11 ++++++++++- rtgui/thumbnail.cc | 10 ++++++---- 15 files changed, 161 insertions(+), 40 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index 5e5e40c79..d88c853df 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -22,6 +22,8 @@ #include "imagedata.h" #include "iptcpairs.h" +#include "imagesource.h" +#include "rt_math.h" #define PRINT_HDR_PS_DETECTION 0 @@ -791,6 +793,39 @@ rtexif::TagDirectory* FramesData::getFrameExifData (unsigned int frame) const return frames.empty() || frame >= frames.size() ? nullptr : frames.at(frame)->getExifData (); } +rtexif::TagDirectory* FramesData::getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const +{ + rtexif::TagDirectory *td = nullptr; + if (frames.empty()) { + return nullptr; + } + if (imgSource && rawParams) { + eSensorType sensorType = imgSource->getSensorType(); + unsigned int imgNum = 0; + if (sensorType == ST_BAYER) { + imgNum = rtengine::LIM(rawParams->bayersensor.imageNum, 1, frames.size()); + /* + // might exist someday ? + } else if (sensorType == ST_FUJI_XTRANS) { + imgNum = rtengine::LIM(rawParams->xtranssensor.imageNum, 1, frames.size()); + } else if (sensorType == ST_NONE && !imgSource->isRAW()) { + // standard image multiframe support should come here (when implemented in GUI) + */ + } + + frames[imgNum]->getExifData (); + + td = getFrameExifData (imgNum); + rtexif::Tag* makeTag; + if (td && (makeTag = td->findTag("Make", true))) { + td = makeTag->getParent(); + } else { + td = getRootExifData(0); + } + } + return td; +} + rtexif::TagDirectory* FramesData::getRootExifData (unsigned int root) const { return roots.empty() || root >= roots.size() ? nullptr : roots.at(root); diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index b9a7a2e70..60011968a 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -107,6 +107,7 @@ public: IIOSampleFormat getSampleFormat (unsigned int frame = 0) const; rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const; rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const; + rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const; procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const; bool hasExif (unsigned int frame = 0) const; bool hasIPTC (unsigned int frame = 0) const; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 4a9eb8e83..9d265f90b 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -732,10 +732,21 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) CurveFactory::curveLightBrightColor (params.colorappearance.curve, params.colorappearance.curve2, params.colorappearance.curve3, lhist16CAM, histLCAM, lhist16CCAM, histCCAM, customColCurve1, customColCurve2, customColCurve3, 1); - float fnum = imgsrc->getMetaData()->getFNumber (); // F number - float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO - float fspeed = imgsrc->getMetaData()->getShutterSpeed () ; // Speed - double fcomp = imgsrc->getMetaData()->getExpComp (); // Compensation +/- + + const FramesMetaData* metaData = imgsrc->getMetaData(); + int imgNum = 0; + if (imgsrc->isRAW()) { + if (imgsrc->getSensorType() == ST_BAYER) { + imgNum = rtengine::LIM(params.raw.bayersensor.imageNum, 0, metaData->getFrameCount() - 1); + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { + //imgNum = rtengine::LIM(params.raw.xtranssensor.imageNum, 0, metaData->getFrameCount() - 1); + } + } + + float fnum = metaData->getFNumber (imgNum); // F number + float fiso = metaData->getISOSpeed (imgNum) ; // ISO + float fspeed = metaData->getShutterSpeed (imgNum) ; // Speed + double fcomp = metaData->getExpComp (imgNum); // Compensation +/- double adap; if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 3bc154446..01b543d9a 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -7063,13 +7063,14 @@ double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_si int w_raw = -1, h_raw = thumb_size; int w_thumb = -1, h_thumb = thumb_size; - Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, w_thumb, h_thumb, 1, FALSE); + eSensorType sensorType = rtengine::ST_NONE; + Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, w_thumb, h_thumb, 1, FALSE); if (!thumb) { return 0.0; } - Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, w_raw, h_raw, 1, 1.0, FALSE, 0); + Thumbnail* raw = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, w_raw, h_raw, 1, 1.0, FALSE, 0); if (!raw) { delete thumb; diff --git a/rtengine/previewimage.cc b/rtengine/previewimage.cc index aba43ace5..e6703aed5 100644 --- a/rtengine/previewimage.cc +++ b/rtengine/previewimage.cc @@ -59,7 +59,8 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext } } else { rtengine::RawMetaDataLocation ri; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, width, height, 1, true, true); + eSensorType sensorType = rtengine::ST_NONE; + tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, width, height, 1, true, true); if (tpp) { data = tpp->getImage8Data(); diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 2a5f28f6d..edf903352 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -48,7 +48,7 @@ namespace rtengine class IImage8; class IImage16; class IImagefloat; - +class ImageSource; /** * This class provides functions to obtain exif and IPTC metadata information @@ -74,6 +74,12 @@ public: * @param frame frame number in the metadata tree * @return The directory of exif metadata tags */ virtual rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const = 0; + /** Returns the directory of exif metadata tags containing at least the 'Make' tag for the requested frame. + * If no usable metadata exist in the frame, send back the best TagDirectory describing the frame content. + * @param imgSource rawimage that we want the metadata from + * @param rawParams RawParams to select the frame number + * @return The directory of exif metadata tags containing at least the 'Make' tag */ + virtual rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const = 0; /** Checks the availability of IPTC tags. * @return Returns true if image contains IPTC tags */ virtual bool hasIPTC (unsigned int frame = 0) const = 0; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index bcb6be6a2..50e4b57b5 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -247,7 +247,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, return tpp; } -Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode) +Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode) { RawImage *ri = new RawImage (fname); unsigned int imageNum = 0; @@ -255,9 +255,12 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL if ( r ) { delete ri; + sensorType = ST_NONE; return nullptr; } + sensorType = ri->getSensorType(); + rml.exifBase = ri->get_exifBase(); rml.ciffBase = ri->get_ciffBase(); rml.ciffLength = ri->get_ciffLen(); @@ -378,7 +381,7 @@ RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname) return rml; } -Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum) +Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum) { RawImage *ri = new RawImage (fname); unsigned int tempImageNum = 0; @@ -387,9 +390,12 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati if ( r ) { delete ri; + sensorType = ST_NONE; return nullptr; } + sensorType = ri->getSensorType(); + int width = ri->get_width(); int height = ri->get_height(); rtengine::Thumbnail* tpp = new rtengine::Thumbnail; @@ -954,11 +960,15 @@ 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, const FramesMetaData *metadata, double& myscale) +IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& myscale) { - int imgNum = 1; + unsigned int imgNum = 0; if (isRaw) { - imgNum = rtengine::LIM(params.raw.bayersensor.imageNum, 0, metadata->getFrameCount() - 1); + if (sensorType == ST_BAYER) { + imgNum = rtengine::LIM(params.raw.bayersensor.imageNum, 0, metadata->getFrameCount() - 1); + } else if (sensorType == ST_FUJI_XTRANS) { + //imgNum = rtengine::LIM(params.raw.xtranssensor.imageNum, 0, metadata->getFrameCount() - 1) + } } std::string camName = metadata->getCamera(imgNum); float shutter = metadata->getShutterSpeed(imgNum); diff --git a/rtengine/rtthumbnail.h b/rtengine/rtthumbnail.h index 5258d0d34..4987cc88c 100644 --- a/rtengine/rtthumbnail.h +++ b/rtengine/rtthumbnail.h @@ -71,13 +71,13 @@ public: void init (); - IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& scale); + IImage8* processImage (const procparams::ProcParams& pparams, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, 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); - static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false); - static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum); + static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false); + static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, int imageNum); static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false); static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index ef3c0948e..cc199389a 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1109,10 +1109,16 @@ private: if (params.colorappearance.enabled) { double adap; - float fnum = imgsrc->getMetaData()->getFNumber ();// F number - float fiso = imgsrc->getMetaData()->getISOSpeed () ;// ISO - float fspeed = imgsrc->getMetaData()->getShutterSpeed () ;//speed - float fcomp = imgsrc->getMetaData()->getExpComp ();//compensation + - + int imgNum = 0; + if (imgsrc->getSensorType() == ST_BAYER) { + imgNum = params.raw.bayersensor.imageNum; + } else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) { + //imgNum = params.raw.xtranssensor.imageNum; + } + float fnum = imgsrc->getMetaData()->getFNumber (imgNum); // F number + float fiso = imgsrc->getMetaData()->getISOSpeed (imgNum) ; // ISO + float fspeed = imgsrc->getMetaData()->getShutterSpeed (imgNum) ; //speed + float fcomp = imgsrc->getMetaData()->getExpComp (imgNum); //compensation + - if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { adap = 2000.; @@ -1285,9 +1291,12 @@ private: } if (tunnelMetaData) { + // Sending back the whole first root, which won't necessarily be the selected frame number + // and may contain subframe depending on initial raw's hierarchy readyImg->setMetadata (ii->getMetaData()->getRootExifData ()); } else { - readyImg->setMetadata (ii->getMetaData()->getRootExifData (), params.exif, params.iptc); + // ask for the correct frame number, but may contain subframe depending on initial raw's hierarchy + readyImg->setMetadata (ii->getMetaData()->getBestExifData(imgsrc, ¶ms.raw), params.exif, params.iptc); } diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 3494d12e8..8a5ee8ae2 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -28,6 +28,7 @@ #include #include +#include #include "rtexif.h" @@ -707,7 +708,7 @@ int TagDirectory::write (int start, unsigned char* buffer) return maxPos; } -void TagDirectory::applyChange (std::string name, std::string value) +void TagDirectory::applyChange (std::string name, Glib::ustring value) { std::string::size_type dp = name.find_first_of ('.'); @@ -741,7 +742,12 @@ void TagDirectory::applyChange (std::string name, std::string value) if (attrib) { Tag* nt = new Tag (this, attrib); - nt->initString (value.c_str()); + if (name == "UserComment") { + // UserComment can be Unicode + nt->initUserComment (value); + } else { + nt->initString (value.c_str()); + } addTag (nt); } } @@ -1907,6 +1913,28 @@ void Tag::initInt (int data, TagType t, int cnt) setInt (data, 0, t); } +void Tag::initUserComment (const Glib::ustring &text) +{ + type = UNDEFINED; + if (text.is_ascii()) { + count = 8 + strlen (text.c_str()); + valuesize = count; + value = new unsigned char[valuesize]; + strcpy ((char*)value, "ASCII"); + value[5] = value[6] = value[7] = 0; + strcpy ((char*)value + 8, text.c_str()); + } else { + wchar_t *commentStr = (wchar_t*)g_utf8_to_utf16 (text.c_str(), -1, NULL, NULL, NULL); + count = 8 + wcslen(commentStr)*2; + valuesize = count; + value = (unsigned char*)new char[valuesize]; + strcpy ((char*)value, "UNICODE"); + value[7] = 0; + wcscpy(((wchar_t*)value) + 4, commentStr); + g_free(commentStr); + } +} + void Tag::initString (const char* text) { diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 666c3a552..887ea2b46 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -171,7 +171,7 @@ public: virtual int calculateSize (); virtual int write (int start, unsigned char* buffer); virtual TagDirectory* clone (TagDirectory* parent); - virtual void applyChange (std::string field, std::string value); + virtual void applyChange (std::string field, Glib::ustring value); virtual void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call ! virtual bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, @@ -225,15 +225,16 @@ public: Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used ~Tag (); - void initType (unsigned char *data, TagType type); - void initInt (int data, TagType t, int count = 1); - void initString (const char* text); - void initSubDir (); - void initSubDir (TagDirectory* dir); - void initMakerNote (MNKind mnk, const TagAttrib* ta); - void initUndefArray (const char* data, int len); - void initLongArray (const char* data, int len); - void initRational (int num, int den); + void initType (unsigned char *data, TagType type); + void initInt (int data, TagType t, int count = 1); + void initUserComment (const Glib::ustring &text); + void initString (const char* text); + void initSubDir (); + void initSubDir (TagDirectory* dir); + void initMakerNote (MNKind mnk, const TagAttrib* ta); + void initUndefArray (const char* data, int len); + void initLongArray (const char* data, int len); + void initRational (int num, int den); // get basic tag properties int getID () const diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 718402ca1..dbb3b2946 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -25,8 +25,9 @@ CacheImageData::CacheImageData () : md5(""), supported(false), format(FT_Invalid), rankOld(-1), inTrashOld(false), recentlySaved(false), timeValid(false), year(0), month(0), day(0), hour(0), min(0), sec(0), exifValid(false), frameCount(1), - fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (false), isPixelShift (false), - sampleFormat(rtengine::IIOSF_UNKNOWN), redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) + fnumber(0.0), shutter(0.0), focalLen(0.0), focalLen35mm(0.0), focusDist(0.f), iso(0), isHDR (false), + isPixelShift (false), sensortype(rtengine::ST_NONE), sampleFormat(rtengine::IIOSF_UNKNOWN), + redAWBMul(-1.0), greenAWBMul(-1.0), blueAWBMul(-1.0), rotate(0), thumbImgType(0) { } @@ -180,6 +181,9 @@ int CacheImageData::load (const Glib::ustring& fname) if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) { thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType"); } + if (keyFile.has_key ("ExtraRawInfo", "SensorType")) { + sensortype = keyFile.get_integer ("ExtraRawInfo", "SensorType"); + } } else { rotate = 0; thumbImgType = 0; @@ -263,6 +267,7 @@ int CacheImageData::save (const Glib::ustring& fname) if (format == FT_Raw) { keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType); + keyFile.set_integer ("ExtraRawInfo", "SensorType", sensortype); } keyData = keyFile.to_data (); diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index bb42ada9e..52675d77b 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -56,6 +56,7 @@ public: unsigned iso; bool isHDR; bool isPixelShift; + int sensortype; rtengine::IIO_Sample_Format sampleFormat; Glib::ustring lens; Glib::ustring camMake; @@ -91,6 +92,7 @@ public: bool hasExif (unsigned int frame = 0) const { return false; } rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const { return nullptr; } rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const { return nullptr; } + rtexif::TagDirectory* getBestExifData (rtengine::ImageSource *imgSource, rtengine::procparams::RAWParams *rawParams) const { return nullptr; } bool hasIPTC (unsigned int frame = 0) const { return false; } rtengine::procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const { return rtengine::procparams::IPTCPairs(); } tm getDateTime (unsigned int frame = 0) const { return tm{}; } diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 52adf1da4..f5c6aa679 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -1143,7 +1143,16 @@ void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, r // if (ev!=EvPhotoLoaded) // saveLabel->set_markup (Glib::ustring("") + M("MAIN_BUTTON_SAVE") + ""); - selectedFrame = params->raw.bayersensor.imageNum; + rtengine::eSensorType sensorType = isrc->getImageSource()->getSensorType(); + + selectedFrame = 0; + if (sensorType == rtengine::ST_BAYER) { + selectedFrame = params->raw.bayersensor.imageNum; + //} else if (sensorType == rtengine::ST_FUJI_XTRANS) { + // selectedFrame = params->raw.xtranssensor.imageNum; + } + selectedFrame = rtengine::LIM(selectedFrame, 0, isrc->getImageSource()->getMetaData()->getFrameCount() - 1); + info_toggled(); } diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 4864a2625..de02be130 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -132,16 +132,18 @@ void Thumbnail::_generateThumbnailImage () bool quick = false; rtengine::RawMetaDataLocation ri; + rtengine::eSensorType sensorType = rtengine::ST_NONE; if ( initial_ && options.internalThumbIfUntouched) { quick = true; - tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, tw, th, 1, TRUE); + tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, tw, th, 1, TRUE); } if ( tpp == nullptr ) { quick = false; - tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, tw, th, 1, pparams.wb.equal, TRUE, pparams.raw.bayersensor.imageNum); + tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, tw, th, 1, pparams.wb.equal, TRUE, pparams.raw.bayersensor.imageNum); } + cfs.sensortype = sensorType; if (tpp) { cfs.format = FT_Raw; cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL; @@ -614,7 +616,7 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro } else { // Full thumbnail: apply profile // image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); - image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, &cfs, scale ); + image = tpp->processImage (pparams, static_cast(cfs.sensortype), h, rtengine::TI_Bilinear, &cfs, scale ); } tpp->getDimensions(lastW, lastH, lastScale); @@ -640,7 +642,7 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro } // rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale ); - rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, &cfs, scale ); + rtengine::IImage8* image = tpp->processImage (pparams, static_cast(cfs.sensortype), h, rtengine::TI_Bilinear, &cfs, scale ); tpp->getDimensions(lastW, lastH, lastScale); delete tpp; From 2ef064f7d40fc0d9ced4afbb796607f2fdc63b19 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Sat, 7 Oct 2017 00:43:45 +0200 Subject: [PATCH 15/27] Various bugfix (see #4008) : 1. RT could crash in some circumstances with single frame image 2. UNICODE UserComment now done when already existing in raw file 3. When editing UserComment in the ExifPanel, the Value filed is now filled with the current value --- rtengine/imagedata.cc | 4 ++-- rtexif/rtexif.cc | 20 +++++++++++++++++++- rtexif/rtexif.h | 7 ++++--- rtgui/exifpanel.cc | 7 ++++--- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index d88c853df..abf5b6ae5 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -803,11 +803,11 @@ rtexif::TagDirectory* FramesData::getBestExifData (ImageSource *imgSource, procp eSensorType sensorType = imgSource->getSensorType(); unsigned int imgNum = 0; if (sensorType == ST_BAYER) { - imgNum = rtengine::LIM(rawParams->bayersensor.imageNum, 1, frames.size()); + imgNum = rtengine::LIM(rawParams->bayersensor.imageNum, 0, frames.size() - 1); /* // might exist someday ? } else if (sensorType == ST_FUJI_XTRANS) { - imgNum = rtengine::LIM(rawParams->xtranssensor.imageNum, 1, frames.size()); + imgNum = rtengine::LIM(rawParams->xtranssensor.imageNum, 0, frames.size() - 1); } else if (sensorType == ST_NONE && !imgSource->isRAW()) { // standard image multiframe support should come here (when implemented in GUI) */ diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc index 8a5ee8ae2..bc0e2002f 100644 --- a/rtexif/rtexif.cc +++ b/rtexif/rtexif.cc @@ -730,7 +730,12 @@ void TagDirectory::applyChange (std::string name, Glib::ustring value) } else if (value == "#delete" && t) { t->setKeep (false); } else if (t && !t->isDirectory()) { - t->valueFromString (value); + if (name == "UserComment") { + // UserComment can be Unicode + t->userCommentFromString (value); + } else { + t->valueFromString (value); + } } else { const TagAttrib* attrib = nullptr; @@ -1752,6 +1757,19 @@ void Tag::valueFromString (const std::string& value) } } +void Tag::userCommentFromString (const Glib::ustring& text) +{ + + if (!allocOwnMemory) { + return; + } + if (value) { + delete [] value; + value = nullptr; + } + initUserComment(text); +} + int Tag::calculateSize () { int size = 0; diff --git a/rtexif/rtexif.h b/rtexif/rtexif.h index 887ea2b46..125d38c94 100644 --- a/rtexif/rtexif.h +++ b/rtexif/rtexif.h @@ -290,9 +290,10 @@ public: // additional getter/setter for more comfortable use - std::string valueToString (); - std::string nameToString (int i = 0); - void valueFromString (const std::string& value); + std::string valueToString (); + std::string nameToString (int i = 0); + void valueFromString (const std::string& value); + void userCommentFromString (const Glib::ustring& text); // functions for writing int calculateSize (); diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 0e7875815..2e47786e5 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -284,11 +284,12 @@ void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children continue; } - if (t->isDirectory()) + if (t->isDirectory()) { for (int j = 0; t->getDirectory (j); j++) { Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M ("EXIFPANEL_SUBDIRECTORY"), currAttrib ? currAttrib->action : AC_DONTWRITE, currAttrib && currAttrib->editable); addDirectory (t->getDirectory (j), ch); - } else { + } + } else { addTag (root, t->nameToString (), t->valueToString (), currAttrib ? (t->getOwnMemory() ? currAttrib->action : AC_SYSTEM) : AC_DONTWRITE, currAttrib && currAttrib->editable); } } @@ -631,11 +632,11 @@ Glib::ustring ExifPanel::getSelection (bool onlyeditable) while (iter) { if (first) { ret = iter->get_value (exifColumns.field_nopango); + editable = iter->get_value (exifColumns.editable); } else { ret = iter->get_value (exifColumns.field_nopango) + "." + ret; } - editable = iter->get_value (exifColumns.editable); iter = iter->parent (); first = false; } From bfc8f2891ad1c206fe8b00fa82d069bbd02272d9 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Mon, 9 Oct 2017 23:31:23 +0200 Subject: [PATCH 16/27] Updated language file (#4008) --- rtdata/languages/Francais | 13 ++++++++++--- rtdata/languages/default | 9 ++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 677b29177..905d2a40d 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -111,7 +111,10 @@ FILEBROWSER_BROWSEPATHHINT;Saisissez le chemin à parcourir\nCtrl-O pour FILEBROWSER_CACHE;Cache FILEBROWSER_CACHECLEARFROMFULL;Supprimer du cache (complet) FILEBROWSER_CACHECLEARFROMPARTIAL;Supprimer du cache (partiel) -FILEBROWSER_CLEARPROFILE;Remettre le profil à zéro +FILEBROWSER_CLEARALL;Supprimer tout +FILEBROWSER_CLEAREXIF;Supprimer les modifications de données EXIF +FILEBROWSER_CLEARIPTC;Supprimer les données IPTC +FILEBROWSER_CLEARPARAMS;Supprimer les paramètres de traitement d'image FILEBROWSER_COLORLABEL_TOOLTIP;Label couleur\n\nUtilisez le menu déroulant ou le raccourci clavier:\nShift-Ctrl-0 Pas de couleur\nShift-Ctrl-1 Rouge\nShift-Ctrl-2 Jaune\nShift-Ctrl-3 Vert\nShift-Ctrl-4 Bleu\nShift-Ctrl-5 Pourpre FILEBROWSER_COPYPROFILE;Copier le profil FILEBROWSER_CURRENT_NAME;Nom courant: @@ -808,6 +811,7 @@ MAIN_TOOLTIP_BACKCOLOR0;Couleur de fond de l'aperçu: Selon le thème\nRa MAIN_TOOLTIP_BACKCOLOR1;Couleur de fond de l'aperçu: Noir\nRaccourci : 9 MAIN_TOOLTIP_BACKCOLOR2;Couleur de fond de l'aperçu: Blanc\nRaccourci: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Vérouille / déverouille la vue Avant\n\nVérouille: garde la vue Avant inchangée - \nutile pour évaluer l'effet cumulatif de plusieurs outils.\nDe plus, une comparaison peut être faite à partir de n'importe quelle étape de l'historique\n\nDéverouille: la vue Avant représentera l'étape précédant la vue Après, montrant l'effet qui vient d'être modifié +MAIN_TOOLTIP_DELETEPROFILE;Supprime le fichier de paramètre accolé à l'image et/ou dans le cache MAIN_TOOLTIP_HIDEHP;Montrer/cacher le panneau gauche (incluant l'historique)\nRaccourci: l MAIN_TOOLTIP_INDCLIPPEDH;Indication hautes lumières hors domaine\nRaccourci: < MAIN_TOOLTIP_INDCLIPPEDS;Indication ombres hors domaine\nRaccourci: > @@ -817,6 +821,7 @@ MAIN_TOOLTIP_PREVIEWG;Affichage du canal Vert\nRaccourci: g MAIN_TOOLTIP_PREVIEWL;Affichage de la Luminosité\nRaccourci: v\n\n0.299*R + 0.587*V + 0.114*B MAIN_TOOLTIP_PREVIEWR;Affichage du canal Rouge\nRaccourci: r MAIN_TOOLTIP_QINFO;Informations rapide sur l'image\nRaccourci: i +MAIN_TOOLTIP_SAVEPROFILE;Enregistrer silencieusement les paramètres de développement courants. N'enregistre pas l'Historique ni les Captures.\nVoir également l'option de sauvegarde automatique à la fermeture dans les Préférences.\nRaccourci: Ctrl+Shift+s MAIN_TOOLTIP_SHOWHIDELP1;Montrer/Cacher le panneau gauche\nRaccourci: l MAIN_TOOLTIP_SHOWHIDERP1;Afficher/Cacher le panneau droit\nRaccourci: Alt-l MAIN_TOOLTIP_SHOWHIDETP1;Afficher/Cacher le panneau supérieur\nRaccourci: Shift-L @@ -1065,9 +1070,11 @@ PREFERENCES_PROFILELOADPR;Priorité de chargement des profils PREFERENCES_PROFILEPRCACHE;Profil dans le Cache PREFERENCES_PROFILEPRFILE;Profil accolé au fichier d'entrée PREFERENCES_PROFILESAVEBOTH;Save processing profile both to the cache and next to the input file -PREFERENCES_PROFILESAVECACHE;Enregistrer la paramètres de traitement dans le Cache -PREFERENCES_PROFILESAVEINPUT;Enregistrer la paramètres de traitement accolé au fichier d'entrée +PREFERENCES_PROFILESAVECACHE;Enregistrer les paramètres de traitement dans le Cache +PREFERENCES_PROFILESAVEINPUT;Enregistrer les paramètres de traitement accolé au fichier d'entrée PREFERENCES_PROFILESAVELOCATION;Processing profile saving location +PREFERENCES_PROFILESAVEONEXIT;Enregistrer le profile lors de la fermeture de l'Éditeur\nou lors du passage à une autre image +PREFERENCES_PROFILESAVEUNMODIFIED;Enregistrer le profil même si non modifié dans l'Éditeur PREFERENCES_PROFILE_NONE;Aucun PREFERENCES_PROPERTY;Propriété PREFERENCES_PRTINTENT;Intention de rendu diff --git a/rtdata/languages/default b/rtdata/languages/default index 0dd58424a..db56ba8a6 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -114,7 +114,10 @@ FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\n< FILEBROWSER_CACHE;Cache FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial -FILEBROWSER_CLEARPROFILE;Clear +FILEBROWSER_CLEARALL;Clear all +FILEBROWSER_CLEAREXIF;Clear EXIF modifications +FILEBROWSER_CLEARIPTC;Clear IPTC data +FILEBROWSER_CLEARPARAMS;Clear processing parameters FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple FILEBROWSER_COPYPROFILE;Copy FILEBROWSER_CURRENT_NAME;Current name: @@ -829,6 +832,7 @@ MAIN_TOOLTIP_BACKCOLOR1;Background color of the preview: Black\nShortcut: MAIN_TOOLTIP_BACKCOLOR2;Background color of the preview: White\nShortcut: 9 MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: Middle grey\nShortcut: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool. +MAIN_TOOLTIP_DELETEPROFILE;Delete the side-car and/or cached processing parameter file MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > @@ -838,6 +842,7 @@ MAIN_TOOLTIP_PREVIEWG;Preview the Green channel.\nShortcut: g MAIN_TOOLTIP_PREVIEWL;Preview the Luminosity.\nShortcut: v\n\n0.299*R + 0.587*G + 0.114*B MAIN_TOOLTIP_PREVIEWR;Preview the Red channel.\nShortcut: r MAIN_TOOLTIP_QINFO;Quick info on the image.\nShortcut: i +MAIN_TOOLTIP_SAVEPROFILE;Silently save the current processing parameters. Does not save the History nor the Snapshots\nSee also the automatic save on closing in the Preferences\nShortcut: Ctrl+Shift+s MAIN_TOOLTIP_SHOWHIDELP1;Show/Hide the left panel.\nShortcut: l MAIN_TOOLTIP_SHOWHIDERP1;Show/Hide the right panel.\nShortcut: Alt-l MAIN_TOOLTIP_SHOWHIDETP1;Show/Hide the top panel.\nShortcut: Shift-l @@ -1093,6 +1098,8 @@ PREFERENCES_PROFILESAVEBOTH;Save processing profile both to the cache and next t PREFERENCES_PROFILESAVECACHE;Save processing profile to the cache PREFERENCES_PROFILESAVEINPUT;Save processing profile next to the input file PREFERENCES_PROFILESAVELOCATION;Processing profile saving location +PREFERENCES_PROFILESAVEONEXIT;Save profile the closing the editor or switching to another image +PREFERENCES_PROFILESAVEUNMODIFIED;Save profile even if leaved untouched in the Editor PREFERENCES_PROFILE_NONE;None PREFERENCES_PROPERTY;Property PREFERENCES_PRTINTENT;Rendering intent From 2b3dfb3f3cf1529a20ecc9df7cbc130fd94bdad4 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Thu, 12 Oct 2017 22:29:42 +0200 Subject: [PATCH 17/27] Added comment to executable_loader.in --- tools/osx/executable_loader.in | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/osx/executable_loader.in b/tools/osx/executable_loader.in index b6025fe59..dcc0cabc4 100644 --- a/tools/osx/executable_loader.in +++ b/tools/osx/executable_loader.in @@ -48,6 +48,7 @@ esac #fi #ln -sf "${app}" /tmp +# Prevent crash when directory name contains special characters AppleLocale=`defaults read -g AppleLocale` export LANG=${AppleLocale%@*}.UTF-8 From fd0d50fe0d4005d2a6afa8afa786c71c9b25445d Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 13 Oct 2017 20:53:15 +0200 Subject: [PATCH 18/27] Use std::string instead of Glib::ustring for the map-key in rtimage.cc, #4140 --- rtgui/rtimage.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/rtimage.cc b/rtgui/rtimage.cc index 16e8e3286..b24158b00 100644 --- a/rtgui/rtimage.cc +++ b/rtgui/rtimage.cc @@ -28,7 +28,7 @@ namespace { -std::map> pixbufCache; +std::map> pixbufCache; } From b6bf4aba05246c1d81d930d734843ec63c671da0 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 13 Oct 2017 20:54:03 +0200 Subject: [PATCH 19/27] Don't create Metadata panel for batch editor, #4140 --- rtgui/batchtoolpanelcoord.cc | 19 +-------- rtgui/toolpanelcoord.cc | 82 +++++++++++------------------------- rtgui/toolpanelcoord.h | 2 +- 3 files changed, 26 insertions(+), 77 deletions(-) diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index be092fbfb..e7672e4c7 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -25,31 +25,14 @@ using namespace rtengine::procparams; -BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), somethingChanged(false), parent(parent) +BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(true), somethingChanged(false), parent(parent) { blockedUpdate = false; - // remove exif panel and iptc panel - std::vector::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel); - - if (epi != toolPanels.end()) { - toolPanels.erase (epi); - } - - std::vector::iterator ipi = std::find (toolPanels.begin(), toolPanels.end(), iptcpanel); - - if (ipi != toolPanels.end()) { - toolPanels.erase (ipi); - } - if (toolBar) { toolBar->setBatchMode (); } - toolPanelNotebook->remove_page (*metadataPanel); - metadataPanel = nullptr; - toiM = nullptr; - for (size_t i = 0; i < toolPanels.size(); i++) { toolPanels[i]->setBatchMode (true); } diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index ad0bd09bc..2032fa6e2 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -28,7 +28,7 @@ using namespace rtengine::procparams; -ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false), editDataProvider (nullptr) +ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), hasChanged (false), editDataProvider (nullptr) { exposurePanel = Gtk::manage (new ToolVBox ()); @@ -70,8 +70,10 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false prsharpening = Gtk::manage (new PrSharpening()); crop = Gtk::manage (new Crop ()); icm = Gtk::manage (new ICMPanel ()); - exifpanel = Gtk::manage (new ExifPanel ()); - iptcpanel = Gtk::manage (new IPTCPanel ()); + if(!batch) { + exifpanel = Gtk::manage (new ExifPanel ()); + iptcpanel = Gtk::manage (new IPTCPanel ()); + } wavelet = Gtk::manage (new Wavelet ()); dirpyrequalizer = Gtk::manage (new DirPyrEqualizer ()); hsvequalizer = Gtk::manage (new HSVEqualizer ()); @@ -99,111 +101,68 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false // Medium -> High ISO addPanel (colorPanel, whitebalance); - toolPanels.push_back (whitebalance); addPanel (exposurePanel, toneCurve); - toolPanels.push_back (toneCurve); addPanel (colorPanel, vibrance); - toolPanels.push_back (vibrance); addPanel (colorPanel, chmixer); - toolPanels.push_back (chmixer); // << TODO: Add "Enabled" addPanel (colorPanel, blackwhite); - toolPanels.push_back (blackwhite); addPanel (exposurePanel, shadowshighlights); - toolPanels.push_back (shadowshighlights); addPanel (detailsPanel, sharpening); - toolPanels.push_back (sharpening); addPanel (detailsPanel, sharpenEdge); - toolPanels.push_back (sharpenEdge); addPanel (detailsPanel, sharpenMicro); - toolPanels.push_back (sharpenMicro); addPanel (colorPanel, hsvequalizer); - toolPanels.push_back (hsvequalizer); // << TODO: Add "Enabled" addPanel (colorPanel, filmSimulation); - toolPanels.push_back (filmSimulation); addPanel (colorPanel, rgbcurves); - toolPanels.push_back (rgbcurves); // << TODO: Add "Enabled" addPanel (colorPanel, colortoning); - toolPanels.push_back (colortoning); addPanel (exposurePanel, epd); - toolPanels.push_back (epd); addPanel (exposurePanel, retinex); - toolPanels.push_back (retinex); addPanel (exposurePanel, pcvignette); - toolPanels.push_back (pcvignette); addPanel (exposurePanel, gradient); - toolPanels.push_back (gradient); addPanel (exposurePanel, lcurve); - toolPanels.push_back (lcurve); // << TODO: Add "Enabled" ??? addPanel (exposurePanel, colorappearance); - toolPanels.push_back (colorappearance); addPanel (detailsPanel, impulsedenoise); - toolPanels.push_back (impulsedenoise); addPanel (detailsPanel, dirpyrdenoise); - toolPanels.push_back (dirpyrdenoise); addPanel (detailsPanel, defringe); - toolPanels.push_back (defringe); addPanel (detailsPanel, dirpyrequalizer); - toolPanels.push_back (dirpyrequalizer); addPanel (waveletPanel, wavelet); - toolPanels.push_back (wavelet); addPanel (transformPanel, crop); - toolPanels.push_back (crop); addPanel (transformPanel, resize); - toolPanels.push_back (resize); addPanel (resize->getPackBox(), prsharpening, 2); - toolPanels.push_back (prsharpening); addPanel (transformPanel, lensgeom); - toolPanels.push_back (lensgeom); addPanel (lensgeom->getPackBox(), rotate, 2); - toolPanels.push_back (rotate); addPanel (lensgeom->getPackBox(), perspective, 2); - toolPanels.push_back (perspective); addPanel (lensgeom->getPackBox(), lensProf, 2); - toolPanels.push_back (lensProf); addPanel (lensgeom->getPackBox(), distortion, 2); - toolPanels.push_back (distortion); addPanel (lensgeom->getPackBox(), cacorrection, 2); - toolPanels.push_back (cacorrection); addPanel (lensgeom->getPackBox(), vignetting, 2); - toolPanels.push_back (vignetting); addPanel (colorPanel, icm); - toolPanels.push_back (icm); addPanel (rawPanel, sensorbayer); - toolPanels.push_back (sensorbayer); addPanel (sensorbayer->getPackBox(), bayerprocess, 2); - toolPanels.push_back (bayerprocess); addPanel (sensorbayer->getPackBox(), bayerrawexposure, 2); - toolPanels.push_back (bayerrawexposure); addPanel (sensorbayer->getPackBox(), bayerpreprocess, 2); - toolPanels.push_back (bayerpreprocess); addPanel (sensorbayer->getPackBox(), rawcacorrection, 2); - toolPanels.push_back (rawcacorrection); addPanel (rawPanel, sensorxtrans); - toolPanels.push_back (sensorxtrans); addPanel (sensorxtrans->getPackBox(), xtransprocess, 2); - toolPanels.push_back (xtransprocess); addPanel (sensorxtrans->getPackBox(), xtransrawexposure, 2); - toolPanels.push_back (xtransrawexposure); addPanel (rawPanel, rawexposure); - toolPanels.push_back (rawexposure); addPanel (rawPanel, preprocess); - toolPanels.push_back (preprocess); addPanel (rawPanel, darkframe); - toolPanels.push_back (darkframe); addPanel (rawPanel, flatfield); - toolPanels.push_back (flatfield); toolPanels.push_back (coarse); - toolPanels.push_back (exifpanel); - toolPanels.push_back (iptcpanel); - metadataPanel = Gtk::manage (new Gtk::Notebook ()); - metadataPanel->set_name ("MetaPanelNotebook"); + if(!batch) { + toolPanels.push_back (exifpanel); + toolPanels.push_back (iptcpanel); + metadataPanel = Gtk::manage (new Gtk::Notebook ()); + metadataPanel->set_name ("MetaPanelNotebook"); + metadataPanel->append_page (*exifpanel, M ("MAIN_TAB_EXIF")); + metadataPanel->append_page (*iptcpanel, M ("MAIN_TAB_IPTC")); + } else { + metadataPanel = nullptr; + } toolPanelNotebook = new Gtk::Notebook (); toolPanelNotebook->set_name ("ToolPanelNotebook"); - metadataPanel->append_page (*exifpanel, M ("MAIN_TAB_EXIF")); - metadataPanel->append_page (*iptcpanel, M ("MAIN_TAB_IPTC")); exposurePanelSW = Gtk::manage (new MyScrolledWindow ()); detailsPanelSW = Gtk::manage (new MyScrolledWindow ()); @@ -256,7 +215,11 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false toiW = Gtk::manage (new TextOrIcon ("wavelet.png", M ("MAIN_TAB_WAVELET"), M ("MAIN_TAB_WAVELET_TOOLTIP"), type)); toiT = Gtk::manage (new TextOrIcon ("transform.png", M ("MAIN_TAB_TRANSFORM"), M ("MAIN_TAB_TRANSFORM_TOOLTIP"), type)); toiR = Gtk::manage (new TextOrIcon ("raw.png", M ("MAIN_TAB_RAW"), M ("MAIN_TAB_RAW_TOOLTIP"), type)); - toiM = Gtk::manage (new TextOrIcon ("meta.png", M ("MAIN_TAB_METADATA"), M ("MAIN_TAB_METADATA_TOOLTIP"), type)); + if(!batch) { + toiM = Gtk::manage (new TextOrIcon ("meta.png", M ("MAIN_TAB_METADATA"), M ("MAIN_TAB_METADATA_TOOLTIP"), type)); + } else { + toiM = nullptr; + } toolPanelNotebook->append_page (*exposurePanelSW, *toiE); toolPanelNotebook->append_page (*detailsPanelSW, *toiD); @@ -264,7 +227,9 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false toolPanelNotebook->append_page (*waveletPanelSW, *toiW); toolPanelNotebook->append_page (*transformPanelSW, *toiT); toolPanelNotebook->append_page (*rawPanelSW, *toiR); - toolPanelNotebook->append_page (*metadataPanel, *toiM); + if(!batch) { + toolPanelNotebook->append_page (*metadataPanel, *toiM); + } toolPanelNotebook->set_current_page (0); @@ -297,6 +262,7 @@ void ToolPanelCoordinator::addPanel (Gtk::Box* where, FoldableToolPanel* panel, expList.push_back (panel->getExpander()); where->pack_start (*panel->getExpander(), false, false); + toolPanels.push_back (panel); } ToolPanelCoordinator::~ToolPanelCoordinator () diff --git a/rtgui/toolpanelcoord.h b/rtgui/toolpanelcoord.h index 5a71ef692..155679687 100644 --- a/rtgui/toolpanelcoord.h +++ b/rtgui/toolpanelcoord.h @@ -198,7 +198,7 @@ public: CoarsePanel* coarse; Gtk::Notebook* toolPanelNotebook; - ToolPanelCoordinator (); + ToolPanelCoordinator (bool batch = false); virtual ~ToolPanelCoordinator (); bool getChangedState () From 93f6bf89b94ef8bad093458bc3f701821522e9d4 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 13 Oct 2017 20:59:49 +0200 Subject: [PATCH 20/27] Multithreaded init phase, #4140 --- rtengine/init.cc | 61 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/rtengine/init.cc b/rtengine/init.cc index 41f599b01..6c1f4b98a 100644 --- a/rtengine/init.cc +++ b/rtengine/init.cc @@ -42,24 +42,65 @@ MyMutex* lcmsMutex = nullptr; int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDir, bool loadAll) { settings = s; - ProfileStore::getInstance()->init (loadAll); - ICCStore::getInstance()->init (s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); - DCPStore::getInstance()->init (Glib::build_filename (baseDir, "dcpprofiles"), loadAll); + ProcParams::init(); + PerceptualToneCurve::init(); + RawImageSource::init(); - CameraConstantsStore::getInstance ()->init (baseDir, userSettingsDir); - ProcParams::init (); - Color::init (); - PerceptualToneCurve::init (); - RawImageSource::init (); +#ifdef _OPENMP +#pragma omp parallel sections +#endif +{ +#ifdef _OPENMP +#pragma omp section +#endif +{ if (s->lensfunDbDirectory.empty() || Glib::path_is_absolute(s->lensfunDbDirectory)) { LFDatabase::init(s->lensfunDbDirectory); } else { LFDatabase::init(Glib::build_filename(baseDir, s->lensfunDbDirectory)); } +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + ProfileStore::getInstance()->init(loadAll); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + ICCStore::getInstance()->init(s->iccDirectory, Glib::build_filename (baseDir, "iccprofiles"), loadAll); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + DCPStore::getInstance()->init(Glib::build_filename (baseDir, "dcpprofiles"), loadAll); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + CameraConstantsStore::getInstance()->init(baseDir, userSettingsDir); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + dfm.init(s->darkFramesPath); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + ffm.init(s->flatFieldsPath); +} +} + + Color::init (); delete lcmsMutex; lcmsMutex = new MyMutex; - dfm.init( s->darkFramesPath ); - ffm.init( s->flatFieldsPath ); return 0; } From 77b357605981392ce5b68b561c4be744f8e89eb8 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 13 Oct 2017 21:05:37 +0200 Subject: [PATCH 21/27] dual-threaded fill of lensfun treestores, #4140 --- rtgui/lensprofile.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 0c3b227aa..899ef289e 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -582,13 +582,27 @@ bool LensProfilePanel::checkLensfunCanCorrect(bool automatch) //----------------------------------------------------------------------------- LensProfilePanel::LFDbHelper::LFDbHelper() +{ +#ifdef _OPENMP +#pragma omp parallel sections +#endif +{ +#ifdef _OPENMP +#pragma omp section +#endif { lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam); - lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); - fillLensfunCameras(); +} +#ifdef _OPENMP +#pragma omp section +#endif +{ + lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens); fillLensfunLenses(); } +} +} void LensProfilePanel::LFDbHelper::fillLensfunCameras() { From 5a0e4de6078efec8171b8154f95e1574c813126d Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 13 Oct 2017 21:23:21 +0200 Subject: [PATCH 22/27] When no lcp is selected, rt does not show (none), fixes #4143 --- rtgui/lensprofile.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtgui/lensprofile.cc b/rtgui/lensprofile.cc index 899ef289e..8da352834 100644 --- a/rtgui/lensprofile.cc +++ b/rtgui/lensprofile.cc @@ -177,7 +177,7 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa if (pp->lensProf.lcpFile.empty()) { Glib::ustring lastFolder = fcbLCPFile->get_current_folder(); fcbLCPFile->set_current_folder(lastFolder); - fcbLCPFile->set_filename(lastFolder + "/."); + fcbLCPFile->unselect_all(); bindCurrentFolder(*fcbLCPFile, options.lastLensProfileDir); updateDisabled(false); } else if (LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) { From e6f57b1978cc59337121e737ddf51acb697fd641 Mon Sep 17 00:00:00 2001 From: heckflosse Date: Fri, 13 Oct 2017 21:34:55 +0200 Subject: [PATCH 23/27] Use std::string instead of Glib::ustring for key of map in camconst, #4140 --- rtengine/camconst.cc | 4 ++-- rtengine/camconst.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtengine/camconst.cc b/rtengine/camconst.cc index 6b4a36c4b..469d18571 100644 --- a/rtengine/camconst.cc +++ b/rtengine/camconst.cc @@ -184,7 +184,7 @@ CameraConst::parseEntry(void *cJSON_, const char *make_model) js = (cJSON *)cJSON_; CameraConst *cc = new CameraConst; - cc->make_model = Glib::ustring(make_model); + cc->make_model = make_model; ji = cJSON_GetObjectItem(js, "dcraw_matrix"); @@ -739,7 +739,7 @@ CameraConstantsStore::get(const char make[], const char model[]) key += " "; key += model; key = key.uppercase(); - std::map::iterator it; + std::map::iterator it; it = mCameraConstants.find(key); if (it == mCameraConstants.end()) { diff --git a/rtengine/camconst.h b/rtengine/camconst.h index 31b65f3e8..47c8d8bee 100644 --- a/rtengine/camconst.h +++ b/rtengine/camconst.h @@ -17,7 +17,7 @@ struct camera_const_levels { class CameraConst { private: - Glib::ustring make_model; + std::string make_model; short dcraw_matrix[12]; int raw_crop[4]; int raw_mask[8][4]; @@ -48,7 +48,7 @@ public: class CameraConstantsStore { private: - std::map mCameraConstants; + std::map mCameraConstants; CameraConstantsStore(); bool parse_camera_constants_file(Glib::ustring filename); From d749c44a5ef0d3cef2c033514e3f27a8d7186633 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Fri, 13 Oct 2017 22:50:32 +0200 Subject: [PATCH 24/27] Revert "Updated language file (#4008)" This reverts commit bfc8f2891ad1c206fe8b00fa82d069bbd02272d9. --- rtdata/languages/Francais | 13 +++---------- rtdata/languages/default | 9 +-------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais index 905d2a40d..677b29177 100644 --- a/rtdata/languages/Francais +++ b/rtdata/languages/Francais @@ -111,10 +111,7 @@ FILEBROWSER_BROWSEPATHHINT;Saisissez le chemin à parcourir\nCtrl-O pour FILEBROWSER_CACHE;Cache FILEBROWSER_CACHECLEARFROMFULL;Supprimer du cache (complet) FILEBROWSER_CACHECLEARFROMPARTIAL;Supprimer du cache (partiel) -FILEBROWSER_CLEARALL;Supprimer tout -FILEBROWSER_CLEAREXIF;Supprimer les modifications de données EXIF -FILEBROWSER_CLEARIPTC;Supprimer les données IPTC -FILEBROWSER_CLEARPARAMS;Supprimer les paramètres de traitement d'image +FILEBROWSER_CLEARPROFILE;Remettre le profil à zéro FILEBROWSER_COLORLABEL_TOOLTIP;Label couleur\n\nUtilisez le menu déroulant ou le raccourci clavier:\nShift-Ctrl-0 Pas de couleur\nShift-Ctrl-1 Rouge\nShift-Ctrl-2 Jaune\nShift-Ctrl-3 Vert\nShift-Ctrl-4 Bleu\nShift-Ctrl-5 Pourpre FILEBROWSER_COPYPROFILE;Copier le profil FILEBROWSER_CURRENT_NAME;Nom courant: @@ -811,7 +808,6 @@ MAIN_TOOLTIP_BACKCOLOR0;Couleur de fond de l'aperçu: Selon le thème\nRa MAIN_TOOLTIP_BACKCOLOR1;Couleur de fond de l'aperçu: Noir\nRaccourci : 9 MAIN_TOOLTIP_BACKCOLOR2;Couleur de fond de l'aperçu: Blanc\nRaccourci: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Vérouille / déverouille la vue Avant\n\nVérouille: garde la vue Avant inchangée - \nutile pour évaluer l'effet cumulatif de plusieurs outils.\nDe plus, une comparaison peut être faite à partir de n'importe quelle étape de l'historique\n\nDéverouille: la vue Avant représentera l'étape précédant la vue Après, montrant l'effet qui vient d'être modifié -MAIN_TOOLTIP_DELETEPROFILE;Supprime le fichier de paramètre accolé à l'image et/ou dans le cache MAIN_TOOLTIP_HIDEHP;Montrer/cacher le panneau gauche (incluant l'historique)\nRaccourci: l MAIN_TOOLTIP_INDCLIPPEDH;Indication hautes lumières hors domaine\nRaccourci: < MAIN_TOOLTIP_INDCLIPPEDS;Indication ombres hors domaine\nRaccourci: > @@ -821,7 +817,6 @@ MAIN_TOOLTIP_PREVIEWG;Affichage du canal Vert\nRaccourci: g MAIN_TOOLTIP_PREVIEWL;Affichage de la Luminosité\nRaccourci: v\n\n0.299*R + 0.587*V + 0.114*B MAIN_TOOLTIP_PREVIEWR;Affichage du canal Rouge\nRaccourci: r MAIN_TOOLTIP_QINFO;Informations rapide sur l'image\nRaccourci: i -MAIN_TOOLTIP_SAVEPROFILE;Enregistrer silencieusement les paramètres de développement courants. N'enregistre pas l'Historique ni les Captures.\nVoir également l'option de sauvegarde automatique à la fermeture dans les Préférences.\nRaccourci: Ctrl+Shift+s MAIN_TOOLTIP_SHOWHIDELP1;Montrer/Cacher le panneau gauche\nRaccourci: l MAIN_TOOLTIP_SHOWHIDERP1;Afficher/Cacher le panneau droit\nRaccourci: Alt-l MAIN_TOOLTIP_SHOWHIDETP1;Afficher/Cacher le panneau supérieur\nRaccourci: Shift-L @@ -1070,11 +1065,9 @@ PREFERENCES_PROFILELOADPR;Priorité de chargement des profils PREFERENCES_PROFILEPRCACHE;Profil dans le Cache PREFERENCES_PROFILEPRFILE;Profil accolé au fichier d'entrée PREFERENCES_PROFILESAVEBOTH;Save processing profile both to the cache and next to the input file -PREFERENCES_PROFILESAVECACHE;Enregistrer les paramètres de traitement dans le Cache -PREFERENCES_PROFILESAVEINPUT;Enregistrer les paramètres de traitement accolé au fichier d'entrée +PREFERENCES_PROFILESAVECACHE;Enregistrer la paramètres de traitement dans le Cache +PREFERENCES_PROFILESAVEINPUT;Enregistrer la paramètres de traitement accolé au fichier d'entrée PREFERENCES_PROFILESAVELOCATION;Processing profile saving location -PREFERENCES_PROFILESAVEONEXIT;Enregistrer le profile lors de la fermeture de l'Éditeur\nou lors du passage à une autre image -PREFERENCES_PROFILESAVEUNMODIFIED;Enregistrer le profil même si non modifié dans l'Éditeur PREFERENCES_PROFILE_NONE;Aucun PREFERENCES_PROPERTY;Propriété PREFERENCES_PRTINTENT;Intention de rendu diff --git a/rtdata/languages/default b/rtdata/languages/default index db56ba8a6..0dd58424a 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -114,10 +114,7 @@ FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\n\nKeyboard shortcuts:\n< FILEBROWSER_CACHE;Cache FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial -FILEBROWSER_CLEARALL;Clear all -FILEBROWSER_CLEAREXIF;Clear EXIF modifications -FILEBROWSER_CLEARIPTC;Clear IPTC data -FILEBROWSER_CLEARPARAMS;Clear processing parameters +FILEBROWSER_CLEARPROFILE;Clear FILEBROWSER_COLORLABEL_TOOLTIP;Color label.\n\nUse dropdown menu or shortcuts:\nShift-Ctrl-0 No Color\nShift-Ctrl-1 Red\nShift-Ctrl-2 Yellow\nShift-Ctrl-3 Green\nShift-Ctrl-4 Blue\nShift-Ctrl-5 Purple FILEBROWSER_COPYPROFILE;Copy FILEBROWSER_CURRENT_NAME;Current name: @@ -832,7 +829,6 @@ MAIN_TOOLTIP_BACKCOLOR1;Background color of the preview: Black\nShortcut: MAIN_TOOLTIP_BACKCOLOR2;Background color of the preview: White\nShortcut: 9 MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: Middle grey\nShortcut: 9 MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool. -MAIN_TOOLTIP_DELETEPROFILE;Delete the side-car and/or cached processing parameter file MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: < MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: > @@ -842,7 +838,6 @@ MAIN_TOOLTIP_PREVIEWG;Preview the Green channel.\nShortcut: g MAIN_TOOLTIP_PREVIEWL;Preview the Luminosity.\nShortcut: v\n\n0.299*R + 0.587*G + 0.114*B MAIN_TOOLTIP_PREVIEWR;Preview the Red channel.\nShortcut: r MAIN_TOOLTIP_QINFO;Quick info on the image.\nShortcut: i -MAIN_TOOLTIP_SAVEPROFILE;Silently save the current processing parameters. Does not save the History nor the Snapshots\nSee also the automatic save on closing in the Preferences\nShortcut: Ctrl+Shift+s MAIN_TOOLTIP_SHOWHIDELP1;Show/Hide the left panel.\nShortcut: l MAIN_TOOLTIP_SHOWHIDERP1;Show/Hide the right panel.\nShortcut: Alt-l MAIN_TOOLTIP_SHOWHIDETP1;Show/Hide the top panel.\nShortcut: Shift-l @@ -1098,8 +1093,6 @@ PREFERENCES_PROFILESAVEBOTH;Save processing profile both to the cache and next t PREFERENCES_PROFILESAVECACHE;Save processing profile to the cache PREFERENCES_PROFILESAVEINPUT;Save processing profile next to the input file PREFERENCES_PROFILESAVELOCATION;Processing profile saving location -PREFERENCES_PROFILESAVEONEXIT;Save profile the closing the editor or switching to another image -PREFERENCES_PROFILESAVEUNMODIFIED;Save profile even if leaved untouched in the Editor PREFERENCES_PROFILE_NONE;None PREFERENCES_PROPERTY;Property PREFERENCES_PRTINTENT;Rendering intent From 1a046611cff3a9c384520ca553665513bb429354 Mon Sep 17 00:00:00 2001 From: Morgan Hardwood Date: Fri, 13 Oct 2017 22:55:23 +0200 Subject: [PATCH 25/27] generateTranslationDiffs --- rtdata/languages/Catala | 14 ++++++++++++-- rtdata/languages/Chinese (Simplified) | 14 ++++++++++++-- rtdata/languages/Chinese (Traditional) | 14 ++++++++++++-- rtdata/languages/Czech | 10 ++++++++++ rtdata/languages/Dansk | 14 ++++++++++++-- rtdata/languages/Deutsch | 14 ++++++++++++++ rtdata/languages/English (UK) | 14 ++++++++++++-- rtdata/languages/English (US) | 14 ++++++++++++-- rtdata/languages/Espanol | 14 ++++++++++++-- rtdata/languages/Euskara | 14 ++++++++++++-- rtdata/languages/Greek | 14 ++++++++++++-- rtdata/languages/Hebrew | 14 ++++++++++++-- rtdata/languages/Italiano | 14 ++++++++++++-- rtdata/languages/Japanese | 14 ++++++++++++-- rtdata/languages/Latvian | 14 ++++++++++++-- rtdata/languages/Magyar | 14 ++++++++++++-- rtdata/languages/Nederlands | 10 ++++++++++ rtdata/languages/Norsk BM | 14 ++++++++++++-- rtdata/languages/Polish | 14 ++++++++++++-- rtdata/languages/Polish (Latin Characters) | 14 ++++++++++++-- rtdata/languages/Portugues (Brasil) | 14 ++++++++++++-- rtdata/languages/Russian | 14 ++++++++++++-- rtdata/languages/Serbian (Cyrilic Characters) | 14 ++++++++++++-- rtdata/languages/Serbian (Latin Characters) | 14 ++++++++++++-- rtdata/languages/Slovak | 14 ++++++++++++-- rtdata/languages/Suomi | 14 ++++++++++++-- rtdata/languages/Swedish | 10 ++++++++++ rtdata/languages/Turkish | 14 ++++++++++++-- 28 files changed, 332 insertions(+), 48 deletions(-) diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala index d006e1995..1e2127bd1 100644 --- a/rtdata/languages/Catala +++ b/rtdata/languages/Catala @@ -976,6 +976,7 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_BYPASS_RAW_LMMSE_ITERATIONS;Bypass [raw] LMMSE Enhancement Steps @@ -1509,10 +1510,19 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: - !PROFILEPANEL_PINTERNAL;Neutral !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_BWMIX_ALGO;Algorithm OYCPM !TP_BWMIX_ALGO_LI;Linear diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified) index e58875107..6c1e54685 100644 --- a/rtdata/languages/Chinese (Simplified) +++ b/rtdata/languages/Chinese (Simplified) @@ -1042,6 +1042,7 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !CURVEEDITOR_EDITPOINT_HINT;Enable edition of node in/out values.\n\nRight-click on a node to select it.\nRight-click on empty space to de-select the node. !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_RAW_DCB_ENHANCE;Bypass [raw] DCB Enhancement Steps !EXPORT_BYPASS_RAW_DCB_ITERATIONS;Bypass [raw] DCB Iterations @@ -1491,10 +1492,19 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: - !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Chinese (Traditional) b/rtdata/languages/Chinese (Traditional) index 5a330fd13..10e5f974a 100644 --- a/rtdata/languages/Chinese (Traditional) +++ b/rtdata/languages/Chinese (Traditional) @@ -471,6 +471,7 @@ TP_WBALANCE_TEMPERATURE;色溫 !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1294,6 +1295,15 @@ TP_WBALANCE_TEMPERATURE;色溫 !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1304,8 +1314,8 @@ TP_WBALANCE_TEMPERATURE;色溫 !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index a7a743377..898ae93c2 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -2170,6 +2170,7 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !!!!!!!!!!!!!!!!!!!!!!!!! !DONT_SHOW_AGAIN;Don't show this message again. +!EXIFPANEL_SHOWALL;Show all !GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done editing, simply close the main RawTherapee window and the image will be automatically imported in GIMP. !HISTORY_MSG_476;CAM02 - Temp out !HISTORY_MSG_477;CAM02 - Green out @@ -2194,6 +2195,15 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - !PREFERENCES_LANG;Language !PREFERENCES_SAVE_TP_OPEN_NOW;Save tools collapsed/expanded state now !PREFERENCES_THEME;Theme +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_NEUTRAL;Reset !TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values diff --git a/rtdata/languages/Dansk b/rtdata/languages/Dansk index da080ee2b..3c6921967 100644 --- a/rtdata/languages/Dansk +++ b/rtdata/languages/Dansk @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Temperatur !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 60a276a20..aa72b5757 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -2218,3 +2218,17 @@ ZOOMPANEL_ZOOMFITSCREEN;An Bildschirm anpassen\nTaste: f ZOOMPANEL_ZOOMIN;Hineinzoomen\nTaste: + ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: - +!!!!!!!!!!!!!!!!!!!!!!!!! +! Untranslated keys follow; remove the ! prefix after an entry is translated. +!!!!!!!!!!!!!!!!!!!!!!!!! + +!EXIFPANEL_SHOWALL;Show all +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK) index 0ab6aae48..165b3de80 100644 --- a/rtdata/languages/English (UK) +++ b/rtdata/languages/English (UK) @@ -42,7 +42,8 @@ PREFERENCES_NAVGUIDEBRUSH;Navigator guide colour PREFERENCES_PRTPROFILE;Colour profile PREFERENCES_SELECTFONT_COLPICKER;Select Colour Picker's font PREFERENCES_TAB_COLORMGR;Colour Management -SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colours from the output profile. +SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colours from the Printer profile. +SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Colour Management. TOOLBAR_TOOLTIP_COLORPICKER;Lockable Colour Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a colour picker\nDrag it around while pressing the left mouse button\nDelete the colour picker with a right mouse button click\nDelete all colour pickers with Shift + Right mouse button click\nRight click away from any colour picker to go back to the Hand tool TOOLBAR_TOOLTIP_STRAIGHTEN;Straighten / fine rotation.\nShortcut: s\n\nIndicate the vertical or horizontal by drawing a guide line over the image preview. Angle of rotation will be shown next to the guide line. Centre of rotation is the geometrical centre of the image. TP_BWMIX_CC_ENABLED;Adjust complementary colour @@ -176,6 +177,7 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !EXIFPANEL_RESETALL;Reset All !EXIFPANEL_RESETALLHINT;Reset all tags to their original values. !EXIFPANEL_RESETHINT;Reset the selected tags to their original values. +!EXIFPANEL_SHOWALL;Show all !EXIFPANEL_SUBDIRECTORY;Subdirectory !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All @@ -1241,8 +1243,17 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !PROGRESSBAR_SAVETIFF;Saving TIFF file... !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) !QINFO_ISO;ISO !QINFO_NOEXIF;Exif data not available. +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FILEFORMAT;File format !SAVEDLG_FORCEFORMATOPTS;Force saving options @@ -1261,7 +1272,6 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US) index abad71651..25054bd30 100644 --- a/rtdata/languages/English (US) +++ b/rtdata/languages/English (US) @@ -72,6 +72,7 @@ !EXIFPANEL_RESETALL;Reset All !EXIFPANEL_RESETALLHINT;Reset all tags to their original values. !EXIFPANEL_RESETHINT;Reset the selected tags to their original values. +!EXIFPANEL_SHOWALL;Show all !EXIFPANEL_SUBDIRECTORY;Subdirectory !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All @@ -1181,8 +1182,17 @@ !PROGRESSBAR_SAVETIFF;Saving TIFF file... !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) !QINFO_ISO;ISO !QINFO_NOEXIF;Exif data not available. +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FILEFORMAT;File format !SAVEDLG_FORCEFORMATOPTS;Force saving options @@ -1201,8 +1211,8 @@ !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol index 141a36c8b..8a83535b1 100644 --- a/rtdata/languages/Espanol +++ b/rtdata/languages/Espanol @@ -1515,6 +1515,7 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1841,9 +1842,18 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nAtajo: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Euskara b/rtdata/languages/Euskara index 2abf08f8b..dd3e410ed 100644 --- a/rtdata/languages/Euskara +++ b/rtdata/languages/Euskara @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Tenperatura !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Greek b/rtdata/languages/Greek index 631b789d9..f41040577 100644 --- a/rtdata/languages/Greek +++ b/rtdata/languages/Greek @@ -462,6 +462,7 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1291,6 +1292,15 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1301,8 +1311,8 @@ TP_WBALANCE_TEMPERATURE;Θερμοκρασία !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Hebrew b/rtdata/languages/Hebrew index 36eaa57b6..346a39cdc 100644 --- a/rtdata/languages/Hebrew +++ b/rtdata/languages/Hebrew @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;מידת חום !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;מידת חום !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;מידת חום !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano index 2a2a4f761..4101355c0 100644 --- a/rtdata/languages/Italiano +++ b/rtdata/languages/Italiano @@ -1346,6 +1346,7 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1712,9 +1713,18 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese index 7665c03dd..787b5dfe6 100644 --- a/rtdata/languages/Japanese +++ b/rtdata/languages/Japanese @@ -1885,6 +1885,7 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_PIPELINE;Processing pipeline !EXPORT_USE_FAST_PIPELINE;Dedicated (full processing on resized image) @@ -2022,9 +2023,18 @@ ZOOMPANEL_ZOOMOUT;ズームアウト\nショートカット: - !PREFERENCES_THEME;Theme !PREFERENCES_TUNNELMETADATA;Copy Exif/IPTC/XMP unchanged to output file !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Latvian b/rtdata/languages/Latvian index a9565f70c..8dc2dc670 100644 --- a/rtdata/languages/Latvian +++ b/rtdata/languages/Latvian @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Temperatūra !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar index 73ad45af0..d98d6e29c 100644 --- a/rtdata/languages/Magyar +++ b/rtdata/languages/Magyar @@ -891,6 +891,7 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_BYPASS_RAW_LMMSE_ITERATIONS;Bypass [raw] LMMSE Enhancement Steps @@ -1447,6 +1448,15 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling !SAVEDLG_SUBSAMP_1;Best compression @@ -1455,8 +1465,8 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés - !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands index f75a8626e..754ba1573 100644 --- a/rtdata/languages/Nederlands +++ b/rtdata/languages/Nederlands @@ -2140,6 +2140,7 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !!!!!!!!!!!!!!!!!!!!!!!!! !DONT_SHOW_AGAIN;Don't show this message again. +!EXIFPANEL_SHOWALL;Show all !GIMP_PLUGIN_INFO;Welcome to the RawTherapee GIMP plugin!\nOnce you are done editing, simply close the main RawTherapee window and the image will be automatically imported in GIMP. !HISTORY_MSG_441;Retinex - Gain transmission !HISTORY_MSG_475;PS - Equalize channel @@ -2169,6 +2170,15 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: - !PREFERENCES_PROFILESAVELOCATION;Processing profile saving location !PREFERENCES_SAVE_TP_OPEN_NOW;Save tools collapsed/expanded state now !PREFERENCES_THEME;Theme +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_NEUTRAL;Reset !TP_COLORAPP_NEUTRAL_TIP;Reset all sliders checkbox and curves to their default values diff --git a/rtdata/languages/Norsk BM b/rtdata/languages/Norsk BM index 7c12038a7..c270541d8 100644 --- a/rtdata/languages/Norsk BM +++ b/rtdata/languages/Norsk BM @@ -462,6 +462,7 @@ TP_WBALANCE_TEMPERATURE;Temperatur !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1291,6 +1292,15 @@ TP_WBALANCE_TEMPERATURE;Temperatur !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1301,8 +1311,8 @@ TP_WBALANCE_TEMPERATURE;Temperatur !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish index 789a76eeb..7845247dc 100644 --- a/rtdata/languages/Polish +++ b/rtdata/languages/Polish @@ -1473,6 +1473,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1789,9 +1790,18 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Polish (Latin Characters) b/rtdata/languages/Polish (Latin Characters) index a32059598..978fa96cf 100644 --- a/rtdata/languages/Polish (Latin Characters) +++ b/rtdata/languages/Polish (Latin Characters) @@ -1473,6 +1473,7 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1789,9 +1790,18 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrot: - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_CBDL_AFT;After Black-and-White !TP_CBDL_BEF;Before Black-and-White diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil) index b1d6b77d3..102f6ac89 100644 --- a/rtdata/languages/Portugues (Brasil) +++ b/rtdata/languages/Portugues (Brasil) @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Temperatura !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Temperatura !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Temperatura !SAVEDLG_TIFFUNCOMPRESSED;Uncompressed TIFF !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian index 2b09c7c65..908bc03df 100644 --- a/rtdata/languages/Russian +++ b/rtdata/languages/Russian @@ -1284,6 +1284,7 @@ ZOOMPANEL_ZOOMOUT;Удалить - !DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1669,9 +1670,18 @@ ZOOMPANEL_ZOOMOUT;Удалить - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_BWMIX_SET_RGBABS;Absolute RGB !TP_BWMIX_SET_RGBREL;Relative RGB diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters) index ec4c6597d..76c8d8693 100644 --- a/rtdata/languages/Serbian (Cyrilic Characters) +++ b/rtdata/languages/Serbian (Cyrilic Characters) @@ -1306,6 +1306,7 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1700,8 +1701,17 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_BL;Bottom-left !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_BWMIX_FILTER_TOOLTIP;The color filter simulates shots taken with a colored filter placed in front of the lens. Colored filters reduce the transmission of specific color ranges and therefore affect their lightness. E.g. a red filter darkens blue skies. diff --git a/rtdata/languages/Serbian (Latin Characters) b/rtdata/languages/Serbian (Latin Characters) index 5cc7873c5..603526a14 100644 --- a/rtdata/languages/Serbian (Latin Characters) +++ b/rtdata/languages/Serbian (Latin Characters) @@ -1306,6 +1306,7 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !DYNPROFILEEDITOR_PROFILE;Processing Profile !EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool. !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_EQUALIZER;Bypass Wavelet Levels !EXPORT_PIPELINE;Processing pipeline @@ -1700,8 +1701,17 @@ ZOOMPANEL_ZOOMOUT;Umanjuje prikaz slike - !PREFERENCES_WLTWO;Two levels !PREFERENCES_WLZER;No !PROFILEPANEL_PDYNAMIC;Dynamic -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_BL;Bottom-left !TOOLBAR_TOOLTIP_COLORPICKER;Lockable Color Picker\n\nWhen enabled:\nClick in the preview with left mouse button to add a color picker\nDrag it around while pressing the left mouse button\nDelete the color picker with a right mouse button click\nDelete all color pickers with Shift + Right mouse button click\nRight click away from any color picker to go back to the Hand tool !TP_BWMIX_FILTER_TOOLTIP;The color filter simulates shots taken with a colored filter placed in front of the lens. Colored filters reduce the transmission of specific color ranges and therefore affect their lightness. E.g. a red filter darkens blue skies. diff --git a/rtdata/languages/Slovak b/rtdata/languages/Slovak index ee719f656..6bacd9d7e 100644 --- a/rtdata/languages/Slovak +++ b/rtdata/languages/Slovak @@ -543,6 +543,7 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve. !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1333,6 +1334,15 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !PROGRESSBAR_NOIMAGES;No images found !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling !SAVEDLG_SUBSAMP_1;Best compression @@ -1341,8 +1351,8 @@ ZOOMPANEL_ZOOMOUT;Oddialiť - !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Suomi b/rtdata/languages/Suomi index 571a3c084..413144a76 100644 --- a/rtdata/languages/Suomi +++ b/rtdata/languages/Suomi @@ -464,6 +464,7 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1293,6 +1294,15 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1302,8 +1312,8 @@ TP_WBALANCE_TEMPERATURE;Lämpötila [K] !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish index 87e0b81a6..cc459eaa1 100644 --- a/rtdata/languages/Swedish +++ b/rtdata/languages/Swedish @@ -1896,6 +1896,7 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !DYNPROFILEEDITOR_NEW;New !DYNPROFILEEDITOR_NEW_RULE;New Dynamic Profile Rule !DYNPROFILEEDITOR_PROFILE;Processing Profile +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_PIPELINE;Processing pipeline !EXPORT_USE_FAST_PIPELINE;Dedicated (full processing on resized image) @@ -2011,6 +2012,15 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: - !PREFERENCES_TAB_DYNAMICPROFILE;Dynamic Profile Rules !PREFERENCES_THEME;Theme !PROFILEPANEL_PDYNAMIC;Dynamic +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !TP_CBDL_METHOD;Process located !TP_COLORAPP_FREE;Free temp+green + CAT02 + [output] !TP_COLORAPP_NEUTRAL;Reset diff --git a/rtdata/languages/Turkish b/rtdata/languages/Turkish index 1e873db1f..5c98df27d 100644 --- a/rtdata/languages/Turkish +++ b/rtdata/languages/Turkish @@ -463,6 +463,7 @@ TP_WBALANCE_TEMPERATURE;Isı !EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV) !EXIFFILTER_FILETYPE;File type !EXIFFILTER_METADATAFILTER;Enable metadata filters +!EXIFPANEL_SHOWALL;Show all !EXPORT_BYPASS;Processing steps to bypass !EXPORT_BYPASS_ALL;Select / Unselect All !EXPORT_BYPASS_DEFRINGE;Bypass Defringe @@ -1292,6 +1293,15 @@ TP_WBALANCE_TEMPERATURE;Isı !PROGRESSBAR_PROCESSING_PROFILESAVED;Processing profile saved !PROGRESSBAR_SNAPSHOT_ADDED;Snapshot added !PROGRESSDLG_PROFILECHANGEDINBROWSER;Processing profile changed in browser +!QINFO_FRAMECOUNT;%2 frames +!QINFO_HDR;HDR / %2 frame(s) +!QINFO_PIXELSHIFT;PixelShift / %2 frame(s) +!SAMPLEFORMAT_0;Unknown data format +!SAMPLEFORMAT_1;Unsigned 8 bits +!SAMPLEFORMAT_2;Unsigned 16 bits +!SAMPLEFORMAT_4;LogLuv 24 bits +!SAMPLEFORMAT_8;LogLuv 32 bits +!SAMPLEFORMAT_16;32 bits floating point !SAVEDLG_AUTOSUFFIX;Automatically add a suffix if the file already exists !SAVEDLG_FORCEFORMATOPTS;Force saving options !SAVEDLG_SUBSAMP;Subsampling @@ -1301,8 +1311,8 @@ TP_WBALANCE_TEMPERATURE;Isı !SAVEDLG_SUBSAMP_TOOLTIP;Best compression:\nJ:a:b 4:2:0\nh/v 2/2\nChroma halved horizontally and vertically.\n\nBalanced:\nJ:a:b 4:2:2\nh/v 2/1\nChroma halved horizontally.\n\nBest quality:\nJ:a:b 4:4:4\nh/v 1/1\nNo chroma subsampling. !SAVEDLG_WARNFILENAME;File will be named !SHCSELECTOR_TOOLTIP;Click right mouse button to reset the position of those 3 sliders. -!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the output profile. -!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate de rendering generated by the output profile of the ICM tool. Most useful for simulating printing outputs. +!SOFTPROOF_GAMUTCHECK_TOOLTIP;If active, indicates in grey the pixels which have out of gamut colors from the Printer profile. +!SOFTPROOF_TOOLTIP;Soft-proofing\nIf active, let you simulate the printer's output by using the Printer profile set in Preferences > Color Management. !THRESHOLDSELECTOR_B;Bottom !THRESHOLDSELECTOR_BL;Bottom-left !THRESHOLDSELECTOR_BR;Bottom-right From 2956be333bda55bbb5dedc4200730b50d866b914 Mon Sep 17 00:00:00 2001 From: Alberto Griggio Date: Fri, 13 Oct 2017 23:06:52 +0200 Subject: [PATCH 26/27] speed up loading of film simulation cluts by using one shared TreeModel for all the combo boxes --- rtgui/filmsimulation.cc | 119 ++++++++++++++++++++++++++++++++-------- rtgui/filmsimulation.h | 29 ++++++++-- 2 files changed, 118 insertions(+), 30 deletions(-) diff --git a/rtgui/filmsimulation.cc b/rtgui/filmsimulation.cc index 716b686e9..89ab31748 100644 --- a/rtgui/filmsimulation.cc +++ b/rtgui/filmsimulation.cc @@ -62,8 +62,8 @@ bool notifySlowParseDir (const std::chrono::system_clock::time_point& startedAt) FilmSimulation::FilmSimulation() : FoldableToolPanel( this, "filmsimulation", M("TP_FILMSIMULATION_LABEL"), false, true ) { - m_clutComboBox = Gtk::manage( new ClutComboBox() ); - int foundClutsCount = m_clutComboBox->fillFromDir( options.clutsDir ); + m_clutComboBox = Gtk::manage( new ClutComboBox(options.clutsDir) ); + int foundClutsCount = m_clutComboBox->foundClutsCount(); if ( foundClutsCount == 0 ) { pack_start( *Gtk::manage( new Gtk::Label( M("TP_FILMSIMULATION_ZEROCLUTSFOUND") ) ) ); @@ -117,7 +117,7 @@ void FilmSimulation::adjusterChanged( Adjuster* a, double newval ) void FilmSimulation::setBatchMode( bool batchMode ) { ToolPanel::setBatchMode( batchMode ); - m_clutComboBox->addUnchangedEntry(); + m_clutComboBox->setBatchMode(batchMode); } void FilmSimulation::read( const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited ) @@ -197,27 +197,100 @@ void FilmSimulation::trimValues( rtengine::procparams::ProcParams* pp ) //:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +std::unique_ptr ClutComboBox::cm; +std::unique_ptr ClutComboBox::cm2; + +ClutComboBox::ClutComboBox(const Glib::ustring &path): + MyComboBox(), + batchMode(false) +{ + if (!cm) { + cm.reset(new ClutModel(path)); + } + if (!cm2 && options.multiDisplayMode) { + cm2.reset(new ClutModel(path)); + } + + set_model(m_model()); + + if (cm->count > 0) { + pack_start(m_columns().label, false); + } + + if (!options.multiDisplayMode) { + signal_map().connect(sigc::mem_fun(*this, &ClutComboBox::updateUnchangedEntry)); + } +} + + +inline Glib::RefPtr &ClutComboBox::m_model() +{ + if (!batchMode || !options.multiDisplayMode) { + return cm->m_model; + } else { + return cm2->m_model; + } +} + + +inline ClutComboBox::ClutColumns &ClutComboBox::m_columns() +{ + if (!batchMode || !options.multiDisplayMode) { + return cm->m_columns; + } else { + return cm2->m_columns; + } +} + + +void ClutComboBox::setBatchMode(bool yes) +{ + if (batchMode != yes) { + batchMode = yes; + set_model(m_model()); + if (batchMode && options.multiDisplayMode) { + updateUnchangedEntry(); + } + } +} + + +void ClutComboBox::updateUnchangedEntry() +{ + auto c = m_model()->children(); + + if (batchMode) { + if (c.empty() || c[c.size()-1][m_columns().clutFilename] != "NULL") { + Gtk::TreeModel::Row row = *(m_model()->append()); + row[m_columns().label] = M("GENERAL_UNCHANGED"); + row[m_columns().clutFilename] = "NULL"; + } + } else { + if (c.size() > 0) { + Gtk::TreeModel::Row row = c[c.size()-1]; + if (row[m_columns().clutFilename] == "NULL") { + std::cout << " removing " << ((void *)this) << std::endl; + m_model()->erase(row); + } + } + } +} + ClutComboBox::ClutColumns::ClutColumns() { add( label ); add( clutFilename ); } -int ClutComboBox::fillFromDir (const Glib::ustring& path) +ClutComboBox::ClutModel::ClutModel(const Glib::ustring &path) { m_model = Gtk::TreeStore::create (m_columns); - set_model (m_model); - - const auto result = parseDir (path); - - if (result > 0) { - pack_start (m_columns.label, false); - } - - return result; + //set_model (m_model); + count = parseDir(path); } -int ClutComboBox::parseDir(const Glib::ustring& path) +int ClutComboBox::ClutModel::parseDir(const Glib::ustring& path) { if (path.empty() || !Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) { return 0; @@ -327,6 +400,11 @@ int ClutComboBox::parseDir(const Glib::ustring& path) return fileCount; } +int ClutComboBox::foundClutsCount() const +{ + return cm->count; +} + Glib::ustring ClutComboBox::getSelectedClut() { Glib::ustring result; @@ -334,7 +412,7 @@ Glib::ustring ClutComboBox::getSelectedClut() Gtk::TreeModel::Row row = *current; if ( row ) { - result = row[ m_columns.clutFilename ]; + result = row[ m_columns().clutFilename ]; } return result; @@ -343,7 +421,7 @@ Glib::ustring ClutComboBox::getSelectedClut() void ClutComboBox::setSelectedClut( Glib::ustring filename ) { if ( !filename.empty() ) { - Gtk::TreeIter found = findRowByClutFilename( m_model->children(), filename ); + Gtk::TreeIter found = findRowByClutFilename( m_model()->children(), filename ); if ( found ) { set_active( found ); @@ -358,7 +436,7 @@ Gtk::TreeIter ClutComboBox::findRowByClutFilename( Gtk::TreeModel::Children chil for( Gtk::TreeModel::Children::iterator it = childs.begin(); !result && it != childs.end(); ++it ) { Gtk::TreeModel::Row row = *it; - if ( row[ m_columns.clutFilename ] == filename ) { + if ( row[ m_columns().clutFilename ] == filename ) { result = it; } else { result = findRowByClutFilename( it->children(), filename ); @@ -367,10 +445,3 @@ Gtk::TreeIter ClutComboBox::findRowByClutFilename( Gtk::TreeModel::Children chil return result; } - -void ClutComboBox::addUnchangedEntry() -{ - Gtk::TreeModel::Row row = *(m_model->append()); - row[m_columns.label] = M("GENERAL_UNCHANGED"); - row[m_columns.clutFilename] = "NULL"; -} diff --git a/rtgui/filmsimulation.h b/rtgui/filmsimulation.h index 9979f45b3..c813f9c85 100644 --- a/rtgui/filmsimulation.h +++ b/rtgui/filmsimulation.h @@ -11,12 +11,16 @@ class ClutComboBox : public MyComboBox { public: - int fillFromDir (const Glib::ustring& path); + ClutComboBox(const Glib::ustring &path); + //int fillFromDir (const Glib::ustring& path); + int foundClutsCount() const; Glib::ustring getSelectedClut(); void setSelectedClut( Glib::ustring filename ); - void addUnchangedEntry(); - + void setBatchMode(bool yes); + private: + void updateUnchangedEntry(); // in batchMode we need to add an extra entry "(Unchanged)". We do this whenever the widget is mapped (connecting to signal_map()), unless options.multiDisplayMode (see the comment below about cm2 in this case) + class ClutColumns : public Gtk::TreeModel::ColumnRecord { public: @@ -25,11 +29,24 @@ private: ClutColumns(); }; - int parseDir (const Glib::ustring& path); + class ClutModel { + public: + Glib::RefPtr m_model; + ClutColumns m_columns; + int count; + ClutModel(const Glib::ustring &path); + int parseDir (const Glib::ustring& path); + }; + + Glib::RefPtr &m_model(); + ClutColumns &m_columns(); + Gtk::TreeIter findRowByClutFilename( Gtk::TreeModel::Children childs, Glib::ustring filename ); - Glib::RefPtr m_model; - ClutColumns m_columns; + static std::unique_ptr cm; // we use a shared TreeModel for all the combo boxes, to save time (no need to reparse the clut dir multiple times)... + static std::unique_ptr cm2; // ... except when options.multiDisplayMode (i.e. editors in their own window), where we need two. This is because we might have two combo boxes displayed at the same time in this case + int count; // the number of clut entries + bool batchMode; }; class FilmSimulation : public ToolParamBlock, public AdjusterListener, public FoldableToolPanel From dfe40677e2d4fc88f89f409c276d63261b384948 Mon Sep 17 00:00:00 2001 From: Hombre57 Date: Fri, 13 Oct 2017 23:25:24 +0200 Subject: [PATCH 27/27] Fix coverity issue --- rtengine/imagedata.cc | 2 +- rtengine/imagedata.h | 2 +- rtengine/imagesource.h | 2 +- rtengine/rawimagesource.h | 2 +- rtengine/stdimagesource.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index abf5b6ae5..ed8e0b52b 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -757,7 +757,7 @@ unsigned int FramesData::getFrameCount () const return dcrawFrameCount ? dcrawFrameCount : frames.size(); } -FrameData *FramesData::getFrameData (int frame) const +FrameData *FramesData::getFrameData (unsigned int frame) const { return frames.empty() || frame >= frames.size() ? nullptr : frames.at(frame); } diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 60011968a..2da97a5d1 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -101,7 +101,7 @@ public: void setDCRawFrameCount (unsigned int frameCount); unsigned int getRootCount () const; unsigned int getFrameCount () const; - FrameData *getFrameData (int frame) const; + FrameData *getFrameData (unsigned int frame) const; bool getPixelShift (unsigned int frame = 0) const; bool getHDR (unsigned int frame = 0) const; IIOSampleFormat getSampleFormat (unsigned int frame = 0) const; diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index 2a67c367a..757e6f5a7 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -107,7 +107,7 @@ public: return 0; } - virtual FrameData* getImageData (int frameNum) = 0; + virtual FrameData* getImageData (unsigned int frameNum) = 0; virtual ImageMatrices* getImageMatrices () = 0; virtual bool isRAW () const = 0; virtual DCPProfile* getDCP (const ColorManagementParams &cmp, ColorTemp &wb, DCPProfile::ApplyState &as) diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h index c50979427..99cc9af64 100644 --- a/rtengine/rawimagesource.h +++ b/rtengine/rawimagesource.h @@ -166,7 +166,7 @@ public: return ri->get_rotateDegree(); } - FrameData* getImageData (int frameNum) + FrameData* getImageData (unsigned int frameNum) { return idata->getFrameData (frameNum); } diff --git a/rtengine/stdimagesource.h b/rtengine/stdimagesource.h index cdb0b14fc..1450d745e 100644 --- a/rtengine/stdimagesource.h +++ b/rtengine/stdimagesource.h @@ -68,7 +68,7 @@ public: void getFullSize (int& w, int& h, int tr = TR_NONE); void getSize (const PreviewProps &pp, int& w, int& h); - FrameData* getImageData (int frameNum) + FrameData* getImageData (unsigned int frameNum) { return idata->getFrameData (frameNum); }