diff --git a/CMakeLists.txt b/CMakeLists.txt index f73cf77be..8dcf6793d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,9 @@ if(HAVE_X86_SSE_MATH) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2 -mfpmath=sse") endif() +# On i386 Linux we can fix unaligned SSE malloc (see GitHub issue #4432) +include(FindUnalignedMalloc) + if(WIN32) # Add additional paths. Look in the MinGW path first, then in the Gtkmm path. # If you wish to build some dependent libraries, you have to install them in MinGW to use them: @@ -339,8 +342,13 @@ if(WITH_LTO) execute_process(COMMAND ar --version OUTPUT_VARIABLE BINUTILS_VERSION_DETECTED) string(REGEX REPLACE ".* ([0-9.]+)\n.*" "\\1" BINUTILS_VERSION_DETECTED "${BINUTILS_VERSION_DETECTED}") if("${BINUTILS_VERSION_DETECTED}" VERSION_LESS "${BINUTILS_VERSION_MININUM}") - SET(CMAKE_AR "/usr/bin/gcc-ar") - SET(CMAKE_RANLIB "/usr/bin/gcc-ranlib") + if(APPLE) + SET(CMAKE_AR "/opt/local/bin/ar") + SET(CMAKE_RANLIB "/opt/local/bin/ranlib") + else() + SET(CMAKE_AR "/usr/bin/gcc-ar") + SET(CMAKE_RANLIB "/usr/bin/gcc-ranlib") + endif() message(STATUS "Binutils version detected as less than " ${BINUTILS_VERSION_MININUM} " - setting CMake parameters to enable LTO linking:\n CMAKE_AR=\"" ${CMAKE_AR} "\"\n CMAKE_RANLIB=\"" ${CMAKE_RANLIB} "\"") endif() diff --git a/LICENSE.txt b/LICENSE.txt index 44a4cfcc8..7fb1c6515 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ RawTherapee - A powerful, cross-platform raw image processing program. Copyright (C) 2004-2012 Gabor Horvath - Copyright (C) 2010-2017 RawTherapee development team. + Copyright (C) 2010-2018 RawTherapee development team. RawTherapee is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 83ad8acc4..a041b0daf 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -1,10 +1,9 @@ -RAWTHERAPEE 5.3-dev RELEASE NOTES ------------------------------ +RAWTHERAPEE 5.5-dev RELEASE NOTES + This is a development version of RawTherapee. We update the code almost daily. Every few months, once enough changes have accumulated and the code is stabilized, we make a new official release. Every code change between these releases is known as a "development" version, and this is one of them. -RawTherapee provides you with a selection of powerful tools with which you can practise the art of developing raw photos. Be sure to read RawPedia to understand how each tool works so that you may make the most of it. +Start by reading the "Getting Started" article on RawPedia: http://rawpedia.rawtherapee.com/ -A great place to start is the "Getting Started" article. Click on "Main page" in the top-left corner when you have finished reading that article to see all other articles. While we only commit tested and relatively stable code and so the development versions should be fairly stable, you should be aware that: - Development versions only had limited testing, so there may be bugs unknown to us. @@ -13,72 +12,91 @@ While we only commit tested and relatively stable code and so the development ve - The way new tools work in the development versions is likely to change as we tweak and tune them, so your processing profiles may produce different results when used in a future stable version. - Bugs present in the stable versions get fixed in the development versions, and make it into the next stable version when we make a new official release. That means that in some ways the development versions can be "more stable" than the latest stable release. At the same time, new features may introduce new bugs. This is a trade-off you should be aware of. -News Relevant to Photographers ------------------------------- -RawTherapee supports most raw formats, including Pentax Pixel Shift, Canon Dual-Pixel, and those from Foveon and X-Trans sensors. + +NEWS RELEVANT TO PHOTOGRAPHERS + +RawTherapee supports most raw formats, including Pentax and Sony Pixel Shift, Canon Dual-Pixel, and those from Foveon and X-Trans sensors. If you're wondering whether it supports your camera's raw format, first download RawTherapee and try for yourself. If a raw format is not supported it will either not open, or the preview in the Editor tab will appear black, white, or have a strong color cast - usually magenta. In that case, read the "Adding Support for New Raw Formats" RawPedia article. In order to use RawTherapee efficiently you should know that: - You can scroll all panels using the mouse scroll-wheel. - You can right-click on a tool's name to automatically expand it while collapsing all others. - To change slider values or drop-down list items with the mouse scroll-wheel, hold the Shift key. This is so that you can safely scroll the panels without accidentally changing a slider or other tool setting. -- All curves support the Shift and Ctrl keys while dragging a point. Shift+drag makes the point snap to meaningful axes (top, bottom, diagonal, other), while Ctrl+drag makes your mouse movement super-fine for precise point positioning. +- All curves support the Shift and Ctrl keys while dragging a point. Shift+drag makes the point snap to a meaningful axis (top, bottom, diagonal, other), while Ctrl+drag makes your mouse movement super-fine for precise point positioning. - There are many keyboard shortcuts which make working with RawTherapee much faster and give you greater control. Make sure you familiarize yourself with them on RawPedia's "Keyboard Shortcuts" page! -New features since 5.3: -- To be filled in when 5.4 is released. +New features since 5.4: +- TODO. + +RawTherapee and other open-source projects require access to sample raw files from various camera makes and models in order to support those raw formats correctly. +You can help by submitting raw files to RPU: +https://raw.pixls.us/ + + + +NEWS RELEVANT TO PACKAGE MAINTAINERS -News Relevant to Package Maintainers ------------------------------------- In general: - To get the source code, either clone from git or use the tarball from http://rawtherapee.com/shared/source/ . Do not use the auto-generated GitHub release tarballs. -- Requires GTK+ version >=3.16, though 3.22 is recommended. +- Requires GTK+ version >=3.16, though >=3.22.24 is recommended. - RawTherapee 5 requires GCC-4.9 or higher, or Clang. - Do not use -ffast-math, it will not make RawTherapee faster but will introduce artifacts. - Use -O3, it will make RawTherapee faster with no known side-effects. - For stable releases use -DCACHE_NAME_SUFFIX="" - For development builds and release-candidates use -DCACHE_NAME_SUFFIX="5-dev" -Changes since 5.2: -- To be filled in when 5.4 is released. +Changes since 5.4: +- TODO. + + + +NEWS RELEVANT TO DEVELOPERS + +See CONTRIBUTING.md + -News Relevant to Developers ---------------------------- -- Announce and discuss your plans in GitHub before starting work. -- Keep branches small so that completed and working features can be merged into the "dev" branch often, and so that they can be abandoned if they head in the wrong direction. -- Use C++11. DOCUMENTATION -------------- -http://rawtherapee.com/blog/documentation + http://rawpedia.rawtherapee.com/ +http://rawtherapee.com/blog/documentation + + REPORTING BUGS --------------- + If you found a problem, don't keep it to yourself. Read the "How to write useful bug reports" article to get the problem fixed: http://rawpedia.rawtherapee.com/How_to_write_useful_bug_reports + + FORUM ------ + RawTherapee shares a forum with users and developers of other Free/Libre/Open Source Software: https://discuss.pixls.us/c/software/rawtherapee + + LIVE CHAT WITH USERS AND DEVELOPERS --------------------------------------- -  Network: freenode -  Server:  chat.freenode.net -  Channel: #rawtherapee + +Network: freenode +Server: chat.freenode.net +Channel: #rawtherapee You can use freenode webchat to communicate without installing anything: http://webchat.freenode.net/?randomnick=1&channels=rawtherapee&prompt=1 More information here: http://rawpedia.rawtherapee.com/IRC + + SOCIAL NETWORKS ---------------- + Google+ -http://plus.google.com/106783532637761598368 +https://plus.google.com/+RawTherapee + + REVISION HISTORY ----------------- + The complete changelog is available at: https://github.com/Beep6581/RawTherapee/commits/ diff --git a/cmake/modules/FindUnalignedMalloc.cmake b/cmake/modules/FindUnalignedMalloc.cmake new file mode 100644 index 000000000..4ddfb2afc --- /dev/null +++ b/cmake/modules/FindUnalignedMalloc.cmake @@ -0,0 +1,49 @@ +# This file is part of RawTherapee. +# +# Copyright (C) 2018 Flössie +# +# 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(CheckCXXSourceCompiles) + +set(CMAKE_REQUIRED_QUIET_COPY "${CMAKE_REQUIRED_QUIET}") +set(CMAKE_REQUIRED_QUIET ON) + +set(TEST_SOURCE +" +#include +#include + +int main() +{ +#if defined(__SSE2__) && (defined(__i386) || defined(_M_IX86)) && defined(__linux) + static_assert(std::alignment_of::value >= 16, \"Unaligned heap objects possible\"); +#endif + + return 0; +} +") + +CHECK_CXX_SOURCE_COMPILES("${TEST_SOURCE}" HAVE_ALIGNED_MALLOC) + +if(NOT HAVE_ALIGNED_MALLOC) + set(HAVE_UNALIGNED_MALLOC 1) +else() + unset(HAVE_ALIGNED_MALLOC) +endif() + +unset(TEST_SOURCE) + +set(CMAKE_REQUIRED_QUIET "${CMAKE_REQUIRED_QUIET_COPY}") +unset(CMAKE_REQUIRED_QUIET_COPY) diff --git a/rawtherapee.astylerc b/rawtherapee.astylerc deleted file mode 100644 index 3d49d821f..000000000 --- a/rawtherapee.astylerc +++ /dev/null @@ -1,8 +0,0 @@ -style=1tbs -indent=spaces=4 -indent-switches -break-blocks -pad-oper -convert-tabs -pad-header -unpad-paren diff --git a/rtdata/dcpprofiles/MINOLTA DYNAX 7D.dcp b/rtdata/dcpprofiles/MINOLTA DYNAX 7D.dcp new file mode 100644 index 000000000..807e4e05f Binary files /dev/null and b/rtdata/dcpprofiles/MINOLTA DYNAX 7D.dcp differ diff --git a/rtdata/dcpprofiles/NIKON D750.dcp b/rtdata/dcpprofiles/NIKON D750.dcp index 6dcef8386..86a676b3e 100644 Binary files a/rtdata/dcpprofiles/NIKON D750.dcp and b/rtdata/dcpprofiles/NIKON D750.dcp differ diff --git a/rtdata/dcpprofiles/SONY DSLR-A580.dcp b/rtdata/dcpprofiles/SONY DSLR-A580.dcp new file mode 100644 index 000000000..73576c892 Binary files /dev/null and b/rtdata/dcpprofiles/SONY DSLR-A580.dcp differ diff --git a/rtdata/images/rt_splash.svg b/rtdata/images/rt_splash.svg index c80cdd5c7..94d9a42b1 100644 --- a/rtdata/images/rt_splash.svg +++ b/rtdata/images/rt_splash.svg @@ -15,7 +15,7 @@ viewBox="0 0 146.05 91.545836" version="1.1" id="svg783" - inkscape:version="0.92.1 r" + inkscape:version="0.92.2 5c3e80d, 2017-08-06" sodipodi:docname="rt_splash.svg" inkscape:export-filename="/tmp/splash.png" inkscape:export-xdpi="96" @@ -517,10 +517,10 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.6106713" - inkscape:cx="274.80436" - inkscape:cy="87.101745" - inkscape:document-units="mm" + inkscape:zoom="1.4142136" + inkscape:cx="366.55779" + inkscape:cy="87.326779" + inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" units="px" @@ -544,7 +544,7 @@ inkscape:snap-nodes="false" inkscape:snap-global="true" inkscape:window-width="1920" - inkscape:window-height="1023" + inkscape:window-height="1019" inkscape:window-x="0" inkscape:window-y="0" inkscape:window-maximized="1"> @@ -599,7 +599,7 @@ image/svg+xml - + @@ -902,10 +902,34 @@ y="2.2370076" x="283.85016" id="tspan3664" - sodipodi:role="line">. 3 + sodipodi:role="line">. 5 + + + Development + Development + style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:17.06666565px;line-height:110.00000238%;font-family:'ITC Eras Std';-inkscape-font-specification:'ITC Eras Std Bold';text-align:end;letter-spacing:-1.06666672px;text-anchor:end;fill:#ffffff;stroke-width:1.06666672px">Release Candidate 1 diff --git a/rtdata/images/splash.png b/rtdata/images/splash.png index 701ef02bf..f3c523b88 100644 Binary files a/rtdata/images/splash.png and b/rtdata/images/splash.png differ diff --git a/rtdata/languages/Czech b/rtdata/languages/Czech index 71c92fed1..66440ad06 100644 --- a/rtdata/languages/Czech +++ b/rtdata/languages/Czech @@ -2243,3 +2243,4 @@ ZOOMPANEL_ZOOMFITCROPSCREEN;Přizpůsobit ořez obrazovce\nZkratka: f ZOOMPANEL_ZOOMFITSCREEN;Přizpůsobit celý obrázek obrazovce\nZkratka: Alt-f ZOOMPANEL_ZOOMIN;Přiblížit\nZkratka: + ZOOMPANEL_ZOOMOUT;Oddálit\nZkratka: - + diff --git a/rtengine/CMakeLists.txt b/rtengine/CMakeLists.txt index 080a76410..230c0957a 100644 --- a/rtengine/CMakeLists.txt +++ b/rtengine/CMakeLists.txt @@ -105,6 +105,7 @@ set(RTENGINESOURCEFILES profilestore.cc rawimage.cc rawimagesource.cc + rcd_demosaic.cc refreshmap.cc rt_algo.cc rtthumbnail.cc diff --git a/rtengine/PF_correct_RT.cc b/rtengine/PF_correct_RT.cc index f89b307be..dbb42db0d 100644 --- a/rtengine/PF_correct_RT.cc +++ b/rtengine/PF_correct_RT.cc @@ -35,7 +35,6 @@ #include "opthelper.h" #include "median.h" #include "jaggedarray.h" -#define BENCHMARK #include "StopWatch.h" namespace rtengine diff --git a/rtengine/camconst.json b/rtengine/camconst.json index 8709c16c7..4a294fe03 100644 --- a/rtengine/camconst.json +++ b/rtengine/camconst.json @@ -2245,12 +2245,6 @@ Camera constants: "ranges": { "black": 512, "white": 16300 } }, - { // Quality A - "make_model": "Sony ILCE-7M2", - "dcraw_matrix": [ 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 ], // DNGv8.7.1 - "ranges": { "black": 512, "white": 16300 } - }, - { // Quality A, correction for frame width "make_model": "Sony ILCE-7R", "dcraw_matrix": [ 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 ], @@ -2258,6 +2252,12 @@ Camera constants: "ranges": { "black": 512, "white": 16300 } }, + { // Quality A + "make_model": "Sony ILCE-7M2", + "dcraw_matrix": [ 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 ], // DNGv8.7.1 + "ranges": { "black": 512, "white": 16300 } + }, + { // Quality B, correction for frame width, crop modes covered "make_model": [ "Sony ILCE-7RM2", "Sony DSC-RX1RM2" ], "dcraw_matrix": [ 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 ], // DNG_v9.1.1 D65 @@ -2265,6 +2265,35 @@ Camera constants: "ranges": { "black": 512, "white": 16300 } }, + { // Quality C, color matrix copied from ILCE-9, LongExposures 2-3sec only + "make_model": "Sony ILCE-7M3", + "dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // ILCE-9, DNG_v9.12 D65 + // "raw_crop": [ 8, 8, 6008, 4008 ], // full raw frame 6048x4024 Dcraw auto identify 6024x4024, jpeg 12,12,6000x4000 + // "ranges": { "black": 512, "white": 16300 } + "ranges": { + "black": 512, + "white": [ + { "iso": [ 50, 64 ], "levels": 16100 }, // typical compressed 16372, non compressed 16383, LongEx iso50,16150 , 16275 + { "iso": [ 80, 100, 125, 160 ], "levels": 16200 }, // typical compressed 16372, non compressed 16383, LongEx iso50,16150 , 16275 + { "iso": [ 200, 250, 320, 400, 500, 640, 800, 1000, 1250 ], "levels": 16200 }, // compressed 16372, non compressed 16383, LongExp 16275 + { "iso": [ 1600, 2000, 2500, 3200, 4000, 5000 ], "levels": 16200 }, // compressed 16372, non compressed 16383, LongExp 16275 + { "iso": [ 6400, 8000, 10000, 12800 ], "levels": 16200 }, // compressed 16372, non compressed 16365-16375-16383, LongExp 16275 + { "iso": [ 16000, 20000, 25600 ], "levels": 16100 }, // 16275-16340-16372, nc 16375-16325-16280, LongExp 16210 + { "iso": [ 32000, 40000, 51200 ], "levels": 16100 }, // 16210-16340-16372, nc 16330, LongExp 16210 + { "iso": [ 64000, 80000, 102400 ], "levels": 16100 }, // g16340 , nc 16330, LongExp 16210 + { "iso": [ 128000, 160000, 204800 ], "levels": 16000 } // r16275, g16340, nc 16330, LongExp 16330-16370 + ] + } + + }, + + { // Quality C, + "make_model": "Sony ILCE-7RM3", + "dcraw_matrix": [ 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 ], // DNG_v10.1 D65 + "raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage + "ranges": { "black": 512, "white": 16300 } + }, + { // Quality B, color matrix copied from a7rm2 "make_model": "Sony ILCE-9", "dcraw_matrix": [ 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 ], // DNG_v9.12 D65 @@ -2291,13 +2320,6 @@ Camera constants: "ranges": { "black": 800, "white": 16300 } }, - { // Quality C, - "make_model": "Sony ILCE-7RM3", - "dcraw_matrix": [ 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 ], // DNG_v10.1 D65 - "raw_crop": [ 0, 0, -36, 0 ], // full raw frame 8000x5320 - 36 rightmost columns are garbage - "ranges": { "black": 512, "white": 16300 } - }, - { // Quality C, No proper color data, beta samples, frame set to official jpeg, "make_model": [ "XIAOYI M1", "YI TECHNOLOGY M1" ], "dcraw_matrix": [ 7158,-1911,-606,-3603,10669,2530,-659,1236,5530 ], // XIAO YI DNG D65 diff --git a/rtengine/dcraw.cc b/rtengine/dcraw.cc index dfde78785..871fcf7c5 100644 --- a/rtengine/dcraw.cc +++ b/rtengine/dcraw.cc @@ -8302,13 +8302,13 @@ void CLASS adobe_coeff (const char *make, const char *model) { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, { "Sony DSLR-A390", 0, 0, { 6038,-1484,-579,-9145,16746,2512,-875,746,7218 } }, - { "Sony DSLR-A450", 0, 0xfeb, + { "Sony DSLR-A450", 0, 0, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, - { "Sony DSLR-A580", 0, 0xfeb, + { "Sony DSLR-A580", 0, 0, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, - { "Sony DSLR-A500", 0, 0xfeb, + { "Sony DSLR-A500", 0, 0, { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } }, - { "Sony DSLR-A5", 0, 0xfeb, + { "Sony DSLR-A5", 0, 0, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, { "Sony DSLR-A700", 0, 0, { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, diff --git a/rtengine/demosaic_algos.cc b/rtengine/demosaic_algos.cc index 03a292c11..89387a9b4 100644 --- a/rtengine/demosaic_algos.cc +++ b/rtengine/demosaic_algos.cc @@ -3927,298 +3927,6 @@ void RawImageSource::cielab (const float (*rgb)[3], float* l, float* a, float *b } -/** -* RATIO CORRECTED DEMOSAICING -* Luis Sanz Rodriguez (luis.sanz.rodriguez(at)gmail(dot)com) -* -* Release 2.3 @ 171125 -* -* Original code from https://github.com/LuisSR/RCD-Demosaicing -* Licensed under the GNU GPL version 3 -*/ -void RawImageSource::rcd_demosaic() -{ - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), "rcd")); - plistener->setProgress(0); - } - - int width = W, height = H; - - std::vector cfa(width * height); - std::vector> rgb(width * height); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - for (int row = 0; row < height; row++) { - for (int col = 0, indx = row * width + col; col < width; col++, indx++) { - int c = FC(row, col); - cfa[indx] = rgb[indx][c] = LIM01(rawData[row][col] / 65535.f); - } - } - - if (plistener) { - plistener->setProgress(0.05); - } - // ------------------------------------------------------------------------ -/* RT - int row, col, indx, c; -*/ - int w1 = width, w2 = 2 * width, w3 = 3 * width, w4 = 4 * width; - - //Tolerance to avoid dividing by zero - static const float eps = 1e-5, epssq = 1e-10; - -/* RT - //Gradients - float N_Grad, E_Grad, W_Grad, S_Grad, NW_Grad, NE_Grad, SW_Grad, SE_Grad; - - //Pixel estimation - float N_Est, E_Est, W_Est, S_Est, NW_Est, NE_Est, SW_Est, SE_Est, V_Est, H_Est, P_Est, Q_Est; - - //Directional discrimination - //float V_Stat, H_Stat, P_Stat, Q_Stat; - float VH_Central_Value, VH_Neighbour_Value, PQ_Central_Value, PQ_Neighbour_Value; -*/ - float *VH_Dir, *PQ_Dir; - - //Low pass filter - float *lpf; - - - /** - * STEP 1: Find cardinal and diagonal interpolation directions - */ - - VH_Dir = ( float ( * ) ) calloc( width * height, sizeof *VH_Dir ); //merror ( VH_Dir, "rcd_demosaicing_171117()" ); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - for (int row = 4; row < height - 4; row++ ) { - for (int col = 4, indx = row * width + col; col < width - 4; col++, indx++ ) { - //Calculate h/v local discrimination - float V_Stat = max(epssq, - 18.0f * cfa[indx] * cfa[indx - w1] - 18.0f * cfa[indx] * cfa[indx + w1] - 36.0f * cfa[indx] * cfa[indx - w2] - 36.0f * cfa[indx] * cfa[indx + w2] + 18.0f * cfa[indx] * cfa[indx - w3] + 18.0f * cfa[indx] * cfa[indx + w3] - 2.0f * cfa[indx] * cfa[indx - w4] - 2.0f * cfa[indx] * cfa[indx + w4] + 38.0f * cfa[indx] * cfa[indx] - 70.0f * cfa[indx - w1] * cfa[indx + w1] - 12.0f * cfa[indx - w1] * cfa[indx - w2] + 24.0f * cfa[indx - w1] * cfa[indx + w2] - 38.0f * cfa[indx - w1] * cfa[indx - w3] + 16.0f * cfa[indx - w1] * cfa[indx + w3] + 12.0f * cfa[indx - w1] * cfa[indx - w4] - 6.0f * cfa[indx - w1] * cfa[indx + w4] + 46.0f * cfa[indx - w1] * cfa[indx - w1] + 24.0f * cfa[indx + w1] * cfa[indx - w2] - 12.0f * cfa[indx + w1] * cfa[indx + w2] + 16.0f * cfa[indx + w1] * cfa[indx - w3] - 38.0f * cfa[indx + w1] * cfa[indx + w3] - 6.0f * cfa[indx + w1] * cfa[indx - w4] + 12.0f * cfa[indx + w1] * cfa[indx + w4] + 46.0f * cfa[indx + w1] * cfa[indx + w1] + 14.0f * cfa[indx - w2] * cfa[indx + w2] - 12.0f * cfa[indx - w2] * cfa[indx + w3] - 2.0f * cfa[indx - w2] * cfa[indx - w4] + 2.0f * cfa[indx - w2] * cfa[indx + w4] + 11.0f * cfa[indx - w2] * cfa[indx - w2] - 12.0f * cfa[indx + w2] * cfa[indx - w3] + 2.0f * cfa[indx + w2] * cfa[indx - w4] - 2.0f * cfa[indx + w2] * cfa[indx + w4] + 11.0f * cfa[indx + w2] * cfa[indx + w2] + 2.0f * cfa[indx - w3] * cfa[indx + w3] - 6.0f * cfa[indx - w3] * cfa[indx - w4] + 10.0f * cfa[indx - w3] * cfa[indx - w3] - 6.0f * cfa[indx + w3] * cfa[indx + w4] + 10.0f * cfa[indx + w3] * cfa[indx + w3] + 1.0f * cfa[indx - w4] * cfa[indx - w4] + 1.0f * cfa[indx + w4] * cfa[indx + w4]); - - float H_Stat = max(epssq, - 18.0f * cfa[indx] * cfa[indx - 1] - 18.0f * cfa[indx] * cfa[indx + 1] - 36.0f * cfa[indx] * cfa[indx - 2] - 36.0f * cfa[indx] * cfa[indx + 2] + 18.0f * cfa[indx] * cfa[indx - 3] + 18.0f * cfa[indx] * cfa[indx + 3] - 2.0f * cfa[indx] * cfa[indx - 4] - 2.0f * cfa[indx] * cfa[indx + 4] + 38.0f * cfa[indx] * cfa[indx] - 70.0f * cfa[indx - 1] * cfa[indx + 1] - 12.0f * cfa[indx - 1] * cfa[indx - 2] + 24.0f * cfa[indx - 1] * cfa[indx + 2] - 38.0f * cfa[indx - 1] * cfa[indx - 3] + 16.0f * cfa[indx - 1] * cfa[indx + 3] + 12.0f * cfa[indx - 1] * cfa[indx - 4] - 6.0f * cfa[indx - 1] * cfa[indx + 4] + 46.0f * cfa[indx - 1] * cfa[indx - 1] + 24.0f * cfa[indx + 1] * cfa[indx - 2] - 12.0f * cfa[indx + 1] * cfa[indx + 2] + 16.0f * cfa[indx + 1] * cfa[indx - 3] - 38.0f * cfa[indx + 1] * cfa[indx + 3] - 6.0f * cfa[indx + 1] * cfa[indx - 4] + 12.0f * cfa[indx + 1] * cfa[indx + 4] + 46.0f * cfa[indx + 1] * cfa[indx + 1] + 14.0f * cfa[indx - 2] * cfa[indx + 2] - 12.0f * cfa[indx - 2] * cfa[indx + 3] - 2.0f * cfa[indx - 2] * cfa[indx - 4] + 2.0f * cfa[indx - 2] * cfa[indx + 4] + 11.0f * cfa[indx - 2] * cfa[indx - 2] - 12.0f * cfa[indx + 2] * cfa[indx - 3] + 2.0f * cfa[indx + 2] * cfa[indx - 4] - 2.0f * cfa[indx + 2] * cfa[indx + 4] + 11.0f * cfa[indx + 2] * cfa[indx + 2] + 2.0f * cfa[indx - 3] * cfa[indx + 3] - 6.0f * cfa[indx - 3] * cfa[indx - 4] + 10.0f * cfa[indx - 3] * cfa[indx - 3] - 6.0f * cfa[indx + 3] * cfa[indx + 4] + 10.0f * cfa[indx + 3] * cfa[indx + 3] + 1.0f * cfa[indx - 4] * cfa[indx - 4] + 1.0f * cfa[indx + 4] * cfa[indx + 4]); - - VH_Dir[indx] = V_Stat / (V_Stat + H_Stat); - } - } - - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgress(0.2); - } - // ------------------------------------------------------------------------- - - /** - * STEP 2: Calculate the low pass filter - */ - - // Step 2.1: Low pass filter incorporating green, red and blue local samples from the raw data - lpf = ( float ( * ) ) calloc( width * height, sizeof *lpf ); //merror ( lpf, "rcd_demosaicing_171125()" ); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - for ( int row = 2; row < height - 2; row++ ) { - for ( int col = 2 + (FC( row, 0 ) & 1), indx = row * width + col; col < width - 2; col += 2, indx += 2 ) { - - lpf[indx] = 0.25f * cfa[indx] + 0.125f * ( cfa[indx - w1] + cfa[indx + w1] + cfa[indx - 1] + cfa[indx + 1] ) + 0.0625f * ( cfa[indx - w1 - 1] + cfa[indx - w1 + 1] + cfa[indx + w1 - 1] + cfa[indx + w1 + 1] ); - - } - } - - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgress(0.4); - } - // ------------------------------------------------------------------------ - - /** - * STEP 3: Populate the green channel - */ - - // Step 3.1: Populate the green channel at blue and red CFA positions -#ifdef _OPENMP - #pragma omp parallel for -#endif - for ( int row = 4; row < height - 4; row++ ) { - for ( int col = 4 + (FC( row, 0 ) & 1), indx = row * width + col; col < width - 4; col += 2, indx += 2 ) { - - // Refined vertical and horizontal local discrimination - float VH_Central_Value = VH_Dir[indx]; - float VH_Neighbourhood_Value = 0.25f * ( VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1] + VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1] ); - - float VH_Disc = ( fabs( 0.5f - VH_Central_Value ) < fabs( 0.5f - VH_Neighbourhood_Value ) ) ? VH_Neighbourhood_Value : VH_Central_Value; - - // Cardinal gradients - float N_Grad = eps + fabs( cfa[indx - w1] - cfa[indx + w1] ) + fabs( cfa[indx] - cfa[indx - w2] ) + fabs( cfa[indx - w1] - cfa[indx - w3] ) + fabs( cfa[indx - w2] - cfa[indx - w4] ); - float S_Grad = eps + fabs( cfa[indx + w1] - cfa[indx - w1] ) + fabs( cfa[indx] - cfa[indx + w2] ) + fabs( cfa[indx + w1] - cfa[indx + w3] ) + fabs( cfa[indx + w2] - cfa[indx + w4] ); - float W_Grad = eps + fabs( cfa[indx - 1] - cfa[indx + 1] ) + fabs( cfa[indx] - cfa[indx - 2] ) + fabs( cfa[indx - 1] - cfa[indx - 3] ) + fabs( cfa[indx - 2] - cfa[indx - 4] ); - float E_Grad = eps + fabs( cfa[indx + 1] - cfa[indx - 1] ) + fabs( cfa[indx] - cfa[indx + 2] ) + fabs( cfa[indx + 1] - cfa[indx + 3] ) + fabs( cfa[indx + 2] - cfa[indx + 4] ); - - // Cardinal pixel estimations - float N_Est = cfa[indx - w1] * ( 1.f + ( lpf[indx] - lpf[indx - w2] ) / ( eps + lpf[indx] + lpf[indx - w2] ) ); - float S_Est = cfa[indx + w1] * ( 1.f + ( lpf[indx] - lpf[indx + w2] ) / ( eps + lpf[indx] + lpf[indx + w2] ) ); - float W_Est = cfa[indx - 1] * ( 1.f + ( lpf[indx] - lpf[indx - 2] ) / ( eps + lpf[indx] + lpf[indx - 2] ) ); - float E_Est = cfa[indx + 1] * ( 1.f + ( lpf[indx] - lpf[indx + 2] ) / ( eps + lpf[indx] + lpf[indx + 2] ) ); - - // Vertical and horizontal estimations - float V_Est = ( S_Grad * N_Est + N_Grad * S_Est ) / max(eps, N_Grad + S_Grad ); - float H_Est = ( W_Grad * E_Est + E_Grad * W_Est ) / max(eps, E_Grad + W_Grad ); - - // G@B and G@R interpolation - rgb[indx][1] = LIM( VH_Disc * H_Est + ( 1.f - VH_Disc ) * V_Est, 0.f, 1.f ); - - } - } - - free( lpf ); - - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgress(0.5); - } - // ------------------------------------------------------------------------ - - /** - * STEP 4: Populate the red and blue channels - */ - - // Step 4.1: Calculate P/Q diagonal local discrimination - PQ_Dir = ( float ( * ) ) calloc( width * height, sizeof *PQ_Dir ); //merror ( PQ_Dir, "rcd_demosaicing_171125()" ); - -#ifdef _OPENMP - #pragma omp parallel for -#endif - for ( int row = 4; row < height - 4; row++ ) { - for ( int col = 4 + (FC( row, 0 ) & 1), indx = row * width + col; col < width - 4; col += 2, indx += 2 ) { - - float P_Stat = max( - 18.f * cfa[indx] * cfa[indx - w1 - 1] - 18.f * cfa[indx] * cfa[indx + w1 + 1] - 36.f * cfa[indx] * cfa[indx - w2 - 2] - 36.f * cfa[indx] * cfa[indx + w2 + 2] + 18.f * cfa[indx] * cfa[indx - w3 - 3] + 18.f * cfa[indx] * cfa[indx + w3 + 3] - 2.f * cfa[indx] * cfa[indx - w4 - 4] - 2.f * cfa[indx] * cfa[indx + w4 + 4] + 38.f * cfa[indx] * cfa[indx] - 70.f * cfa[indx - w1 - 1] * cfa[indx + w1 + 1] - 12.f * cfa[indx - w1 - 1] * cfa[indx - w2 - 2] + 24.f * cfa[indx - w1 - 1] * cfa[indx + w2 + 2] - 38.f * cfa[indx - w1 - 1] * cfa[indx - w3 - 3] + 16.f * cfa[indx - w1 - 1] * cfa[indx + w3 + 3] + 12.f * cfa[indx - w1 - 1] * cfa[indx - w4 - 4] - 6.f * cfa[indx - w1 - 1] * cfa[indx + w4 + 4] + 46.f * cfa[indx - w1 - 1] * cfa[indx - w1 - 1] + 24.f * cfa[indx + w1 + 1] * cfa[indx - w2 - 2] - 12.f * cfa[indx + w1 + 1] * cfa[indx + w2 + 2] + 16.f * cfa[indx + w1 + 1] * cfa[indx - w3 - 3] - 38.f * cfa[indx + w1 + 1] * cfa[indx + w3 + 3] - 6.f * cfa[indx + w1 + 1] * cfa[indx - w4 - 4] + 12.f * cfa[indx + w1 + 1] * cfa[indx + w4 + 4] + 46.f * cfa[indx + w1 + 1] * cfa[indx + w1 + 1] + 14.f * cfa[indx - w2 - 2] * cfa[indx + w2 + 2] - 12.f * cfa[indx - w2 - 2] * cfa[indx + w3 + 3] - 2.f * cfa[indx - w2 - 2] * cfa[indx - w4 - 4] + 2.f * cfa[indx - w2 - 2] * cfa[indx + w4 + 4] + 11.f * cfa[indx - w2 - 2] * cfa[indx - w2 - 2] - 12.f * cfa[indx + w2 + 2] * cfa[indx - w3 - 3] + 2 * cfa[indx + w2 + 2] * cfa[indx - w4 - 4] - 2.f * cfa[indx + w2 + 2] * cfa[indx + w4 + 4] + 11.f * cfa[indx + w2 + 2] * cfa[indx + w2 + 2] + 2.f * cfa[indx - w3 - 3] * cfa[indx + w3 + 3] - 6.f * cfa[indx - w3 - 3] * cfa[indx - w4 - 4] + 10.f * cfa[indx - w3 - 3] * cfa[indx - w3 - 3] - 6.f * cfa[indx + w3 + 3] * cfa[indx + w4 + 4] + 10.f * cfa[indx + w3 + 3] * cfa[indx + w3 + 3] + 1.f * cfa[indx - w4 - 4] * cfa[indx - w4 - 4] + 1.f * cfa[indx + w4 + 4] * cfa[indx + w4 + 4], epssq ); - float Q_Stat = max( - 18.f * cfa[indx] * cfa[indx + w1 - 1] - 18.f * cfa[indx] * cfa[indx - w1 + 1] - 36.f * cfa[indx] * cfa[indx + w2 - 2] - 36.f * cfa[indx] * cfa[indx - w2 + 2] + 18.f * cfa[indx] * cfa[indx + w3 - 3] + 18.f * cfa[indx] * cfa[indx - w3 + 3] - 2.f * cfa[indx] * cfa[indx + w4 - 4] - 2.f * cfa[indx] * cfa[indx - w4 + 4] + 38.f * cfa[indx] * cfa[indx] - 70.f * cfa[indx + w1 - 1] * cfa[indx - w1 + 1] - 12.f * cfa[indx + w1 - 1] * cfa[indx + w2 - 2] + 24.f * cfa[indx + w1 - 1] * cfa[indx - w2 + 2] - 38.f * cfa[indx + w1 - 1] * cfa[indx + w3 - 3] + 16.f * cfa[indx + w1 - 1] * cfa[indx - w3 + 3] + 12.f * cfa[indx + w1 - 1] * cfa[indx + w4 - 4] - 6.f * cfa[indx + w1 - 1] * cfa[indx - w4 + 4] + 46.f * cfa[indx + w1 - 1] * cfa[indx + w1 - 1] + 24.f * cfa[indx - w1 + 1] * cfa[indx + w2 - 2] - 12.f * cfa[indx - w1 + 1] * cfa[indx - w2 + 2] + 16.f * cfa[indx - w1 + 1] * cfa[indx + w3 - 3] - 38.f * cfa[indx - w1 + 1] * cfa[indx - w3 + 3] - 6.f * cfa[indx - w1 + 1] * cfa[indx + w4 - 4] + 12.f * cfa[indx - w1 + 1] * cfa[indx - w4 + 4] + 46.f * cfa[indx - w1 + 1] * cfa[indx - w1 + 1] + 14.f * cfa[indx + w2 - 2] * cfa[indx - w2 + 2] - 12.f * cfa[indx + w2 - 2] * cfa[indx - w3 + 3] - 2.f * cfa[indx + w2 - 2] * cfa[indx + w4 - 4] + 2.f * cfa[indx + w2 - 2] * cfa[indx - w4 + 4] + 11.f * cfa[indx + w2 - 2] * cfa[indx + w2 - 2] - 12.f * cfa[indx - w2 + 2] * cfa[indx + w3 - 3] + 2 * cfa[indx - w2 + 2] * cfa[indx + w4 - 4] - 2.f * cfa[indx - w2 + 2] * cfa[indx - w4 + 4] + 11.f * cfa[indx - w2 + 2] * cfa[indx - w2 + 2] + 2.f * cfa[indx + w3 - 3] * cfa[indx - w3 + 3] - 6.f * cfa[indx + w3 - 3] * cfa[indx + w4 - 4] + 10.f * cfa[indx + w3 - 3] * cfa[indx + w3 - 3] - 6.f * cfa[indx - w3 + 3] * cfa[indx - w4 + 4] + 10.f * cfa[indx - w3 + 3] * cfa[indx - w3 + 3] + 1.f * cfa[indx + w4 - 4] * cfa[indx + w4 - 4] + 1.f * cfa[indx - w4 + 4] * cfa[indx - w4 + 4], epssq ); - - PQ_Dir[indx] = P_Stat / ( P_Stat + Q_Stat ); - - } - } - - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgress(0.7); - } - // ------------------------------------------------------------------------- - - // Step 4.2: Populate the red and blue channels at blue and red CFA positions -#ifdef _OPENMP - #pragma omp parallel for -#endif - for ( int row = 4; row < height - 4; row++ ) { - for ( int col = 4 + (FC( row, 0 ) & 1), indx = row * width + col, c = 2 - FC( row, col ); col < width - 4; col += 2, indx += 2 ) { - - // Refined P/Q diagonal local discrimination - float PQ_Central_Value = PQ_Dir[indx]; - float PQ_Neighbourhood_Value = 0.25f * ( PQ_Dir[indx - w1 - 1] + PQ_Dir[indx - w1 + 1] + PQ_Dir[indx + w1 - 1] + PQ_Dir[indx + w1 + 1] ); - - float PQ_Disc = ( fabs( 0.5f - PQ_Central_Value ) < fabs( 0.5f - PQ_Neighbourhood_Value ) ) ? PQ_Neighbourhood_Value : PQ_Central_Value; - - // Diagonal gradients - float NW_Grad = eps + fabs( rgb[indx - w1 - 1][c] - rgb[indx + w1 + 1][c] ) + fabs( rgb[indx - w1 - 1][c] - rgb[indx - w3 - 3][c] ) + fabs( rgb[indx][1] - rgb[indx - w2 - 2][1] ); - float NE_Grad = eps + fabs( rgb[indx - w1 + 1][c] - rgb[indx + w1 - 1][c] ) + fabs( rgb[indx - w1 + 1][c] - rgb[indx - w3 + 3][c] ) + fabs( rgb[indx][1] - rgb[indx - w2 + 2][1] ); - float SW_Grad = eps + fabs( rgb[indx + w1 - 1][c] - rgb[indx - w1 + 1][c] ) + fabs( rgb[indx + w1 - 1][c] - rgb[indx + w3 - 3][c] ) + fabs( rgb[indx][1] - rgb[indx + w2 - 2][1] ); - float SE_Grad = eps + fabs( rgb[indx + w1 + 1][c] - rgb[indx - w1 - 1][c] ) + fabs( rgb[indx + w1 + 1][c] - rgb[indx + w3 + 3][c] ) + fabs( rgb[indx][1] - rgb[indx + w2 + 2][1] ); - - // Diagonal colour differences - float NW_Est = rgb[indx - w1 - 1][c] - rgb[indx - w1 - 1][1]; - float NE_Est = rgb[indx - w1 + 1][c] - rgb[indx - w1 + 1][1]; - float SW_Est = rgb[indx + w1 - 1][c] - rgb[indx + w1 - 1][1]; - float SE_Est = rgb[indx + w1 + 1][c] - rgb[indx + w1 + 1][1]; - - // P/Q estimations - float P_Est = ( NW_Grad * SE_Est + SE_Grad * NW_Est ) / max(eps, NW_Grad + SE_Grad ); - float Q_Est = ( NE_Grad * SW_Est + SW_Grad * NE_Est ) / max(eps, NE_Grad + SW_Grad ); - - // R@B and B@R interpolation - rgb[indx][c] = LIM( rgb[indx][1] + ( 1.f - PQ_Disc ) * P_Est + PQ_Disc * Q_Est, 0.f, 1.f ); - - } - } - - free( PQ_Dir ); - - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgress(0.825); - } - // ------------------------------------------------------------------------- - - // Step 4.3: Populate the red and blue channels at green CFA positions -#ifdef _OPENMP - #pragma omp parallel for -#endif - for ( int row = 4; row < height - 4; row++ ) { - for ( int col = 4 + (FC( row, 1 ) & 1), indx = row * width + col; col < width - 4; col += 2, indx += 2 ) { - - // Refined vertical and horizontal local discrimination - float VH_Central_Value = VH_Dir[indx]; - float VH_Neighbourhood_Value = 0.25f * ( VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1] + VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1] ); - - float VH_Disc = ( fabs( 0.5f - VH_Central_Value ) < fabs( 0.5f - VH_Neighbourhood_Value ) ) ? VH_Neighbourhood_Value : VH_Central_Value; - - for ( int c = 0; c <= 2; c += 2 ) { - - // Cardinal gradients - float N_Grad = eps + fabs( rgb[indx][1] - rgb[indx - w2][1] ) + fabs( rgb[indx - w1][c] - rgb[indx + w1][c] ) + fabs( rgb[indx - w1][c] - rgb[indx - w3][c] ); - float S_Grad = eps + fabs( rgb[indx][1] - rgb[indx + w2][1] ) + fabs( rgb[indx + w1][c] - rgb[indx - w1][c] ) + fabs( rgb[indx + w1][c] - rgb[indx + w3][c] ); - float W_Grad = eps + fabs( rgb[indx][1] - rgb[indx - 2][1] ) + fabs( rgb[indx - 1][c] - rgb[indx + 1][c] ) + fabs( rgb[indx - 1][c] - rgb[indx - 3][c] ); - float E_Grad = eps + fabs( rgb[indx][1] - rgb[indx + 2][1] ) + fabs( rgb[indx + 1][c] - rgb[indx - 1][c] ) + fabs( rgb[indx + 1][c] - rgb[indx + 3][c] ); - - // Cardinal colour differences - float N_Est = rgb[indx - w1][c] - rgb[indx - w1][1]; - float S_Est = rgb[indx + w1][c] - rgb[indx + w1][1]; - float W_Est = rgb[indx - 1][c] - rgb[indx - 1][1]; - float E_Est = rgb[indx + 1][c] - rgb[indx + 1][1]; - - // Vertical and horizontal estimations - float V_Est = ( N_Grad * S_Est + S_Grad * N_Est ) / max(eps, N_Grad + S_Grad ); - float H_Est = ( E_Grad * W_Est + W_Grad * E_Est ) / max(eps, E_Grad + W_Grad ); - - // R@G and B@G interpolation - rgb[indx][c] = LIM( rgb[indx][1] + ( 1.f - VH_Disc ) * V_Est + VH_Disc * H_Est, 0.f, 1.f ); - - } - } - } - - free(VH_Dir); - - // RT --------------------------------------------------------------------- - if (plistener) { - plistener->setProgress(0.95); - } - -#ifdef _OPENMP - #pragma omp parallel for -#endif - for (int row = 0; row < height; ++row) { - for (int col = 0, idx = row * width + col ; col < width; ++col, ++idx) { - red[row][col] = CLIP(rgb[idx][0] * 65535.f); - green[row][col] = CLIP(rgb[idx][1] * 65535.f); - blue[row][col] = CLIP(rgb[idx][2] * 65535.f); - } - } - - border_interpolate2(width, height, 8); - - if (plistener) { - plistener->setProgress(1); - } - // ------------------------------------------------------------------------- -} - #define fcol(row,col) xtrans[(row)%6][(col)%6] #define isgreen(row,col) (xtrans[(row)%3][(col)%3]&1) diff --git a/rtengine/rcd_demosaic.cc b/rtengine/rcd_demosaic.cc new file mode 100644 index 000000000..f131bc87e --- /dev/null +++ b/rtengine/rcd_demosaic.cc @@ -0,0 +1,302 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (c) 2017-2018 Luis Sanz Rodriguez (luis.sanz.rodriguez(at)gmail(dot)com) and Ingo Weyrich (heckflosse67@gmx.de) + * + * 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 "rawimagesource.h" +#include "rt_math.h" +#include "../rtgui/multilangmgr.h" +#include "opthelper.h" +#include "StopWatch.h" + +using namespace std; + +namespace rtengine +{ + +/** +* RATIO CORRECTED DEMOSAICING +* Luis Sanz Rodriguez (luis.sanz.rodriguez(at)gmail(dot)com) +* +* Release 2.3 @ 171125 +* +* Original code from https://github.com/LuisSR/RCD-Demosaicing +* Licensed under the GNU GPL version 3 +*/ +// Tiled version by Ingo Weyrich (heckflosse67@gmx.de) +void RawImageSource::rcd_demosaic() +{ + BENCHFUN + + volatile double progress = 0.0; + + if (plistener) { + plistener->setProgressStr(Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCD))); + plistener->setProgress(0); + } + + constexpr int rcdBorder = 9; + constexpr int tileSize = 214; + constexpr int tileSizeN = tileSize - 2 * rcdBorder; + const int numTh = H / (tileSizeN) + ((H % (tileSizeN)) ? 1 : 0); + const int numTw = W / (tileSizeN) + ((W % (tileSizeN)) ? 1 : 0); + constexpr int w1 = tileSize, w2 = 2 * tileSize, w3 = 3 * tileSize, w4 = 4 * tileSize; + //Tolerance to avoid dividing by zero + static constexpr float eps = 1e-5f; + static constexpr float epssq = 1e-10f; + +#ifdef _OPENMP +#pragma omp parallel +#endif +{ + int progresscounter = 0; + float *cfa = (float*) calloc(tileSize * tileSize, sizeof *cfa); + float (*rgb)[tileSize * tileSize] = (float (*)[tileSize * tileSize])malloc(3 * sizeof *rgb); + float *VH_Dir = (float*) calloc(tileSize * tileSize, sizeof *VH_Dir); + float *PQ_Dir = (float*) calloc(tileSize * tileSize, sizeof *PQ_Dir); + float *lpf = PQ_Dir; // reuse buffer, they don't overlap in usage + +#ifdef _OPENMP + #pragma omp for schedule(dynamic) collapse(2) nowait +#endif + for(int tr = 0; tr < numTh; ++tr) { + for(int tc = 0; tc < numTw; ++tc) { + const int rowStart = tr * tileSizeN; + const int rowEnd = std::min(rowStart + tileSize, H); + if(rowStart + rcdBorder == rowEnd - rcdBorder) { + continue; + } + const int colStart = tc * tileSizeN; + const int colEnd = std::min(colStart + tileSize, W); + if(colStart + rcdBorder == colEnd - rcdBorder) { + continue; + } + + const int tileRows = std::min(rowEnd - rowStart, tileSize); + const int tilecols = std::min(colEnd - colStart, tileSize); + + for (int row = rowStart; row < rowEnd; row++) { + int indx = (row - rowStart) * tileSize; + int c0 = FC(row, colStart); + int c1 = FC(row, colStart + 1); + int col = colStart; + + for (; col < colEnd - 1; col+=2, indx+=2) { + cfa[indx] = rgb[c0][indx] = LIM01(rawData[row][col] / 65535.f); + cfa[indx + 1] = rgb[c1][indx + 1] = LIM01(rawData[row][col + 1] / 65535.f); + } + if(col < colEnd) { + cfa[indx] = rgb[c0][indx] = LIM01(rawData[row][col] / 65535.f); + } + } + + /** + * STEP 1: Find cardinal and diagonal interpolation directions + */ + + for (int row = 4; row < tileRows - 4; row++) { + for (int col = 4, indx = row * tileSize + col; col < tilecols - 4; col++, indx++) { + const float cfai = cfa[indx]; + //Calculate h/v local discrimination + float V_Stat = max(epssq, -18.f * cfai * (cfa[indx - w1] + cfa[indx + w1] + 2.f * (cfa[indx - w2] + cfa[indx + w2]) - cfa[indx - w3] - cfa[indx + w3]) - 2.f * cfai * (cfa[indx - w4] + cfa[indx + w4] - 19.f * cfai) - cfa[indx - w1] * (70.f * cfa[indx + w1] + 12.f * cfa[indx - w2] - 24.f * cfa[indx + w2] + 38.f * cfa[indx - w3] - 16.f * cfa[indx + w3] - 12.f * cfa[indx - w4] + 6.f * cfa[indx + w4] - 46.f * cfa[indx - w1]) + cfa[indx + w1] * (24.f * cfa[indx - w2] - 12.f * cfa[indx + w2] + 16.f * cfa[indx - w3] - 38.f * cfa[indx + w3] - 6.f * cfa[indx - w4] + 12.f * cfa[indx + w4] + 46.f * cfa[indx + w1]) + cfa[indx - w2] * (14.f * cfa[indx + w2] - 12.f * cfa[indx + w3] - 2.f * cfa[indx - w4] + 2.f * cfa[indx + w4] + 11.f * cfa[indx - w2]) + cfa[indx + w2] * (-12.f * cfa[indx - w3] + 2.f * (cfa[indx - w4] - cfa[indx + w4]) + 11.f * cfa[indx + w2]) + cfa[indx - w3] * (2.f * cfa[indx + w3] - 6.f * cfa[indx - w4] + 10.f * cfa[indx - w3]) + cfa[indx + w3] * (-6.f * cfa[indx + w4] + 10.f * cfa[indx + w3]) + cfa[indx - w4] * cfa[indx - w4] + cfa[indx + w4] * cfa[indx + w4]); + float H_Stat = max(epssq, -18.f * cfai * (cfa[indx - 1] + cfa[indx + 1] + 2.f * (cfa[indx - 2] + cfa[indx + 2]) - cfa[indx - 3] - cfa[indx + 3]) - 2.f * cfai * (cfa[indx - 4] + cfa[indx + 4] - 19.f * cfai) - cfa[indx - 1] * (70.f * cfa[indx + 1] + 12.f * cfa[indx - 2] - 24.f * cfa[indx + 2] + 38.f * cfa[indx - 3] - 16.f * cfa[indx + 3] - 12.f * cfa[indx - 4] + 6.f * cfa[indx + 4] - 46.f * cfa[indx - 1]) + cfa[indx + 1] * (24.f * cfa[indx - 2] - 12.f * cfa[indx + 2] + 16.f * cfa[indx - 3] - 38.f * cfa[indx + 3] - 6.f * cfa[indx - 4] + 12.f * cfa[indx + 4] + 46.f * cfa[indx + 1]) + cfa[indx - 2] * (14.f * cfa[indx + 2] - 12.f * cfa[indx + 3] - 2.f * cfa[indx - 4] + 2.f * cfa[indx + 4] + 11.f * cfa[indx - 2]) + cfa[indx + 2] * (-12.f * cfa[indx - 3] + 2.f * (cfa[indx - 4] - cfa[indx + 4]) + 11.f * cfa[indx + 2]) + cfa[indx - 3] * (2.f * cfa[indx + 3] - 6.f * cfa[indx - 4] + 10.f * cfa[indx - 3]) + cfa[indx + 3] * (-6.f * cfa[indx + 4] + 10.f * cfa[indx + 3]) + cfa[indx - 4] * cfa[indx - 4] + cfa[indx + 4] * cfa[indx + 4]); + + VH_Dir[indx] = V_Stat / (V_Stat + H_Stat); + } + } + + /** + * STEP 2: Calculate the low pass filter + */ + // Step 2.1: Low pass filter incorporating green, red and blue local samples from the raw data + + for (int row = 2; row < tileRows - 2; row++) { + for (int col = 2 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tilecols - 2; col += 2, indx += 2) { + lpf[indx>>1] = 0.25f * cfa[indx] + 0.125f * (cfa[indx - w1] + cfa[indx + w1] + cfa[indx - 1] + cfa[indx + 1]) + 0.0625f * (cfa[indx - w1 - 1] + cfa[indx - w1 + 1] + cfa[indx + w1 - 1] + cfa[indx + w1 + 1]); + } + } + + /** + * STEP 3: Populate the green channel + */ + // Step 3.1: Populate the green channel at blue and red CFA positions + for (int row = 4; row < tileRows - 4; row++) { + for (int col = 4 + (FC(row, 0) & 1), indx = row * tileSize + col; col < tilecols - 4; col += 2, indx += 2) { + + // Refined vertical and horizontal local discrimination + float VH_Central_Value = VH_Dir[indx]; + float VH_Neighbourhood_Value = 0.25f * ((VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1]) + (VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1])); + + float VH_Disc = std::fabs(0.5f - VH_Central_Value) < std::fabs(0.5f - VH_Neighbourhood_Value) ? VH_Neighbourhood_Value : VH_Central_Value; + + // Cardinal gradients + float N_Grad = eps + std::fabs(cfa[indx - w1] - cfa[indx + w1]) + std::fabs(cfa[indx] - cfa[indx - w2]) + std::fabs(cfa[indx - w1] - cfa[indx - w3]) + std::fabs(cfa[indx - w2] - cfa[indx - w4]); + float S_Grad = eps + std::fabs(cfa[indx - w1] - cfa[indx + w1]) + std::fabs(cfa[indx] - cfa[indx + w2]) + std::fabs(cfa[indx + w1] - cfa[indx + w3]) + std::fabs(cfa[indx + w2] - cfa[indx + w4]); + float W_Grad = eps + std::fabs(cfa[indx - 1] - cfa[indx + 1]) + std::fabs(cfa[indx] - cfa[indx - 2]) + std::fabs(cfa[indx - 1] - cfa[indx - 3]) + std::fabs(cfa[indx - 2] - cfa[indx - 4]); + float E_Grad = eps + std::fabs(cfa[indx - 1] - cfa[indx + 1]) + std::fabs(cfa[indx] - cfa[indx + 2]) + std::fabs(cfa[indx + 1] - cfa[indx + 3]) + std::fabs(cfa[indx + 2] - cfa[indx + 4]); + + // Cardinal pixel estimations + float N_Est = cfa[indx - w1] * (1.f + (lpf[indx>>1] - lpf[(indx - w2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx - w2)>>1])); + float S_Est = cfa[indx + w1] * (1.f + (lpf[indx>>1] - lpf[(indx + w2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx + w2)>>1])); + float W_Est = cfa[indx - 1] * (1.f + (lpf[indx>>1] - lpf[(indx - 2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx - 2)>>1])); + float E_Est = cfa[indx + 1] * (1.f + (lpf[indx>>1] - lpf[(indx + 2)>>1]) / (eps + lpf[indx>>1] + lpf[(indx + 2)>>1])); + + // Vertical and horizontal estimations + float V_Est = (S_Grad * N_Est + N_Grad * S_Est) / (N_Grad + S_Grad); + float H_Est = (W_Grad * E_Est + E_Grad * W_Est) / (E_Grad + W_Grad); + + // G@B and G@R interpolation + rgb[1][indx] = VH_Disc * H_Est + (1.f - VH_Disc) * V_Est; + + } + } + /** + * STEP 4: Populate the red and blue channels + */ + + // Step 4.1: Calculate P/Q diagonal local discrimination + for (int row = rcdBorder - 4; row < tileRows - rcdBorder + 4; row++) { + for (int col = rcdBorder - 4 + (FC(row, rcdBorder) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder + 4; col += 2, indx += 2) { + const float cfai = cfa[indx]; + + float P_Stat = max(epssq, - 18.f * cfai * (cfa[indx - w1 - 1] + cfa[indx + w1 + 1] + 2.f * (cfa[indx - w2 - 2] + cfa[indx + w2 + 2]) - cfa[indx - w3 - 3] - cfa[indx + w3 + 3]) - 2.f * cfai * (cfa[indx - w4 - 4] + cfa[indx + w4 + 4] - 19.f * cfai) - cfa[indx - w1 - 1] * (70.f * cfa[indx + w1 + 1] - 12.f * cfa[indx - w2 - 2] + 24.f * cfa[indx + w2 + 2] - 38.f * cfa[indx - w3 - 3] + 16.f * cfa[indx + w3 + 3] + 12.f * cfa[indx - w4 - 4] - 6.f * cfa[indx + w4 + 4] + 46.f * cfa[indx - w1 - 1]) + cfa[indx + w1 + 1] * (24.f * cfa[indx - w2 - 2] - 12.f * cfa[indx + w2 + 2] + 16.f * cfa[indx - w3 - 3] - 38.f * cfa[indx + w3 + 3] - 6.f * cfa[indx - w4 - 4] + 12.f * cfa[indx + w4 + 4] + 46.f * cfa[indx + w1 + 1]) + cfa[indx - w2 - 2] * (14.f * cfa[indx + w2 + 2] - 12.f * cfa[indx + w3 + 3] - 2.f * (cfa[indx - w4 - 4] - cfa[indx + w4 + 4]) + 11.f * cfa[indx - w2 - 2]) - cfa[indx + w2 + 2] * (12.f * cfa[indx - w3 - 3] + 2.f * (cfa[indx - w4 - 4] - cfa[indx + w4 + 4]) + 11.f * cfa[indx + w2 + 2]) + cfa[indx - w3 - 3] * (2.f * cfa[indx + w3 + 3] - 6.f * cfa[indx - w4 - 4] + 10.f * cfa[indx - w3 - 3]) - cfa[indx + w3 + 3] * (6.f * cfa[indx + w4 + 4] + 10.f * cfa[indx + w3 + 3]) + cfa[indx - w4 - 4] * cfa[indx - w4 - 4] + cfa[indx + w4 + 4] * cfa[indx + w4 + 4]); + float Q_Stat = max(epssq, - 18.f * cfai * (cfa[indx + w1 - 1] + cfa[indx - w1 + 1] + 2.f * (cfa[indx + w2 - 2] + cfa[indx - w2 + 2]) - cfa[indx + w3 - 3] - cfa[indx - w3 + 3]) - 2.f * cfai * (cfa[indx + w4 - 4] + cfa[indx - w4 + 4] - 19.f * cfai) - cfa[indx + w1 - 1] * (70.f * cfa[indx - w1 + 1] - 12.f * cfa[indx + w2 - 2] + 24.f * cfa[indx - w2 + 2] - 38.f * cfa[indx + w3 - 3] + 16.f * cfa[indx - w3 + 3] + 12.f * cfa[indx + w4 - 4] - 6.f * cfa[indx - w4 + 4] + 46.f * cfa[indx + w1 - 1]) + cfa[indx - w1 + 1] * (24.f * cfa[indx + w2 - 2] - 12.f * cfa[indx - w2 + 2] + 16.f * cfa[indx + w3 - 3] - 38.f * cfa[indx - w3 + 3] - 6.f * cfa[indx + w4 - 4] + 12.f * cfa[indx - w4 + 4] + 46.f * cfa[indx - w1 + 1]) + cfa[indx + w2 - 2] * (14.f * cfa[indx - w2 + 2] - 12.f * cfa[indx - w3 + 3] - 2.f * (cfa[indx + w4 - 4] - cfa[indx - w4 + 4]) + 11.f * cfa[indx + w2 - 2]) - cfa[indx - w2 + 2] * (12.f * cfa[indx + w3 - 3] + 2.f * (cfa[indx + w4 - 4] - cfa[indx - w4 + 4]) + 11.f * cfa[indx - w2 + 2]) + cfa[indx + w3 - 3] * (2.f * cfa[indx - w3 + 3] - 6.f * cfa[indx + w4 - 4] + 10.f * cfa[indx + w3 - 3]) - cfa[indx - w3 + 3] * (6.f * cfa[indx - w4 + 4] + 10.f * cfa[indx - w3 + 3]) + cfa[indx + w4 - 4] * cfa[indx + w4 - 4] + cfa[indx - w4 + 4] * cfa[indx - w4 + 4]); + + PQ_Dir[indx] = P_Stat / (P_Stat + Q_Stat); + + } + } + + // Step 4.2: Populate the red and blue channels at blue and red CFA positions + for (int row = rcdBorder - 3; row < tileRows - rcdBorder + 3; row++) { + for (int col = rcdBorder - 3 + (FC(row, rcdBorder - 1) & 1), indx = row * tileSize + col, c = 2 - FC(row, col); col < tilecols - rcdBorder + 3; col += 2, indx += 2) { + + // Refined P/Q diagonal local discrimination + float PQ_Central_Value = PQ_Dir[indx]; + float PQ_Neighbourhood_Value = 0.25f * (PQ_Dir[indx - w1 - 1] + PQ_Dir[indx - w1 + 1] + PQ_Dir[indx + w1 - 1] + PQ_Dir[indx + w1 + 1]); + + float PQ_Disc = (std::fabs(0.5f - PQ_Central_Value) < std::fabs(0.5f - PQ_Neighbourhood_Value)) ? PQ_Neighbourhood_Value : PQ_Central_Value; + + // Diagonal gradients + float NW_Grad = eps + std::fabs(rgb[c][indx - w1 - 1] - rgb[c][indx + w1 + 1]) + std::fabs(rgb[c][indx - w1 - 1] - rgb[c][indx - w3 - 3]) + std::fabs(rgb[1][indx] - rgb[1][indx - w2 - 2]); + float NE_Grad = eps + std::fabs(rgb[c][indx - w1 + 1] - rgb[c][indx + w1 - 1]) + std::fabs(rgb[c][indx - w1 + 1] - rgb[c][indx - w3 + 3]) + std::fabs(rgb[1][indx] - rgb[1][indx - w2 + 2]); + float SW_Grad = eps + std::fabs(rgb[c][indx - w1 + 1] - rgb[c][indx + w1 - 1]) + std::fabs(rgb[c][indx + w1 - 1] - rgb[c][indx + w3 - 3]) + std::fabs(rgb[1][indx] - rgb[1][indx + w2 - 2]); + float SE_Grad = eps + std::fabs(rgb[c][indx - w1 - 1] - rgb[c][indx + w1 + 1]) + std::fabs(rgb[c][indx + w1 + 1] - rgb[c][indx + w3 + 3]) + std::fabs(rgb[1][indx] - rgb[1][indx + w2 + 2]); + + // Diagonal colour differences + float NW_Est = rgb[c][indx - w1 - 1] - rgb[1][indx - w1 - 1]; + float NE_Est = rgb[c][indx - w1 + 1] - rgb[1][indx - w1 + 1]; + float SW_Est = rgb[c][indx + w1 - 1] - rgb[1][indx + w1 - 1]; + float SE_Est = rgb[c][indx + w1 + 1] - rgb[1][indx + w1 + 1]; + + // P/Q estimations + float P_Est = (NW_Grad * SE_Est + SE_Grad * NW_Est) / (NW_Grad + SE_Grad); + float Q_Est = (NE_Grad * SW_Est + SW_Grad * NE_Est) / (NE_Grad + SW_Grad); + + // R@B and B@R interpolation + rgb[c][indx] = rgb[1][indx] + (1.f - PQ_Disc) * P_Est + PQ_Disc * Q_Est; + + } + } + + // Step 4.3: Populate the red and blue channels at green CFA positions + for (int row = rcdBorder; row < tileRows - rcdBorder; row++) { + for (int col = rcdBorder + (FC(row, rcdBorder - 1) & 1), indx = row * tileSize + col; col < tilecols - rcdBorder; col += 2, indx += 2) { + + // Refined vertical and horizontal local discrimination + float VH_Central_Value = VH_Dir[indx]; + float VH_Neighbourhood_Value = 0.25f * ((VH_Dir[indx - w1 - 1] + VH_Dir[indx - w1 + 1]) + (VH_Dir[indx + w1 - 1] + VH_Dir[indx + w1 + 1])); + + float VH_Disc = (std::fabs(0.5f - VH_Central_Value) < std::fabs(0.5f - VH_Neighbourhood_Value)) ? VH_Neighbourhood_Value : VH_Central_Value; + float rgb1 = rgb[1][indx]; + float N1 = eps + std::fabs(rgb1 - rgb[1][indx - w2]); + float S1 = eps + std::fabs(rgb1 - rgb[1][indx + w2]); + float W1 = eps + std::fabs(rgb1 - rgb[1][indx - 2]); + float E1 = eps + std::fabs(rgb1 - rgb[1][indx + 2]); + + float rgb1mw1 = rgb[1][indx - w1]; + float rgb1pw1 = rgb[1][indx + w1]; + float rgb1m1 = rgb[1][indx - 1]; + float rgb1p1 = rgb[1][indx + 1]; + for (int c = 0; c <= 2; c += 2) { + // Cardinal gradients + float SNabs = std::fabs(rgb[c][indx - w1] - rgb[c][indx + w1]); + float EWabs = std::fabs(rgb[c][indx - 1] - rgb[c][indx + 1]); + float N_Grad = N1 + SNabs + std::fabs(rgb[c][indx - w1] - rgb[c][indx - w3]); + float S_Grad = S1 + SNabs + std::fabs(rgb[c][indx + w1] - rgb[c][indx + w3]); + float W_Grad = W1 + EWabs + std::fabs(rgb[c][indx - 1] - rgb[c][indx - 3]); + float E_Grad = E1 + EWabs + std::fabs(rgb[c][indx + 1] - rgb[c][indx + 3]); + + // Cardinal colour differences + float N_Est = rgb[c][indx - w1] - rgb1mw1; + float S_Est = rgb[c][indx + w1] - rgb1pw1; + float W_Est = rgb[c][indx - 1] - rgb1m1; + float E_Est = rgb[c][indx + 1] - rgb1p1; + + // Vertical and horizontal estimations + float V_Est = (N_Grad * S_Est + S_Grad * N_Est) / (N_Grad + S_Grad); + float H_Est = (E_Grad * W_Est + W_Grad * E_Est) / (E_Grad + W_Grad); + + // R@G and B@G interpolation + rgb[c][indx] = rgb1 + (1.f - VH_Disc) * V_Est + VH_Disc * H_Est; + + } + } + } + + for (int row = rowStart + rcdBorder; row < rowEnd - rcdBorder; ++row) { + for (int col = colStart + rcdBorder; col < colEnd - rcdBorder; ++col) { + int idx = (row - rowStart) * tileSize + col - colStart ; + red[row][col] = CLIP(rgb[0][idx] * 65535.f); + green[row][col] = CLIP(rgb[1][idx] * 65535.f); + blue[row][col] = CLIP(rgb[2][idx] * 65535.f); + } + } + + if(plistener) { + progresscounter++; + if(progresscounter % 32 == 0) { +#ifdef _OPENMP + #pragma omp critical (rcdprogress) +#endif + { + progress += (double)32 * ((tileSizeN) * (tileSizeN)) / (H * W); + progress = progress > 1.0 ? 1.0 : progress; + plistener->setProgress(progress); + } + } + } + + } + } + + free(cfa); + free(rgb); + free(VH_Dir); + free(PQ_Dir); +} + + border_interpolate2(W, H, rcdBorder); + + if (plistener) { + plistener->setProgress(1); + } + // ------------------------------------------------------------------------- +} + +} /* namespace */ diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 9b6b4596f..155dff2f0 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -1523,6 +1523,11 @@ private: if (params.raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::PIXELSHIFT)) { params.raw.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(params.raw.bayersensor.pixelShiftLmmse ? procparams::RAWParams::BayerSensor::Method::LMMSE : procparams::RAWParams::BayerSensor::Method::AMAZE); } + + // Use Rcd instead of Amaze for fast export + if (params.raw.bayersensor.method == procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::AMAZE)) { + params.raw.bayersensor.method = procparams::RAWParams::BayerSensor::getMethodString(procparams::RAWParams::BayerSensor::Method::RCD); + } } private: diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 540b4d267..c39ed004c 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -1,5 +1,6 @@ # Common source files for both CLI and non-CLI execautables set(CLISOURCEFILES + alignedmalloc.cc edit.cc main-cli.cc multilangmgr.cc @@ -11,6 +12,7 @@ set(CLISOURCEFILES set(NONCLISOURCEFILES adjuster.cc + alignedmalloc.cc batchqueue.cc batchqueuebuttonset.cc batchqueueentry.cc diff --git a/rtgui/alignedmalloc.cc b/rtgui/alignedmalloc.cc new file mode 100644 index 000000000..91fe15a85 --- /dev/null +++ b/rtgui/alignedmalloc.cc @@ -0,0 +1,31 @@ +/* + * This file is part of RawTherapee. + * + * Copyright (C) 2018 Flössie + * + * 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 "config.h" + +#ifdef HAVE_UNALIGNED_MALLOC + +#include + +void* malloc(size_t size) +{ + return memalign(16, size); +} + +#endif diff --git a/rtgui/config.h.in b/rtgui/config.h.in index fdf64b73c..2d1f41dbc 100644 --- a/rtgui/config.h.in +++ b/rtgui/config.h.in @@ -21,6 +21,7 @@ #define __CONFIG_H__ #cmakedefine BUILD_BUNDLE +#cmakedefine HAVE_UNALIGNED_MALLOC #define DATA_SEARCH_PATH "${DATADIR}" #define DOC_SEARCH_PATH "${DOCDIR}" #define CREDITS_SEARCH_PATH "${CREDITSDIR}" diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc index b0bd8334d..4b50c97cc 100644 --- a/rtgui/tonecurve.cc +++ b/rtgui/tonecurve.cc @@ -943,7 +943,6 @@ bool ToneCurve::histmatchingComputed() brightness->setValue(0); contrast->setValue(0); black->setValue(0); - hlcompr->setValue(0); if (!black->getAddMode()) { shcompr->set_sensitive(!((int)black->getValue() == 0));