Skip to content

Commit ebe2130

Browse files
committed
Fix stacking bug
1 parent be3b3ff commit ebe2130

File tree

1 file changed

+48
-20
lines changed

1 file changed

+48
-20
lines changed

DeepSkyStackerKernel/StackingEngine.cpp

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)