some tweaks to the colour propagation method for highlight recovery
with the attempt to make it "smoother" and more realistic (or at least eye pleasing) in some corner cases
This commit is contained in:
@@ -28,6 +28,8 @@
|
|||||||
#include "rawimagesource.h"
|
#include "rawimagesource.h"
|
||||||
#include "rt_math.h"
|
#include "rt_math.h"
|
||||||
#include "opthelper.h"
|
#include "opthelper.h"
|
||||||
|
#include "gauss.h"
|
||||||
|
|
||||||
namespace rtengine
|
namespace rtengine
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -412,6 +414,9 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b
|
|||||||
constexpr float itrans[ColorCount][ColorCount] =
|
constexpr float itrans[ColorCount][ColorCount] =
|
||||||
{ { 1.f, 0.8660254f, -0.5f }, { 1.f, -0.8660254f, -0.5f }, { 1.f, 0.f, 1.f } };
|
{ { 1.f, 0.8660254f, -0.5f }, { 1.f, -0.8660254f, -0.5f }, { 1.f, 0.f, 1.f } };
|
||||||
|
|
||||||
|
std::unique_ptr<PixelsMap> recovered_partial;
|
||||||
|
std::unique_ptr<PixelsMap> recovered_full;
|
||||||
|
|
||||||
if(settings->verbose)
|
if(settings->verbose)
|
||||||
for(int c = 0; c < 3; c++) {
|
for(int c = 0; c < 3; c++) {
|
||||||
printf("chmax[%d] : %f\tclmax[%d] : %f\tratio[%d] : %f\n", c, chmax[c], c, clmax[c], c, chmax[c] / clmax[c]);
|
printf("chmax[%d] : %f\tclmax[%d] : %f\tratio[%d] : %f\n", c, chmax[c], c, clmax[c], c, chmax[c] / clmax[c]);
|
||||||
@@ -566,7 +571,7 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b
|
|||||||
//blur highlight data
|
//blur highlight data
|
||||||
boxblur2(hilite_full[3], hilite_full4, temp, height, width, 1);
|
boxblur2(hilite_full[3], hilite_full4, temp, height, width, 1);
|
||||||
|
|
||||||
temp.free(); // free temporary buffer
|
//temp.free(); // free temporary buffer
|
||||||
|
|
||||||
if(plistener) {
|
if(plistener) {
|
||||||
progress += 0.05;
|
progress += 0.05;
|
||||||
@@ -1104,29 +1109,39 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b
|
|||||||
//now correct clipped channels
|
//now correct clipped channels
|
||||||
if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) {
|
if (pixel[0] > max_f[0] && pixel[1] > max_f[1] && pixel[2] > max_f[2]) {
|
||||||
//all channels clipped
|
//all channels clipped
|
||||||
float Y = (0.299 * clipfix[0] + 0.587 * clipfix[1] + 0.114 * clipfix[2]);
|
// float Y = (0.299 * clipfix[0] + 0.587 * clipfix[1] + 0.114 * clipfix[2]);
|
||||||
|
// float factor = whitept / Y;
|
||||||
|
// red[i][j] = CLIP(clipfix[0] * factor);
|
||||||
|
// green[i][j] = CLIP(clipfix[1] * factor);
|
||||||
|
// blue[i][j] = CLIP(clipfix[2] * factor);
|
||||||
|
red[i][j] = green[i][j] = blue[i][j] = whitept;
|
||||||
|
if (!recovered_full) {
|
||||||
|
recovered_full.reset(new PixelsMap(width, height));
|
||||||
|
}
|
||||||
|
recovered_full->set(j, i);
|
||||||
|
|
||||||
float factor = whitept / Y;
|
|
||||||
red[i][j] = clipfix[0] * factor;
|
|
||||||
green[i][j] = clipfix[1] * factor;
|
|
||||||
blue[i][j] = clipfix[2] * factor;
|
|
||||||
} else {//some channels clipped
|
} else {//some channels clipped
|
||||||
float notclipped[3] = {pixel[0] <= max_f[0] ? 1.f : 0.f, pixel[1] <= max_f[1] ? 1.f : 0.f, pixel[2] <= max_f[2] ? 1.f : 0.f};
|
float notclipped[3] = {pixel[0] <= max_f[0] ? 1.f : 0.f, pixel[1] <= max_f[1] ? 1.f : 0.f, pixel[2] <= max_f[2] ? 1.f : 0.f};
|
||||||
|
|
||||||
if (notclipped[0] == 0.f) { //red clipped
|
if (notclipped[0] == 0.f) { //red clipped
|
||||||
red[i][j] = max(red[i][j], (clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) /
|
red[i][j] = CLIP((clipfix[0] * ((notclipped[1] * pixel[1] + notclipped[2] * pixel[2]) /
|
||||||
(notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2] + epsilon))));
|
(notclipped[1] * clipfix[1] + notclipped[2] * clipfix[2] + epsilon))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notclipped[1] == 0.f) { //green clipped
|
if (notclipped[1] == 0.f) { //green clipped
|
||||||
green[i][j] = max(green[i][j], (clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) /
|
green[i][j] = CLIP((clipfix[1] * ((notclipped[2] * pixel[2] + notclipped[0] * pixel[0]) /
|
||||||
(notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0] + epsilon))));
|
(notclipped[2] * clipfix[2] + notclipped[0] * clipfix[0] + epsilon))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notclipped[2] == 0.f) { //blue clipped
|
if (notclipped[2] == 0.f) { //blue clipped
|
||||||
blue[i][j] = max(blue[i][j], (clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) /
|
blue[i][j] = CLIP((clipfix[2] * ((notclipped[0] * pixel[0] + notclipped[1] * pixel[1]) /
|
||||||
(notclipped[0] * clipfix[0] + notclipped[1] * clipfix[1] + epsilon))));
|
(notclipped[0] * clipfix[0] + notclipped[1] * clipfix[1] + epsilon))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!recovered_partial) {
|
||||||
|
recovered_partial.reset(new PixelsMap(width, height));
|
||||||
|
}
|
||||||
|
recovered_partial->set(j, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
Y = (0.299 * red[i][j] + 0.587 * green[i][j] + 0.114 * blue[i][j]);
|
Y = (0.299 * red[i][j] + 0.587 * green[i][j] + 0.114 * blue[i][j]);
|
||||||
@@ -1141,6 +1156,54 @@ void RawImageSource :: HLRecovery_inpaint (float** red, float** green, float** b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
for (int c = 0; c < 3; ++c) {
|
||||||
|
float **color = c == 0 ? red : c == 1 ? green : blue;
|
||||||
|
|
||||||
|
if (recovered_partial) {
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel
|
||||||
|
#endif
|
||||||
|
gaussianBlur(color, temp, width, height, 1.5f);
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < height; ++i) {
|
||||||
|
for (int j = 0; j < width; ++j) {
|
||||||
|
int skip = recovered_partial->skipIfZero(j, i);
|
||||||
|
if (skip) {
|
||||||
|
j += skip-1;
|
||||||
|
} else if (recovered_partial->get(j, i)) {
|
||||||
|
color[i][j] = temp[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recovered_full) {
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel
|
||||||
|
#endif
|
||||||
|
gaussianBlur(color, temp, width, height, 3.f);
|
||||||
|
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < height; ++i) {
|
||||||
|
for (int j = 0; j < width; ++j) {
|
||||||
|
int skip = recovered_full->skipIfZero(j, i);
|
||||||
|
if (skip) {
|
||||||
|
j += skip-1;
|
||||||
|
} else if (recovered_full->get(j, i)) {
|
||||||
|
color[i][j] = temp[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(plistener) {
|
if(plistener) {
|
||||||
plistener->setProgress(1.00);
|
plistener->setProgress(1.00);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user