1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5  *
6  *  RawTherapee is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  RawTherapee is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 #pragma once
20 
21 #include "rawimagesource.h"
22 
23 namespace rtengine
24 {
25 
convert_row_to_YIQ(const float * const r,const float * const g,const float * const b,float * Y,float * I,float * Q,const int W)26 inline void RawImageSource::convert_row_to_YIQ (const float* const r, const float* const g, const float* const b, float* Y, float* I, float* Q, const int W)
27 {
28 #ifdef _OPENMP
29     #pragma omp simd
30 #endif
31 
32     for (int j = 0; j < W; j++) {
33         Y[j] = .299f * r[j] + .587f * g[j] + .114f * b[j];
34         I[j] = .596f * r[j] - .275f * g[j] - .321f * b[j];
35         Q[j] = .212f * r[j] - .523f * g[j] + .311f * b[j];
36     }
37 }
38 
convert_row_to_RGB(float * r,float * g,float * b,const float * const Y,const float * const I,const float * const Q,const int W)39 inline void RawImageSource::convert_row_to_RGB (float* r, float* g, float* b, const float* const Y, const float* const I, const float* const Q, const int W)
40 {
41 #ifdef _OPENMP
42     #pragma omp simd
43 #endif
44 
45     for (int j = 1; j < W - 1; j++) {
46         r[j] = Y[j] + 0.956f * I[j] + 0.621f * Q[j];
47         g[j] = Y[j] - 0.272f * I[j] - 0.647f * Q[j];
48         b[j] = Y[j] - 1.105f * I[j] + 1.702f * Q[j];
49     }
50 }
51 
convert_to_RGB(float & r,float & g,float & b,const float Y,const float I,const float Q)52 inline void RawImageSource::convert_to_RGB (float &r, float &g, float &b, const float Y, const float I, const float Q)
53 {
54     r = Y + 0.956f * I + 0.621f * Q;
55     g = Y - 0.272f * I - 0.647f * Q;
56     b = Y - 1.105f * I + 1.702f * Q;
57 }
58 
interpolate_row_rb_mul_pp(const array2D<float> & rawData,float * ar,float * ab,float * pg,float * cg,float * ng,int i,float r_mul,float g_mul,float b_mul,int x1,int width,int skip)59 inline void RawImageSource::interpolate_row_rb_mul_pp (const array2D<float> &rawData, float* ar, float* ab, float* pg, float* cg, float* ng, int i, float r_mul, float g_mul, float b_mul, int x1, int width, int skip)
60 {
61 
62     if ((ri->ISRED(i, 0) || ri->ISRED(i, 1)) && pg && ng) {
63         // RGRGR or GRGRGR line
64         for (int j = x1, jx = 0; jx < width; j += skip, jx++) {
65             if (ri->ISRED(i, j)) {
66                 // red is simple
67                 ar[jx] = r_mul * rawData[i][j];
68                 // blue: cross interpolation
69                 float b = 0;
70                 int n = 0;
71 
72                 if (i > 0 && j > 0) {
73                     b += b_mul * rawData[i - 1][j - 1] - g_mul * pg[j - 1];
74                     n++;
75                 }
76 
77                 if (i > 0 && j < W - 1) {
78                     b += b_mul * rawData[i - 1][j + 1] - g_mul * pg[j + 1];
79                     n++;
80                 }
81 
82                 if (i < H - 1 && j > 0) {
83                     b += b_mul * rawData[i + 1][j - 1] - g_mul * ng[j - 1];
84                     n++;
85                 }
86 
87                 if (i < H - 1 && j < W - 1) {
88                     b += b_mul * rawData[i + 1][j + 1] - g_mul * ng[j + 1];
89                     n++;
90                 }
91 
92                 b = g_mul * cg[j] + b / std::max(1, n);
93                 ab[jx] = std::max(0.f, b);
94             } else {
95                 // linear R-G interp. horizontally
96                 float r;
97 
98                 if (j == 0) {
99                     r = g_mul * cg[0] + r_mul * rawData[i][1] - g_mul * cg[1];
100                 } else if (j == W - 1) {
101                     r = g_mul * cg[W - 1] + r_mul * rawData[i][W - 2] - g_mul * cg[W - 2];
102                 } else {
103                     r = g_mul * cg[j] + (r_mul * rawData[i][j - 1] - g_mul * cg[j - 1] + r_mul * rawData[i][j + 1] - g_mul * cg[j + 1]) / 2;
104                 }
105 
106                 ar[jx] = std::max(0.f, r);
107                 // linear B-G interp. vertically
108                 float b;
109 
110                 if (i == 0) {
111                     b = g_mul * ng[j] + b_mul * rawData[1][j] - g_mul * cg[j];
112                 } else if (i == H - 1) {
113                     b = g_mul * pg[j] + b_mul * rawData[H - 2][j] - g_mul * cg[j];
114                 } else {
115                     b = g_mul * cg[j] + (b_mul * rawData[i - 1][j] - g_mul * pg[j] + b_mul * rawData[i + 1][j] - g_mul * ng[j]) / 2;
116                 }
117 
118                 ab[jx] = std::max(0.f, b);
119             }
120         }
121     } else if(pg && ng) {
122         // BGBGB or GBGBGB line
123         for (int j = x1, jx = 0; jx < width; j += skip, jx++) {
124             if (ri->ISBLUE(i, j)) {
125                 // red is simple
126                 ab[jx] = b_mul * rawData[i][j];
127                 // blue: cross interpolation
128                 float r = 0;
129                 int n = 0;
130 
131                 if (i > 0 && j > 0) {
132                     r += r_mul * rawData[i - 1][j - 1] - g_mul * pg[j - 1];
133                     n++;
134                 }
135 
136                 if (i > 0 && j < W - 1) {
137                     r += r_mul * rawData[i - 1][j + 1] - g_mul * pg[j + 1];
138                     n++;
139                 }
140 
141                 if (i < H - 1 && j > 0) {
142                     r += r_mul * rawData[i + 1][j - 1] - g_mul * ng[j - 1];
143                     n++;
144                 }
145 
146                 if (i < H - 1 && j < W - 1) {
147                     r += r_mul * rawData[i + 1][j + 1] - g_mul * ng[j + 1];
148                     n++;
149                 }
150 
151                 r = g_mul * cg[j] + r / std::max(n, 1);
152 
153                 ar[jx] = std::max(0.f, r);
154             } else {
155                 // linear B-G interp. horizontally
156                 float b;
157 
158                 if (j == 0) {
159                     b = g_mul * cg[0] + b_mul * rawData[i][1] - g_mul * cg[1];
160                 } else if (j == W - 1) {
161                     b = g_mul * cg[W - 1] + b_mul * rawData[i][W - 2] - g_mul * cg[W - 2];
162                 } else {
163                     b = g_mul * cg[j] + (b_mul * rawData[i][j - 1] - g_mul * cg[j - 1] + b_mul * rawData[i][j + 1] - g_mul * cg[j + 1]) / 2;
164                 }
165 
166                 ab[jx] = std::max(0.f, b);
167                 // linear R-G interp. vertically
168                 float r;
169 
170                 if (i == 0) {
171                     r = g_mul * ng[j] + r_mul * rawData[1][j] - g_mul * cg[j];
172                 } else if (i == H - 1) {
173                     r = g_mul * pg[j] + r_mul * rawData[H - 2][j] - g_mul * cg[j];
174                 } else {
175                     r = g_mul * cg[j] + (r_mul * rawData[i - 1][j] - g_mul * pg[j] + r_mul * rawData[i + 1][j] - g_mul * ng[j]) / 2;
176                 }
177 
178                 ar[jx] = std::max(0.f, r);
179             }
180         }
181     }
182 }
183 
184 }
185