/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * 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 . */ #ifndef _GAUSS_H_ #define _GAUSS_H_ #include #include #include #include #define NOSSE 1 #ifndef NOSSE #include template void gaussHorizontal3 (T** src, T** dst, T* buffer, int W, int row_from, int row_to, const float c0, const float c1) { typedef float pfloat[4]; pfloat* temp = (pfloat*)buffer + 1; pfloat* tmp = (pfloat*)buffer; __m128 xmm1; xmm1 = _mm_load1_ps (&c0); __m128 xmm2; xmm2 = _mm_load1_ps (&c1); __m128 xmm3; __m128 xmm4; __m128 xmm5; __m128 xmm6; __m128 xmm0; int i; for (i = row_from; i void gaussHorizontal3 (T** src, T** dst, T* buffer, int W, int row_from, int row_to, const int c0, const int c1) { time_t t1 = clock (); const int csum = c0 + 2 * c1; for (int i = row_from; i void gaussVertical3 (T** src, T** dst, T* buffer, int H, int col_from, int col_to, const float c0, const float c1) { typedef float pfloat[4]; pfloat* temp = (pfloat*)buffer + 1; pfloat* tmp = (pfloat*)buffer; __m128 xmm1; xmm1 = _mm_load1_ps (&c0); __m128 xmm2; xmm2 = _mm_load1_ps (&c1); __m128 xmm3; __m128 xmm4; __m128 xmm5; __m128 xmm6; __m128 xmm0; int i; for (i = col_from; i void gaussVertical3 (T** src, T** dst, T* buffer, int H, int col_from, int col_to, const float c0, const float c1) { time_t t1 = clock (); int stride = dst[1] - dst[0]; for (int j=col_from; j void gaussHorizontal (T** src, T** dst, AlignedBuffer* buffer, int W, int row_from, int row_to, double sigma) { if (sigma<0.25) { // dont perform filtering if (src!=dst) for (int i = row_from; i (src, dst, (T*)(buffer->data), W, row_from, row_to, (int) round(c0), 2); double c1 = exp (-1.0 / (2.0 * sigma * sigma)); double csum = 2.0 * c1 + 1.0; c1 /= csum; double c0 = 1.0 / csum; gaussHorizontal3 (src, dst, (T*)(buffer->data), W, row_from, row_to, c0, c1); return; } // horizontal float q = 0.98711 * sigma - 0.96330; if (sigma<2.5) q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); float b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; float b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; float b2 = -1.4281*q*q - 1.26661*q*q*q; float b3 = 0.422205*q*q*q; float B = 1.0 - (b1+b2+b3) / b0; b1 /= b0; b2 /= b0; b3 /= b0; // SSE optimized version: __m128 xmm1; xmm1 = _mm_load1_ps (&B); __m128 xmm2; xmm2 = _mm_load1_ps (&b1); __m128 xmm3; xmm3 = _mm_load1_ps (&b2); __m128 xmm4; xmm4 = _mm_load1_ps (&b3); __m128 xmm5; __m128 xmm6; typedef float pfloat[4]; pfloat* temp = (pfloat*)buffer->data + 1; pfloat* tmp = (pfloat*)buffer->data; memset (temp, 0, W*sizeof(pfloat)); int i; for (i=row_from; i=0; j--) { xmm5 = _mm_load_ps ((float*)&temp[j]); xmm5 =_mm_mul_ps (xmm1, xmm5); xmm6 = _mm_load_ps ((float*)&temp[j+1]); xmm6 = _mm_mul_ps (xmm2, xmm6); xmm5 = _mm_add_ps (xmm6, xmm5); xmm6 = _mm_load_ps ((float*)&temp[j+2]); xmm6 = _mm_mul_ps (xmm6, xmm3); xmm5 = _mm_add_ps (xmm5, xmm6); xmm6 = _mm_load_ps ((float*)&temp[j+3]); xmm6 = _mm_mul_ps (xmm6, xmm4); xmm5 = _mm_add_ps (xmm5, xmm6); _mm_store_ps ((float*)&temp[j], xmm5); } for (int j=0; jdata; for (; i=0; j--) temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; for (int j=0; j void gaussVertical (T** src, T** dst, AlignedBuffer* buffer, int H, int col_from, int col_to, double sigma) { if (sigma<0.25) { // dont perform filtering if (src!=dst) for (int i = 0; i (src, dst, (T*)(buffer->data), H, col_from, col_to, c0, c1); // double c0 = 2.0 / exp (-1.0 / (2.0 * sigma * sigma)); // gaussVertical3 (src, dst, (T*)(buffer->data), H, col_from, col_to, (int) round(c0), 2); return; } // vertical float q = 0.98711 * sigma - 0.96330; if (sigma<2.5) q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); float b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; float b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; float b2 = -1.4281*q*q - 1.26661*q*q*q; float b3 = 0.422205*q*q*q; float B = 1.0 - (b1+b2+b3) / b0; b1 /= b0; b2 /= b0; b3 /= b0; // SSE optimized version: __m128 xmm1; xmm1 = _mm_load1_ps (&B); __m128 xmm2; xmm2 = _mm_load1_ps (&b1); __m128 xmm3; xmm3 = _mm_load1_ps (&b2); __m128 xmm4; xmm4 = _mm_load1_ps (&b3); __m128 xmm5; __m128 xmm6; typedef float pfloat[4]; pfloat* temp = (pfloat*)buffer->data + 1; pfloat* tmp = (pfloat*)buffer->data; memset (temp, 0, H*sizeof(pfloat)); int i; for (i=col_from; i=0; j--) { xmm5 = _mm_load_ps ((float*)&temp[j]); xmm5 =_mm_mul_ps (xmm1, xmm5); xmm6 = _mm_load_ps ((float*)&temp[j+1]); xmm6 = _mm_mul_ps (xmm2, xmm6); xmm5 = _mm_add_ps (xmm6, xmm5); xmm6 = _mm_load_ps ((float*)&temp[j+2]); xmm6 = _mm_mul_ps (xmm6, xmm3); xmm5 = _mm_add_ps (xmm5, xmm6); xmm6 = _mm_load_ps ((float*)&temp[j+3]); xmm6 = _mm_mul_ps (xmm6, xmm4); xmm5 = _mm_add_ps (xmm5, xmm6); _mm_store_ps ((float*)&temp[j], xmm5); } for (int j=0; jdata; for (; i=0; j--) temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; for (int j=0; j void gaussHorizontal3 (T** src, T** dst, T* buffer, int W, int row_from, int row_to, const float c0, const float c1) { for (int i=row_from; i void gaussVertical3 (T** src, T** dst, T* buffer, int H, int col_from, int col_to, const float c0, const float c1) { for (int i=col_from; i void gaussHorizontal (T** src, T** dst, AlignedBuffer* buffer, int W, int row_from, int row_to, double sigma) { if (sigma<0.25) { // dont perform filtering if (src!=dst) for (int i = row_from; i (src, dst, (T*)(buffer->data), W, row_from, row_to, c0, c1); return; } // horizontal double q = 0.98711 * sigma - 0.96330; if (sigma<2.5) q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; double b2 = -1.4281*q*q - 1.26661*q*q*q; double b3 = 0.422205*q*q*q; double B = 1.0 - (b1+b2+b3) / b0; b1 /= b0; b2 /= b0; b3 /= b0; // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering double M[3][3]; M[0][0] = -b3*b1+1.0-b3*b3-b2; M[0][1] = (b3+b1)*(b2+b3*b1); M[0][2] = b3*(b1+b3*b2); M[1][0] = b1+b3*b2; M[1][1] = -(b2-1.0)*(b2+b3*b1); M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; M[2][0] = b3*b1+b2+b1*b1-b2*b2; M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; M[2][2] = b3*(b1+b3*b2); for (int i=0; i<3; i++) for (int j=0; j<3; j++) M[i][j] /= (1.0+b1-b2+b3)*(1.0+b2+(b1-b3)*b3); double* temp2 = (double*)buffer->data; for (int i=row_from; i=0; j--) temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; for (int j=0; j void gaussVertical (T** src, T** dst, AlignedBuffer* buffer, int H, int col_from, int col_to, double sigma) { if (sigma<0.25) { // dont perform filtering if (src!=dst) for (int i = 0; i (src, dst, (T*)(buffer->data), H, col_from, col_to, c0, c1); return; } // vertical double q = 0.98711 * sigma - 0.96330; if (sigma<2.5) q = 3.97156 - 4.14554 * sqrt (1.0 - 0.26891 * sigma); double b0 = 1.57825 + 2.44413*q + 1.4281*q*q + 0.422205*q*q*q; double b1 = 2.44413*q + 2.85619*q*q + 1.26661*q*q*q; double b2 = -1.4281*q*q - 1.26661*q*q*q; double b3 = 0.422205*q*q*q; double B = 1.0 - (b1+b2+b3) / b0; b1 /= b0; b2 /= b0; b3 /= b0; // From: Bill Triggs, Michael Sdika: Boundary Conditions for Young-van Vliet Recursive Filtering double M[3][3]; M[0][0] = -b3*b1+1.0-b3*b3-b2; M[0][1] = (b3+b1)*(b2+b3*b1); M[0][2] = b3*(b1+b3*b2); M[1][0] = b1+b3*b2; M[1][1] = -(b2-1.0)*(b2+b3*b1); M[1][2] = -(b3*b1+b3*b3+b2-1.0)*b3; M[2][0] = b3*b1+b2+b1*b1-b2*b2; M[2][1] = b1*b2+b3*b2*b2-b1*b3*b3-b3*b3*b3-b3*b2+b3; M[2][2] = b3*(b1+b3*b2); for (int i=0; i<3; i++) for (int j=0; j<3; j++) M[i][j] /= (1.0+b1-b2+b3)*(1.0+b2+(b1-b3)*b3); double* temp2 = (double*)buffer->data; for (int i=col_from; i=0; j--) temp2[j] = B * temp2[j] + b1*temp2[j+1] + b2*temp2[j+2] + b3*temp2[j+3]; for (int j=0; j* buffer, int W, int row_from, int row_to, double sigma); void gaussVertical_unsigned (unsigned short** src, unsigned short** dst, AlignedBuffer* buffer, int H, int col_from, int col_to, double sigma); void gaussHorizontal_signed (short** src, short** dst, AlignedBuffer* buffer, int W, int row_from, int row_to, double sigma); void gaussVertical_signed (short** src, short** dst, AlignedBuffer* buffer, int H, int col_from, int col_to, double sigma); void gaussHorizontal_float (float** src, float** dst, AlignedBuffer* buffer, int W, int row_from, int row_to, double sigma); void gaussVertical_float (float** src, float** dst, AlignedBuffer* buffer, int H, int col_from, int col_to, double sigma); #endif