metadata: make sure to include XResolution and YResolution when writing TIFFs
This is mandatory (according to http://dpfmanager.org), and in fact needed for Photoshop compatibility (cherry picked from commit 5d281810cc7a7f7dc563dde030cf90c78dbf55d0)
This commit is contained in:
committed by
Lawrence Lee
parent
939315f67b
commit
522f6f4473
@@ -1098,6 +1098,7 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con
|
|||||||
return IMIO_SUCCESS;
|
return IMIO_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool uncompressed) const
|
int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool uncompressed) const
|
||||||
{
|
{
|
||||||
if (getWidth() < 1 || getHeight() < 1) {
|
if (getWidth() < 1 || getHeight() < 1) {
|
||||||
@@ -1168,6 +1169,31 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||||||
}
|
}
|
||||||
}();*/
|
}();*/
|
||||||
|
|
||||||
|
// somehow Exiv2 (tested with 0.27.3) doesn't seem to be able to update
|
||||||
|
// XResolution and YResolution, so we do it ourselves here....
|
||||||
|
constexpr float default_resolution = 300.f;
|
||||||
|
float x_res = default_resolution;
|
||||||
|
float y_res = default_resolution;
|
||||||
|
int res_unit = RESUNIT_INCH;
|
||||||
|
if (!metadataInfo.filename().empty()) {
|
||||||
|
auto exif = metadataInfo.getOutputExifData();
|
||||||
|
auto it = exif.findKey(Exiv2::ExifKey("Exif.Image.XResolution"));
|
||||||
|
if (it != exif.end()) {
|
||||||
|
x_res = it->toFloat();
|
||||||
|
}
|
||||||
|
it = exif.findKey(Exiv2::ExifKey("Exif.Image.YResolution"));
|
||||||
|
if (it != exif.end()) {
|
||||||
|
y_res = it->toFloat();
|
||||||
|
}
|
||||||
|
it = exif.findKey(Exiv2::ExifKey("Exif.Image.ResolutionUnit"));
|
||||||
|
if (it != exif.end()) {
|
||||||
|
res_unit = it->toLong();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TIFFSetField(out, TIFFTAG_XRESOLUTION, x_res);
|
||||||
|
TIFFSetField(out, TIFFTAG_YRESOLUTION, y_res);
|
||||||
|
TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, res_unit);
|
||||||
|
|
||||||
if (!uncompressed) {
|
if (!uncompressed) {
|
||||||
TIFFSetField (out, TIFFTAG_PREDICTOR, (bps == 16 || bps == 32) && isFloat ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL);
|
TIFFSetField (out, TIFFTAG_PREDICTOR, (bps == 16 || bps == 32) && isFloat ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL);
|
||||||
}
|
}
|
||||||
|
@@ -390,7 +390,12 @@ void Exiv2Metadata::import_exif_pairs(Exiv2::ExifData &out) const
|
|||||||
for (auto &p : *exif_) {
|
for (auto &p : *exif_) {
|
||||||
try {
|
try {
|
||||||
out[p.first] = p.second;
|
out[p.first] = p.second;
|
||||||
} catch (std::exception &exc) {}
|
} catch (std::exception &exc) {
|
||||||
|
if (settings->verbose) {
|
||||||
|
std::cout << "Error setting " << p.first << " to " << p.second
|
||||||
|
<< ": " << exc.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,7 +413,12 @@ void Exiv2Metadata::import_iptc_pairs(Exiv2::IptcData &out) const
|
|||||||
out.add(d);
|
out.add(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (std::exception &exc) {}
|
} catch (std::exception &exc) {
|
||||||
|
if (settings->verbose) {
|
||||||
|
std::cout << "Error setting " << p.first
|
||||||
|
<< ": " << exc.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,4 +525,30 @@ void Exiv2Metadata::cleanup()
|
|||||||
Exiv2::XmpParser::terminate();
|
Exiv2::XmpParser::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Exiv2::ExifData Exiv2Metadata::getOutputExifData() const
|
||||||
|
{
|
||||||
|
Exiv2::ExifData exif = exifData();
|
||||||
|
try {
|
||||||
|
auto xmp = getXmpSidecar(src_);
|
||||||
|
Exiv2::moveXmpToExif(xmp, exif);
|
||||||
|
} catch (std::exception &exc) {
|
||||||
|
if (settings->verbose) {
|
||||||
|
std::cerr << "Error loading metadata from XMP sidecar: "
|
||||||
|
<< exc.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remove_unwanted(exif);
|
||||||
|
import_exif_pairs(exif);
|
||||||
|
for (auto it = exif.begin(); it != exif.end(); ) {
|
||||||
|
if (it->count() > 0) {
|
||||||
|
++it;
|
||||||
|
} else {
|
||||||
|
it = exif.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exif;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace rtengine
|
} // namespace rtengine
|
||||||
|
@@ -60,6 +60,8 @@ public:
|
|||||||
|
|
||||||
void getDimensions(int &w, int &h) const;
|
void getDimensions(int &w, int &h) const;
|
||||||
|
|
||||||
|
Exiv2::ExifData getOutputExifData() const;
|
||||||
|
|
||||||
static Glib::ustring xmpSidecarPath(const Glib::ustring& path);
|
static Glib::ustring xmpSidecarPath(const Glib::ustring& path);
|
||||||
static Exiv2::XmpData getXmpSidecar(const Glib::ustring& path);
|
static Exiv2::XmpData getXmpSidecar(const Glib::ustring& path);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user