diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index 4fd01259c..533c30eeb 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -6935,28 +6935,6 @@ it under the terms of the one of two licenses as you choose: ((int *)mask)[i] = getint(type); black = 0; break; - case 51008: /* OpcodeList1 */ - { - unsigned oldOrder = order; - order = 0x4d4d; // always big endian per definition in https://www.adobe.com/content/dam/acom/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf chapter 7 - unsigned ntags = get4(); // read the number of opcodes - if (ntags < ifp->size / 12) { // rough check for wrong value (happens for example with DNG files from DJI FC6310) - while (ntags-- && !ifp->eof) { - unsigned opcode = get4(); - fseek (ifp, 8, SEEK_CUR); // skip 8 bytes as they don't interest us currently - if (opcode == 4) { // FixBadPixelsConstant - fseek (ifp, 4, SEEK_CUR); // skip 4 bytes as we know that the opcode 4 takes 4 byte - if(get4() == 0) { // if raw 0 values should be treated as bad pixels, set zero_is_bad to true (1). That's the only value currently supported by rt - zero_is_bad = 1; - } - } else { - fseek (ifp, get4(), SEEK_CUR); - } - } - } - order = oldOrder; - break; - } case 51009: /* OpcodeList2 */ meta_offset = ftell(ifp); break; diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index eff903ce6..44a37f296 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -168,10 +168,15 @@ public: } }; +std::uint32_t readFixBadPixelsConstant(TagValueReader &reader) +{ + reader.seekRelative(12); // Skip DNG spec version, flags, and tag size. + return reader.readUInt(); +} + GainMap readGainMap(TagValueReader &reader) { - reader.seekRelative(4); // skip 4 bytes as we know that the opcode 4 takes 4 byte - reader.seekRelative(8); // skip 8 bytes as they don't interest us currently + reader.seekRelative(12); // Skip DNG spec version, flags, and tag size. GainMap gainMap; gainMap.Top = reader.readUInt(); gainMap.Left = reader.readUInt(); @@ -196,7 +201,11 @@ GainMap readGainMap(TagValueReader &reader) return gainMap; } -void readOpcodesList(const Exiv2::Value &value, std::vector &gainMaps) +void readOpcodesList( + const Exiv2::Value &value, + std::uint32_t *fixBadPixelsConstant, + bool *hasFixBadPixelsConstant, + std::vector *gainMaps) { TagValueReader reader(value); std::uint32_t ntags = reader.readUInt(); // read the number of opcodes @@ -205,8 +214,16 @@ void readOpcodesList(const Exiv2::Value &value, std::vector &gainMaps) } while (ntags-- && !reader.isEnd()) { unsigned opcode = reader.readUInt(); - if (opcode == 9 && gainMaps.size() < 4) { - gainMaps.push_back(readGainMap(reader)); + if (opcode == 4 && (fixBadPixelsConstant || hasFixBadPixelsConstant)) { + const auto constant = readFixBadPixelsConstant(reader); + if (fixBadPixelsConstant) { + *fixBadPixelsConstant = constant; + } + if (hasFixBadPixelsConstant) { + *hasFixBadPixelsConstant = true; + } + } else if (opcode == 9 && gainMaps && gainMaps->size() < 4) { + gainMaps->push_back(readGainMap(reader)); } else { reader.seekRelative(8); // skip 8 bytes as they don't interest us currently reader.seekRelative(reader.readUInt()); @@ -826,16 +843,20 @@ FramesData::FramesData(const Glib::ustring &fname, time_t ts) : } } - uint32_t dngVersion = 0; + std::uint32_t dngVersion = 0; if (find_exif_tag("Exif.Image.DNGVersion") && pos->count() == 4) { for (int i = 0; i < 4; i++) { - dngVersion = (dngVersion << 8) + static_cast(to_long(pos, i)); + dngVersion = (dngVersion << 8) + static_cast(to_long(pos, i)); } } - // Read gain maps. + // Read DNG OpcodeList1. + if (dngVersion && (find_exif_tag("Exif.SubImage1.OpcodeList1") || find_exif_tag("Exif.Image.OpcodeList1"))) { + readOpcodesList(pos->value(), &fixBadPixelsConstant, &hasFixBadPixelsConstant_, nullptr); + } + // Read DNG OpcodeList2. if (dngVersion && (find_exif_tag("Exif.SubImage1.OpcodeList2") || find_exif_tag("Exif.Image.OpcodeList2"))) { - readOpcodesList(pos->value(), gain_maps_); + readOpcodesList(pos->value(), nullptr, nullptr, &gain_maps_); } } catch (const std::exception& e) { if (settings->verbose) { @@ -1078,6 +1099,16 @@ void FramesData::fillBasicTags(Exiv2::ExifData &exif) const set_exif(exif, "Exif.Photo.DateTimeOriginal", buf); } +std::uint32_t FramesData::getFixBadPixelsConstant() const +{ + return fixBadPixelsConstant; +} + +bool FramesData::hasFixBadPixelsConstant() const +{ + return hasFixBadPixelsConstant_; +} + std::vector FramesData::getGainMaps() const { return gain_maps_; diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 434b96a52..1d7f715d3 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -60,6 +60,8 @@ private: time_t modTimeStamp; bool isPixelShift; bool isHDR; + std::uint32_t fixBadPixelsConstant; + bool hasFixBadPixelsConstant_{false}; std::vector gain_maps_; int w_; int h_; @@ -90,6 +92,8 @@ public: std::string getOrientation() const override; Glib::ustring getFileName() const override; int getRating() const override; + std::uint32_t getFixBadPixelsConstant() const override; + bool hasFixBadPixelsConstant() const override; std::vector getGainMaps() const override; void getDimensions(int &w, int &h) const override; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 7c77d57c6..53c850dac 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -1439,7 +1439,7 @@ void RawImageSource::preprocess(const RAWParams &raw, const LensProfParams &lens int totBP = 0; // Hold count of bad pixels to correct - if (ri->zeroIsBad()) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica) + if (ri->zeroIsBad() || (getMetaData()->hasFixBadPixelsConstant() && getMetaData()->getFixBadPixelsConstant() == 0)) { // mark all pixels with value zero as bad, has to be called before FF and DF. dcraw sets this flag only for some cameras (mainly Panasonic and Leica) bitmapBads.reset(new PixelsMap(W, H)); totBP = findZeroPixels(*bitmapBads); diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 0db06849a..e5b374faa 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include #include @@ -159,6 +160,8 @@ public: static FramesMetaData* fromFile(const Glib::ustring& fname); virtual Glib::ustring getFileName() const = 0; + virtual std::uint32_t getFixBadPixelsConstant() const = 0; + virtual bool hasFixBadPixelsConstant() const = 0; virtual std::vector getGainMaps() const = 0; virtual void getDimensions(int &w, int &h) const = 0; }; diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc index 13a2e31e0..0f9826fb0 100644 --- a/rtgui/cacheimagedata.cc +++ b/rtgui/cacheimagedata.cc @@ -362,6 +362,16 @@ int CacheImageData::save (const Glib::ustring& fname) } } +std::uint32_t CacheImageData::getFixBadPixelsConstant() const +{ + return 0; +} + +bool CacheImageData::hasFixBadPixelsConstant() const +{ + return false; +} + std::vector CacheImageData::getGainMaps() const { return std::vector(); diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 12c4ed476..91abdbf83 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -117,6 +117,8 @@ public: bool getHDR() const override { return isHDR; } std::string getImageType() const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; } rtengine::IIOSampleFormat getSampleFormat() const override { return sampleFormat; } + std::uint32_t getFixBadPixelsConstant() const override; + bool hasFixBadPixelsConstant() const override; std::vector getGainMaps() const override; void getDimensions(int &w, int &h) const override {