jcelaya / hdrmerge

HDR exposure merging
http://jcelaya.github.io/hdrmerge/
Other
355 stars 78 forks source link

Add support for Pentax HDR raw files with 3 frames #137

Closed heckflosse closed 6 years ago

heckflosse commented 6 years ago

First patch.

Raw file for test can be downloaded here

@Hombre57 please test :grin:

diff --git a/src/ImageIO.cpp b/src/ImageIO.cpp
index cc3c33a..552e2a2 100644
--- a/src/ImageIO.cpp
+++ b/src/ImageIO.cpp
@@ -33,9 +33,10 @@
 using namespace std;
 using namespace hdrmerge;

-Image ImageIO::loadRawImage(RawParameters & rawParameters) {
+Image ImageIO::loadRawImage(RawParameters & rawParameters, int shot_select) {
     LibRaw rawProcessor;
     auto & d = rawProcessor.imgdata;
+    d.params.shot_select = shot_select;
     if (rawProcessor.open_file(rawParameters.fileName.toLocal8Bit().constData()) == LIBRAW_SUCCESS) {
         Log::msg(Log::DEBUG, "Number of frames : ", d.idata.raw_count);
         libraw_decoder_info_t decoder_info;
@@ -57,7 +58,16 @@ Image ImageIO::loadRawImage(RawParameters & rawParameters) {
     return Image(d.rawdata.raw_image, rawParameters);
 }

+int ImageIO::getFrameCount(RawParameters & rawParameters) {
+    LibRaw rawProcessor;
+    auto & d = rawProcessor.imgdata;
+    if (rawProcessor.open_file(rawParameters.fileName.toLocal8Bit().constData()) == LIBRAW_SUCCESS) {
+        return d.idata.raw_count;
+    } else {
+        return 0;
+    }

+}

 ImageIO::QDateInterval ImageIO::getImageCreationInterval(const QString & fileName) {
     LibRaw rawProcessor;
@@ -79,27 +89,66 @@ int ImageIO::load(const LoadOptions & options, ProgressIndicator & progress) {
     rawParameters.clear();
     {
         Timer t("Load files");
-        #pragma omp parallel for schedule(dynamic)
-        for (int i = 0; i < numImages; ++i) {
-            if (!error) { // We cannot break from the for loop if we are using OpenMP
-                QString name = options.fileNames[i];
-                #pragma omp critical
-                progress.advance(p += step, "Loading %1", name.toLocal8Bit().constData());
-                unique_ptr<RawParameters> params(new RawParameters(name));
-                Image image = loadRawImage(*params);
-                #pragma omp critical
-                if (!error) { // Report on the first image that fails, ignore the rest
-                    if (!image.good()) {
-                        error = 1;
-                        failedImage = i;
-                    } else if (stack.size() && !params->isSameFormat(*rawParameters.front())) {
-                        error = 2;
-                        failedImage = i;
-                    } else {
-                        int pos = stack.addImage(std::move(image));
-                        rawParameters.emplace_back(std::move(params));
-                        for (int j = rawParameters.size() - 1; j > pos; --j)
-                            rawParameters[j - 1].swap(rawParameters[j]);
+        if(numImages == 1) { // check for multiframe raw files
+            QString name = options.fileNames[0];
+            unique_ptr<RawParameters> params(new RawParameters(name));
+            int frameCount = getFrameCount(*params);
+            if(frameCount == 3 || frameCount == 1) {
+                for (int i = 0; i < frameCount; ++i) {
+                    if (!error) { // We cannot break from the for loop if we are using OpenMP
+                        QString name = options.fileNames[0];
+                        #pragma omp critical
+                        progress.advance(p += step, "Loading %1", name.toLocal8Bit().constData());
+                        unique_ptr<RawParameters> params(new RawParameters(name));
+
+                        Image image;
+                        {
+                            Timer t("loadRawImage");
+                            image = loadRawImage(*params, i);
+                        }
+                        if (!error) { // Report on the first image that fails, ignore the rest
+                            if (!image.good()) {
+                                error = 1;
+                                failedImage = i;
+                            } else if (stack.size() && !params->isSameFormat(*rawParameters.front())) {
+                                error = 2;
+                                failedImage = i;
+                            } else {
+                                int pos = stack.addImage(std::move(image));
+                                rawParameters.emplace_back(std::move(params));
+                                for (int j = rawParameters.size() - 1; j > pos; --j)
+                                    rawParameters[j - 1].swap(rawParameters[j]);
+                            }
+                        }
+                    }
+                }
+            }
+        } else {
+            for (int i = 0; i < numImages; ++i) {
+                if (!error) { // We cannot break from the for loop if we are using OpenMP
+                    QString name = options.fileNames[i];
+                    #pragma omp critical
+                    progress.advance(p += step, "Loading %1", name.toLocal8Bit().constData());
+                    unique_ptr<RawParameters> params(new RawParameters(name));
+
+                    Image image;
+                    {
+                        Timer t("loadRawImage");
+                        image = loadRawImage(*params);
+                    }
+                    if (!error) { // Report on the first image that fails, ignore the rest
+                        if (!image.good()) {
+                            error = 1;
+                            failedImage = i;
+                        } else if (stack.size() && !params->isSameFormat(*rawParameters.front())) {
+                            error = 2;
+                            failedImage = i;
+                        } else {
+                            int pos = stack.addImage(std::move(image));
+                            rawParameters.emplace_back(std::move(params));
+                            for (int j = rawParameters.size() - 1; j > pos; --j)
+                                rawParameters[j - 1].swap(rawParameters[j]);
+                        }
                     }
                 }
             }
diff --git a/src/ImageIO.hpp b/src/ImageIO.hpp
index ea812a7..4a81980 100644
--- a/src/ImageIO.hpp
+++ b/src/ImageIO.hpp
@@ -51,7 +51,8 @@ public:
     QString buildOutputFileName() const;
     QString getInputPath() const;
     QString replaceArguments(const QString & pattern, const QString & outFileName) const;
-    static Image loadRawImage(RawParameters & rawParameters);
+    static int getFrameCount(RawParameters & rawParameters) ;
+    static Image loadRawImage(RawParameters & rawParameters, int shot_select = 0);
     static QImage renderPreview(const Array2D<float> & rawData, const RawParameters & rawParameters, float expShift, bool halfsize = false);

     struct QDateInterval {
Hombre57 commented 6 years ago
Hombre57 commented 6 years ago

@heckflosse Works nice ! That's a great improvement :+1: :1st_place_medal:

Hombre57 commented 6 years ago

Would it be possible to change the label on the second window (added files) to explain there's 3 frames in the DNG file ? (but it's already good as is)

heckflosse commented 6 years ago

@Hombre57 Thanks for testing :+1: