* Use target_include_directories to specify include paths * Specify project root (parent of rtgui and rtengine) as include path * Replace relative includes with normal includes
499 lines
22 KiB
C++
499 lines
22 KiB
C++
////////////////////////////////////////////////////////////////
|
|
//
|
|
// Fast demosaicing algorithm
|
|
//
|
|
// copyright (c) 2008-2010 Emil Martinec <ejmartin@uchicago.edu>
|
|
//
|
|
//
|
|
// code dated: August 26, 2010
|
|
//
|
|
// fast_demo.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 <https://www.gnu.org/licenses/>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#include <cmath>
|
|
#include "rawimagesource.h"
|
|
#include "rtgui/multilangmgr.h"
|
|
#include "opthelper.h"
|
|
|
|
using namespace std;
|
|
using namespace rtengine;
|
|
|
|
namespace
|
|
{
|
|
unsigned fc(const unsigned int cfa[2][2], int r, int c) {
|
|
return cfa[r & 1][c & 1];
|
|
}
|
|
}
|
|
|
|
#define TS 224
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
/*
|
|
LUTf RawImageSource::initInvGrad()
|
|
{
|
|
LUTf invGrad (0x10000);
|
|
|
|
//set up directional weight function
|
|
for (int i=0; i<0x10000; i++)
|
|
invGrad[i] = 1.0/SQR(1.0+i);
|
|
|
|
return invGrad;
|
|
}
|
|
*/
|
|
#define INVGRAD(i) (16.0f/SQR(4.0f+i))
|
|
#ifdef __SSE2__
|
|
#define INVGRADV(i) (c16v*_mm_rcp_ps(SQRV(fourv+i)))
|
|
#endif
|
|
//LUTf RawImageSource::invGrad = RawImageSource::initInvGrad();
|
|
|
|
void RawImageSource::fast_demosaic()
|
|
{
|
|
|
|
double progress = 0.0;
|
|
const bool plistenerActive = plistener;
|
|
|
|
//int winx=0, winy=0;
|
|
//int winw=W, winh=H;
|
|
|
|
if (plistener) {
|
|
plistener->setProgressStr (Glib::ustring::compose(M("TP_RAW_DMETHOD_PROGRESSBAR"), M("TP_RAW_FAST")));
|
|
plistener->setProgress (progress);
|
|
}
|
|
|
|
|
|
const unsigned int cfarray[2][2] = {{FC(0,0), FC(0,1)}, {FC(1,0), FC(1,1)}};
|
|
const int bord = 5;
|
|
|
|
float clip_pt = 4 * 65535 * initialGain;
|
|
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
#ifdef _OPENMP
|
|
#pragma omp parallel
|
|
#endif
|
|
{
|
|
|
|
char *buffer;
|
|
float *greentile;
|
|
float *redtile;
|
|
float *bluetile;
|
|
#define CLF 1
|
|
// assign working space
|
|
buffer = (char *) calloc(3 * sizeof(float) * TS * TS + 3 * CLF * 64 + 63, 1);
|
|
char *data;
|
|
data = (char*)( ( uintptr_t(buffer) + uintptr_t(63)) / 64 * 64);
|
|
|
|
greentile = (float (*)) data; //pointers to array
|
|
redtile = (float (*)) ((char*)greentile + sizeof(float) * TS * TS + CLF * 64);
|
|
bluetile = (float (*)) ((char*)redtile + sizeof(float) * TS * TS + CLF * 64);
|
|
|
|
#ifdef _OPENMP
|
|
#pragma omp sections
|
|
#endif
|
|
{
|
|
#ifdef _OPENMP
|
|
#pragma omp section
|
|
#endif
|
|
{
|
|
|
|
//first, interpolate borders using bilinear
|
|
for (int i = 0; i < H; i++)
|
|
{
|
|
|
|
float sum[6];
|
|
int imin = max(0, i - 1);
|
|
int imax = min(i + 2, H);
|
|
|
|
for (int j = 0; j < bord; j++) { //first few columns
|
|
for (int c = 0; c < 6; c++) {
|
|
sum[c] = 0;
|
|
}
|
|
|
|
int jmin = max(0, j - 1);
|
|
|
|
for (int i1 = imin; i1 < imax; i1++)
|
|
for (int j1 = jmin; j1 < j + 2; j1++) {
|
|
int c = fc(cfarray, i1, j1);
|
|
sum[c] += rawData[i1][j1];
|
|
sum[c + 3]++;
|
|
}
|
|
|
|
int c = fc(cfarray, i, j);
|
|
|
|
if (c == 1) {
|
|
red[i][j] = sum[0] / sum[3];
|
|
green[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
green[i][j] = sum[1] / sum[4];
|
|
|
|
if (c == 0) {
|
|
red[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
red[i][j] = sum[0] / sum[3];
|
|
blue[i][j] = rawData[i][j];
|
|
}
|
|
}
|
|
}//j
|
|
|
|
for (int j = W - bord; j < W; j++) { //last few columns
|
|
for (int c = 0; c < 6; c++) {
|
|
sum[c] = 0;
|
|
}
|
|
|
|
int jmax = min(j + 2, W);
|
|
|
|
for (int i1 = imin; i1 < imax; i1++)
|
|
for (int j1 = j - 1; j1 < jmax; j1++) {
|
|
int c = fc(cfarray, i1, j1);
|
|
sum[c] += rawData[i1][j1];
|
|
sum[c + 3]++;
|
|
}
|
|
|
|
int c = fc(cfarray, i, j);
|
|
|
|
if (c == 1) {
|
|
red[i][j] = sum[0] / sum[3];
|
|
green[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
green[i][j] = sum[1] / sum[4];
|
|
|
|
if (c == 0) {
|
|
red[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
red[i][j] = sum[0] / sum[3];
|
|
blue[i][j] = rawData[i][j];
|
|
}
|
|
}
|
|
}//j
|
|
}//i
|
|
|
|
}
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
#ifdef _OPENMP
|
|
#pragma omp section
|
|
#endif
|
|
{
|
|
|
|
for (int j = bord; j < W - bord; j++)
|
|
{
|
|
float sum[6];
|
|
|
|
for (int i = 0; i < bord; i++) { //first few rows
|
|
for (int c = 0; c < 6; c++) {
|
|
sum[c] = 0;
|
|
}
|
|
|
|
for (int i1 = max(0, i - 1); i1 < i + 2; i1++)
|
|
for (int j1 = j - 1; j1 < j + 2; j1++) {
|
|
int c = fc(cfarray, i1, j1);
|
|
sum[c] += rawData[i1][j1];
|
|
sum[c + 3]++;
|
|
}
|
|
|
|
int c = fc(cfarray, i, j);
|
|
|
|
if (c == 1) {
|
|
red[i][j] = sum[0] / sum[3];
|
|
green[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
green[i][j] = sum[1] / sum[4];
|
|
|
|
if (c == 0) {
|
|
red[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
red[i][j] = sum[0] / sum[3];
|
|
blue[i][j] = rawData[i][j];
|
|
}
|
|
}
|
|
}//i
|
|
|
|
for (int i = H - bord; i < H; i++) { //last few rows
|
|
for (int c = 0; c < 6; c++) {
|
|
sum[c] = 0;
|
|
}
|
|
|
|
for (int i1 = i - 1; i1 < min(i + 2, H); i1++)
|
|
for (int j1 = j - 1; j1 < j + 2; j1++) {
|
|
int c = fc(cfarray, i1, j1);
|
|
sum[c] += rawData[i1][j1];
|
|
sum[c + 3]++;
|
|
}
|
|
|
|
int c = fc(cfarray, i, j);
|
|
|
|
if (c == 1) {
|
|
red[i][j] = sum[0] / sum[3];
|
|
green[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
green[i][j] = sum[1] / sum[4];
|
|
|
|
if (c == 0) {
|
|
red[i][j] = rawData[i][j];
|
|
blue[i][j] = sum[2] / sum[5];
|
|
} else {
|
|
red[i][j] = sum[0] / sum[3];
|
|
blue[i][j] = rawData[i][j];
|
|
}
|
|
}
|
|
}//i
|
|
}//j
|
|
|
|
}
|
|
}
|
|
#ifdef _OPENMP
|
|
#pragma omp single
|
|
#endif
|
|
{
|
|
if(plistenerActive) {
|
|
progress += 0.1;
|
|
plistener->setProgress(progress);
|
|
}
|
|
}
|
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
int progressCounter = 0;
|
|
const double progressInc = 16.0 * (1.0 - progress) / ((H * W) / ((TS - 4) * (TS - 4)));
|
|
|
|
#ifdef _OPENMP
|
|
#pragma omp for nowait
|
|
#endif
|
|
|
|
for (int top = bord - 2; top < H - bord + 2; top += TS - (4))
|
|
for (int left = bord - 2; left < W - bord + 2; left += TS - (4)) {
|
|
int bottom = min(top + TS, H - bord + 2);
|
|
int right = min(left + TS, W - bord + 2);
|
|
|
|
#ifdef __SSE2__
|
|
__m128 wtuv, wtdv, wtlv, wtrv;
|
|
__m128 greenv, tempv, absv, abs2v;
|
|
__m128 c16v = _mm_set1_ps( 16.0f );
|
|
__m128 fourv = _mm_set1_ps( 4.0f );
|
|
vmask selmask;
|
|
vmask andmask = _mm_set_epi32( 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff );
|
|
|
|
if(fc(cfarray, top, left) == 1) {
|
|
selmask = _mm_set_epi32( 0, 0xffffffff, 0, 0xffffffff );
|
|
} else {
|
|
selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 );
|
|
}
|
|
|
|
#endif
|
|
|
|
// interpolate G using gradient weights
|
|
for (int i = top, rr = 0; i < bottom; i++, rr++) {
|
|
float wtu, wtd, wtl, wtr;
|
|
#ifdef __SSE2__
|
|
selmask = (vmask)_mm_andnot_ps( (__m128)selmask, (__m128)andmask);
|
|
int j, cc;
|
|
for (j = left, cc = 0; j < right - 3; j += 4, cc += 4) {
|
|
tempv = LVFU(rawData[i][j]);
|
|
absv = vabsf(LVFU(rawData[i - 1][j]) - LVFU(rawData[i + 1][j]));
|
|
wtuv = INVGRADV(absv + vabsf(tempv - LVFU(rawData[i - 2][j])) + vabsf(LVFU(rawData[i - 1][j]) - LVFU(rawData[i - 3][j])));
|
|
wtdv = INVGRADV(absv + vabsf(tempv - LVFU(rawData[i + 2][j])) + vabsf(LVFU(rawData[i + 1][j]) - LVFU(rawData[i + 3][j])));
|
|
abs2v = vabsf(LVFU(rawData[i][j - 1]) - LVFU(rawData[i][j + 1]));
|
|
wtlv = INVGRADV(abs2v + vabsf(tempv - LVFU(rawData[i][j - 2])) + vabsf(LVFU(rawData[i][j - 1]) - LVFU(rawData[i][j - 3])));
|
|
wtrv = INVGRADV(abs2v + vabsf(tempv - LVFU(rawData[i][j + 2])) + vabsf(LVFU(rawData[i][j + 1]) - LVFU(rawData[i][j + 3])));
|
|
greenv = (wtuv * LVFU(rawData[i - 1][j]) + wtdv * LVFU(rawData[i + 1][j]) + wtlv * LVFU(rawData[i][j - 1]) + wtrv * LVFU(rawData[i][j + 1])) / (wtuv + wtdv + wtlv + wtrv);
|
|
_mm_store_ps(&greentile[rr * TS + cc], vself(selmask, greenv, tempv));
|
|
_mm_store_ps(&redtile[rr * TS + cc], tempv);
|
|
_mm_store_ps(&bluetile[rr * TS + cc], tempv);
|
|
}
|
|
|
|
for (; j < right; j++, cc++) {
|
|
|
|
if (fc(cfarray, i, j) == 1) {
|
|
greentile[rr * TS + cc] = rawData[i][j];
|
|
|
|
} else {
|
|
//compute directional weights using image gradients
|
|
wtu = INVGRAD((abs(rawData[i + 1][j] - rawData[i - 1][j]) + abs(rawData[i][j] - rawData[i - 2][j]) + abs(rawData[i - 1][j] - rawData[i - 3][j])));
|
|
wtd = INVGRAD((abs(rawData[i - 1][j] - rawData[i + 1][j]) + abs(rawData[i][j] - rawData[i + 2][j]) + abs(rawData[i + 1][j] - rawData[i + 3][j])));
|
|
wtl = INVGRAD((abs(rawData[i][j + 1] - rawData[i][j - 1]) + abs(rawData[i][j] - rawData[i][j - 2]) + abs(rawData[i][j - 1] - rawData[i][j - 3])));
|
|
wtr = INVGRAD((abs(rawData[i][j - 1] - rawData[i][j + 1]) + abs(rawData[i][j] - rawData[i][j + 2]) + abs(rawData[i][j + 1] - rawData[i][j + 3])));
|
|
|
|
//store in rgb array the interpolated G value at R/B grid points using directional weighted average
|
|
greentile[rr * TS + cc] = (wtu * rawData[i - 1][j] + wtd * rawData[i + 1][j] + wtl * rawData[i][j - 1] + wtr * rawData[i][j + 1]) / (wtu + wtd + wtl + wtr);
|
|
}
|
|
|
|
redtile[rr * TS + cc] = rawData[i][j];
|
|
bluetile[rr * TS + cc] = rawData[i][j];
|
|
}
|
|
|
|
#else
|
|
|
|
for (int j = left, cc = 0; j < right; j++, cc++) {
|
|
if (fc(cfarray, i, j) == 1) {
|
|
greentile[rr * TS + cc] = rawData[i][j];
|
|
} else {
|
|
//compute directional weights using image gradients
|
|
wtu = INVGRAD((abs(rawData[i + 1][j] - rawData[i - 1][j]) + abs(rawData[i][j] - rawData[i - 2][j]) + abs(rawData[i - 1][j] - rawData[i - 3][j])));
|
|
wtd = INVGRAD((abs(rawData[i - 1][j] - rawData[i + 1][j]) + abs(rawData[i][j] - rawData[i + 2][j]) + abs(rawData[i + 1][j] - rawData[i + 3][j])));
|
|
wtl = INVGRAD((abs(rawData[i][j + 1] - rawData[i][j - 1]) + abs(rawData[i][j] - rawData[i][j - 2]) + abs(rawData[i][j - 1] - rawData[i][j - 3])));
|
|
wtr = INVGRAD((abs(rawData[i][j - 1] - rawData[i][j + 1]) + abs(rawData[i][j] - rawData[i][j + 2]) + abs(rawData[i][j + 1] - rawData[i][j + 3])));
|
|
|
|
//store in rgb array the interpolated G value at R/B grid points using directional weighted average
|
|
greentile[rr * TS + cc] = (wtu * rawData[i - 1][j] + wtd * rawData[i + 1][j] + wtl * rawData[i][j - 1] + wtr * rawData[i][j + 1]) / (wtu + wtd + wtl + wtr);
|
|
}
|
|
|
|
redtile[rr * TS + cc] = rawData[i][j];
|
|
bluetile[rr * TS + cc] = rawData[i][j];
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
#ifdef __SSE2__
|
|
__m128 zd25v = _mm_set1_ps(0.25f);
|
|
__m128 clip_ptv = _mm_set1_ps( clip_pt );
|
|
#endif
|
|
|
|
for (int i = top + 1, rr = 1; i < bottom - 1; i++, rr++) {
|
|
if (fc(cfarray, i, left + (fc(cfarray, i, 2) & 1) + 1) == 0)
|
|
#ifdef __SSE2__
|
|
for (int j = left + 1, cc = 1; j < right - 1; j += 4, cc += 4) {
|
|
//interpolate B/R colors at R/B sites
|
|
_mm_storeu_ps(&bluetile[rr * TS + cc], LVFU(greentile[rr * TS + cc]) - zd25v * ((LVFU(greentile[(rr - 1)*TS + (cc - 1)]) + LVFU(greentile[(rr - 1)*TS + (cc + 1)]) + LVFU(greentile[(rr + 1)*TS + cc + 1]) + LVFU(greentile[(rr + 1)*TS + cc - 1])) -
|
|
vminf(LVFU(rawData[i - 1][j - 1]) + LVFU(rawData[i - 1][j + 1]) + LVFU(rawData[i + 1][j + 1]) + LVFU(rawData[i + 1][j - 1]), clip_ptv)));
|
|
}
|
|
|
|
#else
|
|
|
|
for (int cc = (fc(cfarray, i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) {
|
|
//interpolate B/R colors at R/B sites
|
|
bluetile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + (cc - 1)] + greentile[(rr - 1) * TS + (cc + 1)] + greentile[(rr + 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc - 1]) -
|
|
min(clip_pt, rawData[i - 1][j - 1] + rawData[i - 1][j + 1] + rawData[i + 1][j + 1] + rawData[i + 1][j - 1]));
|
|
}
|
|
|
|
#endif
|
|
else
|
|
#ifdef __SSE2__
|
|
for (int j = left + 1, cc = 1; j < right - 1; j += 4, cc += 4) {
|
|
//interpolate B/R colors at R/B sites
|
|
_mm_storeu_ps(&redtile[rr * TS + cc], LVFU(greentile[rr * TS + cc]) - zd25v * ((LVFU(greentile[(rr - 1)*TS + cc - 1]) + LVFU(greentile[(rr - 1)*TS + cc + 1]) + LVFU(greentile[(rr + 1)*TS + cc + 1]) + LVFU(greentile[(rr + 1)*TS + cc - 1])) -
|
|
vminf(LVFU(rawData[i - 1][j - 1]) + LVFU(rawData[i - 1][j + 1]) + LVFU(rawData[i + 1][j + 1]) + LVFU(rawData[i + 1][j - 1]), clip_ptv)));
|
|
}
|
|
|
|
#else
|
|
|
|
for (int cc = (fc(cfarray, i, 2) & 1) + 1, j = left + cc; j < right - 1; j += 2, cc += 2) {
|
|
//interpolate B/R colors at R/B sites
|
|
redtile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc - 1] + greentile[(rr - 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc + 1] + greentile[(rr + 1) * TS + cc - 1]) -
|
|
min(clip_pt, rawData[i - 1][j - 1] + rawData[i - 1][j + 1] + rawData[i + 1][j + 1] + rawData[i + 1][j - 1]));
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef __SSE2__
|
|
__m128 temp1v, temp2v, greensumv;
|
|
selmask = _mm_set_epi32( 0xffffffff, 0, 0xffffffff, 0 );
|
|
#endif
|
|
|
|
// interpolate R/B using color differences
|
|
for (int i = top + 2, rr = 2; i < bottom - 2; i++, rr++) {
|
|
#ifdef __SSE2__
|
|
|
|
for (int cc = 2 + (fc(cfarray, i, 2) & 1), j = left + cc; j < right - 2; j += 4, cc += 4) {
|
|
// no need to take care about the borders of the tile. There's enough free space.
|
|
//interpolate R and B colors at G sites
|
|
greenv = LVFU(greentile[rr * TS + cc]);
|
|
greensumv = LVFU(greentile[(rr - 1) * TS + cc]) + LVFU(greentile[(rr + 1) * TS + cc]) + LVFU(greentile[rr * TS + cc - 1]) + LVFU(greentile[rr * TS + cc + 1]);
|
|
|
|
temp1v = LVFU(redtile[rr * TS + cc]);
|
|
temp2v = greenv - zd25v * (greensumv - LVFU(redtile[(rr - 1) * TS + cc]) - LVFU(redtile[(rr + 1) * TS + cc]) - LVFU(redtile[rr * TS + cc - 1]) - LVFU(redtile[rr * TS + cc + 1]));
|
|
|
|
_mm_storeu_ps( &redtile[rr * TS + cc], vself(selmask, temp1v, temp2v));
|
|
|
|
temp1v = LVFU(bluetile[rr * TS + cc]);
|
|
|
|
temp2v = greenv - zd25v * (greensumv - LVFU(bluetile[(rr - 1) * TS + cc]) - LVFU(bluetile[(rr + 1) * TS + cc]) - LVFU(bluetile[rr * TS + cc - 1]) - LVFU(bluetile[rr * TS + cc + 1]));
|
|
|
|
_mm_storeu_ps( &bluetile[rr * TS + cc], vself(selmask, temp1v, temp2v));
|
|
}
|
|
|
|
#else
|
|
|
|
for (int cc = 2 + (fc(cfarray, i, 2) & 1), j = left + cc; j < right - 2; j += 2, cc += 2) {
|
|
//interpolate R and B colors at G sites
|
|
redtile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc] - redtile[(rr - 1) * TS + cc]) + (greentile[(rr + 1) * TS + cc] - redtile[(rr + 1) * TS + cc]) +
|
|
(greentile[rr * TS + cc - 1] - redtile[rr * TS + cc - 1]) + (greentile[rr * TS + cc + 1] - redtile[rr * TS + cc + 1]));
|
|
bluetile[rr * TS + cc] = greentile[rr * TS + cc] - 0.25f * ((greentile[(rr - 1) * TS + cc] - bluetile[(rr - 1) * TS + cc]) + (greentile[(rr + 1) * TS + cc] - bluetile[(rr + 1) * TS + cc]) +
|
|
(greentile[rr * TS + cc - 1] - bluetile[rr * TS + cc - 1]) + (greentile[rr * TS + cc + 1] - bluetile[rr * TS + cc + 1]));
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
for (int i = top + 2, rr = 2; i < bottom - 2; i++, rr++) {
|
|
#ifdef __SSE2__
|
|
int j, cc;
|
|
for (j = left + 2, cc = 2; j < right - 5; j += 4, cc += 4) {
|
|
_mm_storeu_ps(&red[i][j], vmaxf(LVFU(redtile[rr * TS + cc]), ZEROV));
|
|
_mm_storeu_ps(&green[i][j], vmaxf(LVFU(greentile[rr * TS + cc]), ZEROV));
|
|
_mm_storeu_ps(&blue[i][j], vmaxf(LVFU(bluetile[rr * TS + cc]), ZEROV));
|
|
}
|
|
|
|
for (; j < right - 2; j++, cc++) {
|
|
red[i][j] = std::max(0.f, redtile[rr * TS + cc]);
|
|
green[i][j] = std::max(0.f, greentile[rr * TS + cc]);
|
|
blue[i][j] = std::max(0.f, bluetile[rr * TS + cc]);
|
|
}
|
|
|
|
#else
|
|
|
|
for (int j = left + 2, cc = 2; j < right - 2; j++, cc++) {
|
|
red[i][j] = std::max(0.f, redtile[rr * TS + cc]);
|
|
green[i][j] = std::max(0.f, greentile[rr * TS + cc]);
|
|
blue[i][j] = std::max(0.f, bluetile[rr * TS + cc]);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
if(plistenerActive && ((++progressCounter) % 16 == 0)) {
|
|
#ifdef _OPENMP
|
|
#pragma omp critical (updateprogress)
|
|
#endif
|
|
{
|
|
progress += progressInc;
|
|
progress = min(1.0, progress);
|
|
plistener->setProgress (progress);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
free(buffer);
|
|
} // End of parallelization
|
|
|
|
if(plistenerActive) {
|
|
plistener->setProgress(1.00);
|
|
}
|
|
|
|
|
|
|
|
}
|
|
#undef TS
|
|
#undef CLF
|