improved support for metadata editing
(cherry picked from commit 85da0b51ecf7ece768c0267aead71dd94404d4dc)
This commit is contained in:
parent
8a5aa6c119
commit
b92e77fb96
128
rtdata/images/svg/edit-small.svg
Normal file
128
rtdata/images/svg/edit-small.svg
Normal file
@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="edit-small.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#E0E1E2"
|
||||
bordercolor="#666768"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.04"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="7.5803253"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-bbox-midpoints="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1374"
|
||||
originx="1"
|
||||
originy="1"
|
||||
empspacing="7"
|
||||
dotted="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:description>RawTherapee icon.</dc:description>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1"
|
||||
transform="translate(0,-8)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 55,16 H 65 M 60,11 V 21"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4977" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 24,16 H 34 M 29,11 V 21"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4981" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 39,16 H 49 M 44,11 V 21"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4983" />
|
||||
<path
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.413246,9.78023 c 0.784726,0 2.23775,1.576711 2.23775,2.428236 0,0.851523 -1.091559,1.184475 -1.091559,1.184475 l -2.237749,-2.428235 c 0,0 0.306833,-1.184476 1.091558,-1.184476 z M 9.762249,11.571765 12,14 6.405626,20.070587 4.1678762,17.642352 Z m -6.1538101,6.677647 2.237749,2.428235 -0.027314,0.02964 -3.9160622,1.821176 1.6783123,-4.249412 z"
|
||||
id="path1658"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzcczccccccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
136
rtdata/images/svg/edit.svg
Normal file
136
rtdata/images/svg/edit.svg
Normal file
@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24px"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="edit.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#E0E1E2"
|
||||
bordercolor="#666768"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="34.25"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="12"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-bbox-midpoints="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1374"
|
||||
originx="1"
|
||||
originy="1"
|
||||
empspacing="11"
|
||||
dotted="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:description>RawTherapee icon.</dc:description>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 17.761905,2 C 18.897428,2 21,4.1025723 21,5.238095 c 0,1.1355228 -1.57952,1.57952 -1.57952,1.57952 L 16.182385,3.57952 c 0,0 0.443997,-1.57952 1.57952,-1.57952 z M 15.372861,4.3890438 18.610956,7.6271387 10.515719,15.722376 7.277624,12.484281 Z M 6.4681002,13.293805 9.7061953,16.5319 9.6666663,16.571429 4,19 6.4285712,13.333334 Z"
|
||||
id="path1658"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzcczccccccccccc" />
|
||||
<path
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -34.951172,1.048828 c -1.402705,0 -4,2.5972953 -4,4 0,1.4027047 1.951172,1.9511719 1.951172,1.9511719 l 4,-4 c 0,0 -0.548467,-1.9511719 -1.951172,-1.9511719 z M -32,3.9999999 l -4,4 L -26,18 -22,14 Z M -21,15 l -4,4 0.04883,0.04883 7,3 -3,-7 z"
|
||||
id="path1658-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzcczccccccccccc" />
|
||||
<path
|
||||
style="fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M -34,6.9999999 -25,16 l -1,1 -9,-9.0000001 z"
|
||||
id="path1682"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -24,19 5,2 -4,-3 z"
|
||||
id="path1686"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
id="path1690"
|
||||
cx="-35"
|
||||
cy="19"
|
||||
r="3" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
d="M -36.898437,16.679688 A 3,3 0 0 0 -38,19 a 3,3 0 0 0 3,3 3,3 0 0 0 2.322266,-1.101562 A 3.5,3.5 0 0 1 -33.5,21 3.5,3.5 0 0 1 -37,17.5 a 3.5,3.5 0 0 1 0.101563,-0.820312 z"
|
||||
id="circle1692" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.6 KiB |
@ -77,8 +77,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
|
||||
EXIFPANEL_BASIC_GROUP;Basic
|
||||
EXPORT_BYPASS;Processing steps to bypass
|
||||
EXPORT_BYPASS_ALL;Select / Unselect All
|
||||
EXPORT_BYPASS_DEFRINGE;Bypass Defringe
|
||||
@ -1548,7 +1547,7 @@ MAIN_TAB_COLOR;Color
|
||||
MAIN_TAB_COLOR_TOOLTIP;Shortcut: <b>Alt-c</b>
|
||||
MAIN_TAB_DETAIL;Detail
|
||||
MAIN_TAB_DETAIL_TOOLTIP;Shortcut: <b>Alt-d</b>
|
||||
MAIN_TAB_DEVELOP; Batch Edit
|
||||
MAIN_TAB_DEVELOP; Batch Edit
|
||||
MAIN_TAB_EXIF;Exif
|
||||
MAIN_TAB_EXPORT; Fast Export
|
||||
MAIN_TAB_EXPOSURE;Exposure
|
||||
|
@ -699,3 +699,36 @@ double FramesMetaData::apertureFromString(std::string s)
|
||||
|
||||
return std::atof(s.c_str());
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
template<class T>
|
||||
void set_exif(Exiv2::ExifData &exif, const std::string &key, T val)
|
||||
{
|
||||
try {
|
||||
exif[key] = val;
|
||||
} catch (std::exception &exc) {}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void FramesData::fillBasicTags(Exiv2::ExifData &exif) const
|
||||
{
|
||||
if (!hasExif()) {
|
||||
return;
|
||||
}
|
||||
set_exif(exif, "Exif.Photo.ISOSpeedRatings", getISOSpeed());
|
||||
set_exif(exif, "Exif.Photo.FNumber", Exiv2::DoubleValue(getFNumber()));
|
||||
//set_exif(exif, "Exif.Photo.ExposureTime", Exiv2::DoubleValue(getShutterSpeed()));
|
||||
set_exif(exif, "Exif.Photo.ExposureTime", shutterToString(getShutterSpeed()));
|
||||
set_exif(exif, "Exif.Photo.FocalLength", Exiv2::DoubleValue(getFocalLen()));
|
||||
set_exif(exif, "Exif.Photo.ExposureBiasValue", Exiv2::DoubleValue(getExpComp()));
|
||||
set_exif(exif, "Exif.Image.Make", getMake());
|
||||
set_exif(exif, "Exif.Image.Model", getModel());
|
||||
set_exif(exif, "Exif.Photo.LensModel", getLens());
|
||||
char buf[256];
|
||||
auto t = getDateTime();
|
||||
strftime(buf, 256, "%Y:%m:%d %H:%M:%S", &t);
|
||||
set_exif(exif, "Exif.Photo.DateTimeOriginal", buf);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "imageio.h"
|
||||
#include "metadata.h"
|
||||
|
||||
namespace Glib
|
||||
{
|
||||
@ -83,6 +84,8 @@ public:
|
||||
std::string getOrientation() const override;
|
||||
Glib::ustring getFileName() const override;
|
||||
int getRating() const override;
|
||||
|
||||
void fillBasicTags(Exiv2::ExifData &exif) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "metadata.h"
|
||||
#include "settings.h"
|
||||
#include "imagedata.h"
|
||||
#include "../rtgui/version.h"
|
||||
#include "../rtgui/pathutils.h"
|
||||
|
||||
@ -309,6 +310,16 @@ void Exiv2Metadata::remove_unwanted(Exiv2::ExifData &dst) const
|
||||
static const std::vector<std::string> badpatterns = {
|
||||
"Exif.SubImage"
|
||||
};
|
||||
|
||||
if (exif_keys_ && !src_.empty()) {
|
||||
try {
|
||||
FramesData fd(src_);
|
||||
fd.fillBasicTags(dst);
|
||||
} catch (std::exception &exc) {
|
||||
std::cout << "Error reading metadata from " << src_
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = dst.begin(); it != dst.end(); ) {
|
||||
if (badtags.find(it->key()) != badtags.end()) {
|
||||
|
@ -379,33 +379,6 @@ bool saveToKeyfile(
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string> exif_keys = {
|
||||
{"Copyright", "Exif.Image.Copyright"},
|
||||
{"Artist", "Exif.Image.Artist"},
|
||||
{"ImageDescription", "Exif.Image.ImageDescription"},
|
||||
{"Exif.UserComment", "Exif.Photo.UserComment"}
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> iptc_keys = {
|
||||
{"Title", "Iptc.Application2.ObjectName"},
|
||||
{"Category", "Iptc.Application2.Category"},
|
||||
{"SupplementalCategories", "Iptc.Application2.SuppCategory"},
|
||||
{"Keywords", "Iptc.Application2.Keywords"},
|
||||
{"Instructions", "Iptc.Application2.SpecialInstructions"},
|
||||
{"DateCreated", "Iptc.Application2.DateCreated"},
|
||||
{"Creator", "Iptc.Application2.Byline"},
|
||||
{"CreatorJobTitle", "Iptc.Application2.BylineTitle"},
|
||||
{"City", "Iptc.Application2.City"},
|
||||
{"Province", "Iptc.Application2.ProvinceState"},
|
||||
{"Country", "Iptc.Application2.CountryName"},
|
||||
{"TransReference", "Iptc.Application2.TransmissionReference"},
|
||||
{"Headline", "Iptc.Application2.Headline"},
|
||||
{"Credit", "Iptc.Application2.Credit"},
|
||||
{"Source", "Iptc.Application2.Source"},
|
||||
{"Copyright", "Iptc.Application2.Copyright"},
|
||||
{"Caption", "Iptc.Application2.Caption"},
|
||||
{"CaptionWriter", "Iptc.Application2.Writer"}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -5247,23 +5220,6 @@ Glib::ustring RAWParams::getFlatFieldBlurTypeString(FlatFieldBlurType type)
|
||||
}
|
||||
|
||||
|
||||
MetaDataParams::MetaDataParams():
|
||||
mode(MetaDataParams::TUNNEL),
|
||||
exifKeys{"ALL"}
|
||||
{
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator==(const MetaDataParams &other) const
|
||||
{
|
||||
return mode == other.mode
|
||||
&& exifKeys == other.exifKeys;
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator!=(const MetaDataParams &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
FilmNegativeParams::FilmNegativeParams() :
|
||||
enabled(false),
|
||||
redRatio(1.36),
|
||||
@ -5316,6 +5272,90 @@ bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const std::map<std::string, std::string> exif_keys = {
|
||||
{"Copyright", "Exif.Image.Copyright"},
|
||||
{"Artist", "Exif.Image.Artist"},
|
||||
{"ImageDescription", "Exif.Image.ImageDescription"},
|
||||
{"Exif.UserComment", "Exif.Photo.UserComment"},
|
||||
{"ISOSpeed", "Exif.Photo.ISOSpeedRatings"},
|
||||
{"FNumber", "Exif.Photo.FNumber"},
|
||||
{"ShutterSpeed", "Exif.Photo.ExposureTime"},
|
||||
{"FocalLength", "Exif.Photo.FocalLength"},
|
||||
{"ExpComp", "Exif.Photo.ExposureBiasValue"},
|
||||
{"Flash", "Exif.Photo.Flash"},
|
||||
{"Make", "Exif.Image.Make"},
|
||||
{"Model", "Exif.Image.Model"},
|
||||
{"Lens", "Exif.Photo.LensModel"},
|
||||
{"DateTime", "Exif.Photo.DateTimeOriginal"}
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> iptc_keys = {
|
||||
{"Title", "Iptc.Application2.ObjectName"},
|
||||
{"Category", "Iptc.Application2.Category"},
|
||||
{"SupplementalCategories", "Iptc.Application2.SuppCategory"},
|
||||
{"Keywords", "Iptc.Application2.Keywords"},
|
||||
{"Instructions", "Iptc.Application2.SpecialInstructions"},
|
||||
{"DateCreated", "Iptc.Application2.DateCreated"},
|
||||
{"Creator", "Iptc.Application2.Byline"},
|
||||
{"CreatorJobTitle", "Iptc.Application2.BylineTitle"},
|
||||
{"City", "Iptc.Application2.City"},
|
||||
{"Province", "Iptc.Application2.ProvinceState"},
|
||||
{"Country", "Iptc.Application2.CountryName"},
|
||||
{"TransReference", "Iptc.Application2.TransmissionReference"},
|
||||
{"Headline", "Iptc.Application2.Headline"},
|
||||
{"Credit", "Iptc.Application2.Credit"},
|
||||
{"Source", "Iptc.Application2.Source"},
|
||||
{"Copyright", "Iptc.Application2.Copyright"},
|
||||
{"Caption", "Iptc.Application2.Caption"},
|
||||
{"CaptionWriter", "Iptc.Application2.Writer"}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
std::vector<std::string> MetaDataParams::basicExifKeys = {
|
||||
"Exif.Image.Copyright",
|
||||
"Exif.Image.Artist",
|
||||
"Exif.Image.ImageDescription",
|
||||
"Exif.Photo.UserComment",
|
||||
"Exif.Image.Make",
|
||||
"Exif.Image.Model",
|
||||
"Exif.Photo.LensModel",
|
||||
"Exif.Photo.FNumber",
|
||||
"Exif.Photo.ExposureTime",
|
||||
"Exif.Photo.FocalLength",
|
||||
"Exif.Photo.ISOSpeedRatings",
|
||||
"Exif.Photo.ExposureBiasValue",
|
||||
"Exif.Photo.Flash",
|
||||
"Exif.Photo.DateTimeOriginal"
|
||||
};
|
||||
|
||||
|
||||
MetaDataParams::MetaDataParams():
|
||||
mode(MetaDataParams::TUNNEL),
|
||||
exifKeys{"*"},
|
||||
exif{},
|
||||
iptc{}
|
||||
{
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator==(const MetaDataParams &other) const
|
||||
{
|
||||
return mode == other.mode
|
||||
&& exifKeys == other.exifKeys
|
||||
&& exif == other.exif
|
||||
&& iptc == other.iptc;
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator!=(const MetaDataParams &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
ProcParams::ProcParams()
|
||||
{
|
||||
setDefaults();
|
||||
@ -5414,8 +5454,8 @@ void ProcParams::setDefaults()
|
||||
raw = {};
|
||||
|
||||
metadata = {};
|
||||
exif.clear();
|
||||
iptc.clear();
|
||||
//exif.clear();
|
||||
//iptc.clear();
|
||||
|
||||
// -1 means that there's no pp3 data with rank yet. In this case, the
|
||||
// embedded Rating metadata should take precedence. -1 should never be
|
||||
@ -6876,10 +6916,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
||||
for (auto &p : exif_keys) {
|
||||
m[p.second] = p.first;
|
||||
}
|
||||
for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); ++i) {
|
||||
auto it = m.find(i->first);
|
||||
for (auto &p : metadata.exif) {
|
||||
auto it = m.find(p.first);
|
||||
if (it != m.end()) {
|
||||
keyFile.set_string("Exif", it->second, i->second);
|
||||
keyFile.set_string("Exif", it->second, p.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6890,10 +6930,10 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
||||
for (auto &p : iptc_keys) {
|
||||
m[p.second] = p.first;
|
||||
}
|
||||
for (IPTCPairs::const_iterator i = iptc.begin(); i != iptc.end(); ++i) {
|
||||
auto it = m.find(i->first);
|
||||
for (auto &p : metadata.iptc) {
|
||||
auto it = m.find(p.first);
|
||||
if (it != m.end()) {
|
||||
Glib::ArrayHandle<Glib::ustring> values = i->second;
|
||||
Glib::ArrayHandle<Glib::ustring> values = p.second;
|
||||
keyFile.set_string_list("IPTC", it->second, values);
|
||||
}
|
||||
}
|
||||
@ -9383,7 +9423,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
||||
for (const auto& key : keyFile.get_keys("Exif")) {
|
||||
auto it = exif_keys.find(key);
|
||||
if (it != exif_keys.end()) {
|
||||
exif[it->second] = keyFile.get_string("Exif", key);
|
||||
metadata.exif[it->second] = keyFile.get_string("Exif", key);
|
||||
|
||||
if (pedited) {
|
||||
pedited->exif = true;
|
||||
@ -9413,16 +9453,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
||||
}
|
||||
|
||||
auto kk = it->second;
|
||||
const IPTCPairs::iterator element = iptc.find(kk);
|
||||
const IPTCPairs::iterator element = metadata.iptc.find(kk);
|
||||
|
||||
if (element != iptc.end()) {
|
||||
if (element != metadata.iptc.end()) {
|
||||
// it already exist so we cleanup the values
|
||||
element->second.clear();
|
||||
}
|
||||
|
||||
// TODO: look out if merging Keywords and SupplementalCategories from the procparams chain would be interesting
|
||||
for (const auto& currLoadedTagValue : keyFile.get_string_list("IPTC", key)) {
|
||||
iptc[kk].push_back(currLoadedTagValue);
|
||||
metadata.iptc[kk].push_back(currLoadedTagValue);
|
||||
}
|
||||
|
||||
if (pedited) {
|
||||
@ -9500,8 +9540,6 @@ bool ProcParams::operator ==(const ProcParams& other) const
|
||||
&& rgbCurves == other.rgbCurves
|
||||
&& colorToning == other.colorToning
|
||||
&& metadata == other.metadata
|
||||
&& exif == other.exif
|
||||
&& iptc == other.iptc
|
||||
&& dehaze == other.dehaze
|
||||
&& filmNegative == other.filmNegative;
|
||||
}
|
||||
|
@ -1718,25 +1718,6 @@ struct ColorManagementParams {
|
||||
bool operator !=(const ColorManagementParams& other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters for metadata handling
|
||||
*/
|
||||
struct MetaDataParams {
|
||||
enum Mode {
|
||||
TUNNEL,
|
||||
EDIT,
|
||||
STRIP
|
||||
};
|
||||
Mode mode;
|
||||
std::vector<std::string> exifKeys;
|
||||
|
||||
MetaDataParams();
|
||||
|
||||
bool operator ==(const MetaDataParams &other) const;
|
||||
bool operator !=(const MetaDataParams &other) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Minimal wrapper allowing forward declaration for representing a key/value for the exif metadata information
|
||||
*/
|
||||
@ -1841,6 +1822,29 @@ private:
|
||||
std::map<Glib::ustring, std::vector<Glib::ustring>> pairs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters for metadata handling
|
||||
*/
|
||||
struct MetaDataParams {
|
||||
enum Mode {
|
||||
TUNNEL,
|
||||
EDIT,
|
||||
STRIP
|
||||
};
|
||||
Mode mode;
|
||||
std::vector<std::string> exifKeys;
|
||||
ExifPairs exif;
|
||||
IPTCPairs iptc;
|
||||
|
||||
MetaDataParams();
|
||||
|
||||
bool operator ==(const MetaDataParams &other) const;
|
||||
bool operator !=(const MetaDataParams &other) const;
|
||||
|
||||
static std::vector<std::string> basicExifKeys;
|
||||
};
|
||||
|
||||
|
||||
struct WaveletParams {
|
||||
std::vector<double> ccwcurve;
|
||||
std::vector<double> wavdenoise;
|
||||
@ -2355,8 +2359,8 @@ public:
|
||||
int ppVersion; ///< Version of the PP file from which the parameters have been read
|
||||
|
||||
MetaDataParams metadata; ///< Metadata parameters
|
||||
ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image
|
||||
IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image
|
||||
// ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image
|
||||
// IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image
|
||||
|
||||
/**
|
||||
* The constructor only sets the hand-wired defaults.
|
||||
|
@ -1737,9 +1737,9 @@ private:
|
||||
readyImg->setMetadata(std::move(info));
|
||||
break;
|
||||
case MetaDataParams::EDIT:
|
||||
info.setExif(params.exif);
|
||||
info.setIptc(params.iptc);
|
||||
if (!(params.metadata.exifKeys.size() == 1 && params.metadata.exifKeys[0] == "ALL")) {
|
||||
info.setExif(params.metadata.exif);
|
||||
info.setIptc(params.metadata.iptc);
|
||||
if (!(params.metadata.exifKeys.size() == 1 && params.metadata.exifKeys[0] == "*")) {
|
||||
info.setExifKeys(&(params.metadata.exifKeys));
|
||||
}
|
||||
readyImg->setMetadata(std::move(info));
|
||||
|
@ -34,15 +34,12 @@ using namespace rtengine::procparams;
|
||||
ExifPanel::ExifPanel() :
|
||||
idata(nullptr),
|
||||
changeList(new rtengine::procparams::ExifPairs),
|
||||
defChangeList(new rtengine::procparams::ExifPairs),
|
||||
editableTags{
|
||||
{"Exif.Photo.UserComment", "User Comment"},
|
||||
{"Exif.Image.Artist", "Artist"},
|
||||
{"Exif.Image.Copyright", "Copyright"},
|
||||
{"Exif.Image.ImageDescription", "Image Description"},
|
||||
{ "Exif.Photo.LensModel", "Lens Model" }
|
||||
}
|
||||
defChangeList(new rtengine::procparams::ExifPairs)
|
||||
{
|
||||
for (auto &k : MetaDataParams::basicExifKeys) {
|
||||
editableTags.push_back(std::make_pair(k, ""));
|
||||
}
|
||||
|
||||
set_orientation(Gtk::ORIENTATION_VERTICAL);
|
||||
exifTree = Gtk::manage (new Gtk::TreeView());
|
||||
scrolledWindow = Gtk::manage (new Gtk::ScrolledWindow());
|
||||
@ -60,11 +57,29 @@ ExifPanel::ExifPanel() :
|
||||
exifTreeModel = Gtk::TreeStore::create(exifColumns);
|
||||
exifTree->set_model(exifTreeModel);
|
||||
exifTree->set_grid_lines(Gtk::TREE_VIEW_GRID_LINES_NONE);
|
||||
//exifTree->set_show_expanders(false);
|
||||
exifTree->set_show_expanders(false);
|
||||
exifTree->set_tooltip_column(0);
|
||||
exifTree->set_enable_search(false);
|
||||
|
||||
keepicon = RTImage::createPixbufFromFile ("tick-small.png");
|
||||
editicon = RTImage::createPixbufFromFile("add-small.png");
|
||||
//keepicon = RTImage::createPixbufFromFile("tick-small.png");
|
||||
editicon = RTImage::createPixbufFromFile("edit-small.png");
|
||||
open_icon_ = RTImage::createPixbufFromFile("expander-open-small.png");
|
||||
closed_icon_ = RTImage::createPixbufFromFile("expander-closed-small.png");
|
||||
|
||||
exif_active_renderer_.property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
|
||||
exif_active_renderer_.signal_toggled().connect(sigc::mem_fun(this, &ExifPanel::onKeyActiveToggled));
|
||||
exif_active_column_.pack_start(exif_active_renderer_);
|
||||
exif_active_column_.set_cell_data_func(exif_active_renderer_, sigc::mem_fun(this, &ExifPanel::setKeyActive));
|
||||
|
||||
exifTree->append_column(exif_active_column_);
|
||||
|
||||
// {
|
||||
// Gtk::TreeView::Column *c = Gtk::manage(new Gtk::TreeView::Column(""));
|
||||
// Gtk::CellRendererPixbuf *pb = Gtk::manage(new Gtk::CellRendererPixbuf());
|
||||
// c->pack_start(*pb, false);
|
||||
// c->add_attribute(*pb, "pixbuf", exifColumns.expander_icon);
|
||||
// exifTree->append_column(*c);
|
||||
// }
|
||||
|
||||
Gtk::TreeView::Column *viewcol = Gtk::manage (new Gtk::TreeView::Column ("Field Name"));
|
||||
Gtk::CellRendererPixbuf* render_pb = Gtk::manage (new Gtk::CellRendererPixbuf ());
|
||||
@ -85,15 +100,8 @@ ExifPanel::ExifPanel() :
|
||||
render_pb->property_yalign() = 0;
|
||||
render_txt->property_yalign() = 0;
|
||||
|
||||
exif_active_renderer_.property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
|
||||
exif_active_renderer_.signal_toggled().connect(sigc::mem_fun(this, &ExifPanel::onKeyActiveToggled));
|
||||
exif_active_column_.pack_start(exif_active_renderer_);
|
||||
exif_active_column_.set_cell_data_func(exif_active_renderer_, sigc::mem_fun(this, &ExifPanel::setKeyActive));
|
||||
|
||||
exifTree->append_column(exif_active_column_);
|
||||
|
||||
exifTree->append_column(*viewcol);
|
||||
exifTree->set_expander_column(*viewcol);
|
||||
//exifTree->set_expander_column(*viewcol);
|
||||
|
||||
Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value"));
|
||||
Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText());
|
||||
@ -131,14 +139,14 @@ ExifPanel::ExifPanel() :
|
||||
|
||||
activate_all_ = addbtn("EXIFPANEL_ACTIVATE_ALL_HINT", "tick.png");
|
||||
activate_none_ = addbtn("EXIFPANEL_ACTIVATE_NONE_HINT", "box.png");
|
||||
add = addbtn("EXIFPANEL_ADDEDIT", "add.png");
|
||||
add = addbtn("EXIFPANEL_ADDEDIT", "edit.png");
|
||||
reset = addbtn("EXIFPANEL_RESETHINT", "undo.png", "redo.png");
|
||||
resetAll = addbtn("EXIFPANEL_RESETALLHINT", "undo-all.png", "redo-all.png");
|
||||
|
||||
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->signal_row_activated().connect(sigc::mem_fun(*this, &ExifPanel::onExifRowActivated));
|
||||
|
||||
reset->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetPressed) );
|
||||
resetAll->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetAllPressed) );
|
||||
@ -146,6 +154,10 @@ ExifPanel::ExifPanel() :
|
||||
activate_all_->signal_clicked().connect(sigc::mem_fun(*this, &ExifPanel::activateAllPressed));
|
||||
activate_none_->signal_clicked().connect(sigc::mem_fun(*this, &ExifPanel::activateNonePressed));
|
||||
|
||||
exifTree->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &ExifPanel::onExifTreeClick));
|
||||
exifTree->signal_row_expanded().connect(sigc::mem_fun(*this, &ExifPanel::onExifRowExpanded));
|
||||
exifTree->signal_row_collapsed().connect(sigc::mem_fun(*this, &ExifPanel::onExifRowCollapsed));
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
@ -157,7 +169,7 @@ void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
{
|
||||
disableListener();
|
||||
|
||||
*changeList = pp->exif;
|
||||
*changeList = pp->metadata.exif;
|
||||
initial_active_keys_.clear();
|
||||
initial_active_keys_.insert(pp->metadata.exifKeys.begin(), pp->metadata.exifKeys.end());
|
||||
cur_active_keys_ = initial_active_keys_;
|
||||
@ -170,54 +182,15 @@ void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
|
||||
void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
pp->exif = *changeList;
|
||||
|
||||
std::unordered_set<std::string> prev;
|
||||
bool all_active = (cur_active_keys_.size() == 1 && *(cur_active_keys_.begin()) == "ALL");
|
||||
|
||||
if (!all_active) {
|
||||
prev = cur_active_keys_;
|
||||
}
|
||||
|
||||
pp->metadata.exifKeys.clear();
|
||||
|
||||
bool none_active = true;
|
||||
|
||||
auto root = exifTreeModel->children();
|
||||
// for (auto &entry : root->children()) {
|
||||
// Glib::ustring key = entry[exifColumns.key];
|
||||
// prev.erase(key);
|
||||
// if (entry[exifColumns.active]) {
|
||||
// pp->metadata.exifKeys.push_back(key);
|
||||
// none_active = false;
|
||||
// } else {
|
||||
// all_active = false;
|
||||
// }
|
||||
// }
|
||||
for (auto &group : root->children()) {
|
||||
for (auto &entry : group.children()) {
|
||||
std::string key = entry[exifColumns.key];
|
||||
prev.erase(key);
|
||||
if (entry[exifColumns.active]) {
|
||||
pp->metadata.exifKeys.push_back(key);
|
||||
none_active = false;
|
||||
} else {
|
||||
all_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (all_active) {
|
||||
pp->metadata.exifKeys = { "ALL" };
|
||||
} else if (!none_active) {
|
||||
pp->metadata.exifKeys.insert(pp->metadata.exifKeys.end(), prev.begin(), prev.end());
|
||||
}
|
||||
pp->metadata.exif = *changeList;
|
||||
cur_active_keys_ = get_active_keys();
|
||||
pp->metadata.exifKeys.assign(cur_active_keys_.begin(), cur_active_keys_.end());
|
||||
std::sort(pp->metadata.exifKeys.begin(), pp->metadata.exifKeys.end());
|
||||
}
|
||||
|
||||
void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited)
|
||||
{
|
||||
*defChangeList = defParams->exif;
|
||||
*defChangeList = defParams->metadata.exif;
|
||||
}
|
||||
|
||||
void ExifPanel::setImageData (const FramesMetaData* id)
|
||||
@ -240,11 +213,13 @@ void ExifPanel::addTag(const std::string &key, const std::pair<Glib::ustring, Gl
|
||||
{
|
||||
auto root = exifTreeModel->children();
|
||||
|
||||
for (auto it = root.rbegin(), end = root.rend(); it != end; ++it) {
|
||||
auto row = *it;
|
||||
// for (auto it = root.rbegin(), end = root.rend(); it != end; ++it) {
|
||||
// auto row = *it;
|
||||
for (auto &row : root) {
|
||||
// auto row = *it;
|
||||
std::string key = row[exifColumns.key];
|
||||
if (row[exifColumns.is_group] && key == label.first) {
|
||||
return it->children();
|
||||
return row./*it->*/children();
|
||||
}
|
||||
}
|
||||
auto it = exifTreeModel->append(root);
|
||||
@ -253,7 +228,7 @@ void ExifPanel::addTag(const std::string &key, const std::pair<Glib::ustring, Gl
|
||||
row[exifColumns.editable] = false;
|
||||
row[exifColumns.edited] = false;
|
||||
row[exifColumns.key] = label.first;
|
||||
row[exifColumns.label] = "<i>" + label.first + "</i>";
|
||||
row[exifColumns.label] = "<b>" + label.first + "</b>";
|
||||
row[exifColumns.value_nopango] = "";
|
||||
row[exifColumns.value] = "";
|
||||
row[exifColumns.is_group] = true;
|
||||
@ -275,13 +250,13 @@ void ExifPanel::addTag(const std::string &key, const std::pair<Glib::ustring, Gl
|
||||
row[exifColumns.label] = escapeHtmlChars(label.second);
|
||||
row[exifColumns.value] = value;//escapeHtmlChars(value);
|
||||
|
||||
bool active = (cur_active_keys_.size() == 1 && *(cur_active_keys_.begin()) == "ALL") || cur_active_keys_.find(key) != cur_active_keys_.end();
|
||||
bool active = all_keys_active() || cur_active_keys_.find(key) != cur_active_keys_.end();
|
||||
row[exifColumns.active] = active;
|
||||
|
||||
if (edited) {
|
||||
row[exifColumns.icon] = editicon;
|
||||
} else if (editable) {
|
||||
row[exifColumns.icon] = keepicon;
|
||||
// } else if (editable) {
|
||||
// row[exifColumns.icon] = keepicon;
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,15 +293,16 @@ void ExifPanel::refreshTags()
|
||||
pos = s.find('.');
|
||||
if (pos != std::string::npos) {
|
||||
g = s.substr(0, pos);
|
||||
s = s.substr(pos+1);
|
||||
// s = s.substr(pos+1);
|
||||
}
|
||||
s = tag.tagLabel();
|
||||
return std::make_pair(g, Glib::ustring(s));
|
||||
};
|
||||
|
||||
try {
|
||||
rtengine::Exiv2Metadata meta(fn);
|
||||
meta.load();
|
||||
auto& exif = meta.exifData();
|
||||
Exiv2::ExifData exif = meta.exifData();
|
||||
|
||||
const auto to_value =
|
||||
[&](Exiv2::Exifdatum &tag) -> Glib::ustring
|
||||
@ -338,6 +314,9 @@ void ExifPanel::refreshTags()
|
||||
return "<i>(Not shown)</i>";
|
||||
};
|
||||
|
||||
if (const rtengine::FramesData *fd = dynamic_cast<const rtengine::FramesData *>(idata)) {
|
||||
fd->fillBasicTags(exif);
|
||||
}
|
||||
|
||||
for (const auto& p : *changeList) {
|
||||
try {
|
||||
@ -346,12 +325,18 @@ void ExifPanel::refreshTags()
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& p : editableTags) {
|
||||
const auto pos = exif.findKey(Exiv2::ExifKey(p.first));
|
||||
for (auto& p : editableTags) {
|
||||
Exiv2::ExifKey k(p.first);
|
||||
const auto pos = exif.findKey(k);
|
||||
bool edited = false;
|
||||
Glib::ustring value = "";
|
||||
auto lbl = std::make_pair(M("EXIFPANEL_BASIC_GROUP"), k.tagLabel());
|
||||
p.second = k.tagLabel();
|
||||
if (pos != exif.end() && pos->size()) {
|
||||
const bool edited = changeList->find(pos->key()) != changeList->end();
|
||||
addTag(pos->key(), to_label(*pos), pos->print(&exif), true, edited);
|
||||
edited = changeList->find(pos->key()) != changeList->end();
|
||||
value = pos->print(&exif);
|
||||
}
|
||||
addTag(p.first, lbl, value, true, edited);
|
||||
}
|
||||
std::set<std::string> keyset;
|
||||
for (const auto& tag : exif) {
|
||||
@ -406,6 +391,7 @@ void ExifPanel::resetIt(const Gtk::TreeModel::const_iterator& iter)
|
||||
|
||||
void ExifPanel::resetPressed()
|
||||
{
|
||||
cur_active_keys_ = get_active_keys();
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
|
||||
@ -490,10 +476,13 @@ void ExifPanel::addPressed ()
|
||||
hb2->show ();
|
||||
|
||||
if (dialog->run () == Gtk::RESPONSE_OK) {
|
||||
cur_active_keys_ = get_active_keys();
|
||||
auto key = editableTags[tcombo->get_active_row_number()].first;
|
||||
const auto value = ventry->get_text();
|
||||
(*changeList)[key] = value;
|
||||
cur_active_keys_.insert(key);
|
||||
if (!all_keys_active()) {
|
||||
cur_active_keys_.insert(key);
|
||||
}
|
||||
refreshTags();
|
||||
notifyListener();
|
||||
}
|
||||
@ -556,6 +545,11 @@ void ExifPanel::onKeyActiveToggled(const Glib::ustring &path)
|
||||
for (auto &c : row.children()) {
|
||||
c[exifColumns.active] = b;
|
||||
}
|
||||
} else if (!b) {
|
||||
it = row.parent();
|
||||
if (it) {
|
||||
(*it)[exifColumns.active] = b;
|
||||
}
|
||||
}
|
||||
notifyListener();
|
||||
}
|
||||
@ -568,3 +562,78 @@ void ExifPanel::setKeyActive(Gtk::CellRenderer *renderer, const Gtk::TreeModel::
|
||||
static_cast<Gtk::CellRendererToggle *>(renderer)->set_active(row[exifColumns.active]);
|
||||
}
|
||||
|
||||
|
||||
bool ExifPanel::all_keys_active() const
|
||||
{
|
||||
return (cur_active_keys_.size() == 1 && *(cur_active_keys_.begin()) == "*");
|
||||
}
|
||||
|
||||
|
||||
std::unordered_set<std::string> ExifPanel::get_active_keys() const
|
||||
{
|
||||
bool all_active = true;
|
||||
std::unordered_set<std::string> ret;
|
||||
auto root = exifTreeModel->children();
|
||||
for (auto &group : root->children()) {
|
||||
for (auto &entry : group.children()) {
|
||||
std::string key = entry[exifColumns.key];
|
||||
if (entry[exifColumns.active]) {
|
||||
ret.insert(key);
|
||||
} else {
|
||||
all_active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (all_active) {
|
||||
ret.clear();
|
||||
ret.insert("*");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ExifPanel::onExifTreeClick(GdkEventButton *event)
|
||||
{
|
||||
Gtk::TreeModel::Path pth;
|
||||
Gtk::TreeViewColumn *col;
|
||||
int cell_x;
|
||||
int cell_y;
|
||||
if (exifTree->get_path_at_pos(event->x, event->y, pth, col, cell_x, cell_y) && col == exifTree->get_column(1) && cell_x <= 22) {
|
||||
auto it = exifTreeModel->get_iter(pth);
|
||||
auto row = *it;
|
||||
if (row[exifColumns.is_group]) {
|
||||
if (exifTree->row_expanded(pth)) {
|
||||
exifTree->collapse_row(pth);
|
||||
} else {
|
||||
exifTree->expand_row(pth, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExifPanel::onExifRowExpanded(const Gtk::TreeModel::iterator &it, const Gtk::TreeModel::Path &path)
|
||||
{
|
||||
auto row = *it;
|
||||
if (row[exifColumns.is_group]) {
|
||||
row[exifColumns.icon] = open_icon_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExifPanel::onExifRowCollapsed(const Gtk::TreeModel::iterator &it, const Gtk::TreeModel::Path &path)
|
||||
{
|
||||
auto row = *it;
|
||||
if (row[exifColumns.is_group]) {
|
||||
row[exifColumns.icon] = closed_icon_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExifPanel::onExifRowActivated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column)
|
||||
{
|
||||
auto it = exifTreeModel->get_iter(path);
|
||||
auto row = *it;
|
||||
if (row[exifColumns.editable]) {
|
||||
addPressed();
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ private:
|
||||
class ExifColumns : public Gtk::TreeModelColumnRecord
|
||||
{
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > icon;
|
||||
// Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf>> expander_icon;
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf>> icon;
|
||||
Gtk::TreeModelColumn<std::string> key;
|
||||
Gtk::TreeModelColumn<Glib::ustring> label;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value;
|
||||
@ -71,10 +72,13 @@ private:
|
||||
add(editable);
|
||||
add(active);
|
||||
add(is_group);
|
||||
// add(expander_icon);
|
||||
}
|
||||
};
|
||||
Glib::RefPtr<Gdk::Pixbuf> keepicon;
|
||||
//Glib::RefPtr<Gdk::Pixbuf> keepicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> editicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> open_icon_;
|
||||
Glib::RefPtr<Gdk::Pixbuf> closed_icon_;
|
||||
|
||||
ExifColumns exifColumns;
|
||||
Gtk::TreeView* exifTree;
|
||||
@ -90,7 +94,7 @@ private:
|
||||
Gtk::CellRendererToggle exif_active_renderer_;
|
||||
Gtk::TreeView::Column exif_active_column_;
|
||||
|
||||
const std::vector<std::pair<std::string, Glib::ustring>> editableTags;
|
||||
std::vector<std::pair<std::string, Glib::ustring>> editableTags;
|
||||
|
||||
std::unordered_set<std::string> initial_active_keys_;
|
||||
std::unordered_set<std::string> cur_active_keys_;
|
||||
@ -106,7 +110,14 @@ private:
|
||||
|
||||
void setKeyActive(Gtk::CellRenderer *renderer, const Gtk::TreeModel::iterator &it);
|
||||
void onKeyActiveToggled(const Glib::ustring &path);
|
||||
|
||||
|
||||
bool all_keys_active() const;
|
||||
std::unordered_set<std::string> get_active_keys() const;
|
||||
|
||||
void onExifTreeClick(GdkEventButton *event);
|
||||
void onExifRowExpanded(const Gtk::TreeModel::iterator &it, const Gtk::TreeModel::Path &path);
|
||||
void onExifRowCollapsed(const Gtk::TreeModel::iterator &it, const Gtk::TreeModel::Path &path);
|
||||
void onExifRowActivated(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *column);
|
||||
|
||||
public:
|
||||
ExifPanel ();
|
||||
|
@ -467,8 +467,8 @@ void IPTCPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
disableListener ();
|
||||
changeList->clear();
|
||||
|
||||
if (!pp->iptc.empty()) {
|
||||
*changeList = pp->iptc;
|
||||
if (!pp->metadata.iptc.empty()) {
|
||||
*changeList = pp->metadata.iptc;
|
||||
} else {
|
||||
*changeList = *embeddedData;
|
||||
}
|
||||
@ -480,13 +480,13 @@ void IPTCPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
void IPTCPanel::write (ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
|
||||
pp->iptc = *changeList;
|
||||
pp->metadata.iptc = *changeList;
|
||||
}
|
||||
|
||||
void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited)
|
||||
{
|
||||
|
||||
*defChangeList = defParams->iptc;
|
||||
*defChangeList = defParams->metadata.iptc;
|
||||
}
|
||||
|
||||
void IPTCPanel::setImageData (const FramesMetaData* id)
|
||||
|
@ -6612,15 +6612,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
|
||||
|
||||
// Exif changes are added to the existing ones
|
||||
if (exif) {
|
||||
for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); ++i) {
|
||||
toEdit.exif[i->first] = i->second;
|
||||
for (procparams::ExifPairs::const_iterator i = mods.metadata.exif.begin(); i != mods.metadata.exif.end(); ++i) {
|
||||
toEdit.metadata.exif[i->first] = i->second;
|
||||
}
|
||||
}
|
||||
|
||||
// IPTC changes are added to the existing ones
|
||||
if (iptc) {
|
||||
for (procparams::IPTCPairs::const_iterator i = mods.iptc.begin(); i != mods.iptc.end(); ++i) {
|
||||
toEdit.iptc[i->first] = i->second;
|
||||
for (procparams::IPTCPairs::const_iterator i = mods.metadata.iptc.begin(); i != mods.metadata.iptc.end(); ++i) {
|
||||
toEdit.metadata.iptc[i->first] = i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1215,7 +1215,7 @@ void Thumbnail::saveMetadata()
|
||||
return;
|
||||
}
|
||||
|
||||
if (pparams->exif.empty() && pparams->iptc.empty()) {
|
||||
if (pparams->metadata.exif.empty() && pparams->metadata.iptc.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1224,8 +1224,8 @@ void Thumbnail::saveMetadata()
|
||||
auto xmp = rtengine::Exiv2Metadata::getXmpSidecar(fname);
|
||||
rtengine::Exiv2Metadata meta;
|
||||
meta.xmpData() = std::move(xmp);
|
||||
meta.setExif(pparams->exif);
|
||||
meta.setIptc(pparams->iptc);
|
||||
meta.setExif(pparams->metadata.exif);
|
||||
meta.setIptc(pparams->metadata.iptc);
|
||||
meta.saveToXmp(fn);
|
||||
if (options.rtSettings.verbose) {
|
||||
std::cout << "saved edited metadata for " << fname << " to "
|
||||
|
@ -141,7 +141,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit
|
||||
addfavoritePanel (detailsPanel, dehaze);
|
||||
addfavoritePanel (advancedPanel, wavelet);
|
||||
addfavoritePanel(locallabPanel, locallab);
|
||||
|
||||
|
||||
addfavoritePanel (transformPanel, crop);
|
||||
addfavoritePanel (transformPanel, resize);
|
||||
addPanel (resize->getPackBox(), prsharpening, 2);
|
||||
@ -187,7 +187,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit
|
||||
transformPanelSW = Gtk::manage (new MyScrolledWindow ());
|
||||
rawPanelSW = Gtk::manage (new MyScrolledWindow ());
|
||||
advancedPanelSW = Gtk::manage (new MyScrolledWindow ());
|
||||
locallabPanelSW = Gtk::manage(new MyScrolledWindow());
|
||||
locallabPanelSW = Gtk::manage(new MyScrolledWindow());
|
||||
|
||||
// load panel endings
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@ -585,8 +585,8 @@ void ToolPanelCoordinator::profileChange(
|
||||
|
||||
// Reset IPTC values when switching procparams from the History
|
||||
if (event == rtengine::EvHistoryBrowsed) {
|
||||
mergedParams->iptc.clear();
|
||||
mergedParams->exif.clear();
|
||||
mergedParams->metadata.iptc.clear();
|
||||
mergedParams->metadata.exif.clear();
|
||||
}
|
||||
|
||||
// And apply the partial profile nparams to mergedParams
|
||||
|
Loading…
x
Reference in New Issue
Block a user