diff --git a/rtdata/languages/Catala b/rtdata/languages/Catala
index e702cbe49..a2d8012cd 100644
--- a/rtdata/languages/Catala
+++ b/rtdata/languages/Catala
@@ -1867,9 +1867,9 @@ ZOOMPANEL_ZOOMOUT;Allunya\nDrecera: -
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/Chinese (Simplified) b/rtdata/languages/Chinese (Simplified)
index 387d8fb85..556f609ea 100644
--- a/rtdata/languages/Chinese (Simplified)
+++ b/rtdata/languages/Chinese (Simplified)
@@ -1814,9 +1814,9 @@ ZOOMPANEL_ZOOMOUT;缩放拉远\n快捷键: -
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech
index 5c807b61d..af9ae0c88 100644
--- a/rtdata/languages/Czech
+++ b/rtdata/languages/Czech
@@ -961,8 +961,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Barva pozadí náhledu: bílá\nZkratka: 9
MAIN_TOOLTIP_BACKCOLOR3;Barva pozadí náhledu: středně šedá\nZkratka: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Zamknout / Odemknout pohled Před\n\nZamknout: ponechá pohled Před nezměněn.\nUžitečné pro posouzení výsledného efektu po použití více nástrojů.\nNavíc může být porovnání provedeno proti kterémukoli stavu v historii.\n\nOdemknout: pohled Před bude následovat pohled Poté, vždy jen o jeden krok zpět, představí vliv právě použitého nástroje.
MAIN_TOOLTIP_HIDEHP;Zobrazit či schovat levý panel (obsahující historii).\nZkratka: l
-MAIN_TOOLTIP_INDCLIPPEDH;Zvýraznit oříznutá světla.\nZkratka: <
-MAIN_TOOLTIP_INDCLIPPEDS;Zvýraznit oříznuté stíny.\nZkratka: >
+MAIN_TOOLTIP_INDCLIPPEDH;Zvýraznit oříznutá světla.\nZkratka: >
+MAIN_TOOLTIP_INDCLIPPEDS;Zvýraznit oříznuté stíny.\nZkratka: <
MAIN_TOOLTIP_PREVIEWB;Náhled modrého kanálu.\nZkratka: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Náhled masky zaostření.\nZkratka: Shift-f\n\nVíce přesné u snímků s nízkou hloubkou ostrosti, nízkým šumem a na vyšších úrovních zvětšení.\n\nPoužijte přiblížení v rozsahu 10 až 30% pro zlepšení přesnosti detekce u zašuměných snímků.
MAIN_TOOLTIP_PREVIEWG;Náhled zeleného kanálu.\nZkratka: g
@@ -2340,9 +2340,9 @@ ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: -
!TP_DEHAZE_LUMINANCE;Luminance only
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_PDSHARPENING_LABEL;Capture Sharpening
!TP_SHARPENING_GAMMA;Gamma
diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch
index 2f7dbaf4c..0ee886945 100644
--- a/rtdata/languages/Deutsch
+++ b/rtdata/languages/Deutsch
@@ -82,8 +82,8 @@
#81 15.04.2019 Erweiterung (TooWaBoo) RT 5.6
#82 25.05.2019 Erweiterung (TooWaBoo) RT 5.6
#83 06.07.2019 Erweiterung (TooWaBoo) RT 5.6
-#84 18.07.2019 Erweiterung (TooWaBoo) RT 5.6
#84 06.10.2019 Erweiterung (TooWaBoo) RT 5.7
+#84 18.07.2019 Erweiterung (TooWaBoo) RT 5.6
ABOUT_TAB_BUILD;Version
ABOUT_TAB_CREDITS;Danksagungen
@@ -809,6 +809,7 @@ HISTORY_MSG_490;(Dynamikkompression)\nIntensität
HISTORY_MSG_491;(Weißabgleich)
HISTORY_MSG_492;(RGB-Kurven)
HISTORY_MSG_493;(L*a*b*)
+HISTORY_MSG_494;(Eingangsschärfung)
HISTORY_MSG_CLAMPOOG;(Belichtung) - Farben\nauf Farbraum beschränken
HISTORY_MSG_COLORTONING_LABGRID_VALUE;(Farbanpassungen)\nL*a*b*-Farbkorrektur
HISTORY_MSG_COLORTONING_LABREGION_AB;(Farbanpassungen)\nL*a*b*-Farbkorrektur\nBereich
@@ -826,6 +827,7 @@ HISTORY_MSG_COLORTONING_LABREGION_SHOWMASK;(Farbanpassungen)\nL*a*b*-Farbkorrekt
HISTORY_MSG_COLORTONING_LABREGION_SLOPE;(Farbanpassungen)\nL*a*b*-Farbkorrektur\nBereich - Steigung
HISTORY_MSG_DEHAZE_DEPTH;(Bildschleier entfernen)\nTiefe
HISTORY_MSG_DEHAZE_ENABLED;(Bildschleier entfernen)
+HISTORY_MSG_DEHAZE_LUMINANCE;(Bildschleier entfernen)\nNur Luminanz
HISTORY_MSG_DEHAZE_SHOW_DEPTH_MAP;(Bildschleier entfernen)\nMaske anzeigen
HISTORY_MSG_DEHAZE_STRENGTH;(Bildschleier entfernen)\nIntensität
HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST;(Sensor—Matrix)\nFarbinterpolation\nAuto-Kontrastschwelle
@@ -846,6 +848,13 @@ HISTORY_MSG_LOCALCONTRAST_LIGHTNESS;(Lokaler Kontrast)\nHelle Bereiche
HISTORY_MSG_LOCALCONTRAST_RADIUS;(Lokaler Kontrast)\nRadius
HISTORY_MSG_METADATA_MODE;(Metadaten)\nKopiermodus
HISTORY_MSG_MICROCONTRAST_CONTRAST;(Mikrokontrast)\nKontrastschwelle
+HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;(Eingangsschärfung)\nAuto-Schwelle
+HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;(Eingangsschärfung)\nAuto-Radius
+HISTORY_MSG_PDSHARPEN_CONTRAST;(Eingangsschärfung)\nKontrastschwelle
+HISTORY_MSG_PDSHARPEN_GAMMA;(Eingangsschärfung)\nGamma
+HISTORY_MSG_PDSHARPEN_ITERATIONS;(Eingangsschärfung)\nIterationen
+HISTORY_MSG_PDSHARPEN_RADIUS;(Eingangsschärfung)\nRadius
+HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;(Eingangsschärfung)\nRandschärfe erhöhen
HISTORY_MSG_PIXELSHIFT_DEMOSAIC;(Sensor-Matrix)\nFarbinterpolation - PS\nBewegungsmethode
HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;(Sensor-Matrix)\nVorverarbeitung\nRichtung
HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;(Sensor-Matrix)\nVorverarbeitung\nPDAF-Zeilenfilter
@@ -856,6 +865,7 @@ HISTORY_MSG_RAW_BORDER;(Sensor-Matrix)\nFarbinterpolation\nBildrand
HISTORY_MSG_RESIZE_ALLOWUPSCALING;(Skalieren)\nHochskalieren zulassen
HISTORY_MSG_SHARPENING_BLUR;(Schärfung)\nWeichzeichnerradius
HISTORY_MSG_SHARPENING_CONTRAST;(Schärfung)\nKontrastschwelle
+HISTORY_MSG_SHARPENING_GAMMA;(Schärfung) - Gamma
HISTORY_MSG_SH_COLORSPACE;Farbraum
HISTORY_MSG_SOFTLIGHT_ENABLED;(Weiches Licht)
HISTORY_MSG_SOFTLIGHT_STRENGTH;(Weiches Licht)\nIntensität
@@ -1012,8 +1022,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Hintergrundfarbe der Vorschau: Weiß\nTaste: 9
MAIN_TOOLTIP_BACKCOLOR3;Hintergrundfarbe der Vorschau: Mittleres Grau\nTaste: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Vorher-Ansicht: Sperren / Entsperren\n\nGesperrt: Friert die Vorher-Ansicht ein, so\ndass sich die Gesamtwirkung mehrerer\nBearbeitungsschritte beurteilen lässt.\n\nEntsperrt: Die Vorher-Ansicht hinkt dem\naktuellen Bild immer einen Bearbeitungs-\nschritt hinterher.
MAIN_TOOLTIP_HIDEHP;Linkes Bedienfeld ein-/ausblenden.\nTaste: l
-MAIN_TOOLTIP_INDCLIPPEDH;Anzeige zu heller Bereiche ein-/ausschalten.\nTaste: <
-MAIN_TOOLTIP_INDCLIPPEDS;Anzeige zu dunkler Bereiche ein-/ausschalten.\nTaste: >
+MAIN_TOOLTIP_INDCLIPPEDH;Anzeige zu heller Bereiche ein-/ausschalten.\nTaste: >
+MAIN_TOOLTIP_INDCLIPPEDS;Anzeige zu dunkler Bereiche ein-/ausschalten.\nTaste: <
MAIN_TOOLTIP_PREVIEWB;Vorschau Blau-Kanal\nTaste: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Vorschau Fokusmaske\nTaste: Umschalt + f\n\nPräziser bei Bildern mit geringer Tiefenschärfe,\nniedrigem Rauschen und bei hoher Vergrößerung.
MAIN_TOOLTIP_PREVIEWG;Vorschau Grün-Kanal\nTaste: g
@@ -1614,6 +1624,7 @@ TP_DEFRINGE_RADIUS;Radius
TP_DEFRINGE_THRESHOLD;Schwelle
TP_DEHAZE_DEPTH;Tiefe
TP_DEHAZE_LABEL;Bildschleier entfernen
+TP_DEHAZE_LUMINANCE;Nur Luminanz
TP_DEHAZE_SHOW_DEPTH_MAP;Maske anzeigen
TP_DEHAZE_STRENGTH;Intensität
TP_DIRPYRDENOISE_CHROMINANCE_AMZ;Auto-Multizonen
@@ -1724,9 +1735,9 @@ TP_EXPOS_BLACKPOINT_LABEL;Schwarzpunkt
TP_EXPOS_WHITEPOINT_LABEL;Weißpunkt
TP_FILMNEGATIVE_BLUE;Blauverhältnis
TP_FILMNEGATIVE_GREEN;Bezugsexponent (Kontrast)
-TP_FILMNEGATIVE_GUESS_TOOLTIP;Berechnet die Exponenten durch Auswahl zweier neutraler\nReferenzpunkte im Bild. Weiß (Hellgrau) und Schwarz (Dunkelgrau).\nDie Reihenfolge spielt keine Rolle. Die Exponenten werden aktualisiert,\nnachdem der zweite Punkt ausgewählt wurde.
+TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
TP_FILMNEGATIVE_LABEL;Filmnegativ
-TP_FILMNEGATIVE_PICK;Weißen und schwarzen Bereich auswählen
+TP_FILMNEGATIVE_PICK;Pick neutral spots
TP_FILMNEGATIVE_RED;Rotverhältnis
TP_FILMSIMULATION_LABEL;Filmsimulation
TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee sucht nach Hald-CLUT-Bildern, die für die Filmsimulation benötigt werden, in einem Ordner, der viel Zeit benötigt.\nGehen Sie zu\n< Einstellungen > Bildbearbeitung > Filmsimulation >\nund prüfen Sie welcher Order benutzt wird. Wählen Sie den Ordner aus, der nur die Hald-CLUT-Bilder beinhaltet, oder einen leeren Ordner, wenn Sie die Filsimulation nicht verwenden möchten.\n\nWeitere Informationen über die Filmsimulation finden Sie auf RawPedia.\n\nMöchten Sie die Suche beenden?
@@ -1876,6 +1887,7 @@ TP_PCVIGNETTE_ROUNDNESS;Form
TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Form:\n0 = Rechteck\n50 = Ellipse\n100 = Kreis
TP_PCVIGNETTE_STRENGTH;Intensität
TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filterstärke in Blendenstufen (bezogen auf die Bildecken).
+TP_PDSHARPENING_LABEL;Eingangsschärfung
TP_PERSPECTIVE_HORIZONTAL;Horizontal
TP_PERSPECTIVE_LABEL;Perspektive
TP_PERSPECTIVE_VERTICAL;Vertikal
@@ -2105,12 +2117,14 @@ TP_SHARPENING_BLUR;Weichzeichnerradius
TP_SHARPENING_CONTRAST;Kontrastschwelle
TP_SHARPENING_EDRADIUS;Radius
TP_SHARPENING_EDTOLERANCE;Kantentoleranz
+TP_SHARPENING_GAMMA;Gamma
TP_SHARPENING_HALOCONTROL;Halokontrolle
TP_SHARPENING_HCAMOUNT;Intensität
TP_SHARPENING_LABEL;Schärfung
TP_SHARPENING_METHOD;Methode
TP_SHARPENING_ONLYEDGES;Nur Kanten schärfen
TP_SHARPENING_RADIUS;Radius
+TP_SHARPENING_RADIUS_BOOST;Randschärfe erhöhen
TP_SHARPENING_RLD;RL-Dekonvolution
TP_SHARPENING_RLD_AMOUNT;Intensität
TP_SHARPENING_RLD_DAMPING;Dämpfung
@@ -2372,21 +2386,3 @@ ZOOMPANEL_ZOOMFITSCREEN;An Bildschirm anpassen.\nTaste: Alt + f
ZOOMPANEL_ZOOMIN;Hineinzoomen\nTaste: +
ZOOMPANEL_ZOOMOUT;Herauszoomen\nTaste: -
-!!!!!!!!!!!!!!!!!!!!!!!!!
-! Untranslated keys follow; remove the ! prefix after an entry is translated.
-!!!!!!!!!!!!!!!!!!!!!!!!!
-
-HISTORY_MSG_494;(Eingangsschärfung)
-HISTORY_MSG_DEHAZE_LUMINANCE;(Bildschleier entfernen)\nNur Luminanz
-HISTORY_MSG_PDSHARPEN_AUTO_CONTRAST;(Eingangsschärfung)\nAuto-Schwelle
-HISTORY_MSG_PDSHARPEN_AUTO_RADIUS;(Eingangsschärfung)\nAuto-Radius
-HISTORY_MSG_PDSHARPEN_CONTRAST;(Eingangsschärfung)\nKontrastschwelle
-HISTORY_MSG_PDSHARPEN_GAMMA;(Eingangsschärfung)\nGamma
-HISTORY_MSG_PDSHARPEN_ITERATIONS;(Eingangsschärfung)\nIterationen
-HISTORY_MSG_PDSHARPEN_RADIUS;(Eingangsschärfung)\nRadius
-HISTORY_MSG_PDSHARPEN_RADIUS_BOOST;(Eingangsschärfung)\nRandschärfe erhöhen
-HISTORY_MSG_SHARPENING_GAMMA;(Schärfung) - Gamma
-TP_DEHAZE_LUMINANCE;Nur Luminanz
-TP_PDSHARPENING_LABEL;Eingangsschärfung
-TP_SHARPENING_GAMMA;Gamma
-TP_SHARPENING_RADIUS_BOOST;Randschärfe erhöhen
diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK)
index a36a3d1a9..6c1398a16 100644
--- a/rtdata/languages/English (UK)
+++ b/rtdata/languages/English (UK)
@@ -88,6 +88,7 @@ TP_DIRPYREQUALIZER_ALGO;Skin Colour Range
TP_DIRPYREQUALIZER_ALGO_TOOLTIP;Fine: closer to the colours of the skin, minimizing the action on other colours\nLarge: avoid more artifacts.
TP_DIRPYREQUALIZER_TOOLTIP;Attempts to reduce artifacts in the transitions between skin colours (hue, chroma, luma) and the rest of the image.
TP_EXPOSURE_CLAMPOOG;Clip out-of-gamut colours
+TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no colour) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to colour cast.
TP_GRADIENT_CENTER;Centre
TP_GRADIENT_CENTER_X;Centre X
@@ -1022,8 +1023,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh
!MAIN_TAB_TRANSFORM_TOOLTIP;Shortcut: Alt-t
!MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool.
!MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l
-!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: <
-!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: >
+!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: >
+!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: <
!MAIN_TOOLTIP_PREVIEWB;Preview the blue channel.\nShortcut: b
!MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\nZoom out to 10-30% to improve detection accuracy on noisy images.
!MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g
@@ -1681,9 +1682,8 @@ TP_WBALANCE_EQBLUERED_TOOLTIP;Allows to deviate from the normal behaviour of "wh
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US)
index aa5239911..6aeae1a45 100644
--- a/rtdata/languages/English (US)
+++ b/rtdata/languages/English (US)
@@ -939,8 +939,8 @@
!MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9
!MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool.
!MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l
-!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: <
-!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: >
+!MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: >
+!MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: <
!MAIN_TOOLTIP_PREVIEWB;Preview the blue channel.\nShortcut: b
!MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\nZoom out to 10-30% to improve detection accuracy on noisy images.
!MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g
@@ -1652,9 +1652,9 @@
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/Espanol b/rtdata/languages/Espanol
index 27aa39c12..211f968e2 100644
--- a/rtdata/languages/Espanol
+++ b/rtdata/languages/Espanol
@@ -979,8 +979,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Color de fondo de la previsualización: Blanco\nT
MAIN_TOOLTIP_BACKCOLOR3;Color de fondo de la vista previa: Medio gris \nMétodo rápido: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Bloquear / Desbloquear la vista Antes\n\nBloquear: la vista Antes permanece inalterada - \nútil para evaluar el efecto acumulativo de varias herramientas.\nAdemás, se puede hacer una comparación con cualquier estado en el Historial\n\nDesbloquear: la vista Antes seguirá a la vista Después un paso por detrás, mostrando la imagen antes del efecto de la herramienta que se está usando
MAIN_TOOLTIP_HIDEHP;Mostrar/Ocultar panel izquierdo (incluyendo historial).\nTecla de Atajo: i
-MAIN_TOOLTIP_INDCLIPPEDH;Indicación de luces altas recortadas.\nTecla de Atajo: <
-MAIN_TOOLTIP_INDCLIPPEDS;Indicación de sombras recortadas.\nTecla de Atajo: >
+MAIN_TOOLTIP_INDCLIPPEDH;Indicación de luces altas recortadas.\nTecla de Atajo: >
+MAIN_TOOLTIP_INDCLIPPEDS;Indicación de sombras recortadas.\nTecla de Atajo: <
MAIN_TOOLTIP_PREVIEWB;Previsualización Canal azul.\nTecla de Atajo: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Previsualización Máscara de Foco.\nTecla de Atajo: Shift-F\n\nMás preciso en imágenes con poca profundidad de campo, bajo ruido y a mayores niveles de aumento\n\nPara mejorar la precisión en imágenes con ruido evalúe usando menor aumento (10%-30%)\n\nLa vista previa es realizada más lentamente cuando la Máscara de Foco esta activa.
MAIN_TOOLTIP_PREVIEWG;Previsualización Canal verde.\nTecla de Atajo: g
@@ -2358,9 +2358,9 @@ ZOOMPANEL_ZOOMOUT;Reducir Zoom\nTecla de Atajo: -
!TP_DEHAZE_LUMINANCE;Luminance only
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected
!TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected
diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 9f9485c70..82ef3fcd2 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -916,8 +916,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Couleur de fond de l'aperçu: Blanc\nRaccourci: <
MAIN_TOOLTIP_BACKCOLOR3;Couleur de fond de l'aperçu: Gris moyen\nRaccourci : 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Vérouille / déverouille la vue Avant\n\nVérouille: garde la vue Avant inchangée - \nutile pour évaluer l'effet cumulatif de plusieurs outils.\nDe plus, une comparaison peut être faite à partir de n'importe quelle étape de l'historique\n\nDéverouille: la vue Avant représentera l'étape précédant la vue Après, montrant l'effet qui vient d'être modifié
MAIN_TOOLTIP_HIDEHP;Montrer/cacher le panneau gauche (incluant l'historique)\nRaccourci: l
-MAIN_TOOLTIP_INDCLIPPEDH;Indication hautes lumières hors domaine\nRaccourci: <
-MAIN_TOOLTIP_INDCLIPPEDS;Indication ombres hors domaine\nRaccourci: >
+MAIN_TOOLTIP_INDCLIPPEDH;Indication hautes lumières hors domaine\nRaccourci: >
+MAIN_TOOLTIP_INDCLIPPEDS;Indication ombres hors domaine\nRaccourci: <
MAIN_TOOLTIP_PREVIEWB;Affichage du canal Bleu\nRaccourci: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Affichage du Masque du focus\nRaccourci: Shift-f\n\nPlus précis sur les images avec une faible profondeur de champ, à faible bruit et à des niveaux de zoom élevé\n\nPour améliorer la précision de détection des images bruitées, évaluez les à un facteur de zoom de 10-30%\n\nLa prévisualisation met plus de temps à se calculer lorsque cet outil est actif.
MAIN_TOOLTIP_PREVIEWG;Affichage du canal Vert\nRaccourci: g
@@ -2291,9 +2291,9 @@ ZOOMPANEL_ZOOMOUT;Zoom Arrière\nRaccourci: -
!TP_DEHAZE_LUMINANCE;Luminance only
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected
!TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected
diff --git a/rtdata/languages/Italiano b/rtdata/languages/Italiano
index 7ba18b2d8..4649aea62 100644
--- a/rtdata/languages/Italiano
+++ b/rtdata/languages/Italiano
@@ -519,8 +519,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Colore di sfondo dell'anteprima: Nero\nScorciatoi
MAIN_TOOLTIP_BACKCOLOR2;Colore di sfondo dell'anteprima: Bianco\nScorciatoia: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Blocca/Sblocca la vista Prima\n\nBlocca: Conserva la vista Prima.\nUtile per valutare l'effetto cumulativo di diversi strumenti.\nIn più, possono essere confrontati diversi passi della cronologia.\n\nSblocca: la vista Prima segue di un passo la vista Dopo, mostrando l'immagine prima dell'effetto dello strumento corrente.
MAIN_TOOLTIP_HIDEHP;Mostra/Nascondi il pannello sinistro (inclusa la cronologia)\nScorciatoia: l
-MAIN_TOOLTIP_INDCLIPPEDH;Indicazione delle alteluci tosate.\nScorciatoia: <
-MAIN_TOOLTIP_INDCLIPPEDS;Indicazione delle ombre tosate.\nScorciatoia: >
+MAIN_TOOLTIP_INDCLIPPEDH;Indicazione delle alteluci tosate.\nScorciatoia: >
+MAIN_TOOLTIP_INDCLIPPEDS;Indicazione delle ombre tosate.\nScorciatoia: <
MAIN_TOOLTIP_PREVIEWB;Anteprima del Canale Blu.\nScorciatoia: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Anteprima della Focus Mask.\nScorciatoia: Maiuscolo-F\n\nPiù accurato su immagini con bassa profondità di campo, poco rumore e ad elevati livelli di zoom.\n\nPer aumentare l'accuratezza della rilevazione su immagini con molto rumore, riduci le dimensioni del 10-30%.
MAIN_TOOLTIP_PREVIEWG;Anteprima del Canale Verde.\nScorciatoia: g
@@ -1919,9 +1919,9 @@ ZOOMPANEL_ZOOMOUT;Rimpicciolisci.\nScorciatoia: -
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/Japanese b/rtdata/languages/Japanese
index 83b8caa30..511f6daf0 100644
--- a/rtdata/languages/Japanese
+++ b/rtdata/languages/Japanese
@@ -960,8 +960,8 @@ MAIN_TOOLTIP_BACKCOLOR2;プレビューの背景色を指定します: 白中間のグレー\nショートカット: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;固定 / 固定解除 - 補正前 の表示設定\n\n固定: 補正前をそのまま表示し変更されません\n複数のツールの累積効果を評価するのに役立ちます\nさらに、比較は履歴上のどこからでも行うことができます\n\n固定解除: 現在使用のツールの効果が 補正後 に表示され、その1段階前が 補正前 に表示されます
MAIN_TOOLTIP_HIDEHP;左パネル 表示/非表示 (履歴含む)\nショートカット: l
-MAIN_TOOLTIP_INDCLIPPEDH;ハイライト・クリッピング領域の表示\nショートカット: <
-MAIN_TOOLTIP_INDCLIPPEDS;シャドウ・クリッピング領域の表示\nショートカット: >
+MAIN_TOOLTIP_INDCLIPPEDH;ハイライト・クリッピング領域の表示\nショートカット: >
+MAIN_TOOLTIP_INDCLIPPEDS;シャドウ・クリッピング領域の表示\nショートカット: <
MAIN_TOOLTIP_PREVIEWB;ブルー チャンネル表示\nショートカット: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;フォーカス・マスク表示\nショートカット: Shift-f\n\n浅い被写界深度、低ノイズ、高ズームの画像の場合は、より正確に\n\nノイズの多い画像に対しては、検出精度を向上させるため10から30%縮小して評価します\n\nフォーカス・マスクをオンにすると表示に時間が掛かります
MAIN_TOOLTIP_PREVIEWG;グリーン チャンネル表示\nショートカット: g
@@ -1672,9 +1672,9 @@ TP_EXPOS_BLACKPOINT_LABEL;raw ブラック・ポイント
TP_EXPOS_WHITEPOINT_LABEL;raw ホワイト・ポイント
TP_FILMNEGATIVE_BLUE;ブルーの比率
TP_FILMNEGATIVE_GREEN;参考指数(コントラスト)
-TP_FILMNEGATIVE_GUESS_TOOLTIP;画像の中でニュートラルな参考ポイントを2点選んで指数を計算します;白い(明るいグレー)1点と黒い(暗いグレー)1点を選びます。順番は関係ありません。2つ目のポイントが選択されると指数が更新されます。
+TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
TP_FILMNEGATIVE_LABEL;ネガフィルム
-TP_FILMNEGATIVE_PICK;白と黒のポイントをピックアップする
+TP_FILMNEGATIVE_PICK;Pick neutral spots
TP_FILMNEGATIVE_RED;レッドの比率
TP_FILMSIMULATION_LABEL;フィルムシミュレーション
TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapeeはフィルムシミュレーション機能に使う画像をHald CLUTフォルダーの中から探すよう設計されています(プログラムに組み込むにはフォルダーが大き過ぎるため)。\n変更するには、環境設定 > 画像処理 > フィルムシミュレーションと進み\nどのフォルダーが使われているか確認します。機能を利用する場合は、Hald CLUTだけが入っているフォルダーを指定するか、 この機能を使わない場合はそのフォルダーを空にしておきます。\n\n詳しくはRawPediaを参照して下さい。\n\nフィルム画像のスキャンを止めますか?
diff --git a/rtdata/languages/Magyar b/rtdata/languages/Magyar
index 11c48c3d9..8ee6e66e4 100644
--- a/rtdata/languages/Magyar
+++ b/rtdata/languages/Magyar
@@ -1832,9 +1832,9 @@ ZOOMPANEL_ZOOMOUT;Kicsinyítés -
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/Nederlands b/rtdata/languages/Nederlands
index 5e2c92742..ebfdbed9d 100644
--- a/rtdata/languages/Nederlands
+++ b/rtdata/languages/Nederlands
@@ -788,8 +788,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Achtergrond kleur van het voorbeeld: Zwart\nSnelt
MAIN_TOOLTIP_BACKCOLOR2;Achtergrond kleur van het voorbeeld: Wit\nSneltoets: 0
MAIN_TOOLTIP_BEFOREAFTERLOCK;Vergrendel / Ontgrendel de Voorafbeelding.\n\nVergrendel: hou de Voorafbeelding ongewijzigd.\nDit is handig om het cumulatieve effect van meerdere gereedschappen te beoordelen.\nBovendien kan er worden vergeleken met elke stap in de geschiedenislijst.\n\nOntgrendel: de Voorafbeelding volgt een stap achter de Naafbeelding en laat de afbeelding zien zonder het effect van het huidige gereedschap.
MAIN_TOOLTIP_HIDEHP;Toon/verberg linkerpaneel (geschiedenis).\nSneltoets: H
-MAIN_TOOLTIP_INDCLIPPEDH;Overbelichtingsindicatie.\nSneltoets: <
-MAIN_TOOLTIP_INDCLIPPEDS;Onderbelichtingsindicatie.\nSneltoets: >
+MAIN_TOOLTIP_INDCLIPPEDH;Overbelichtingsindicatie.\nSneltoets: >
+MAIN_TOOLTIP_INDCLIPPEDS;Onderbelichtingsindicatie.\nSneltoets: <
MAIN_TOOLTIP_PREVIEWB;Bekijk het Blauwe kanaal.\nSneltoets: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Bekijk het Focus Masker.\nSneltoets: Shift-F\n\nAccurater bij afbeeldingen met geringe scherptediepte, weinig ruis en hogere zoomniveaus.\n\nBekijk de afbeelding op lagere zoomniveaus (10-30%) om de accuratesse te vergroten bij afbeeldingen met veel ruis.\n\nHet voorbeeld wordt langzamer aangemaakt als Focus Masker aanstaat.
MAIN_TOOLTIP_PREVIEWG;Bekijk het Groene kanaal.\nSneltoets: g
@@ -2246,9 +2246,9 @@ ZOOMPANEL_ZOOMOUT;Zoom uit\nSneltoets: -
!TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail.
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_ICM_WORKING_TRC;Tone response curve:
!TP_ICM_WORKING_TRC_CUSTOM;Custom
diff --git a/rtdata/languages/Polish b/rtdata/languages/Polish
index 2e8a4549f..86461bf6d 100644
--- a/rtdata/languages/Polish
+++ b/rtdata/languages/Polish
@@ -563,8 +563,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Kolor tła podglądu: Czarny\nSkrót: 9
MAIN_TOOLTIP_BACKCOLOR2;Kolor tła podglądu: Biały\nSkrót: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Zablokuj / Odblokuj widok Przed\n\nZablokuj: nie zmieniaj widoku Przed - \nPrzydatne w porównywaniu zablokowanego obrazu z obrazem na ktorym wykonano wiele zmian.\n\nOdblokuj: widok Przed będzie śledził widok Po o jeden krok do tyłu, pokazując obraz przed efektem aktualnie użytego narzędzia.
MAIN_TOOLTIP_HIDEHP;Pokaż/ukryj lewy panel (razem z historią).\nSkrót: l
-MAIN_TOOLTIP_INDCLIPPEDH;Pokaż obcięte prześwietlenia.\nSkrót: <
-MAIN_TOOLTIP_INDCLIPPEDS;Pokaż obcięte niedoświetlenia.\nSkrót: >
+MAIN_TOOLTIP_INDCLIPPEDH;Pokaż obcięte prześwietlenia.\nSkrót: >
+MAIN_TOOLTIP_INDCLIPPEDS;Pokaż obcięte niedoświetlenia.\nSkrót: <
MAIN_TOOLTIP_PREVIEWB;Podgląd kanału niebieskiego.\nSkrót: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Podgląd maski ostrości.\nSkrót: Shift-f\n\nDokładniejsze w przypadku zdjęc o płytkiej głębi ostrości, niskim pozimie szumów i o większym przybliżeniu. W przypadku zdjęć o wyższym poziomie szumów maska ostrości będzie dokładniejsza przy mniejszym zoomie (10-30%).
MAIN_TOOLTIP_PREVIEWG;Podgląd kanału zielonego.\nSkrót: g
@@ -1945,9 +1945,9 @@ ZOOMPANEL_ZOOMOUT;Oddal\nSkrót: -
!TP_EXPOSURE_TCMODE_PERCEPTUAL;Perceptual
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
!TP_ICM_APPLYBASELINEEXPOSUREOFFSET;Baseline exposure
diff --git a/rtdata/languages/Portugues b/rtdata/languages/Portugues
index c4adbc7f9..dea314f46 100644
--- a/rtdata/languages/Portugues
+++ b/rtdata/languages/Portugues
@@ -916,8 +916,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Cor de fundo da pré-visualização: branco\nAtal
MAIN_TOOLTIP_BACKCOLOR3;Cor de fundo da pré-visualização: cinza médio\nAtalho: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Bloquear / desbloquear a visualização antes\n\nBloquear: manter a visualização antes inalterada.\nÚtil para avaliar o efeito cumulativo de várias ferramentas.\nAlém disso, podem ser feitas comparações a qualquer momento no histórico.\n\nDesbloquear: a visualização antes seguirá a visualização depois um passo antes, mostrando a imagem antes do efeito da ferramenta atualmente utilizada.
MAIN_TOOLTIP_HIDEHP;Mostrar o painel esquerdo (incluindo o histórico).\nAtalho: l
-MAIN_TOOLTIP_INDCLIPPEDH;Ver altas luzes cortadas.\nAtalho: <
-MAIN_TOOLTIP_INDCLIPPEDS;Ver sombras cortadas.\nAtalho: >
+MAIN_TOOLTIP_INDCLIPPEDH;Ver altas luzes cortadas.\nAtalho: >
+MAIN_TOOLTIP_INDCLIPPEDS;Ver sombras cortadas.\nAtalho: <
MAIN_TOOLTIP_PREVIEWB;Pré-visualizar o canal azul.\nAtalho: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Pré-visualizar a máscara de foco.\nAtalho: Shift-f\n\nMais preciso em imagens com pouca profundidade de campo, baixo ruído e níveis de zoom mais altos.\n\nUtilize um zoom menor entre 10-30% para melhorar a precisão da deteção de imagens com muito ruído.
MAIN_TOOLTIP_PREVIEWG;Pré-visualizar o canal verde.\nAtalho: g
@@ -2290,9 +2290,9 @@ ZOOMPANEL_ZOOMOUT;Afastar\nAtalho: -
!TP_DEHAZE_LUMINANCE;Luminance only
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected
!TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected
diff --git a/rtdata/languages/Portugues (Brasil) b/rtdata/languages/Portugues (Brasil)
index 259cabb7e..c6ff58310 100644
--- a/rtdata/languages/Portugues (Brasil)
+++ b/rtdata/languages/Portugues (Brasil)
@@ -923,8 +923,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Cor de fundo da pré-visualização: Branco\nAtal
MAIN_TOOLTIP_BACKCOLOR3;Cor de fundo da pré-visualização: Cinza médio\nAtalho: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Travar / Destravar a Antes visualização\n\nTravar: mantenha o Antes visualização inalterada.\nÚtil para avaliar o efeito cumulativo de várias ferramentas.\nAlém disso, comparações podem ser feitas a qualquer momento.\n\nDestravar: o Antes visualização seguinte Depois visualização anterior, mostrando a imagem antes do efeito da ferramenta atualmente utilizada.
MAIN_TOOLTIP_HIDEHP;Mostrar/Ocultar o painel esquerdo (incluindo o histórico).\nAtalho: l
-MAIN_TOOLTIP_INDCLIPPEDH;Indicação de realce recortado.\nAtalho: <
-MAIN_TOOLTIP_INDCLIPPEDS;Indicação de sombra recortada.\nAtalho: >
+MAIN_TOOLTIP_INDCLIPPEDH;Indicação de realce recortado.\nAtalho: >
+MAIN_TOOLTIP_INDCLIPPEDS;Indicação de sombra recortada.\nAtalho: <
MAIN_TOOLTIP_PREVIEWB;Pré-visualize o Canal Azul.\nAtalho: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Pré-visualize a Máscara de Foco.\nAtalho: Shift-f\n\nMais preciso em imagens com pouca profundidade de campo, baixo ruído e níveis de zoom mais altos.\n\nPara melhorar a precisão da detecção de imagens ruidosas, avalie com zoom menor, cerca de 10-30%.
MAIN_TOOLTIP_PREVIEWG;Pré-visualize o Canal verde.\nAtalho: g
@@ -1626,7 +1626,7 @@ TP_EXPOSURE_TCMODE_WEIGHTEDSTD;Padrão Ponderado
TP_EXPOS_BLACKPOINT_LABEL;Pontos Pretos Raw
TP_EXPOS_WHITEPOINT_LABEL;Pontos Brancos Raw
TP_FILMNEGATIVE_BLUE;Relação de azul
-TP_FILMNEGATIVE_PICK;Escolher os pontos brancos e pretos
+TP_FILMNEGATIVE_PICK;Pick neutral spots
TP_FILMNEGATIVE_RED;Relação de vermelho
TP_FILMSIMULATION_LABEL;Simulação de Filme
TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee está configurado para procurar por imagens Hald CLUT, que são usadas para a ferramenta Simulação de Filme, numa pasta que está demorando para carregar.\nVá para Preferências > Processamento de Imagem > Simulação de Filme\npara ver qual pasta está sendo usada. Deves apontar RawTherapee para uma pasta que contenha apenas imagens Hald CLUT e nada mais, ou para uma pasta vazia, se não quiseres usar a ferramenta Simulação de Filme.\n\nLeia o artigo sobre Simulação de Filme na RawPedia para mais informações.\n\nDesejas cancelar a verificação agora?
@@ -2293,7 +2293,7 @@ ZOOMPANEL_ZOOMOUT;Menos Zoom\nAtalho: -
!TP_CROP_PPI;PPI
!TP_DEHAZE_LUMINANCE;Luminance only
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
!TP_LENSPROFILE_LENS_WARNING;Warning: the crop factor used for lens profiling is larger than the crop factor of the camera, the results might be wrong.
!TP_LENSPROFILE_USE_HEADER;Correct
diff --git a/rtdata/languages/Russian b/rtdata/languages/Russian
index 2014f9aad..9f8f47da0 100644
--- a/rtdata/languages/Russian
+++ b/rtdata/languages/Russian
@@ -613,8 +613,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Фоновый цвет предпросмотра:
MAIN_TOOLTIP_BACKCOLOR2;Фоновый цвет предпросмотра: Белый\nГорячая клавиша: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Заблокировать / Разблокировать предыдущий вид\n\nЗаблокировать: сохраняет предыдущий вид неизменным.\nПолезно для оценки общего эффекта от применения нескольких инструментов.\nК тому же, сравнения могут быть произведены на любом состоянии истории\n\nРазблокировать: предыдущий вид будет следовать сразу за следующим, показывая состояние изображения до применения текущего инструмента.
MAIN_TOOLTIP_HIDEHP;Показать/скрыть левую панель (включая историю).\nГорячая клавиша l
-MAIN_TOOLTIP_INDCLIPPEDH;Индикатор пересветов.\nГорячая клавиша: <
-MAIN_TOOLTIP_INDCLIPPEDS;Индикатор затемнений.\nГорячая клавиша: >
+MAIN_TOOLTIP_INDCLIPPEDH;Индикатор пересветов.\nГорячая клавиша: >
+MAIN_TOOLTIP_INDCLIPPEDS;Индикатор затемнений.\nГорячая клавиша: <
MAIN_TOOLTIP_PREVIEWB;Просмотреть канал синего.\nГорячая клавиша: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Просмотреть Маску резкости.\nГорячая клавиша: Shift-F\n\nБолее точна на изображениях с небольшой глубиной резкости, малым шумом и при большем приближении изображения\n\nДля улучшения определения на шумных изображениях используйте на маленьком зуме 10-30%
MAIN_TOOLTIP_PREVIEWG;Просмотреть канал зеленого.\nГорячая клавиша: g
@@ -1990,9 +1990,9 @@ ZOOMPANEL_ZOOMOUT;Отдалить\nГорячая клавиша: -
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
!TP_FLATFIELD_CLIPCONTROL;Clip control
diff --git a/rtdata/languages/Serbian (Cyrilic Characters) b/rtdata/languages/Serbian (Cyrilic Characters)
index 0e940be55..63b838201 100644
--- a/rtdata/languages/Serbian (Cyrilic Characters)
+++ b/rtdata/languages/Serbian (Cyrilic Characters)
@@ -1918,9 +1918,9 @@ ZOOMPANEL_ZOOMOUT;Умањује приказ слике -
!TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FILMSIMULATION_LABEL;Film Simulation
!TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtdata/languages/Swedish b/rtdata/languages/Swedish
index fbc55624d..b39d95e02 100644
--- a/rtdata/languages/Swedish
+++ b/rtdata/languages/Swedish
@@ -698,8 +698,8 @@ MAIN_TOOLTIP_BACKCOLOR1;Bakgrundsfärg: Svart\nKortkommando: 9
MAIN_TOOLTIP_BACKCOLOR2;Bakgrundsfärg: Vit\nKortkommando: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Lås / Lås upp före-vyn\n\nLås: behåll före-vyn oförändrad.\nAnvändbart för att utvärdera den sammanlagda effekten av flera stegs redigering. Dessutom kan jämförelser göras gentemot varje annat steg i historiken.\n\nLås upp: Före-vyn kommer hela tiden visa ett tidigare steg jämfört med efter-vyn, och visar därmed effekten av det verktyg som användes senast.
MAIN_TOOLTIP_HIDEHP;Visa/göm den vänstra panelen. Kortkommando: l
-MAIN_TOOLTIP_INDCLIPPEDH;Markera högdagerindikation.\nKortkommando: <
-MAIN_TOOLTIP_INDCLIPPEDS;Markera skuggindikation.\nKortkommando: >
+MAIN_TOOLTIP_INDCLIPPEDH;Markera högdagerindikation.\nKortkommando: >
+MAIN_TOOLTIP_INDCLIPPEDS;Markera skuggindikation.\nKortkommando: <
MAIN_TOOLTIP_PREVIEWB;Förhandsgranska den blå kanalen.\nGenväg: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Förhandsgranska fokusmasken.\nKortkommando: Shift-f\n\nNoggrannare på bilder med kort skärpedjup, lågt brus och där en hög zoom-grad är vald.\n\nFör att förbättra detekteringen för brusiga bilder, utvärdera vid en zoom-grad om 10-30%\n\nFörhandsvisningen görs långsammare med fokusmasken påslagen.
MAIN_TOOLTIP_PREVIEWG;Förhandsgranska den gröna kanalen.\nGenväg: g
@@ -2133,9 +2133,9 @@ ZOOMPANEL_ZOOMOUT;Förminska.\nKortkommando: -
!TP_EXPOSURE_HISTMATCHING_TOOLTIP;Automatically adjust sliders and curves (except exposure compensation) to match the look of the embedded JPEG thumbnail.
!TP_FILMNEGATIVE_BLUE;Blue ratio
!TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-!TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+!TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
!TP_FILMNEGATIVE_LABEL;Film Negative
-!TP_FILMNEGATIVE_PICK;Pick white and black spots
+!TP_FILMNEGATIVE_PICK;Pick neutral spots
!TP_FILMNEGATIVE_RED;Red ratio
!TP_FLATFIELD_CLIPCONTROL;Clip control
!TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, clip control can lead to color cast.
diff --git a/rtdata/languages/default b/rtdata/languages/default
index cad717e6f..f21a352f0 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -938,8 +938,8 @@ MAIN_TOOLTIP_BACKCOLOR2;Background color of the preview: white\nShortcut:
MAIN_TOOLTIP_BACKCOLOR3;Background color of the preview: middle grey\nShortcut: 9
MAIN_TOOLTIP_BEFOREAFTERLOCK;Lock / Unlock the Before view\n\nLock: keep the Before view unchanged.\nUseful to evaluate the cumulative effect of multiple tools.\nAdditionally, comparisons can be made to any state in the History.\n\nUnlock: the Before view will follow the After view one step behind, showing the image before the effect of the currently used tool.
MAIN_TOOLTIP_HIDEHP;Show/Hide the left panel (including the history).\nShortcut: l
-MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: <
-MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: >
+MAIN_TOOLTIP_INDCLIPPEDH;Clipped highlight indication.\nShortcut: >
+MAIN_TOOLTIP_INDCLIPPEDS;Clipped shadow indication.\nShortcut: <
MAIN_TOOLTIP_PREVIEWB;Preview the blue channel.\nShortcut: b
MAIN_TOOLTIP_PREVIEWFOCUSMASK;Preview the focus mask.\nShortcut: Shift-f\n\nMore accurate on images with shallow depth of field, low noise and at higher zoom levels.\nZoom out to 10-30% to improve detection accuracy on noisy images.
MAIN_TOOLTIP_PREVIEWG;Preview the green channel.\nShortcut: g
@@ -1651,9 +1651,9 @@ TP_EXPOS_BLACKPOINT_LABEL;Raw Black Points
TP_EXPOS_WHITEPOINT_LABEL;Raw White Points
TP_FILMNEGATIVE_BLUE;Blue ratio
TP_FILMNEGATIVE_GREEN;Reference exponent (contrast)
-TP_FILMNEGATIVE_GUESS_TOOLTIP;Calculate exponents by picking two neutral reference spots in the image; one white (light gray) and one black (dark gray). The order does not matter. The exponents will be updated after the second spot is picked.
+TP_FILMNEGATIVE_GUESS_TOOLTIP;Automatically set the red and blue ratios by picking two patches which had a neutral hue (no color) in the original scene. The patches should differ in brightness. Set the white balance afterwards.
TP_FILMNEGATIVE_LABEL;Film Negative
-TP_FILMNEGATIVE_PICK;Pick white and black spots
+TP_FILMNEGATIVE_PICK;Pick neutral spots
TP_FILMNEGATIVE_RED;Red ratio
TP_FILMSIMULATION_LABEL;Film Simulation
TP_FILMSIMULATION_SLOWPARSEDIR;RawTherapee is configured to look for Hald CLUT images, which are used for the Film Simulation tool, in a folder which is taking too long to load.\nGo to Preferences > Image Processing > Film Simulation\nto see which folder is being used. You should either point RawTherapee to a folder which contains only Hald CLUT images and nothing more, or to an empty folder if you don't want to use the Film Simulation tool.\n\nRead the Film Simulation article in RawPedia for more information.\n\nDo you want to cancel the scan now?
diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt
index 52ec61b2f..71dffc1e6 100644
--- a/rtengine/CMakeLists.txt
+++ b/rtengine/CMakeLists.txt
@@ -33,6 +33,7 @@ set(RTENGINESOURCEFILES
ahd_demosaic_RT.cc
amaze_demosaic_RT.cc
badpixels.cc
+ boxblur.cc
CA_correct_RT.cc
calc_distort.cc
camconst.cc
diff --git a/rtengine/FTblockDN.cc b/rtengine/FTblockDN.cc
index d1e659114..8fd0ba29e 100644
--- a/rtengine/FTblockDN.cc
+++ b/rtengine/FTblockDN.cc
@@ -479,6 +479,7 @@ enum nrquality {QUALITY_STANDARD, QUALITY_HIGH};
void ImProcFunctions::RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve, const NoiseCurve & noiseCCurve, float &nresi, float &highresi)
{
BENCHFUN
+
//#ifdef _DEBUG
MyTime t1e, t2e;
t1e.set();
@@ -687,8 +688,8 @@ BENCHFUN
}
}
- int tilesize;
- int overlap;
+ int tilesize = 0;
+ int overlap = 0;
if (settings->leveldnti == 0) {
tilesize = 1024;
@@ -1341,8 +1342,6 @@ BENCHFUN
#ifdef _OPENMP
int masterThread = omp_get_thread_num();
-#endif
-#ifdef _OPENMP
#pragma omp parallel num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1)
#endif
{
@@ -1351,11 +1350,9 @@ BENCHFUN
#else
int subThread = 0;
#endif
- float blurbuffer[TS * TS] ALIGNED64;
float *Lblox = LbloxArray[subThread];
float *fLblox = fLbloxArray[subThread];
float pBuf[width + TS + 2 * blkrad * offset] ALIGNED16;
- float nbrwt[TS * TS] ALIGNED64;
#ifdef _OPENMP
#pragma omp for
#endif
@@ -1430,7 +1427,7 @@ BENCHFUN
for (int hblk = 0; hblk < numblox_W; ++hblk) {
- RGBtile_denoise(fLblox, hblk, noisevar_Ldetail, nbrwt, blurbuffer);
+ RGBtile_denoise(fLblox, hblk, noisevar_Ldetail);
}//end of horizontal block loop
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1447,14 +1444,8 @@ BENCHFUN
//add row of blocks to output image tile
RGBoutput_tile_row(Lblox, Ldetail, tilemask_out, height, width, topproc);
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
}//end of vertical block loop
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
}
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#ifdef _OPENMP
#pragma omp parallel for num_threads(denoiseNestedLevels) if (denoiseNestedLevels>1)
@@ -2041,26 +2032,20 @@ BENCHFUN
}//end of main RGB_denoise
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
-void ImProcFunctions::RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer) //for DCT
+void ImProcFunctions::RGBtile_denoise(float* fLblox, int hblproc, float noisevar_Ldetail) //for DCT
{
- int blkstart = hblproc * TS * TS;
+ float nbrwt[TS * TS] ALIGNED64;
+ const int blkstart = hblproc * TS * TS;
- boxabsblur(fLblox + blkstart, nbrwt, 3, 3, TS, TS, blurbuffer); //blur neighbor weights for more robust estimation //for DCT
+ boxabsblur(fLblox + blkstart, nbrwt, 3, TS, TS, false); //blur neighbor weights for more robust estimation //for DCT
#ifdef __SSE2__
- __m128 tempv;
- __m128 noisevar_Ldetailv = _mm_set1_ps(noisevar_Ldetail);
- __m128 onev = _mm_set1_ps(1.0f);
+ const vfloat noisevar_Ldetailv = F2V(-1.f / noisevar_Ldetail);
+ const vfloat onev = F2V(1.f);
for (int n = 0; n < TS * TS; n += 4) { //for DCT
- tempv = onev - xexpf(-SQRV(LVF(nbrwt[n])) / noisevar_Ldetailv);
- _mm_storeu_ps(&fLblox[blkstart + n], LVFU(fLblox[blkstart + n]) * tempv);
+ const vfloat tempv = onev - xexpf(SQRV(LVF(nbrwt[n])) * noisevar_Ldetailv);
+ STVF(fLblox[blkstart + n], LVF(fLblox[blkstart + n]) * tempv);
}//output neighbor averaged result
#else
@@ -2071,14 +2056,7 @@ void ImProcFunctions::RGBtile_denoise(float * fLblox, int hblproc, float noiseva
#endif
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- //printf("vblk=%d hlk=%d wsqave=%f || ",vblproc,hblproc,wsqave);
-
-}//end of function tile_denoise
-
-
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+}
void ImProcFunctions::RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top)
{
@@ -2207,7 +2185,7 @@ void ImProcFunctions::Noise_residualAB(const wavelet_decomposition &WaveletCoeff
chmaxresid = maxresid;
}
-bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3])
+bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3])
{
int maxlvl = min(WaveletCoeffs_L.maxlevel(), 5);
const float eps = 0.01f;
@@ -2258,23 +2236,22 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet
//simple wavelet shrinkage
float * sfave = buffer[0] + 32;
float * sfaved = buffer[2] + 96;
- float * blurBuffer = buffer[1] + 64;
float mad_Lr = madL[lvl][dir - 1];
float levelFactor = mad_Lr * 5.f / (lvl + 1);
#ifdef __SSE2__
- __m128 mad_Lv;
- __m128 ninev = _mm_set1_ps(9.0f);
- __m128 epsv = _mm_set1_ps(eps);
- __m128 mag_Lv;
- __m128 levelFactorv = _mm_set1_ps(levelFactor);
+ vfloat mad_Lv;
+ vfloat ninev = F2V(9.0f);
+ vfloat epsv = F2V(eps);
+ vfloat mag_Lv;
+ vfloat levelFactorv = F2V(levelFactor);
int coeffloc_L;
for (coeffloc_L = 0; coeffloc_L < Hlvl_L * Wlvl_L - 3; coeffloc_L += 4) {
mad_Lv = LVFU(noisevarlum[coeffloc_L]) * levelFactorv;
mag_Lv = SQRV(LVFU(WavCoeffs_L[dir][coeffloc_L]));
- _mm_storeu_ps(&sfave[coeffloc_L], mag_Lv / (mag_Lv + mad_Lv * xexpf(-mag_Lv / (mad_Lv * ninev)) + epsv));
+ STVFU(sfave[coeffloc_L], mag_Lv / (mag_Lv + mad_Lv * xexpf(-mag_Lv / (mad_Lv * ninev)) + epsv));
}
for (; coeffloc_L < Hlvl_L * Wlvl_L; ++coeffloc_L) {
@@ -2294,15 +2271,15 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet
}
#endif
- boxblur(sfave, sfaved, blurBuffer, lvl + 2, lvl + 2, Wlvl_L, Hlvl_L); //increase smoothness by locally averaging shrinkage
+ boxblur(sfave, sfaved, lvl + 2, Wlvl_L, Hlvl_L, false); //increase smoothness by locally averaging shrinkage
#ifdef __SSE2__
- __m128 sfavev;
- __m128 sf_Lv;
+ vfloat sfavev;
+ vfloat sf_Lv;
for (coeffloc_L = 0; coeffloc_L < Hlvl_L * Wlvl_L - 3; coeffloc_L += 4) {
sfavev = LVFU(sfaved[coeffloc_L]);
sf_Lv = LVFU(sfave[coeffloc_L]);
- _mm_storeu_ps(&WavCoeffs_L[dir][coeffloc_L], LVFU(WavCoeffs_L[dir][coeffloc_L]) * (SQRV(sfavev) + SQRV(sf_Lv)) / (sfavev + sf_Lv + epsv));
+ STVFU(WavCoeffs_L[dir][coeffloc_L], LVFU(WavCoeffs_L[dir][coeffloc_L]) * (SQRV(sfavev) + SQRV(sf_Lv)) / (sfavev + sf_Lv + epsv));
//use smoothed shrinkage unless local shrinkage is much less
}
@@ -2340,7 +2317,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &Wavelet
return (!memoryAllocationFailed);
}
-bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab,
+bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab,
float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)
{
int maxlvl = WaveletCoeffs_L.maxlevel();
@@ -2422,12 +2399,12 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele
if (noisevar_ab > 0.001f) {
#ifdef __SSE2__
- __m128 onev = _mm_set1_ps(1.f);
- __m128 mad_abrv = _mm_set1_ps(mad_abr);
- __m128 rmad_Lm9v = onev / _mm_set1_ps(mad_Lr * 9.f);
- __m128 mad_abv;
- __m128 mag_Lv, mag_abv;
- __m128 tempabv;
+ vfloat onev = F2V(1.f);
+ vfloat mad_abrv = F2V(mad_abr);
+ vfloat rmad_Lm9v = onev / F2V(mad_Lr * 9.f);
+ vfloat mad_abv;
+ vfloat mag_Lv, mag_abv;
+ vfloat tempabv;
int coeffloc_ab;
for (coeffloc_ab = 0; coeffloc_ab < Hlvl_ab * Wlvl_ab - 3; coeffloc_ab += 4) {
@@ -2437,7 +2414,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele
mag_Lv = LVFU(WavCoeffs_L[dir][coeffloc_ab]);
mag_abv = SQRV(tempabv);
mag_Lv = SQRV(mag_Lv) * rmad_Lm9v;
- _mm_storeu_ps(&WavCoeffs_ab[dir][coeffloc_ab], tempabv * SQRV((onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv)))));
+ STVFU(WavCoeffs_ab[dir][coeffloc_ab], tempabv * SQRV((onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv)))));
}
// few remaining pixels
@@ -2470,9 +2447,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele
}
for (int i = 2; i >= 0; i--) {
- if (buffer[i] != nullptr) {
- delete[] buffer[i];
- }
+ delete[] buffer[i];
}
}
@@ -2480,7 +2455,7 @@ bool ImProcFunctions::WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &Wavele
}
-bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge)//mod JD
+bool ImProcFunctions::WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge)//mod JD
{
@@ -2530,16 +2505,14 @@ bool ImProcFunctions::WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L,
}
for (int i = 3; i >= 0; i--) {
- if (buffer[i] != nullptr) {
- delete[] buffer[i];
- }
+ delete[] buffer[i];
}
}
return (!memoryAllocationFailed);
}
-bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab,
+bool ImProcFunctions::WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab,
float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb)//mod JD
{
@@ -2596,7 +2569,7 @@ bool ImProcFunctions::WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir,
+void ImProcFunctions::ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir,
float *noisevarlum, float * madL, float * vari, int edge)
{
@@ -2607,12 +2580,12 @@ void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float *
float * sfaved = buffer[1] + 64;
float * blurBuffer = buffer[2] + 96;
- int W_L = WaveletCoeffs_L.level_W(level);
- int H_L = WaveletCoeffs_L.level_H(level);
+ const int W_L = WaveletCoeffs_L.level_W(level);
+ const int H_L = WaveletCoeffs_L.level_H(level);
float ** WavCoeffs_L = WaveletCoeffs_L.level_coeffs(level);
-// printf("OK lev=%d\n",level);
- float mad_L = madL[dir - 1] ;
+ const float mad_L = madL[dir - 1] ;
+ const float levelFactor = mad_L * 5.f / static_cast(level + 1);
if (edge == 1 && vari) {
noisevarlum = blurBuffer; // we need one buffer, but fortunately we don't have to allocate a new one because we can use blurBuffer
@@ -2622,71 +2595,45 @@ void ImProcFunctions::ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float *
}
}
- float levelFactor = mad_L * 5.f / static_cast(level + 1);
+ int i = 0;
#ifdef __SSE2__
- __m128 magv;
- __m128 levelFactorv = _mm_set1_ps(levelFactor);
- __m128 mad_Lv;
- __m128 ninev = _mm_set1_ps(9.0f);
- __m128 epsv = _mm_set1_ps(eps);
- int i;
+ const vfloat levelFactorv = F2V(levelFactor);
+ const vfloat ninev = F2V(9.f);
+ const vfloat epsv = F2V(eps);
- for (i = 0; i < W_L * H_L - 3; i += 4) {
- mad_Lv = LVFU(noisevarlum[i]) * levelFactorv;
- magv = SQRV(LVFU(WavCoeffs_L[dir][i]));
- _mm_storeu_ps(&sfave[i], magv / (magv + mad_Lv * xexpf(-magv / (ninev * mad_Lv)) + epsv));
+ for (; i < W_L * H_L - 3; i += 4) {
+ const vfloat mad_Lv = LVFU(noisevarlum[i]) * levelFactorv;
+ const vfloat magv = SQRV(LVFU(WavCoeffs_L[dir][i]));
+ STVFU(sfave[i], magv / (magv + mad_Lv * xexpf(-magv / (ninev * mad_Lv)) + epsv));
}
-
+#endif
// few remaining pixels
for (; i < W_L * H_L; ++i) {
- float mag = SQR(WavCoeffs_L[dir][i]);
+ const float mag = SQR(WavCoeffs_L[dir][i]);
sfave[i] = mag / (mag + levelFactor * noisevarlum[i] * xexpf(-mag / (9 * levelFactor * noisevarlum[i])) + eps);
}
-#else
-
- for (int i = 0; i < W_L * H_L; ++i) {
-
- float mag = SQR(WavCoeffs_L[dir][i]);
- float shrinkfactor = mag / (mag + levelFactor * noisevarlum[i] * xexpf(-mag / (9 * levelFactor * noisevarlum[i])) + eps);
- sfave[i] = shrinkfactor;
- }
-
-#endif
- boxblur(sfave, sfaved, blurBuffer, level + 2, level + 2, W_L, H_L); //increase smoothness by locally averaging shrinkage
+ boxblur(sfave, sfaved, level + 2, W_L, H_L, false); //increase smoothness by locally averaging shrinkage
+ i = 0;
#ifdef __SSE2__
- __m128 sfv;
- for (i = 0; i < W_L * H_L - 3; i += 4) {
- sfv = LVFU(sfave[i]);
+ for (; i < W_L * H_L - 3; i += 4) {
+ const vfloat sfv = LVFU(sfave[i]);
//use smoothed shrinkage unless local shrinkage is much less
- _mm_storeu_ps(&WavCoeffs_L[dir][i], _mm_loadu_ps(&WavCoeffs_L[dir][i]) * (SQRV(LVFU(sfaved[i])) + SQRV(sfv)) / (LVFU(sfaved[i]) + sfv + epsv));
+ STVFU(WavCoeffs_L[dir][i], LVFU(WavCoeffs_L[dir][i]) * (SQRV(LVFU(sfaved[i])) + SQRV(sfv)) / (LVFU(sfaved[i]) + sfv + epsv));
}
-
+#endif
// few remaining pixels
for (; i < W_L * H_L; ++i) {
- float sf = sfave[i];
-
+ const float sf = sfave[i];
//use smoothed shrinkage unless local shrinkage is much less
WavCoeffs_L[dir][i] *= (SQR(sfaved[i]) + SQR(sf)) / (sfaved[i] + sf + eps);
}//now luminance coefficients are denoised
-
-#else
-
- for (int i = 0; i < W_L * H_L; ++i) {
- float sf = sfave[i];
-
- //use smoothed shrinkage unless local shrinkage is much less
- WavCoeffs_L[dir][i] *= (SQR(sfaved[i]) + SQR(sf)) / (sfaved[i] + sf + eps);
-
- }//now luminance coefficients are denoised
-
-#endif
}
-void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
+void ImProcFunctions::ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch,
bool denoiseMethodRgb, float * madL, float * madaab, bool madCalculated)
@@ -2700,7 +2647,6 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavele
float * sfaveab = buffer[0] + 32;
float * sfaveabd = buffer[1] + 64;
- float * blurBuffer = buffer[2] + 96;
int W_ab = WaveletCoeffs_ab.level_W(level);
int H_ab = WaveletCoeffs_ab.level_H(level);
@@ -2724,12 +2670,12 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavele
if (noisevar_ab > 0.001f) {
madab = useNoiseCCurve ? madab : madab * noisevar_ab;
#ifdef __SSE2__
- __m128 onev = _mm_set1_ps(1.f);
- __m128 mad_abrv = _mm_set1_ps(madab);
+ vfloat onev = F2V(1.f);
+ vfloat mad_abrv = F2V(madab);
- __m128 rmadLm9v = onev / _mm_set1_ps(mad_L * 9.f);
- __m128 mad_abv ;
- __m128 mag_Lv, mag_abv;
+ vfloat rmadLm9v = onev / F2V(mad_L * 9.f);
+ vfloat mad_abv ;
+ vfloat mag_Lv, mag_abv;
int coeffloc_ab;
for (coeffloc_ab = 0; coeffloc_ab < H_ab * W_ab - 3; coeffloc_ab += 4) {
@@ -2738,7 +2684,7 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavele
mag_Lv = LVFU(WavCoeffs_L[dir][coeffloc_ab]);
mag_abv = SQRV(LVFU(WavCoeffs_ab[dir][coeffloc_ab]));
mag_Lv = (SQRV(mag_Lv)) * rmadLm9v;
- _mm_storeu_ps(&sfaveab[coeffloc_ab], (onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv))));
+ STVFU(sfaveab[coeffloc_ab], (onev - xexpf(-(mag_abv / mad_abv) - (mag_Lv))));
}
// few remaining pixels
@@ -2761,18 +2707,18 @@ void ImProcFunctions::ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavele
#endif
- boxblur(sfaveab, sfaveabd, blurBuffer, level + 2, level + 2, W_ab, H_ab); //increase smoothness by locally averaging shrinkage
+ boxblur(sfaveab, sfaveabd, level + 2, W_ab, H_ab, false); //increase smoothness by locally averaging shrinkage
#ifdef __SSE2__
- __m128 epsv = _mm_set1_ps(eps);
- __m128 sfabv;
- __m128 sfaveabv;
+ vfloat epsv = F2V(eps);
+ vfloat sfabv;
+ vfloat sfaveabv;
for (coeffloc_ab = 0; coeffloc_ab < H_ab * W_ab - 3; coeffloc_ab += 4) {
sfabv = LVFU(sfaveab[coeffloc_ab]);
sfaveabv = LVFU(sfaveabd[coeffloc_ab]);
//use smoothed shrinkage unless local shrinkage is much less
- _mm_storeu_ps(&WavCoeffs_ab[dir][coeffloc_ab], LVFU(WavCoeffs_ab[dir][coeffloc_ab]) * (SQRV(sfaveabv) + SQRV(sfabv)) / (sfaveabv + sfabv + epsv));
+ STVFU(WavCoeffs_ab[dir][coeffloc_ab], LVFU(WavCoeffs_ab[dir][coeffloc_ab]) * (SQRV(sfaveabv) + SQRV(sfabv)) / (sfaveabv + sfabv + epsv));
}
// few remaining pixels
@@ -2919,8 +2865,8 @@ void ImProcFunctions::ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
}
-void ImProcFunctions::WaveletDenoiseAll_info(int levwav, wavelet_decomposition &WaveletCoeffs_a,
- wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice,
+void ImProcFunctions::WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a,
+ const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice,
float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb)
{
@@ -3106,7 +3052,7 @@ void ImProcFunctions::calcautodn_info(float &chaut, float &delta, int Nb, int le
}
-void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread)
+void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, const bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread)
{
if ((settings->leveldnautsimpl == 1 && dnparams.Cmethod == "MAN") || (settings->leveldnautsimpl == 0 && dnparams.C2method == "MANU")) {
//nothing to do
@@ -3173,8 +3119,8 @@ void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc,
const float gain = pow(2.0f, float(expcomp));
- int tilesize;
- int overlap;
+ int tilesize = 0;
+ int overlap = 0;
if (settings->leveldnti == 0) {
tilesize = 1024;
@@ -3275,16 +3221,16 @@ void ImProcFunctions::RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc,
for (int i = tiletop; i < tilebottom; i += 2) {
int i1 = i - tiletop;
#ifdef __SSE2__
- __m128 aNv, bNv;
- __m128 c100v = _mm_set1_ps(100.f);
+ vfloat aNv, bNv;
+ vfloat c100v = F2V(100.f);
int j;
for (j = tileleft; j < tileright - 7; j += 8) {
int j1 = j - tileleft;
aNv = LVFU(acalc[i >> 1][j >> 1]);
bNv = LVFU(bcalc[i >> 1][j >> 1]);
- _mm_storeu_ps(&noisevarhue[i1 >> 1][j1 >> 1], xatan2f(bNv, aNv));
- _mm_storeu_ps(&noisevarchrom[i1 >> 1][j1 >> 1], vmaxf(vsqrtf(SQRV(aNv) + SQRV(bNv)),c100v));
+ STVFU(noisevarhue[i1 >> 1][j1 >> 1], xatan2f(bNv, aNv));
+ STVFU(noisevarchrom[i1 >> 1][j1 >> 1], vmaxf(vsqrtf(SQRV(aNv) + SQRV(bNv)),c100v));
}
for (; j < tileright; j += 2) {
diff --git a/rtengine/boxblur.cc b/rtengine/boxblur.cc
new file mode 100644
index 000000000..491ffae14
--- /dev/null
+++ b/rtengine/boxblur.cc
@@ -0,0 +1,420 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (C) 2010 Emil Martinec
+ * Copyright (C) 2019 Ingo Weyrich
+ *
+ * RawTherapee is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * RawTherapee is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with RawTherapee. If not, see .
+*/
+
+#include
+#include
+
+#include "boxblur.h"
+
+#include "rt_math.h"
+#include "opthelper.h"
+
+namespace rtengine
+{
+
+void boxblur(float** src, float** dst, int radius, int W, int H, bool multiThread)
+{
+ //box blur using rowbuffers and linebuffers instead of a full size buffer
+
+ if (radius == 0) {
+ if (src != dst) {
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+
+ for (int row = 0; row < H; ++row) {
+ for (int col = 0; col < W; ++col) {
+ dst[row][col] = src[row][col];
+ }
+ }
+ }
+ return;
+ }
+
+ constexpr int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+ std::unique_ptr buffer(new float[numCols * (radius + 1)]);
+
+ //horizontal blur
+ float* const lineBuffer = buffer.get();
+#ifdef _OPENMP
+ #pragma omp for
+#endif
+ for (int row = 0; row < H; ++row) {
+ float len = radius + 1;
+ float tempval = src[row][0];
+ lineBuffer[0] = tempval;
+ for (int j = 1; j <= radius; j++) {
+ tempval += src[row][j];
+ }
+
+ tempval /= len;
+ dst[row][0] = tempval;
+
+ for (int col = 1; col <= radius; ++col) {
+ lineBuffer[col] = src[row][col];
+ tempval = (tempval * len + src[row][col + radius]) / (len + 1);
+ dst[row][col] = tempval;
+ ++len;
+ }
+ int pos = 0;
+ for (int col = radius + 1; col < W - radius; ++col) {
+ const float oldVal = lineBuffer[pos];
+ lineBuffer[pos] = src[row][col];
+ tempval = tempval + (src[row][col + radius] - oldVal) / len;
+ dst[row][col] = tempval;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+
+ for (int col = W - radius; col < W; ++col) {
+ tempval = (tempval * len - lineBuffer[pos]) / (len - 1);
+ dst[row][col] = tempval;
+ --len;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ }
+
+ //vertical blur
+#ifdef __SSE2__
+ vfloat (* const rowBuffer)[2] = (vfloat(*)[2]) buffer.get();
+ const vfloat leninitv = F2V(radius + 1);
+ const vfloat onev = F2V(1.f);
+ vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
+
+#ifdef _OPENMP
+ #pragma omp for nowait
+#endif
+
+ for (int col = 0; col < W - 7; col += 8) {
+ lenv = leninitv;
+ tempv = LVFU(dst[0][col]);
+ temp1v = LVFU(dst[0][col + 4]);
+ rowBuffer[0][0] = tempv;
+ rowBuffer[0][1] = temp1v;
+
+ for (int i = 1; i <= radius; ++i) {
+ tempv = tempv + LVFU(dst[i][col]);
+ temp1v = temp1v + LVFU(dst[i][col + 4]);
+ }
+
+ tempv = tempv / lenv;
+ temp1v = temp1v / lenv;
+ STVFU(dst[0][col], tempv);
+ STVFU(dst[0][col + 4], temp1v);
+
+ for (int row = 1; row <= radius; ++row) {
+ rowBuffer[row][0] = LVFU(dst[row][col]);
+ rowBuffer[row][1] = LVFU(dst[row][col + 4]);
+ lenp1v = lenv + onev;
+ tempv = (tempv * lenv + LVFU(dst[row + radius][col])) / lenp1v;
+ temp1v = (temp1v * lenv + LVFU(dst[row + radius][col + 4])) / lenp1v;
+ STVFU(dst[row][col], tempv);
+ STVFU(dst[row][col + 4], temp1v);
+ lenv = lenp1v;
+ }
+
+ rlenv = onev / lenv;
+ int pos = 0;
+ for (int row = radius + 1; row < H - radius; ++row) {
+ vfloat oldVal0 = rowBuffer[pos][0];
+ vfloat oldVal1 = rowBuffer[pos][1];
+ rowBuffer[pos][0] = LVFU(dst[row][col]);
+ rowBuffer[pos][1] = LVFU(dst[row][col + 4]);
+ tempv = tempv + (LVFU(dst[row + radius][col]) - oldVal0) * rlenv ;
+ temp1v = temp1v + (LVFU(dst[row + radius][col + 4]) - oldVal1) * rlenv ;
+ STVFU(dst[row][col], tempv);
+ STVFU(dst[row][col + 4], temp1v);
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+
+ for (int row = H - radius; row < H; ++row) {
+ lenm1v = lenv - onev;
+ tempv = (tempv * lenv - rowBuffer[pos][0]) / lenm1v;
+ temp1v = (temp1v * lenv - rowBuffer[pos][1]) / lenm1v;
+ STVFU(dst[row][col], tempv);
+ STVFU(dst[row][col + 4], temp1v);
+ lenv = lenm1v;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ }
+
+#else
+ float (* const rowBuffer)[8] = (float(*)[8]) buffer.get();
+#ifdef _OPENMP
+ #pragma omp for nowait
+#endif
+
+ for (int col = 0; col < W - numCols + 1; col += 8) {
+ float len = radius + 1;
+
+ for (int k = 0; k < numCols; ++k) {
+ rowBuffer[0][k] = dst[0][col + k];
+ }
+
+ for (int i = 1; i <= radius; ++i) {
+ for (int k = 0; k < numCols; ++k) {
+ dst[0][col + k] += dst[i][col + k];
+ }
+ }
+
+ for(int k = 0; k < numCols; ++k) {
+ dst[0][col + k] /= len;
+ }
+
+ for (int row = 1; row <= radius; ++row) {
+ for(int k = 0; k < numCols; ++k) {
+ rowBuffer[row][k] = dst[row][col + k];
+ dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
+ }
+
+ len ++;
+ }
+
+ int pos = 0;
+ for (int row = radius + 1; row < H - radius; ++row) {
+ for(int k = 0; k < numCols; ++k) {
+ float oldVal = rowBuffer[pos][k];
+ rowBuffer[pos][k] = dst[row][col + k];
+ dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) / len;
+ }
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+
+ for (int row = H - radius; row < H; ++row) {
+ for(int k = 0; k < numCols; ++k) {
+ dst[row][col + k] = (dst[row - 1][col + k] * len - rowBuffer[pos][k]) / (len - 1);
+ }
+ len --;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ }
+
+#endif
+ //vertical blur, remaining columns
+#ifdef _OPENMP
+ #pragma omp single
+#endif
+ {
+ const int remaining = W % numCols;
+
+ if (remaining > 0) {
+ float (* const rowBuffer)[8] = (float(*)[8]) buffer.get();
+ const int col = W - remaining;
+
+ float len = radius + 1;
+ for(int k = 0; k < remaining; ++k) {
+ rowBuffer[0][k] = dst[0][col + k];
+ }
+ for (int row = 1; row <= radius; ++row) {
+ for(int k = 0; k < remaining; ++k) {
+ dst[0][col + k] += dst[row][col + k];
+ }
+ }
+ for(int k = 0; k < remaining; ++k) {
+ dst[0][col + k] /= len;
+ }
+ for (int row = 1; row <= radius; ++row) {
+ for(int k = 0; k < remaining; ++k) {
+ rowBuffer[row][k] = dst[row][col + k];
+ dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
+ }
+ len ++;
+ }
+ const float rlen = 1.f / len;
+ int pos = 0;
+ for (int row = radius + 1; row < H - radius; ++row) {
+ for(int k = 0; k < remaining; ++k) {
+ float oldVal = rowBuffer[pos][k];
+ rowBuffer[pos][k] = dst[row][col + k];
+ dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) * rlen;
+ }
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ for (int row = H - radius; row < H; ++row) {
+ for(int k = 0; k < remaining; ++k) {
+ dst[row][col + k] = (dst[(row - 1)][col + k] * len - rowBuffer[pos][k]) / (len - 1);
+ }
+ len --;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ }
+ }
+ }
+}
+
+void boxabsblur(float** src, float** dst, int radius, int W, int H, bool multiThread)
+{
+ //abs box blur using rowbuffers and linebuffers instead of a full size buffer, W should be a multiple of 16
+
+ if (radius == 0) {
+ if (src != dst) {
+#ifdef _OPENMP
+ #pragma omp parallel for if (multiThread)
+#endif
+
+ for (int row = 0; row < H; ++row) {
+ for (int col = 0; col < W; ++col) {
+ dst[row][col] = std::fabs(src[row][col]);
+ }
+ }
+ }
+ return;
+ }
+
+ constexpr int numCols = 16; // process numCols columns at once for better usage of L1 cpu cache
+#ifdef _OPENMP
+ #pragma omp parallel if (multiThread)
+#endif
+ {
+ float buffer[numCols * (radius + 1)] ALIGNED64;
+
+ //horizontal blur
+ float* const lineBuffer = buffer;
+#ifdef _OPENMP
+ #pragma omp for
+#endif
+ for (int row = 0; row < H; ++row) {
+ float len = radius + 1;
+ float tempval = std::fabs(src[row][0]);
+ lineBuffer[0] = tempval;
+ for (int j = 1; j <= radius; j++) {
+ tempval += std::fabs(src[row][j]);
+ }
+
+ tempval /= len;
+ dst[row][0] = tempval;
+
+ for (int col = 1; col <= radius; ++col) {
+ lineBuffer[col] = std::fabs(src[row][col]);
+ tempval = (tempval * len + std::fabs(src[row][col + radius])) / (len + 1);
+ dst[row][col] = tempval;
+ ++len;
+ }
+
+ const float rlen = 1.f / len;
+ int pos = 0;
+ for (int col = radius + 1; col < W - radius; ++col) {
+ const float oldVal = lineBuffer[pos];
+ lineBuffer[pos] = std::fabs(src[row][col]);
+ tempval = tempval + (std::fabs(src[row][col + radius]) - oldVal) * rlen;
+ dst[row][col] = tempval;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+
+ for (int col = W - radius; col < W; ++col) {
+ tempval = (tempval * len - lineBuffer[pos]) / (len - 1);
+ dst[row][col] = tempval;
+ --len;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ }
+
+ //vertical blur
+ float (* const rowBuffer)[numCols] = (float(*)[numCols]) buffer;
+#ifdef _OPENMP
+ #pragma omp for
+#endif
+
+ for (int col = 0; col < W; col += numCols) {
+ float len = radius + 1;
+
+ for (int k = 0; k < numCols; ++k) {
+ rowBuffer[0][k] = dst[0][col + k];
+ }
+
+ for (int i = 1; i <= radius; ++i) {
+ for (int k = 0; k < numCols; ++k) {
+ dst[0][col + k] += dst[i][col + k];
+ }
+ }
+
+ for(int k = 0; k < numCols; ++k) {
+ dst[0][col + k] /= len;
+ }
+
+ for (int row = 1; row <= radius; ++row) {
+ for(int k = 0; k < numCols; ++k) {
+ rowBuffer[row][k] = dst[row][col + k];
+ dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
+ }
+
+ ++len;
+ }
+
+ const float rlen = 1.f / len;
+ int pos = 0;
+ for (int row = radius + 1; row < H - radius; ++row) {
+ for(int k = 0; k < numCols; ++k) {
+ float oldVal = rowBuffer[pos][k];
+ rowBuffer[pos][k] = dst[row][col + k];
+ dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) * rlen;
+ }
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+
+ for (int row = H - radius; row < H; ++row) {
+ for(int k = 0; k < numCols; ++k) {
+ dst[row][col + k] = (dst[row - 1][col + k] * len - rowBuffer[pos][k]) / (len - 1);
+ }
+ --len;
+ ++pos;
+ pos = pos <= radius ? pos : 0;
+ }
+ }
+ }
+}
+
+void boxblur(float* src, float* dst, int radius, int W, int H, bool multiThread)
+{
+ float* srcp[H];
+ float* dstp[H];
+ for (int i = 0; i < H; ++i) {
+ srcp[i] = src + i * W;
+ dstp[i] = dst + i * W;
+ }
+ boxblur(srcp, dstp, radius, W, H, multiThread);
+}
+
+void boxabsblur(float* src, float* dst, int radius, int W, int H, bool multiThread)
+{
+ float* srcp[H];
+ float* dstp[H];
+ for (int i = 0; i < H; ++i) {
+ srcp[i] = src + i * W;
+ dstp[i] = dst + i * W;
+ }
+ boxabsblur(srcp, dstp, radius, W, H, multiThread);
+}
+
+}
diff --git a/rtengine/boxblur.h b/rtengine/boxblur.h
index 1689c5ed1..57fba9119 100644
--- a/rtengine/boxblur.h
+++ b/rtengine/boxblur.h
@@ -1,7 +1,7 @@
/*
* This file is part of RawTherapee.
*
- * Copyright (C) 2010 Emil Martinec
+ * Copyright (C) 2019 Ingo Weyrich
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -15,873 +15,15 @@
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
- */
-#ifndef _BOXBLUR_H_
-#define _BOXBLUR_H_
-
-#include
-#include
-#include
-#include
-#include
-#include "alignedbuffer.h"
-#include "rt_math.h"
-#include "opthelper.h"
+*/
+#pragma once
namespace rtengine
{
-// classical filtering if the support window is small:
-
-template void boxblur (T** src, A** dst, int radx, int rady, int W, int H)
-{
- //box blur image; box range = (radx,rady)
- assert(2*radx+1 < W);
- assert(2*rady+1 < H);
-
- AlignedBuffer* buffer = new AlignedBuffer (W * H);
- float* temp = buffer->data;
-
- if (radx == 0) {
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- temp[row * W + col] = (float)src[row][col];
- }
- } else {
- //horizontal blur
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int row = 0; row < H; row++) {
- int len = radx + 1;
- temp[row * W + 0] = (float)src[row][0] / len;
-
- for (int j = 1; j <= radx; j++) {
- temp[row * W + 0] += (float)src[row][j] / len;
- }
-
- for (int col = 1; col <= radx; col++) {
- temp[row * W + col] = (temp[row * W + col - 1] * len + (float)src[row][col + radx]) / (len + 1);
- len ++;
- }
-
- for (int col = radx + 1; col < W - radx; col++) {
- temp[row * W + col] = temp[row * W + col - 1] + ((float)(src[row][col + radx] - src[row][col - radx - 1])) / len;
- }
-
- for (int col = W - radx; col < W; col++) {
- temp[row * W + col] = (temp[row * W + col - 1] * len - src[row][col - radx - 1]) / (len - 1);
- len --;
- }
- }
- }
-
- if (rady == 0) {
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- dst[row][col] = temp[row * W + col];
- }
- } else {
- //vertical blur
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int col = 0; col < W; col++) {
- int len = rady + 1;
- dst[0][col] = temp[0 * W + col] / len;
-
- for (int i = 1; i <= rady; i++) {
- dst[0][col] += temp[i * W + col] / len;
- }
-
- for (int row = 1; row <= rady; row++) {
- dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + rady) * W + col]) / (len + 1);
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- dst[row][col] = dst[(row - 1)][col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
- }
-
- for (int row = H - rady; row < H; row++) {
- dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
- len --;
- }
- }
- }
-
- delete buffer;
+void boxblur(float** src, float** dst, int radius, int W, int H, bool multiThread);
+void boxblur(float* src, float* dst, int radius, int W, int H, bool multiThread);
+void boxabsblur(float** src, float** dst, int radius, int W, int H, bool multiThread);
+void boxabsblur(float* src, float* dst, int radius, int W, int H, bool multiThread);
}
-
-template void boxblur (T** src, A** dst, T* buffer, int radx, int rady, int W, int H)
-{
- //box blur image; box range = (radx,rady)
-
- float* temp = buffer;
-
- if (radx == 0) {
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- temp[row * W + col] = (float)src[row][col];
- }
- } else {
- //horizontal blur
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int row = 0; row < H; row++) {
- float len = radx + 1;
- float tempval = (float)src[row][0];
-
- for (int j = 1; j <= radx; j++) {
- tempval += (float)src[row][j];
- }
-
- tempval /= len;
- temp[row * W + 0] = tempval;
-
- for (int col = 1; col <= radx; col++) {
- temp[row * W + col] = tempval = (tempval * len + (float)src[row][col + radx]) / (len + 1);
- len ++;
- }
-
- for (int col = radx + 1; col < W - radx; col++) {
- temp[row * W + col] = tempval = tempval + ((float)(src[row][col + radx] - src[row][col - radx - 1])) / len;
- }
-
- for (int col = W - radx; col < W; col++) {
- temp[row * W + col] = tempval = (tempval * len - src[row][col - radx - 1]) / (len - 1);
- len --;
- }
- }
- }
-
- if (rady == 0) {
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- dst[row][col] = temp[row * W + col];
- }
- } else {
- const int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache
-#ifdef __SSE2__
- vfloat leninitv = F2V( (float)(rady + 1));
- vfloat onev = F2V( 1.f );
- vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
-
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int col = 0; col < W - 7; col += 8) {
- lenv = leninitv;
- tempv = LVFU(temp[0 * W + col]);
- temp1v = LVFU(temp[0 * W + col + 4]);
-
- for (int i = 1; i <= rady; i++) {
- tempv = tempv + LVFU(temp[i * W + col]);
- temp1v = temp1v + LVFU(temp[i * W + col + 4]);
- }
-
- tempv = tempv / lenv;
- temp1v = temp1v / lenv;
- STVFU(dst[0][col], tempv);
- STVFU(dst[0][col + 4], temp1v);
-
- for (int row = 1; row <= rady; row++) {
- lenp1v = lenv + onev;
- tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v;
- temp1v = (temp1v * lenv + LVFU(temp[(row + rady) * W + col + 4])) / lenp1v;
- STVFU(dst[row][col], tempv);
- STVFU(dst[row][col + 4], temp1v);
- lenv = lenp1v;
- }
-
- rlenv = onev / lenv;
-
- for (int row = rady + 1; row < H - rady; row++) {
- tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ;
- temp1v = temp1v + (LVFU(temp[(row + rady) * W + col + 4]) - LVFU(temp[(row - rady - 1) * W + col + 4])) * rlenv ;
- STVFU(dst[row][col], tempv);
- STVFU(dst[row][col + 4], temp1v);
- }
-
- for (int row = H - rady; row < H; row++) {
- lenm1v = lenv - onev;
- tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v;
- temp1v = (temp1v * lenv - LVFU(temp[(row - rady - 1) * W + col + 4])) / lenm1v;
- STVFU(dst[row][col], tempv);
- STVFU(dst[row][col + 4], temp1v);
- lenv = lenm1v;
- }
- }
-
-#else
- //vertical blur
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int col = 0; col < W - numCols + 1; col += 8) {
- float len = rady + 1;
-
- for(int k = 0; k < numCols; k++) {
- dst[0][col + k] = temp[0 * W + col + k];
- }
-
- for (int i = 1; i <= rady; i++) {
- for(int k = 0; k < numCols; k++) {
- dst[0][col + k] += temp[i * W + col + k];
- }
- }
-
- for(int k = 0; k < numCols; k++) {
- dst[0][col + k] /= len;
- }
-
- for (int row = 1; row <= rady; row++) {
- for(int k = 0; k < numCols; k++) {
- dst[row][col + k] = (dst[(row - 1)][col + k] * len + temp[(row + rady) * W + col + k]) / (len + 1);
- }
-
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- for(int k = 0; k < numCols; k++) {
- dst[row][col + k] = dst[(row - 1)][col + k] + (temp[(row + rady) * W + col + k] - temp[(row - rady - 1) * W + col + k]) / len;
- }
- }
-
- for (int row = H - rady; row < H; row++) {
- for(int k = 0; k < numCols; k++) {
- dst[row][col + k] = (dst[(row - 1)][col + k] * len - temp[(row - rady - 1) * W + col + k]) / (len - 1);
- }
-
- len --;
- }
- }
-
-#endif
-#ifdef _OPENMP
- #pragma omp single
-#endif
-
- for (int col = W - (W % numCols); col < W; col++) {
- float len = rady + 1;
- dst[0][col] = temp[0 * W + col] / len;
-
- for (int i = 1; i <= rady; i++) {
- dst[0][col] += temp[i * W + col] / len;
- }
-
- for (int row = 1; row <= rady; row++) {
- dst[row][col] = (dst[(row - 1)][col] * len + temp[(row + rady) * W + col]) / (len + 1);
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- dst[row][col] = dst[(row - 1)][col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
- }
-
- for (int row = H - rady; row < H; row++) {
- dst[row][col] = (dst[(row - 1)][col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
- len --;
- }
- }
- }
-
-}
-
-inline void boxblur (float** src, float** dst, int radius, int W, int H, bool multiThread)
-{
- //box blur using rowbuffers and linebuffers instead of a full size buffer
-
- if (radius == 0) {
- if (src != dst) {
-#ifdef _OPENMP
- #pragma omp parallel for if (multiThread)
-#endif
-
- for (int row = 0; row < H; row++) {
- for (int col = 0; col < W; col++) {
- dst[row][col] = src[row][col];
- }
- }
- }
- return;
- }
-
- constexpr int numCols = 8; // process numCols columns at once for better usage of L1 cpu cache
-#ifdef _OPENMP
- #pragma omp parallel if (multiThread)
-#endif
- {
- std::unique_ptr buffer(new float[numCols * (radius + 1)]);
-
- //horizontal blur
- float* const lineBuffer = buffer.get();
-#ifdef _OPENMP
- #pragma omp for
-#endif
- for (int row = 0; row < H; row++) {
- float len = radius + 1;
- float tempval = src[row][0];
- lineBuffer[0] = tempval;
- for (int j = 1; j <= radius; j++) {
- tempval += src[row][j];
- }
-
- tempval /= len;
- dst[row][0] = tempval;
-
- for (int col = 1; col <= radius; col++) {
- lineBuffer[col] = src[row][col];
- tempval = (tempval * len + src[row][col + radius]) / (len + 1);
- dst[row][col] = tempval;
- ++len;
- }
- int pos = 0;
- for (int col = radius + 1; col < W - radius; col++) {
- const float oldVal = lineBuffer[pos];
- lineBuffer[pos] = src[row][col];
- tempval = tempval + (src[row][col + radius] - oldVal) / len;
- dst[row][col] = tempval;
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
-
- for (int col = W - radius; col < W; col++) {
- tempval = (tempval * len - lineBuffer[pos]) / (len - 1);
- dst[row][col] = tempval;
- --len;
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
- }
-
- //vertical blur
-#ifdef __SSE2__
- vfloat (* const rowBuffer)[2] = (vfloat(*)[2]) buffer.get();
- const vfloat leninitv = F2V(radius + 1);
- const vfloat onev = F2V(1.f);
- vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
-
-#ifdef _OPENMP
- #pragma omp for nowait
-#endif
-
- for (int col = 0; col < W - 7; col += 8) {
- lenv = leninitv;
- tempv = LVFU(dst[0][col]);
- temp1v = LVFU(dst[0][col + 4]);
- rowBuffer[0][0] = tempv;
- rowBuffer[0][1] = temp1v;
-
- for (int i = 1; i <= radius; i++) {
- tempv = tempv + LVFU(dst[i][col]);
- temp1v = temp1v + LVFU(dst[i][col + 4]);
- }
-
- tempv = tempv / lenv;
- temp1v = temp1v / lenv;
- STVFU(dst[0][col], tempv);
- STVFU(dst[0][col + 4], temp1v);
-
- for (int row = 1; row <= radius; row++) {
- rowBuffer[row][0] = LVFU(dst[row][col]);
- rowBuffer[row][1] = LVFU(dst[row][col + 4]);
- lenp1v = lenv + onev;
- tempv = (tempv * lenv + LVFU(dst[row + radius][col])) / lenp1v;
- temp1v = (temp1v * lenv + LVFU(dst[row + radius][col + 4])) / lenp1v;
- STVFU(dst[row][col], tempv);
- STVFU(dst[row][col + 4], temp1v);
- lenv = lenp1v;
- }
-
- rlenv = onev / lenv;
- int pos = 0;
- for (int row = radius + 1; row < H - radius; row++) {
- vfloat oldVal0 = rowBuffer[pos][0];
- vfloat oldVal1 = rowBuffer[pos][1];
- rowBuffer[pos][0] = LVFU(dst[row][col]);
- rowBuffer[pos][1] = LVFU(dst[row][col + 4]);
- tempv = tempv + (LVFU(dst[row + radius][col]) - oldVal0) * rlenv ;
- temp1v = temp1v + (LVFU(dst[row + radius][col + 4]) - oldVal1) * rlenv ;
- STVFU(dst[row][col], tempv);
- STVFU(dst[row][col + 4], temp1v);
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
-
- for (int row = H - radius; row < H; row++) {
- lenm1v = lenv - onev;
- tempv = (tempv * lenv - rowBuffer[pos][0]) / lenm1v;
- temp1v = (temp1v * lenv - rowBuffer[pos][1]) / lenm1v;
- STVFU(dst[row][col], tempv);
- STVFU(dst[row][col + 4], temp1v);
- lenv = lenm1v;
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
- }
-
-#else
- float (* const rowBuffer)[8] = (float(*)[8]) buffer.get();
-#ifdef _OPENMP
- #pragma omp for nowait
-#endif
-
- for (int col = 0; col < W - numCols + 1; col += 8) {
- float len = radius + 1;
-
- for (int k = 0; k < numCols; k++) {
- rowBuffer[0][k] = dst[0][col + k];
- }
-
- for (int i = 1; i <= radius; i++) {
- for (int k = 0; k < numCols; k++) {
- dst[0][col + k] += dst[i][col + k];
- }
- }
-
- for(int k = 0; k < numCols; k++) {
- dst[0][col + k] /= len;
- }
-
- for (int row = 1; row <= radius; row++) {
- for(int k = 0; k < numCols; k++) {
- rowBuffer[row][k] = dst[row][col + k];
- dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
- }
-
- len ++;
- }
-
- int pos = 0;
- for (int row = radius + 1; row < H - radius; row++) {
- for(int k = 0; k < numCols; k++) {
- float oldVal = rowBuffer[pos][k];
- rowBuffer[pos][k] = dst[row][col + k];
- dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) / len;
- }
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
-
- for (int row = H - radius; row < H; row++) {
- for(int k = 0; k < numCols; k++) {
- dst[row][col + k] = (dst[row - 1][col + k] * len - rowBuffer[pos][k]) / (len - 1);
- }
- len --;
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
- }
-
-#endif
- //vertical blur, remaining columns
-#ifdef _OPENMP
- #pragma omp single
-#endif
- {
- const int remaining = W % numCols;
-
- if (remaining > 0) {
- float (* const rowBuffer)[8] = (float(*)[8]) buffer.get();
- const int col = W - remaining;
-
- float len = radius + 1;
- for(int k = 0; k < remaining; ++k) {
- rowBuffer[0][k] = dst[0][col + k];
- }
- for (int row = 1; row <= radius; ++row) {
- for(int k = 0; k < remaining; ++k) {
- dst[0][col + k] += dst[row][col + k];
- }
- }
- for(int k = 0; k < remaining; ++k) {
- dst[0][col + k] /= len;
- }
- for (int row = 1; row <= radius; ++row) {
- for(int k = 0; k < remaining; ++k) {
- rowBuffer[row][k] = dst[row][col + k];
- dst[row][col + k] = (dst[row - 1][col + k] * len + dst[row + radius][col + k]) / (len + 1);
- }
- len ++;
- }
- const float rlen = 1.f / len;
- int pos = 0;
- for (int row = radius + 1; row < H - radius; ++row) {
- for(int k = 0; k < remaining; ++k) {
- float oldVal = rowBuffer[pos][k];
- rowBuffer[pos][k] = dst[row][col + k];
- dst[row][col + k] = dst[row - 1][col + k] + (dst[row + radius][col + k] - oldVal) * rlen;
- }
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
- for (int row = H - radius; row < H; ++row) {
- for(int k = 0; k < remaining; ++k) {
- dst[row][col + k] = (dst[(row - 1)][col + k] * len - rowBuffer[pos][k]) / (len - 1);
- }
- len --;
- ++pos;
- pos = pos <= radius ? pos : 0;
- }
- }
- }
- }
-}
-
-template void boxblur (T* src, A* dst, A* buffer, int radx, int rady, int W, int H)
-{
- //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1)
-
- float* temp = buffer;
-
- if (radx == 0) {
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- temp[row * W + col] = src[row * W + col];
- }
- } else {
- //horizontal blur
- for (int row = H - 1; row >= 0; row--) {
- int len = radx + 1;
- float tempval = (float)src[row * W];
-
- for (int j = 1; j <= radx; j++) {
- tempval += (float)src[row * W + j];
- }
-
- tempval = tempval / len;
- temp[row * W] = tempval;
-
- for (int col = 1; col <= radx; col++) {
- tempval = (tempval * len + src[row * W + col + radx]) / (len + 1);
- temp[row * W + col] = tempval;
- len ++;
- }
-
- float reclen = 1.f / len;
-
- for (int col = radx + 1; col < W - radx; col++) {
- tempval = tempval + ((float)(src[row * W + col + radx] - src[row * W + col - radx - 1])) * reclen;
- temp[row * W + col] = tempval;
- }
-
- for (int col = W - radx; col < W; col++) {
- tempval = (tempval * len - src[row * W + col - radx - 1]) / (len - 1);
- temp[row * W + col] = tempval;
- len --;
- }
- }
- }
-
- if (rady == 0) {
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- dst[row * W + col] = temp[row * W + col];
- }
- } else {
- //vertical blur
-#ifdef __SSE2__
- vfloat leninitv = F2V( (float)(rady + 1));
- vfloat onev = F2V( 1.f );
- vfloat tempv, temp1v, lenv, lenp1v, lenm1v, rlenv;
- int col;
-
- for (col = 0; col < W - 7; col += 8) {
- lenv = leninitv;
- tempv = LVFU(temp[0 * W + col]);
- temp1v = LVFU(temp[0 * W + col + 4]);
-
- for (int i = 1; i <= rady; i++) {
- tempv = tempv + LVFU(temp[i * W + col]);
- temp1v = temp1v + LVFU(temp[i * W + col + 4]);
- }
-
- tempv = tempv / lenv;
- temp1v = temp1v / lenv;
- STVFU(dst[0 * W + col], tempv);
- STVFU(dst[0 * W + col + 4], temp1v);
-
- for (int row = 1; row <= rady; row++) {
- lenp1v = lenv + onev;
- tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v;
- temp1v = (temp1v * lenv + LVFU(temp[(row + rady) * W + col + 4])) / lenp1v;
- STVFU(dst[row * W + col], tempv);
- STVFU(dst[row * W + col + 4], temp1v);
- lenv = lenp1v;
- }
-
- rlenv = onev / lenv;
-
- for (int row = rady + 1; row < H - rady; row++) {
- tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ;
- temp1v = temp1v + (LVFU(temp[(row + rady) * W + col + 4]) - LVFU(temp[(row - rady - 1) * W + col + 4])) * rlenv ;
- STVFU(dst[row * W + col], tempv);
- STVFU(dst[row * W + col + 4], temp1v);
- }
-
- for (int row = H - rady; row < H; row++) {
- lenm1v = lenv - onev;
- tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v;
- temp1v = (temp1v * lenv - LVFU(temp[(row - rady - 1) * W + col + 4])) / lenm1v;
- STVFU(dst[row * W + col], tempv);
- STVFU(dst[row * W + col + 4], temp1v);
- lenv = lenm1v;
- }
- }
-
- for (; col < W - 3; col += 4) {
- lenv = leninitv;
- tempv = LVFU(temp[0 * W + col]);
-
- for (int i = 1; i <= rady; i++) {
- tempv = tempv + LVFU(temp[i * W + col]);
- }
-
- tempv = tempv / lenv;
- STVFU(dst[0 * W + col], tempv);
-
- for (int row = 1; row <= rady; row++) {
- lenp1v = lenv + onev;
- tempv = (tempv * lenv + LVFU(temp[(row + rady) * W + col])) / lenp1v;
- STVFU(dst[row * W + col], tempv);
- lenv = lenp1v;
- }
-
- rlenv = onev / lenv;
-
- for (int row = rady + 1; row < H - rady; row++) {
- tempv = tempv + (LVFU(temp[(row + rady) * W + col]) - LVFU(temp[(row - rady - 1) * W + col])) * rlenv ;
- STVFU(dst[row * W + col], tempv);
- }
-
- for (int row = H - rady; row < H; row++) {
- lenm1v = lenv - onev;
- tempv = (tempv * lenv - LVFU(temp[(row - rady - 1) * W + col])) / lenm1v;
- STVFU(dst[row * W + col], tempv);
- lenv = lenm1v;
- }
- }
-
- for (; col < W; col++) {
- int len = rady + 1;
- dst[0 * W + col] = temp[0 * W + col] / len;
-
- for (int i = 1; i <= rady; i++) {
- dst[0 * W + col] += temp[i * W + col] / len;
- }
-
- for (int row = 1; row <= rady; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
- }
-
- for (int row = H - rady; row < H; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
- len --;
- }
- }
-
-#else
-
- for (int col = 0; col < W; col++) {
- int len = rady + 1;
- dst[0 * W + col] = temp[0 * W + col] / len;
-
- for (int i = 1; i <= rady; i++) {
- dst[0 * W + col] += temp[i * W + col] / len;
- }
-
- for (int row = 1; row <= rady; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
- }
-
- for (int row = H - rady; row < H; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
- len --;
- }
- }
-
-#endif
- }
-
-}
-
-template void boxabsblur (T* src, A* dst, int radx, int rady, int W, int H, float * temp)
-{
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- //box blur image; box range = (radx,rady) i.e. box size is (2*radx+1)x(2*rady+1)
-
- if (radx == 0) {
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- temp[row * W + col] = fabs(src[row * W + col]);
- }
- } else {
- //horizontal blur
- for (int row = 0; row < H; row++) {
- int len = radx + 1;
- float tempval = fabsf((float)src[row * W + 0]);
-
- for (int j = 1; j <= radx; j++) {
- tempval += fabsf((float)src[row * W + j]);
- }
-
- tempval /= len;
- temp[row * W + 0] = tempval;
-
- for (int col = 1; col <= radx; col++) {
- tempval = (tempval * len + fabsf(src[row * W + col + radx])) / (len + 1);
- temp[row * W + col] = tempval;
- len ++;
- }
-
- float rlen = 1.f / (float)len;
-
- for (int col = radx + 1; col < W - radx; col++) {
- tempval = tempval + ((float)(fabsf(src[row * W + col + radx]) - fabsf(src[row * W + col - radx - 1]))) * rlen;
- temp[row * W + col] = tempval;
- }
-
- for (int col = W - radx; col < W; col++) {
- tempval = (tempval * len - fabsf(src[row * W + col - radx - 1])) / (len - 1);
- temp[row * W + col] = tempval;
- len --;
- }
- }
- }
-
- if (rady == 0) {
- for (int row = 0; row < H; row++)
- for (int col = 0; col < W; col++) {
- dst[row * W + col] = temp[row * W + col];
- }
- } else {
- //vertical blur
-#ifdef __SSE2__
- vfloat leninitv = F2V( (float)(rady + 1));
- vfloat onev = F2V( 1.f );
- vfloat tempv, lenv, lenp1v, lenm1v, rlenv;
-
- for (int col = 0; col < W - 3; col += 4) {
- lenv = leninitv;
- tempv = LVF(temp[0 * W + col]);
-
- for (int i = 1; i <= rady; i++) {
- tempv = tempv + LVF(temp[i * W + col]);
- }
-
- tempv = tempv / lenv;
- STVF(dst[0 * W + col], tempv);
-
- for (int row = 1; row <= rady; row++) {
- lenp1v = lenv + onev;
- tempv = (tempv * lenv + LVF(temp[(row + rady) * W + col])) / lenp1v;
- STVF(dst[row * W + col], tempv);
- lenv = lenp1v;
- }
-
- rlenv = onev / lenv;
-
- for (int row = rady + 1; row < H - rady; row++) {
- tempv = tempv + (LVF(temp[(row + rady) * W + col]) - LVF(temp[(row - rady - 1) * W + col])) * rlenv;
- STVF(dst[row * W + col], tempv);
- }
-
- for (int row = H - rady; row < H; row++) {
- lenm1v = lenv - onev;
- tempv = (tempv * lenv - LVF(temp[(row - rady - 1) * W + col])) / lenm1v;
- STVF(dst[row * W + col], tempv);
- lenv = lenm1v;
- }
- }
-
- for (int col = W - (W % 4); col < W; col++) {
- int len = rady + 1;
- dst[0 * W + col] = temp[0 * W + col] / len;
-
- for (int i = 1; i <= rady; i++) {
- dst[0 * W + col] += temp[i * W + col] / len;
- }
-
- for (int row = 1; row <= rady; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
- }
-
- for (int row = H - rady; row < H; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
- len --;
- }
- }
-
-#else
-
- for (int col = 0; col < W; col++) {
- int len = rady + 1;
- dst[0 * W + col] = temp[0 * W + col] / len;
-
- for (int i = 1; i <= rady; i++) {
- dst[0 * W + col] += temp[i * W + col] / len;
- }
-
- for (int row = 1; row <= rady; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len + temp[(row + rady) * W + col]) / (len + 1);
- len ++;
- }
-
- for (int row = rady + 1; row < H - rady; row++) {
- dst[row * W + col] = dst[(row - 1) * W + col] + (temp[(row + rady) * W + col] - temp[(row - rady - 1) * W + col]) / len;
- }
-
- for (int row = H - rady; row < H; row++) {
- dst[row * W + col] = (dst[(row - 1) * W + col] * len - temp[(row - rady - 1) * W + col]) / (len - 1);
- len --;
- }
- }
-
-#endif
- }
-
-}
-
-}
-#endif /* _BOXBLUR_H_ */
diff --git a/rtengine/capturesharpening.cc b/rtengine/capturesharpening.cc
index 38fe0897c..a080b4f36 100644
--- a/rtengine/capturesharpening.cc
+++ b/rtengine/capturesharpening.cc
@@ -668,7 +668,7 @@ BENCHFUN
buildClipMaskBayer(rawData, W, H, clipMask, whites);
const unsigned int fc[2] = {FC(0,0), FC(1,0)};
if (sharpeningParams.autoRadius) {
- radius = calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc);
+ radius = std::min(calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc), 1.15f);
}
} else if (ri->getSensorType() == ST_FUJI_XTRANS) {
float whites[6][6];
@@ -696,14 +696,14 @@ BENCHFUN
}
}
if (sharpeningParams.autoRadius) {
- radius = calcRadiusXtrans(rawData, W, H, 1000.f, clipVal, i, j);
+ radius = std::min(calcRadiusXtrans(rawData, W, H, 1000.f, clipVal, i, j), 1.15f);
}
} else if (ri->get_colors() == 1) {
buildClipMaskMono(rawData, W, H, clipMask, (ri->get_white(0) - c_black[0]) * scale_mul[0] * clipLimit);
if (sharpeningParams.autoRadius) {
const unsigned int fc[2] = {0, 0};
- radius = calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc);
+ radius = std::min(calcRadiusBayer(rawData, W, H, 1000.f, clipVal, fc), 1.15f);
}
}
diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc
index ef209118b..eb206a15f 100644
--- a/rtengine/dcraw.cc
+++ b/rtengine/dcraw.cc
@@ -2418,7 +2418,7 @@ void CLASS hasselblad_correct()
void CLASS hasselblad_load_raw()
{
struct jhead jh;
- int *back[5], diff[12];
+ int diff[12];
if (!ljpeg_start (&jh, 0)) {
return;
@@ -2426,18 +2426,10 @@ void CLASS hasselblad_load_raw()
order = 0x4949;
ph1_bithuff_t ph1_bithuff(this, ifp, order);
hb_bits(-1);
- back[4] = (int *) calloc(raw_width, 3 * sizeof **back);
- merror(back[4], "hasselblad_load_raw()");
- for (int c = 0; c < 3; ++c) {
- back[c] = back[4] + c * raw_width;
- }
- const int sh = tiff_samples > 1;
- cblack[6] >>= sh;
const int shot = LIM(shot_select, 1, tiff_samples) - 1;
+ const int predictor_init = static_cast(0x8000 + load_flags);
for (int row = 0; row < raw_height; ++row) {
- for (int c = 0; c < 4; ++c) {
- back[(c + 3) & 3] = back[c];
- }
+ int stashed_predictors[2] = {predictor_init, predictor_init};
for (int col = 0; col < raw_width; col += 2) {
for (int s = 0; s < tiff_samples * 2; s += 2) {
const int len[2]= {
@@ -2455,18 +2447,10 @@ void CLASS hasselblad_load_raw()
}
}
for (int s = col; s < col + 2; ++s) {
- int pred;
- if (col) {
- pred = back[2][s - 2];
- if (row > 1 && jh.psv == 11) {
- pred += back[0][s] / 2 - back[0][s - 2] / 2;
- }
- } else {
- pred = 0x8000 + load_flags;
- }
+ int pred = stashed_predictors[s & 1];
for (int c = 0; c < tiff_samples; ++c) {
pred += diff[(s & 1) * tiff_samples + c];
- const unsigned upix = pred >> sh & 0xffff;
+ const unsigned upix = pred & 0xffff;
if (raw_image && c == shot) {
RAW(row, s) = upix;
}
@@ -2479,12 +2463,13 @@ void CLASS hasselblad_load_raw()
*ip = c < 4 ? upix : (*ip + upix) >> 1;
}
}
+ if (c == (tiff_samples-1)) {
+ stashed_predictors[s & 1] = pred;
+ }
}
- back[2][s] = pred;
}
}
}
- free(back[4]);
ljpeg_end(&jh);
if (image) {
mix_green = 1;
diff --git a/rtengine/gauss.cc b/rtengine/gauss.cc
index ca330f9b9..8d9e5de38 100644
--- a/rtengine/gauss.cc
+++ b/rtengine/gauss.cc
@@ -16,12 +16,16 @@
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see .
*/
-#include "gauss.h"
-#include "rt_math.h"
#include
#include
-#include "opthelper.h"
+#include
+
+#include "gauss.h"
+
#include "boxblur.h"
+#include "opthelper.h"
+#include "rt_math.h"
+
namespace
{
@@ -1349,7 +1353,7 @@ template void gaussVerticalmult (T** src, T** dst, const int W, const i
}
#endif
-template void gaussianBlurImpl(T** src, T** dst, const int W, const int H, const double sigma, T *buffer = nullptr, eGaussType gausstype = GAUSS_STANDARD, T** buffer2 = nullptr)
+template void gaussianBlurImpl(T** src, T** dst, const int W, const int H, const double sigma, bool useBoxBlur, eGaussType gausstype = GAUSS_STANDARD, T** buffer2 = nullptr)
{
static constexpr auto GAUSS_SKIP = 0.25;
static constexpr auto GAUSS_3X3_LIMIT = 0.6;
@@ -1357,7 +1361,7 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int
static constexpr auto GAUSS_7X7_LIMIT = 1.15;
static constexpr auto GAUSS_DOUBLE = 25.0;
- if(buffer) {
+ if (useBoxBlur) {
// special variant for very large sigma, currently only used by retinex algorithm
// use iterated boxblur to approximate gaussian blur
// Compute ideal averaging filter width and number of iterations
@@ -1393,10 +1397,10 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int
sizes[i] = ((i < m ? wl : wu) - 1) / 2;
}
- rtengine::boxblur(src, dst, buffer, sizes[0], sizes[0], W, H);
+ rtengine::boxblur(src, dst, sizes[0], W, H, true);
for(int i = 1; i < n; i++) {
- rtengine::boxblur(dst, dst, buffer, sizes[i], sizes[i], W, H);
+ rtengine::boxblur(dst, dst, sizes[i], W, H, true);
}
} else {
if (sigma < GAUSS_SKIP) {
@@ -1532,8 +1536,8 @@ template void gaussianBlurImpl(T** src, T** dst, const int W, const int
}
}
-void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, float *buffer, eGaussType gausstype, float** buffer2)
+void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, bool useBoxBlur, eGaussType gausstype, float** buffer2)
{
- gaussianBlurImpl(src, dst, W, H, sigma, buffer, gausstype, buffer2);
+ gaussianBlurImpl(src, dst, W, H, sigma, useBoxBlur, gausstype, buffer2);
}
diff --git a/rtengine/gauss.h b/rtengine/gauss.h
index b63301d2b..f78762df3 100644
--- a/rtengine/gauss.h
+++ b/rtengine/gauss.h
@@ -21,6 +21,6 @@
enum eGaussType {GAUSS_STANDARD, GAUSS_MULT, GAUSS_DIV};
-void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, float *buffer = nullptr, eGaussType gausstype = GAUSS_STANDARD, float** buffer2 = nullptr);
+void gaussianBlur(float** src, float** dst, const int W, const int H, const double sigma, bool useBoxBlur = false, eGaussType gausstype = GAUSS_STANDARD, float** buffer2 = nullptr);
#endif
\ No newline at end of file
diff --git a/rtengine/guidedfilter.cc b/rtengine/guidedfilter.cc
index 159e89504..feb108198 100644
--- a/rtengine/guidedfilter.cc
+++ b/rtengine/guidedfilter.cc
@@ -105,7 +105,7 @@ void guidedFilter(const array2D &guide, const array2D &src, array2
[multithread](array2D &d, array2D &s, int rad) -> void
{
rad = LIM(rad, 0, (min(s.width(), s.height()) - 1) / 2 - 1);
- boxblur(s, d, rad, s.width(), s.height(), multithread);
+ boxblur(static_cast(s), static_cast(d), rad, s.width(), s.height(), multithread);
};
const int W = src.width();
diff --git a/rtengine/improcfun.h b/rtengine/improcfun.h
index 3a3d461a0..684927e47 100644
--- a/rtengine/improcfun.h
+++ b/rtengine/improcfun.h
@@ -198,20 +198,20 @@ public:
void Median_Denoise(float **src, float **dst, float upperBound, int width, int height, Median medianType, int iterations, int numThreads, float **buffer = nullptr);
void RGB_denoise(int kall, Imagefloat * src, Imagefloat * dst, Imagefloat * calclum, float * ch_M, float *max_r, float *max_b, bool isRAW, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, const NoiseCurve & noiseLCurve, const NoiseCurve & noiseCCurve, float &nresi, float &highresi);
void RGB_denoise_infoGamCurve(const procparams::DirPyrDenoiseParams & dnparams, const bool isRAW, LUTf &gamcurve, float &gam, float &gamthresh, float &gamslope);
- void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
- void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail, float * nbrwt, float * blurbuffer); //for DCT
+ void RGB_denoise_info(Imagefloat * src, Imagefloat * provicalc, bool isRAW, const LUTf &gamcurve, float gam, float gamthresh, float gamslope, const procparams::DirPyrDenoiseParams & dnparams, const double expcomp, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float & maxblueaut, float &minredaut, float & minblueaut, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc, bool multiThread = false);
+ void RGBtile_denoise(float * fLblox, int hblproc, float noisevar_Ldetail); //for DCT
void RGBoutput_tile_row(float *bloxrow_L, float ** Ldetail, float ** tilemask_out, int height, int width, int top);
- bool WaveletDenoiseAllL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge);
- bool WaveletDenoiseAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
- void WaveletDenoiseAll_info(int levwav, wavelet_decomposition &WaveletCoeffs_a,
- wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
+ bool WaveletDenoiseAllL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3], float * vari, int edge);
+ bool WaveletDenoiseAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
+ void WaveletDenoiseAll_info(int levwav, const wavelet_decomposition &WaveletCoeffs_a,
+ const wavelet_decomposition &WaveletCoeffs_b, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float & minblueaut, int schoice, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
float &maxchred, float &maxchblue, float &minchred, float &minchblue, int &nb, float &chau, float &chred, float &chblue, bool denoiseMethodRgb);
- bool WaveletDenoiseAll_BiShrinkL(wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]);
- bool WaveletDenoiseAll_BiShrinkAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab,
+ bool WaveletDenoiseAll_BiShrinkL(const wavelet_decomposition &WaveletCoeffs_L, float *noisevarlum, float madL[8][3]);
+ bool WaveletDenoiseAll_BiShrinkAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float *noisevarchrom, float madL[8][3], float noisevar_ab,
const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb);
- void ShrinkAllL(wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
- void ShrinkAllAB(wavelet_decomposition &WaveletCoeffs_L, wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
+ void ShrinkAllL(const wavelet_decomposition &WaveletCoeffs_L, float **buffer, int level, int dir, float *noisevarlum, float * madL, float * vari, int edge);
+ void ShrinkAllAB(const wavelet_decomposition &WaveletCoeffs_L, const wavelet_decomposition &WaveletCoeffs_ab, float **buffer, int level, int dir,
float *noisevarchrom, float noisevar_ab, const bool useNoiseCCurve, bool autoch, bool denoiseMethodRgb, float * madL, float * madaab = nullptr, bool madCalculated = false);
void ShrinkAll_info(float ** WavCoeffs_a, float ** WavCoeffs_b,
int W_ab, int H_ab, float **noisevarlum, float **noisevarchrom, float **noisevarhue, float &chaut, int &Nb, float &redaut, float &blueaut, float &maxredaut, float &maxblueaut, float &minredaut, float &minblueaut, int schoice, int lvl, float &chromina, float &sigma, float &lumema, float &sigma_L, float &redyel, float &skinc, float &nsknc,
diff --git a/rtengine/ipretinex.cc b/rtengine/ipretinex.cc
index 7117c9f2a..de6f4960a 100644
--- a/rtengine/ipretinex.cc
+++ b/rtengine/ipretinex.cc
@@ -43,6 +43,7 @@
#include "gauss.h"
#include "improcfun.h"
+#include "jaggedarray.h"
#include "median.h"
#include "opthelper.h"
#include "procparams.h"
@@ -50,8 +51,6 @@
#include "rtengine.h"
#include "StopWatch.h"
-#define clipretinex( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val )
-
namespace
{
void retinex_scales( float* scales, int nscales, int mode, int s, float high)
@@ -138,360 +137,422 @@ namespace rtengine
extern const Settings* settings;
-void RawImageSource::MSR(float** luminance, float** originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, const RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax)
+void RawImageSource::MSR(float** luminance, float** originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax)
{
+BENCHFUN
+ if (!deh.enabled) {
+ return;
+ }
- if (deh.enabled) {//enabled
- float maxtr, mintr;
- constexpr float eps = 2.f;
- bool useHsl = deh.retinexcolorspace == "HSLLOG";
- bool useHslLin = deh.retinexcolorspace == "HSLLIN";
- float offse = (float) deh.offs; //def = 0 not use
- int iter = deh.iter;
- int gradient = deh.scal;
- int scal = 3;//disabled scal
- int nei = (int) (2.8f * deh.neigh); //def = 220
- float vart = (float)deh.vart / 100.f;//variance
- float gradvart = (float)deh.grad;
- float gradstr = (float)deh.grads;
- float strength = (float) deh.str / 100.f; // Blend with original L channel data
- float limD = (float) deh.limd;
- limD = pow(limD, 1.7f);//about 2500 enough
- limD *= useHslLin ? 10.f : 1.f;
- float ilimD = 1.f / limD;
- float hig = ((float) deh.highl) / 100.f;
- scal = deh.skal;
+ constexpr float eps = 2.f;
+ const bool useHsl = deh.retinexcolorspace == "HSLLOG";
+ const bool useHslLin = deh.retinexcolorspace == "HSLLIN";
+ const float offse = deh.offs; //def = 0 not use
+ const int iter = deh.iter;
+ const int gradient = deh.scal;
+ int scal = deh.skal;
+ const int nei = 2.8f * deh.neigh; //def = 220
+ const float vart = deh.vart / 100.f;//variance
+ const float gradvart = deh.grad;
+ const float gradstr = deh.grads;
+ const float strength = deh.str / 100.f; // Blend with original L channel data
+ float limD = deh.limd;
+ limD = pow(limD, 1.7f);//about 2500 enough
+ limD *= useHslLin ? 10.f : 1.f;
+ const float ilimD = 1.f / limD;
+ const float hig = deh.highl / 100.f;
- int H_L = height;
- int W_L = width;
+ const int H_L = height;
+ const int W_L = width;
- float *tran[H_L] ALIGNED16;
- float *tranBuffer = nullptr;
+ constexpr float elogt = 2.71828f;
+ bool lhutili = false;
- constexpr float elogt = 2.71828f;
- bool lhutili = false;
+ FlatCurve* shcurve = new FlatCurve(deh.lhcurve); //curve L=f(H)
- FlatCurve* shcurve = new FlatCurve(deh.lhcurve); //curve L=f(H)
-
- if (!shcurve || shcurve->isIdentity()) {
- if (shcurve) {
- delete shcurve;
- shcurve = nullptr;
- }
- } else {
- lhutili = true;
+ if (!shcurve || shcurve->isIdentity()) {
+ if (shcurve) {
+ delete shcurve;
+ shcurve = nullptr;
}
+ } else {
+ lhutili = true;
+ }
- bool higplus = false ;
- int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" )
+ bool higplus = false ;
+ int moderetinex = 2; // default to 2 ( deh.retinexMethod == "high" )
- if(deh.retinexMethod == "highliplus") {
- higplus = true;
- moderetinex = 3;
- } else if (deh.retinexMethod == "uni") {
- moderetinex = 0;
- } else if (deh.retinexMethod == "low") {
- moderetinex = 1;
- } else { /*if (deh.retinexMethod == "highli") */
- moderetinex = 3;
- }
+ if(deh.retinexMethod == "highliplus") {
+ higplus = true;
+ moderetinex = 3;
+ } else if (deh.retinexMethod == "uni") {
+ moderetinex = 0;
+ } else if (deh.retinexMethod == "low") {
+ moderetinex = 1;
+ } else { /*if (deh.retinexMethod == "highli") */
+ moderetinex = 3;
+ }
- constexpr float aahi = 49.f / 99.f; ////reduce sensibility 50%
- constexpr float bbhi = 1.f - aahi;
+ constexpr float aahi = 49.f / 99.f; ////reduce sensibility 50%
+ constexpr float bbhi = 1.f - aahi;
+ float high = bbhi + aahi * (float) deh.highl;
- for(int it = 1; it < iter + 1; it++) { //iter nb max of iterations
- float high = bbhi + aahi * (float) deh.highl;
+ for (int it = 1; it < iter + 1; it++) { //iter nb max of iterations
+ float grad = 1.f;
+ float sc = scal;
- float grad = 1.f;
- float sc = scal;
-
- if(gradient == 0) {
- grad = 1.f;
- sc = 3.f;
- } else if(gradient == 1) {
- grad = 0.25f * it + 0.75f;
- sc = -0.5f * it + 4.5f;
- } else if(gradient == 2) {
- grad = 0.5f * it + 0.5f;
- sc = -0.75f * it + 5.75f;
- } else if(gradient == 3) {
- grad = 0.666f * it + 0.333f;
- sc = -0.75f * it + 5.75f;
- } else if(gradient == 4) {
- grad = 0.8f * it + 0.2f;
- sc = -0.75f * it + 5.75f;
- } else if(gradient == 5) {
- if(moderetinex != 3) {
- grad = 2.5f * it - 1.5f;
- } else {
- float aa = (11.f * high - 1.f) / 4.f;
- float bb = 1.f - aa;
- grad = aa * it + bb;
- }
-
- sc = -0.75f * it + 5.75f;
- } else if(gradient == 6) {
- if(moderetinex != 3) {
- grad = 5.f * it - 4.f;
- } else {
- float aa = (21.f * high - 1.f) / 4.f;
- float bb = 1.f - aa;
- grad = aa * it + bb;
- }
-
- sc = -0.75f * it + 5.75f;
- }
-
- else if(gradient == -1) {
- grad = -0.125f * it + 1.125f;
- sc = 3.f;
- }
-
- if(iter == 1) {
- sc = scal;
+ if (gradient == 0) {
+ grad = 1.f;
+ sc = 3.f;
+ } else if (gradient == 1) {
+ grad = 0.25f * it + 0.75f;
+ sc = -0.5f * it + 4.5f;
+ } else if (gradient == 2) {
+ grad = 0.5f * it + 0.5f;
+ sc = -0.75f * it + 5.75f;
+ } else if (gradient == 3) {
+ grad = 0.666f * it + 0.333f;
+ sc = -0.75f * it + 5.75f;
+ } else if (gradient == 4) {
+ grad = 0.8f * it + 0.2f;
+ sc = -0.75f * it + 5.75f;
+ } else if (gradient == 5) {
+ if (moderetinex != 3) {
+ grad = 2.5f * it - 1.5f;
} else {
- //adjust sc in function of choice of scale by user if iterations
- if(scal < 3) {
- sc -= 1;
+ float aa = (11.f * high - 1.f) / 4.f;
+ float bb = 1.f - aa;
+ grad = aa * it + bb;
+ }
- if(sc < 1.f) {//avoid 0
- sc = 1.f;
- }
+ sc = -0.75f * it + 5.75f;
+ } else if (gradient == 6) {
+ if (moderetinex != 3) {
+ grad = 5.f * it - 4.f;
+ } else {
+ float aa = (21.f * high - 1.f) / 4.f;
+ float bb = 1.f - aa;
+ grad = aa * it + bb;
+ }
+
+ sc = -0.75f * it + 5.75f;
+ } else if (gradient == -1) {
+ grad = -0.125f * it + 1.125f;
+ sc = 3.f;
+ }
+
+ if (iter == 1) {
+ sc = scal;
+ } else {
+ //adjust sc in function of choice of scale by user if iterations
+ if (scal < 3) {
+ sc -= 1;
+ if (sc < 1.f) {//avoid 0
+ sc = 1.f;
}
+ } else if (scal > 4) {
+ sc += 1;
+ }
+ }
- if(scal > 4) {
- sc += 1;
+ float varx = vart;
+ float limdx = limD;
+ float ilimdx = ilimD;
+
+ if (gradvart != 0) {
+ if (gradvart == 1) {
+ varx = vart * (-0.125f * it + 1.125f);
+ limdx = limD * (-0.125f * it + 1.125f);
+ ilimdx = 1.f / limdx;
+ } else if (gradvart == 2) {
+ varx = vart * (-0.2f * it + 1.2f);
+ limdx = limD * (-0.2f * it + 1.2f);
+ ilimdx = 1.f / limdx;
+ } else if (gradvart == -1) {
+ varx = vart * (0.125f * it + 0.875f);
+ limdx = limD * (0.125f * it + 0.875f);
+ ilimdx = 1.f / limdx;
+ } else if (gradvart == -2) {
+ varx = vart * (0.4f * it + 0.6f);
+ limdx = limD * (0.4f * it + 0.6f);
+ ilimdx = 1.f / limdx;
+ }
+ }
+
+ scal = round(sc);
+ float ks = 1.f;
+
+ if (gradstr != 0) {
+ if (gradstr == 1) {
+ if (it <= 3) {
+ ks = -0.3f * it + 1.6f;
+ } else {
+ ks = 0.5f;
+ }
+ } else if (gradstr == 2) {
+ if (it <= 3) {
+ ks = -0.6f * it + 2.2f;
+ } else {
+ ks = 0.3f;
+ }
+ } else if (gradstr == -1) {
+ if (it <= 3) {
+ ks = 0.2f * it + 0.6f;
+ } else {
+ ks = 1.2f;
+ }
+ } else if (gradstr == -2) {
+ if (it <= 3) {
+ ks = 0.4f * it + 0.2f;
+ } else {
+ ks = 1.5f;
}
}
+ }
- float varx = vart;
- float limdx = limD;
- float ilimdx = ilimD;
+ const float strengthx = ks * strength;
- if(gradvart != 0) {
- if(gradvart == 1) {
- varx = vart * (-0.125f * it + 1.125f);
- limdx = limD * (-0.125f * it + 1.125f);
- ilimdx = 1.f / limdx;
- } else if(gradvart == 2) {
- varx = vart * (-0.2f * it + 1.2f);
- limdx = limD * (-0.2f * it + 1.2f);
- ilimdx = 1.f / limdx;
- } else if(gradvart == -1) {
- varx = vart * (0.125f * it + 0.875f);
- limdx = limD * (0.125f * it + 0.875f);
- ilimdx = 1.f / limdx;
- } else if(gradvart == -2) {
- varx = vart * (0.4f * it + 0.6f);
- limdx = limD * (0.4f * it + 0.6f);
- ilimdx = 1.f / limdx;
- }
- }
+ constexpr auto maxRetinexScales = 8;
+ float RetinexScales[maxRetinexScales];
- scal = round(sc);
- float ks = 1.f;
+ retinex_scales(RetinexScales, scal, moderetinex, nei / grad, high);
- if(gradstr != 0) {
- if(gradstr == 1) {
- if(it <= 3) {
- ks = -0.3f * it + 1.6f;
- } else {
- ks = 0.5f;
- }
- } else if(gradstr == 2) {
- if(it <= 3) {
- ks = -0.6f * it + 2.2f;
- } else {
- ks = 0.3f;
- }
- } else if(gradstr == -1) {
- if(it <= 3) {
- ks = 0.2f * it + 0.6f;
- } else {
- ks = 1.2f;
- }
- } else if(gradstr == -2) {
- if(it <= 3) {
- ks = 0.4f * it + 0.2f;
- } else {
- ks = 1.5f;
- }
- }
- }
+ const int shHighlights = deh.highlights;
+ const int shShadows = deh.shadows;
- float strengthx = ks * strength;
+ int mapmet = 0;
- constexpr auto maxRetinexScales = 8;
- float RetinexScales[maxRetinexScales];
+ if(deh.mapMethod == "map") {
+ mapmet = 2;
+ } else if(deh.mapMethod == "mapT") {
+ mapmet = 3;
+ } else if(deh.mapMethod == "gaus") {
+ mapmet = 4;
+ }
- retinex_scales( RetinexScales, scal, moderetinex, nei / grad, high );
+ const double shradius = mapmet == 4 ? (double) deh.radius : 40.;
- float *src[H_L] ALIGNED16;
- float *srcBuffer = new float[H_L * W_L];
+ int viewmet = 0;
- for (int i = 0; i < H_L; i++) {
- src[i] = &srcBuffer[i * W_L];
- }
+ if(deh.viewMethod == "mask") {
+ viewmet = 1;
+ } else if(deh.viewMethod == "tran") {
+ viewmet = 2;
+ } else if(deh.viewMethod == "tran2") {
+ viewmet = 3;
+ } else if(deh.viewMethod == "unsharp") {
+ viewmet = 4;
+ }
- int h_th = 0, s_th = 0;
-
- int shHighlights = deh.highlights;
- int shShadows = deh.shadows;
-
- int mapmet = 0;
-
- if(deh.mapMethod == "map") {
- mapmet = 2;
- } else if(deh.mapMethod == "mapT") {
- mapmet = 3;
- } else if(deh.mapMethod == "gaus") {
- mapmet = 4;
- }
-
- const double shradius = mapmet == 4 ? (double) deh.radius : 40.;
-
- int viewmet = 0;
-
- if(deh.viewMethod == "mask") {
- viewmet = 1;
- } else if(deh.viewMethod == "tran") {
- viewmet = 2;
- } else if(deh.viewMethod == "tran2") {
- viewmet = 3;
- } else if(deh.viewMethod == "unsharp") {
- viewmet = 4;
- }
+ std::unique_ptr> srcBuffer(new JaggedArray(W_L, H_L));
+ float** src = *(srcBuffer.get());
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for
#endif
- for (int i = 0; i < H_L; i++)
- for (int j = 0; j < W_L; j++) {
- src[i][j] = luminance[i][j] + eps;
- luminance[i][j] = 0.f;
- }
-
- float *out[H_L] ALIGNED16;
- float *outBuffer = new float[H_L * W_L];
-
- for (int i = 0; i < H_L; i++) {
- out[i] = &outBuffer[i * W_L];
+ for (int i = 0; i < H_L; i++)
+ for (int j = 0; j < W_L; j++) {
+ src[i][j] = luminance[i][j] + eps;
+ luminance[i][j] = 0.f;
}
- if(viewmet == 3 || viewmet == 2) {
- tranBuffer = new float[H_L * W_L];
+ JaggedArray out(W_L, H_L);
+ JaggedArray& tran = out; // tran and out can safely use the same buffer
- for (int i = 0; i < H_L; i++) {
- tran[i] = &tranBuffer[i * W_L];
- }
- }
+ const float logBetaGain = xlogf(16384.f);
+ float pond = logBetaGain / (float) scal;
- const float logBetaGain = xlogf(16384.f);
- float pond = logBetaGain / (float) scal;
+ if(!useHslLin) {
+ pond /= log(elogt);
+ }
- if(!useHslLin) {
- pond /= log(elogt);
- }
+ std::unique_ptr shmap;
+ if (((mapmet == 2 || mapmet == 3 || mapmet == 4) && it == 1)) {
+ shmap.reset(new SHMap(W_L, H_L));
+ }
- auto shmap = ((mapmet == 2 || mapmet == 3 || mapmet == 4) && it == 1) ? new SHMap (W_L, H_L) : nullptr;
+ std::unique_ptr buffer;
+ if (mapmet > 0) {
+ buffer.reset(new float[W_L * H_L]);
+ }
- float *buffer = new float[W_L * H_L];;
-
- for ( int scale = scal - 1; scale >= 0; scale-- ) {
-#ifdef _OPENMP
- #pragma omp parallel
-#endif
- {
- if(scale == scal - 1)
- {
- gaussianBlur (src, out, W_L, H_L, RetinexScales[scale], buffer);
- } else { // reuse result of last iteration
- // out was modified in last iteration => restore it
- if((((mapmet == 2 && scale > 1) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1)
- {
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int i = 0; i < H_L; i++) {
- for (int j = 0; j < W_L; j++) {
- out[i][j] = buffer[i * W_L + j];
- }
- }
- }
-
- gaussianBlur (out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), buffer);
- }
- if((((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1 && scale > 0)
- {
- // out will be modified => store it for use in next iteration. We even don't need a new buffer because 'buffer' is free after gaussianBlur :)
-#ifdef _OPENMP
- #pragma omp for
-#endif
-
- for (int i = 0; i < H_L; i++) {
- for (int j = 0; j < W_L; j++) {
- buffer[i * W_L + j] = out[i][j];
- }
- }
- }
- }
-
- if(((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
- shmap->updateL (out, shradius, true, 1);
- h_th = shmap->max_f - deh.htonalwidth * (shmap->max_f - shmap->avg) / 100;
- s_th = deh.stonalwidth * (shmap->avg - shmap->min_f) / 100;
- }
-
-#ifdef __SSE2__
- vfloat pondv = F2V(pond);
- vfloat limMinv = F2V(ilimdx);
- vfloat limMaxv = F2V(limdx);
-
-#endif
-
- if(mapmet > 0 && mapcontlutili && it == 1) {
- // TODO: When rgbcurvespeedup branch is merged into master we can simplify the code by
- // 1) in rawimagesource.retinexPrepareCurves() insert
- // mapcurve *= 0.5f;
- // after
- // CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI);
- // 2) remove the division by 2.f from the code 7 lines below this line
+ for (int scale = scal - 1; scale >= 0; --scale) {
+ if (scale == scal - 1) {
+ gaussianBlur(src, out, W_L, H_L, RetinexScales[scale], true);
+ } else { // reuse result of last iteration
+ // out was modified in last iteration => restore it
+ if((((mapmet == 2 && scale > 1) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < H_L; i++) {
for (int j = 0; j < W_L; j++) {
- out[i][j] = mapcurve[2.f * out[i][j]] / 2.f;
+ out[i][j] = buffer[i * W_L + j];
}
}
-
}
- if(((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
- float hWeight = (100.f - shHighlights) / 100.f;
- float sWeight = (100.f - shShadows) / 100.f;
+ gaussianBlur(out, out, W_L, H_L, sqrtf(SQR(RetinexScales[scale]) - SQR(RetinexScales[scale + 1])), true);
+ }
+
+ if ((((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) || (mapmet > 0 && mapcontlutili)) && it == 1 && scale > 0) {
+ // out will be modified => store it for use in next iteration.
#ifdef _OPENMP
- #pragma omp parallel for schedule(dynamic,16)
+ #pragma omp parallel for
#endif
- for (int i = 0; i < H_L; i++) {
- for (int j = 0; j < W_L; j++) {
- float mapval = 1.f + shmap->map[i][j];
- float factor = 1.f;
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ buffer[i * W_L + j] = out[i][j];
+ }
+ }
+ }
+ int h_th = 0;
+ int s_th = 0;
+ if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
+ shmap->updateL(out, shradius, true, 1);
+ h_th = shmap->max_f - deh.htonalwidth * (shmap->max_f - shmap->avg) / 100;
+ s_th = deh.stonalwidth * (shmap->avg - shmap->min_f) / 100;
+ }
- if (mapval > h_th) {
- factor = (h_th + hWeight * (mapval - h_th)) / mapval;
- } else if (mapval < s_th) {
- factor = (s_th - sWeight * (s_th - mapval)) / mapval;
- }
+ if (mapmet > 0 && mapcontlutili && it == 1) {
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
- out[i][j] *= factor;
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ out[i][j] = mapcurve[2.f * out[i][j]];
+ }
+ }
+ }
+
+ if (((mapmet == 2 && scale > 2) || mapmet == 3 || mapmet == 4) && it == 1) {
+ const float hWeight = (100.f - shHighlights) / 100.f;
+ const float sWeight = (100.f - shShadows) / 100.f;
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ const float mapval = 1.f + shmap->map[i][j];
+ float factor;
+
+ if (mapval > h_th) {
+ factor = (h_th + hWeight * (mapval - h_th)) / mapval;
+ } else if (mapval < s_th) {
+ factor = (s_th - sWeight * (s_th - mapval)) / mapval;
+ } else {
+ factor = 1.f;
}
+
+ out[i][j] *= factor;
+ }
+ }
+ }
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = 0; i < H_L; i++) {
+ int j = 0;
+
+#ifdef __SSE2__
+ const vfloat pondv = F2V(pond);
+ const vfloat limMinv = F2V(ilimdx);
+ const vfloat limMaxv = F2V(limdx);
+ if( useHslLin) {
+ for (; j < W_L - 3; j += 4) {
+ STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv));
+ }
+ } else {
+ for (; j < W_L - 3; j += 4) {
+ STVFU(luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv)));
+ }
+ }
+
+#endif
+
+ if(useHslLin) {
+ for (; j < W_L; j++) {
+ luminance[i][j] += pond * LIM(src[i][j] / out[i][j], ilimdx, limdx);
+ }
+ } else {
+ for (; j < W_L; j++) {
+ luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimdx, limdx)); // /logt ?
+ }
+ }
+ }
+ }
+
+ srcBuffer.reset();
+
+ float mean = 0.f;
+ float stddv = 0.f;
+ // I call mean_stddv2 instead of mean_stddv ==> logBetaGain
+
+ float maxtr, mintr;
+ mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ //printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr);
+
+ //mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr);
+ if (dehatransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve
+ float asig = 0.166666f / stddv;
+ float bsig = 0.5f - asig * mean;
+ float amax = 0.333333f / (maxtr - mean - stddv);
+ float bmax = 1.f - amax * maxtr;
+ float amin = 0.333333f / (mean - stddv - mintr);
+ float bmin = -amin * mintr;
+
+ asig *= 500.f;
+ bsig *= 500.f;
+ amax *= 500.f;
+ bmax *= 500.f;
+ amin *= 500.f;
+ bmin *= 500.f;
+
+#ifdef _OPENMP
+ #pragma omp parallel for schedule(dynamic,16)
+#endif
+
+ for (int i = 0; i < H_L; i++ ) {
+ for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission
+ float absciss;
+ if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
+ absciss = asig * luminance[i][j] + bsig;
+ } else if (luminance[i][j] >= mean) {
+ absciss = amax * luminance[i][j] + bmax;
+ } else { /*if(luminance[i][j] <= mean - stddv)*/
+ absciss = amin * luminance[i][j] + bmin;
+ }
+
+ //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve
+ luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission
+
+ if(viewmet == 3 || viewmet == 2) {
+ tran[i][j] = luminance[i][j];
+ }
+ }
+ }
+
+ // median filter on transmission ==> reduce artifacts
+ if (deh.medianmap && it == 1) { //only one time
+ JaggedArray tmL(W_L, H_L);
+ constexpr int borderL = 1;
+
+#ifdef _OPENMP
+ #pragma omp parallel for
+#endif
+
+ for (int i = borderL; i < H_L - borderL; i++) {
+ for (int j = borderL; j < W_L - borderL; j++) {
+ tmL[i][j] = median(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3
}
}
@@ -499,307 +560,164 @@ void RawImageSource::MSR(float** luminance, float** originalLuminance, float **e
#pragma omp parallel for
#endif
- for (int i = 0; i < H_L; i++) {
- int j = 0;
-
-#ifdef __SSE2__
-
- if(useHslLin) {
- for (; j < W_L - 3; j += 4) {
- _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * (vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) ));
- }
- } else {
- for (; j < W_L - 3; j += 4) {
- _mm_storeu_ps(&luminance[i][j], LVFU(luminance[i][j]) + pondv * xlogf(vclampf(LVFU(src[i][j]) / LVFU(out[i][j]), limMinv, limMaxv) ));
- }
- }
-
-#endif
-
- if(useHslLin) {
- for (; j < W_L; j++) {
- luminance[i][j] += pond * (LIM(src[i][j] / out[i][j], ilimdx, limdx));
- }
- } else {
- for (; j < W_L; j++) {
- luminance[i][j] += pond * xlogf(LIM(src[i][j] / out[i][j], ilimdx, limdx)); // /logt ?
- }
+ for (int i = borderL; i < H_L - borderL; i++ ) {
+ for (int j = borderL; j < W_L - borderL; j++) {
+ luminance[i][j] = tmL[i][j];
}
}
}
- if(mapmet > 1) {
- if(shmap) {
- delete shmap;
- }
- }
-
- shmap = nullptr;
-
- delete [] buffer;
- delete [] srcBuffer;
-
- float mean = 0.f;
- float stddv = 0.f;
// I call mean_stddv2 instead of mean_stddv ==> logBetaGain
+ //mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr);
+ mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ }
- mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
- //printf("mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", mean, stddv, delta, maxtr, mintr);
+ constexpr float epsil = 0.1f;
- //mean_stddv( luminance, mean, stddv, W_L, H_L, logBetaGain, maxtr, mintr);
- if (dehatransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve
- float asig = 0.166666f / stddv;
- float bsig = 0.5f - asig * mean;
- float amax = 0.333333f / (maxtr - mean - stddv);
- float bmax = 1.f - amax * maxtr;
- float amin = 0.333333f / (mean - stddv - mintr);
- float bmin = -amin * mintr;
+ mini = mean - varx * stddv;
- asig *= 500.f;
- bsig *= 500.f;
- amax *= 500.f;
- bmax *= 500.f;
- amin *= 500.f;
- bmin *= 500.f;
+ if (mini < mintr) {
+ mini = mintr + epsil;
+ }
-#ifdef _OPENMP
- #pragma omp parallel
-#endif
- {
- float absciss;
-#ifdef _OPENMP
- #pragma omp for schedule(dynamic,16)
-#endif
+ maxi = mean + varx * stddv;
- for (int i = 0; i < H_L; i++ )
- for (int j = 0; j < W_L; j++) { //for mintr to maxtr evalate absciss in function of original transmission
- if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
- absciss = asig * luminance[i][j] + bsig;
- } else if (luminance[i][j] >= mean) {
- absciss = amax * luminance[i][j] + bmax;
- } else { /*if(luminance[i][j] <= mean - stddv)*/
- absciss = amin * luminance[i][j] + bmin;
- }
+ if (maxi > maxtr) {
+ maxi = maxtr - epsil;
+ }
- //TODO : move multiplication by 4.f and subtraction of 1.f inside the curve
- luminance[i][j] *= (-1.f + 4.f * dehatransmissionCurve[absciss]); //new transmission
+ float delta = maxi - mini;
+ //printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr);
- if(viewmet == 3 || viewmet == 2) {
- tran[i][j] = luminance[i][j];
- }
- }
- }
+ if ( !delta ) {
+ delta = 1.0f;
+ }
- // median filter on transmission ==> reduce artifacts
- if (deh.medianmap && it == 1) { //only one time
- int wid = W_L;
- int hei = H_L;
- float *tmL[hei] ALIGNED16;
- float *tmLBuffer = new float[wid * hei];
- int borderL = 1;
-
- for (int i = 0; i < hei; i++) {
- tmL[i] = &tmLBuffer[i * wid];
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int i = borderL; i < hei - borderL; i++) {
- for (int j = borderL; j < wid - borderL; j++) {
- tmL[i][j] = median(luminance[i][j], luminance[i - 1][j], luminance[i + 1][j], luminance[i][j + 1], luminance[i][j - 1], luminance[i - 1][j - 1], luminance[i - 1][j + 1], luminance[i + 1][j - 1], luminance[i + 1][j + 1]); //3x3
- }
- }
-
-#ifdef _OPENMP
- #pragma omp parallel for
-#endif
-
- for (int i = borderL; i < hei - borderL; i++ ) {
- for (int j = borderL; j < wid - borderL; j++) {
- luminance[i][j] = tmL[i][j];
- }
- }
-
- delete [] tmLBuffer;
-
- }
-
- // I call mean_stddv2 instead of mean_stddv ==> logBetaGain
- //mean_stddv( luminance, mean, stddv, W_L, H_L, 1.f, maxtr, mintr);
- mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
-
- }
-
- float epsil = 0.1f;
-
- mini = mean - varx * stddv;
-
- if (mini < mintr) {
- mini = mintr + epsil;
- }
-
- maxi = mean + varx * stddv;
-
- if (maxi > maxtr) {
- maxi = maxtr - epsil;
- }
-
- float delta = maxi - mini;
- //printf("maxi=%f mini=%f mean=%f std=%f delta=%f maxtr=%f mintr=%f\n", maxi, mini, mean, stddv, delta, maxtr, mintr);
-
- if ( !delta ) {
- delta = 1.0f;
- }
-
- float cdfactor = 32768.f / delta;
- maxCD = -9999999.f;
- minCD = 9999999.f;
- // coeff for auto "transmission" with 2 sigma #95% data
- float aza = 16300.f / (2.f * stddv);
- float azb = -aza * (mean - 2.f * stddv);
- float bza = 16300.f / (2.f * stddv);
- float bzb = 16300.f - bza * (mean);
+ // coeff for auto "transmission" with 2 sigma #95% data
+ const float aza = 16300.f / (2.f * stddv);
+ const float azb = -aza * (mean - 2.f * stddv);
+ const float bza = 16300.f / (2.f * stddv);
+ const float bzb = 16300.f - bza * (mean);
//prepare work for curve gain
#ifdef _OPENMP
- #pragma omp parallel for
+ #pragma omp parallel for
#endif
- for (int i = 0; i < H_L; i++) {
- for (int j = 0; j < W_L; j++) {
- luminance[i][j] = luminance[i][j] - mini;
- }
+ for (int i = 0; i < H_L; i++) {
+ for (int j = 0; j < W_L; j++) {
+ luminance[i][j] = luminance[i][j] - mini;
}
+ }
- mean = 0.f;
- stddv = 0.f;
- // I call mean_stddv2 instead of mean_stddv ==> logBetaGain
+ mean = 0.f;
+ stddv = 0.f;
+ // I call mean_stddv2 instead of mean_stddv ==> logBetaGain
- mean_stddv2( luminance, mean, stddv, W_L, H_L, maxtr, mintr);
- float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f;
+ mean_stddv2(luminance, mean, stddv, W_L, H_L, maxtr, mintr);
+ float asig = 0.f, bsig = 0.f, amax = 0.f, bmax = 0.f, amin = 0.f, bmin = 0.f;
- if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve
- asig = 0.166666f / stddv;
- bsig = 0.5f - asig * mean;
- amax = 0.333333f / (maxtr - mean - stddv);
- bmax = 1.f - amax * maxtr;
- amin = 0.333333f / (mean - stddv - mintr);
- bmin = -amin * mintr;
+ if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) { //if curve
+ asig = 0.166666f / stddv;
+ bsig = 0.5f - asig * mean;
+ amax = 0.333333f / (maxtr - mean - stddv);
+ bmax = 1.f - amax * maxtr;
+ amin = 0.333333f / (mean - stddv - mintr);
+ bmin = -amin * mintr;
- asig *= 500.f;
- bsig *= 500.f;
- amax *= 500.f;
- bmax *= 500.f;
- amin *= 500.f;
- bmin *= 500.f;
- }
+ asig *= 500.f;
+ bsig *= 500.f;
+ amax *= 500.f;
+ bmax *= 500.f;
+ amin *= 500.f;
+ bmin *= 500.f;
+ }
+
+ const float cdfactor = 32768.f / delta;
+ maxCD = -9999999.f;
+ minCD = 9999999.f;
#ifdef _OPENMP
- #pragma omp parallel
-#endif
- {
- float cdmax = -999999.f, cdmin = 999999.f;
-#ifdef _OPENMP
- #pragma omp for schedule(dynamic,16) nowait
+ #pragma omp parallel for reduction(max:maxCD) reduction(min:minCD) schedule(dynamic, 16)
#endif
- for ( int i = 0; i < H_L; i ++ )
- for (int j = 0; j < W_L; j++) {
- float gan;
+ for ( int i = 0; i < H_L; i ++ ) {
+ for (int j = 0; j < W_L; j++) {
+ float gan;
- if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) {
- float absciss;
-
- if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
- absciss = asig * luminance[i][j] + bsig;
- } else if (luminance[i][j] >= mean) {
- absciss = amax * luminance[i][j] + bmax;
- } else { /*if(luminance[i][j] <= mean - stddv)*/
- absciss = amin * luminance[i][j] + bmin;
- }
-
-
- // float cd = cdfactor * ( luminance[i][j] - mini ) + offse;
- // TODO : move multiplication by 2.f inside the curve
- gan = 2.f * (dehagaintransmissionCurve[absciss]); //new gain function transmission
- } else {
- gan = 0.5f;
- }
-
- float cd = gan * cdfactor * ( luminance[i][j] ) + offse;
-
- cdmax = cd > cdmax ? cd : cdmax;
- cdmin = cd < cdmin ? cd : cdmin;
-
- float str = strengthx;
-
- if(lhutili && it == 1) { // S=f(H)
- {
- float HH = exLuminance[i][j];
- float valparam;
-
- if(useHsl || useHslLin) {
- valparam = float((shcurve->getVal(HH) - 0.5f));
- } else {
- valparam = float((shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f));
- }
-
- str *= (1.f + 2.f * valparam);
- }
- }
-
- if(higplus && exLuminance[i][j] > 65535.f * hig) {
- str *= hig;
- }
-
- if(viewmet == 0) {
- luminance[i][j] = intp(str, clipretinex( cd, 0.f, 32768.f ), originalLuminance[i][j]);
- } else if(viewmet == 1) {
- luminance[i][j] = out[i][j];
- } else if(viewmet == 4) {
- luminance[i][j] = originalLuminance[i][j] + str * (originalLuminance[i][j] - out[i][j]);//unsharp
- } else if(viewmet == 2) {
- if(tran[i][j] <= mean) {
- luminance[i][j] = azb + aza * tran[i][j]; //auto values
- } else {
- luminance[i][j] = bzb + bza * tran[i][j];
- }
- } else { /*if(viewmet == 3) */
- luminance[i][j] = 1000.f + tran[i][j] * 700.f; //arbitrary values to help display log values which are between -20 to + 30 - usage values -4 + 5
- }
+ if (dehagaintransmissionCurve && mean != 0.f && stddv != 0.f) {
+ float absciss;
+ if (LIKELY(fabsf(luminance[i][j] - mean) < stddv)) {
+ absciss = asig * luminance[i][j] + bsig;
+ } else if (luminance[i][j] >= mean) {
+ absciss = amax * luminance[i][j] + bmax;
+ } else { /*if(luminance[i][j] <= mean - stddv)*/
+ absciss = amin * luminance[i][j] + bmin;
}
-#ifdef _OPENMP
- #pragma omp critical
-#endif
- {
- maxCD = maxCD > cdmax ? maxCD : cdmax;
- minCD = minCD < cdmin ? minCD : cdmin;
+
+ // float cd = cdfactor * ( luminance[i][j] - mini ) + offse;
+ // TODO : move multiplication by 2.f inside the curve
+ gan = 2.f * dehagaintransmissionCurve[absciss]; //new gain function transmission
+ } else {
+ gan = 0.5f;
+ }
+
+ const float cd = gan * cdfactor * luminance[i][j] + offse;
+
+ maxCD = cd > maxCD ? cd : maxCD;
+ minCD = cd < minCD ? cd : minCD;
+
+ float str = strengthx;
+
+ if (lhutili && it == 1) { // S=f(H)
+ {
+ const float HH = exLuminance[i][j];
+ float valparam;
+
+ if(useHsl || useHslLin) {
+ valparam = shcurve->getVal(HH) - 0.5f;
+ } else {
+ valparam = shcurve->getVal(Color::huelab_to_huehsv2(HH)) - 0.5f;
+ }
+
+ str *= (1.f + 2.f * valparam);
+ }
+ }
+
+ if (higplus && exLuminance[i][j] > 65535.f * hig) {
+ str *= hig;
+ }
+
+ if (viewmet == 0) {
+ luminance[i][j] = intp(str, LIM(cd, 0.f, 32768.f), originalLuminance[i][j]);
+ } else if (viewmet == 1) {
+ luminance[i][j] = out[i][j];
+ } else if (viewmet == 4) {
+ luminance[i][j] = originalLuminance[i][j] + str * (originalLuminance[i][j] - out[i][j]);//unsharp
+ } else if (viewmet == 2) {
+ if(tran[i][j] <= mean) {
+ luminance[i][j] = azb + aza * tran[i][j]; //auto values
+ } else {
+ luminance[i][j] = bzb + bza * tran[i][j];
+ }
+ } else { /*if (viewmet == 3) */
+ luminance[i][j] = 1000.f + tran[i][j] * 700.f; //arbitrary values to help display log values which are between -20 to + 30 - usage values -4 + 5
}
}
-
- delete [] outBuffer;
- outBuffer = nullptr;
- //printf("cdmin=%f cdmax=%f\n",minCD, maxCD);
- Tmean = mean;
- Tsigma = stddv;
- Tmin = mintr;
- Tmax = maxtr;
-
- if (shcurve) {
- delete shcurve;
- shcurve = nullptr;
- }
}
- if(tranBuffer) {
- delete [] tranBuffer;
- }
+ Tmean = mean;
+ Tsigma = stddv;
+ Tmin = mintr;
+ Tmax = maxtr;
+ if (shcurve) {
+ delete shcurve;
+ shcurve = nullptr;
+ }
}
}
diff --git a/rtengine/ipsharpen.cc b/rtengine/ipsharpen.cc
index bbd1de155..0b1332ec9 100644
--- a/rtengine/ipsharpen.cc
+++ b/rtengine/ipsharpen.cc
@@ -207,13 +207,13 @@ BENCHFUN
for (int k = 0; k < sharpenParam.deconviter; k++) {
if (!needdamp) {
// apply gaussian blur and divide luminance by result of gaussian blur
- gaussianBlur(tmpI, tmp, W, H, sigma, nullptr, GAUSS_DIV, luminance);
+ gaussianBlur(tmpI, tmp, W, H, sigma, false, GAUSS_DIV, luminance);
} else {
// apply gaussian blur + damping
gaussianBlur(tmpI, tmp, W, H, sigma);
dcdamping(tmp, luminance, damping, W, H);
}
- gaussianBlur(tmp, tmpI, W, H, sigma, nullptr, GAUSS_MULT);
+ gaussianBlur(tmp, tmpI, W, H, sigma, false, GAUSS_MULT);
} // end for
#ifdef _OPENMP
diff --git a/rtengine/ipwavelet.cc b/rtengine/ipwavelet.cc
index 07e9da85b..6631aae32 100644
--- a/rtengine/ipwavelet.cc
+++ b/rtengine/ipwavelet.cc
@@ -32,7 +32,6 @@
#include "improcfun.h"
#include "LUT.h"
#include "array2D.h"
-#include "boxblur.h"
#include "rt_math.h"
#include "mytime.h"
#include "sleef.c"
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 34a50b944..b5bbe5b8a 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1950,8 +1950,8 @@ void RawImageSource::retinexPrepareCurves(const RetinexParams &retinexParams, LU
CurveFactory::curveDehaContL (retinexcontlutili, retinexParams.cdcurve, cdcurve, 1, lhist16RETI, histLRETI);
}
- CurveFactory::mapcurve (mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI);
-
+ CurveFactory::mapcurve(mapcontlutili, retinexParams.mapcurve, mapcurve, 1, lhist16RETI, histLRETI);
+ mapcurve *= 0.5f;
retinexParams.getCurves(retinextransmissionCurve, retinexgaintransmissionCurve);
}
diff --git a/rtengine/rawimagesource.h b/rtengine/rawimagesource.h
index aff252842..b21f01ece 100644
--- a/rtengine/rawimagesource.h
+++ b/rtengine/rawimagesource.h
@@ -200,7 +200,7 @@ public:
}
static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]);
- void MSR(float** luminance, float **originalLuminance, float **exLuminance, LUTf & mapcurve, bool &mapcontlutili, int width, int height, const RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
+ void MSR(float** luminance, float **originalLuminance, float **exLuminance, const LUTf& mapcurve, bool mapcontlutili, int width, int height, const RetinexParams &deh, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax);
void HLRecovery_inpaint (float** red, float** green, float** blue) override;
static void HLRecovery_Luminance (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval);
static void HLRecovery_CIELab (float* rin, float* gin, float* bin, float* rout, float* gout, float* bout, int width, float maxval, double cam[3][3], double icam[3][3]);
diff --git a/rtengine/rescale.h b/rtengine/rescale.h
index e9d476fea..8e1f99271 100644
--- a/rtengine/rescale.h
+++ b/rtengine/rescale.h
@@ -21,6 +21,7 @@
#pragma once
#include "array2D.h"
+#include "rt_math.h"
namespace rtengine {
diff --git a/rtengine/shmap.cc b/rtengine/shmap.cc
index 6b59c4b40..368442f2b 100644
--- a/rtengine/shmap.cc
+++ b/rtengine/shmap.cc
@@ -85,21 +85,14 @@ void SHMap::update (Imagefloat* img, double radius, double lumi[3], bool hq, int
if (!hq) {
fillLuminance( img, map, lumi);
- float *buffer = nullptr;
-
- if(radius > 40.) {
- // When we pass another buffer to gaussianBlur, it will use iterated boxblur which is less prone to artifacts
- buffer = new float[W * H];
- }
+ const bool useBoxBlur = radius > 40.0; // boxblur is less prone to artifacts for large radi
#ifdef _OPENMP
- #pragma omp parallel
+ #pragma omp parallel if (!useBoxBlur)
#endif
{
- gaussianBlur (map, map, W, H, radius, buffer);
+ gaussianBlur (map, map, W, H, radius, useBoxBlur);
}
-
- delete [] buffer;
}
else {