@@ -876,14 +876,7 @@ bool computeOffsets(CStackingEngine* const pStackingEngine, OldProgressBase* con
876876 return !stop;
877877}
878878
879-
880- void CStackingEngine::ComputeOffsets ()
881- {
882- ZFUNCTRACE_RUNTIME ();
883-
884- if (bitmapsToStack.empty ())
885- return ;
886-
879+ namespace {
887880 constexpr auto QualityComp = [](const CLightFrameInfo& l, const CLightFrameInfo& r)
888881 {
889882 if (l.m_bStartingFrame )
@@ -892,6 +885,15 @@ void CStackingEngine::ComputeOffsets()
892885 return false ;
893886 return l.quality > r.quality ;
894887 };
888+ }
889+
890+ void CStackingEngine::ComputeOffsets ()
891+ {
892+ ZFUNCTRACE_RUNTIME ();
893+
894+ if (bitmapsToStack.empty ())
895+ return ;
896+
895897 std::ranges::sort (bitmapsToStack, QualityComp);
896898
897899 this ->m_lNrStackable = bitmapsToStack[0 ].m_bDisabled ? 0 : std::min (static_cast <int >(bitmapsToStack.size ()), 1 );
@@ -966,13 +968,15 @@ void CStackingEngine::RemoveNonStackableLightFrames(CAllStackingTasks& tasks)
966968 newFrameInfoList.push_back (frameInfo);
967969 }
968970
969- // If the list is empty - consider that the task is done
970- if (newFrameInfoList.empty ())
971- taskInfo.m_bDone = true ;
971+ const bool nothingToDo = newFrameInfoList.empty ();
972972
973- // Remove non stackable light frames from the list
973+ // Remove non stackable light frames from the list.
974974 if (newFrameInfoList.size () < taskInfo.m_vBitmaps .size ())
975- taskInfo.m_vBitmaps = std::move (newFrameInfoList);
975+ taskInfo.m_vBitmaps .swap (newFrameInfoList);
976+
977+ // If the list was empty, consider that the task is done.
978+ if (nothingToDo)
979+ taskInfo.m_bDone = true ;
976980 }
977981 }
978982}
@@ -1175,7 +1179,10 @@ int CStackingEngine::findBitmapIndex(const fs::path& file) const
11751179{
11761180 ZFUNCTRACE_RUNTIME ();
11771181
1178- const auto it = std::ranges::find (this ->bitmapsToStack , file, &CLightFrameInfo::filePath);
1182+ const auto it = std::ranges::find_if (
1183+ this ->bitmapsToStack ,
1184+ [&file](CLightFrameInfo const & bitmapToStack) { return bitmapToStack.filePath .compare (file) == 0 ; }
1185+ );
11791186 return it == std::ranges::end (bitmapsToStack) ? -1 : static_cast <int >(std::ranges::distance (std::ranges::begin (bitmapsToStack), it));
11801187/*
11811188 for (size_t i = 0; i < bitmapsToStack.size(); i++)
@@ -2189,16 +2196,38 @@ bool CStackingEngine::StackAll(CAllStackingTasks& tasks, std::shared_ptr<CMemory
21892196 pTaskInfo->m_Method = MBP_FASTAVERAGE;
21902197 }
21912198
2199+ // bitmapsToStack:
2200+ // Is a vector<LightFrameInfo>, so it contains the bi-linear alignment parameters, the image quality, etc.
2201+ // It is sorted by quality.
2202+ //
2203+ // pStackingInfo->m_pLightTask->m_vBitmaps:
2204+ // Is a vector<FrameInfo>, so it contains only basic information, like file path, picture type, etc.
2205+ //
2206+ // FYI: LightFrameInfo derives from FrameInfo.
2207+
2208+ const auto GetLightframeInfoIndexes = [this ](FRAMEINFOVECTOR const & frameInfoVector) -> std::vector<int >
2209+ {
21922210 constexpr bool UseQualityOrder = true ;
21932211
2194- const auto ReadTask = [this , pStackingInfo, UseQualityOrder](const size_t lightFrameNdx, OldProgressBase* pProgress) -> std::pair<std::shared_ptr<CMemoryBitmap>, int >
2212+ std::vector<int > indexes (frameInfoVector.size ());
2213+ std::ranges::transform (frameInfoVector, indexes.begin (), [this ](CFrameInfo const & frameInfo) { return findBitmapIndex (frameInfo.filePath ); });
2214+ // Indexes contains the indexes of the frameInfoVector into the vector bitmapsToStack.
2215+ if constexpr (UseQualityOrder)
2216+ std::ranges::sort (indexes);
2217+ // After sorting, the light frames are sorted by quality, because bitmapsToStack is sorted by quality.
2218+ return indexes;
2219+ };
2220+
2221+ const auto ReadTask = [this , lightFrameIndexes = GetLightframeInfoIndexes (pStackingInfo->m_pLightTask ->m_vBitmaps )](
2222+ const size_t lightFrameNdx, OldProgressBase* pProgress
2223+ ) -> std::pair<std::shared_ptr<CMemoryBitmap>, int >
21952224 {
2196- if (lightFrameNdx >= (UseQualityOrder ? bitmapsToStack .size () : pStackingInfo-> m_pLightTask -> m_vBitmaps . size () ))
2225+ if (lightFrameNdx >= lightFrameIndexes .size ())
21972226 return { {}, -1 };
2198- const int bitmapNdx = UseQualityOrder ? static_cast < int >(lightFrameNdx) : findBitmapIndex (pStackingInfo-> m_pLightTask -> m_vBitmaps [lightFrameNdx]. filePath );
2227+ const int bitmapNdx = lightFrameIndexes[lightFrameNdx]; // That's the index into the vector this->bitmapsToStack.
21992228 if (bitmapNdx < 0 )
22002229 return { {}, -1 };
2201- const auto & lightframeInfo = bitmapsToStack[bitmapNdx];
2230+ const auto & lightframeInfo = this -> bitmapsToStack [bitmapNdx];
22022231 if (lightframeInfo.m_bDisabled )
22032232 return { {}, -1 };
22042233
@@ -2217,8 +2246,7 @@ bool CStackingEngine::StackAll(CAllStackingTasks& tasks, std::shared_ptr<CMemory
22172246 using T = std::future<bool >;
22182247 T futureForWriteTempFile{};
22192248
2220- const size_t sizeOfBitmapVector = UseQualityOrder ? this ->bitmapsToStack .size () : pStackingInfo->m_pLightTask ->m_vBitmaps .size ();
2221- for (size_t i = 0 ; i < sizeOfBitmapVector && !bStop; ++i)
2249+ for (size_t i = 0 ; i < pStackingInfo->m_pLightTask ->m_vBitmaps .size () && !bStop; ++i)
22222250 {
22232251 auto [pBitmap, bitmapNdx] = futureForRead.get ();
22242252 futureForRead = std::async (std::launch::async, ReadTask, i + 1 , nullptr ); // Immediately load next lightframe asynchronously (need to set progress pointer to null).
0 commit comments