Made unlinked stretch white balancing

This commit is contained in:
2023-11-14 23:47:47 +01:00
parent e97e10fb5b
commit 544e4abf92
4 changed files with 52 additions and 32 deletions
+29 -17
View File
@@ -123,7 +123,7 @@ const RawImage::Stats& RawImage::imageStats()
}
template<typename T, typename U, int ch>
void calcStats(const T *data, size_t n, RawImage::Stats &stats)
void calcStats(const T *data, size_t n, size_t w, RawImage::Stats &stats)
{
U sum[4] = {0};
U sumSq[4] = {0};
@@ -150,7 +150,7 @@ void calcStats(const T *data, size_t n, RawImage::Stats &stats)
if(d > sat)saturated[x]++;
};
auto findMedian = [n, histSize](uint32_t histogram[]) -> size_t
auto findMedian = [histSize](uint32_t histogram[], size_t n) -> size_t
{
size_t histSum = 0;
for(size_t o=0; o < histSize; o++)
@@ -162,6 +162,13 @@ void calcStats(const T *data, size_t n, RawImage::Stats &stats)
return 0;
};
size_t na[4] = {n, n, n, n};
if constexpr(ch == 1)
{
na[1] /= 4;
na[2] /= 2;
na[3] /= 4;
}
for(size_t i = 0; i < n; i++)
{
statsFunc(data[i*ch], 0);
@@ -170,18 +177,23 @@ void calcStats(const T *data, size_t n, RawImage::Stats &stats)
statsFunc(data[i*ch + 1], 1);
statsFunc(data[i*ch + 2], 2);
}
if constexpr(ch == 1)
{
int bayer = (i % w & 1) + (i / w & 1) + 1;
statsFunc(data[i], bayer);
}
}
for(int i = 0; i < 3; i++)
for(int i = 0; i < 4; i++)
{
stats.m_min[i] = min[i];
stats.m_max[i] = max[i];
stats.m_mean[i] = (double)sum[i] / n;
stats.m_mean[i] = (double)sum[i] / na[i];
stats.m_saturated[i] = saturated[i];
double sum2 = (double)sum[i] * sum[i];
stats.m_stdDev[i] = std::sqrt((sumSq[i] - sum2 / n) / (n - 1));
stats.m_stdDev[i] = std::sqrt((sumSq[i] - sum2 / na[i]) / (na[i] - 1));
uint32_t median = findMedian(histogram[i]);
uint32_t median = findMedian(histogram[i], na[i]);
stats.m_median[i] = median;
uint32_t madHist[65536] = {0};
madHist[0] = histogram[i][median];
@@ -190,7 +202,7 @@ void calcStats(const T *data, size_t n, RawImage::Stats &stats)
if(median + o < histSize)madHist[o] += histogram[i][median + o];
if(o <= median)madHist[o] += histogram[i][median - o];
}
stats.m_mad[i] = findMedian(madHist);
stats.m_mad[i] = findMedian(madHist, na[i]);
if constexpr(!std::numeric_limits<T>::is_integer)
{
stats.m_median[i] /= 65535.0;
@@ -213,33 +225,33 @@ void RawImage::calcStats()
{
case UINT8:
if(channels()==1)
::calcStats<uint8_t, uint64_t, 1>(static_cast<const uint8_t*>(origData()), size(), m_stats);
::calcStats<uint8_t, uint64_t, 1>(static_cast<const uint8_t*>(origData()), size(), width(), m_stats);
else
::calcStats<uint8_t, uint64_t, 4>(static_cast<const uint8_t*>(origData()), size(), m_stats);
::calcStats<uint8_t, uint64_t, 4>(static_cast<const uint8_t*>(origData()), size(), width(), m_stats);
break;
case UINT16:
if(channels()==1)
::calcStats<uint16_t, uint64_t, 1>(static_cast<const uint16_t*>(origData()), size(), m_stats);
::calcStats<uint16_t, uint64_t, 1>(static_cast<const uint16_t*>(origData()), size(), width(), m_stats);
else
::calcStats<uint16_t, uint64_t, 4>(static_cast<const uint16_t*>(origData()), size(), m_stats);
::calcStats<uint16_t, uint64_t, 4>(static_cast<const uint16_t*>(origData()), size(), width(), m_stats);
break;
case UINT32:
if(channels()==1)
::calcStats<uint32_t, double, 1>(static_cast<const uint32_t*>(origData()), size(), m_stats);
::calcStats<uint32_t, double, 1>(static_cast<const uint32_t*>(origData()), size(), width(), m_stats);
else
::calcStats<uint32_t, double, 4>(static_cast<const uint32_t*>(origData()), size(), m_stats);
::calcStats<uint32_t, double, 4>(static_cast<const uint32_t*>(origData()), size(), width(), m_stats);
break;
case FLOAT32:
if(channels()==1)
::calcStats<float, double, 1>(static_cast<const float*>(origData()), size(), m_stats);
::calcStats<float, double, 1>(static_cast<const float*>(origData()), size(), width(), m_stats);
else
::calcStats<float, double, 4>(static_cast<const float*>(origData()), size(), m_stats);
::calcStats<float, double, 4>(static_cast<const float*>(origData()), size(), width(), m_stats);
break;
case FLOAT64:
if(channels()==1)
::calcStats<double, double, 1>(static_cast<const double*>(origData()), size(), m_stats);
::calcStats<double, double, 1>(static_cast<const double*>(origData()), size(), width(), m_stats);
else
::calcStats<double, double, 4>(static_cast<const double*>(origData()), size(), m_stats);
::calcStats<double, double, 4>(static_cast<const double*>(origData()), size(), width(), m_stats);
break;
}
}