//////////////////////////////////////////////////////////////// // // combine demosaic algorithms // // // copyright (c) 2018 Ingo Weyrich // // blends output of two demosaicers based on contrast // // // dual_demosaic_RT.cc 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. // // This program 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 this program. If not, see . // //////////////////////////////////////////////////////////////// #include "jaggedarray.h" #include "rtengine.h" #include "rawimagesource.h" #include "rt_math.h" #include "procparams.h" //#define BENCHMARK #include "StopWatch.h" #include "rt_algo.h" using namespace std; namespace rtengine { void RawImageSource::dual_demosaic_RT(bool isBayer, const RAWParams &raw, int winw, int winh, const array2D &rawData, array2D &red, array2D &green, array2D &blue, double &contrast, bool autoContrast) { BENCHFUN if (contrast == 0.f && !autoContrast) { // contrast == 0.0 means only first demosaicer will be used if(isBayer) { if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) ) { amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCBVNG4) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCDVNG4) ) { rcd_demosaic(options.chunkSizeRCD, options.measure); } } else { if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FOUR_PASS) ) { xtrans_interpolate (3, true, options.chunkSizeXT, options.measure); } else { xtrans_interpolate (1, false, options.chunkSizeXT, options.measure); } } return; } array2D redTmp(winw, winh); array2D greenTmp(winw, winh); array2D blueTmp(winw, winh); array2D L(winw, winh); if (isBayer) { vng4_demosaic(rawData, redTmp, greenTmp, blueTmp); if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::AMAZEVNG4) || raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::PIXELSHIFT)) { amaze_demosaic_RT(0, 0, winw, winh, rawData, red, green, blue, options.chunkSizeAMAZE, options.measure); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::DCBVNG4) ) { dcb_demosaic(raw.bayersensor.dcb_iterations, raw.bayersensor.dcb_enhance); } else if (raw.bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::RCDVNG4) ) { rcd_demosaic(options.chunkSizeRCD, options.measure); } } else { if (raw.xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FOUR_PASS) ) { xtrans_interpolate (3, true, options.chunkSizeXT, options.measure); } else { xtrans_interpolate (1, false, options.chunkSizeXT, options.measure); } fast_xtrans_interpolate(rawData, redTmp, greenTmp, blueTmp); } const float xyz_rgb[3][3] = { // XYZ from RGB { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, { 0.019334, 0.119193, 0.950227 } }; #ifdef _OPENMP #pragma omp parallel #endif { #ifdef _OPENMP #pragma omp for #endif for(int i = 0; i < winh; ++i) { Color::RGB2L(red[i], green[i], blue[i], L[i], xyz_rgb, winw); } } // calculate contrast based blend factors to use vng4 in regions with low contrast JaggedArray blend(winw, winh); float contrastf = contrast / 100.f; buildBlendMask(L, blend, winw, winh, contrastf, 1.f, autoContrast); contrast = contrastf * 100.f; // the following is split into 3 loops intentionally to avoid cache conflicts on CPUs with only 4-way cache #ifdef _OPENMP #pragma omp parallel for #endif for(int i = 0; i < winh; ++i) { for(int j = 0; j < winw; ++j) { red[i][j] = intp(blend[i][j], red[i][j], redTmp[i][j]); } } #ifdef _OPENMP #pragma omp parallel for #endif for(int i = 0; i < winh; ++i) { for(int j = 0; j < winw; ++j) { green[i][j] = intp(blend[i][j], green[i][j], greenTmp[i][j]); } } #ifdef _OPENMP #pragma omp parallel for #endif for(int i = 0; i < winh; ++i) { for(int j = 0; j < winw; ++j) { blue[i][j] = intp(blend[i][j], blue[i][j], blueTmp[i][j]); } } } }