41 #ifndef vpBAYERCONVERSION_H 42 #define vpBAYERCONVERSION_H 46 #include <visp3/core/vpMath.h> 50 #define m_assert(msg, expr) assert( ( (void)( msg ), ( expr ) ) ) 54 T demosaicPhiBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
56 return static_cast<T
>(0.5f*bayer[(i-1)*width + j] + 0.5f*bayer[(i+1)*width + j]);
60 T demosaicThetaBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
62 return static_cast<T
>(0.5f*bayer[i*width + j - 1] + 0.5f*bayer[i*width + j + 1]);
66 T demosaicCheckerBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
68 return static_cast<T
>(0.25f*bayer[(i-1)*width + j-1] + 0.25f*bayer[(i-1)*width + j+1] + 0.25f*bayer[(i+1)*width + j-1] + 0.25f*bayer[(i+1)*width + j+1]);
72 T demosaicCrossBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
74 return static_cast<T
>(0.25f*bayer[(i-1)*width + j] + 0.25f*bayer[i*width + j-1] + 0.25f*bayer[i*width + j+1] + 0.25f*bayer[(i+1)*width + j]);
79 T demosaicPhiMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
81 return vpMath::saturate<T>((-bayer[(i-2)*width + j] - bayer[(i-1)*width + j-1] + 4*bayer[(i-1)*width + j] - bayer[(i-1)*width + j+1] +
82 0.5f*bayer[i*width + j-2] + 5*bayer[i*width + j] + 0.5f*bayer[i*width + j+2] - bayer[(i+1)*width + j-1] + 4*bayer[(i+1)*width + j] -
83 bayer[(i+1)*width + j+1] - bayer[(i+2)*width + j]) * 0.125f);
87 T demosaicThetaMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
89 return vpMath::saturate<T>((0.5f*bayer[(i-2)*width + j] - bayer[(i-1)*width + j-1] - bayer[(i-1)*width + j+1] - bayer[i*width + j-2] +
90 4*bayer[i*width + j-1] + 5*bayer[i*width + j] + 4*bayer[i*width + j+1] - bayer[i*width + j+2] - bayer[(i+1)*width + j-1] -
91 bayer[(i+1)*width + j+1] + 0.5f*bayer[(i+2)*width + j]) * 0.125f);
95 T demosaicCheckerMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
97 return vpMath::saturate<T>((-1.5f*bayer[(i-2)*width + j] + 2*bayer[(i-1)*width + j-1] + 2*bayer[(i-1)*width + j+1] -
98 1.5f*bayer[i*width + j-2] + 6*bayer[i*width + j] - 1.5f*bayer[i*width + j+2] + 2*bayer[(i+1)*width + j-1] +
99 2*bayer[(i+1)*width + j+1] - 1.5f*bayer[(i+2)*width + j]) * 0.125f);
102 template <
typename T>
103 T demosaicCrossMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
105 return vpMath::saturate<T>((-bayer[(i-2)*width + j] + 2*bayer[(i-1)*width + j] - bayer[i*width + j-2] + 2*bayer[i*width + j-1] +
106 4*bayer[i*width + j] + 2*bayer[i*width + j+1] - bayer[i*width + j+2] + 2*bayer[(i+1)*width + j] - bayer[(i+2)*width + j]) * 0.125f);
109 template <
typename T>
110 void demosaicBGGRToRGBaBilinearTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
112 m_assert(
"width must be >= 4", width >= 4);
113 m_assert(
"height must be >= 4", height >= 4);
114 m_assert(
"width must be a multiple of 2", width % 2 == 0);
115 m_assert(
"height must be a multiple of 2", height % 2 == 0);
118 rgba[0] = bggr[width + 1];
123 rgba[(width-1)*4 + 0] = bggr[2*width - 1];
124 rgba[(width-1)*4 + 1] = bggr[width - 1];
125 rgba[(width-1)*4 + 2] = bggr[width - 2];
128 rgba[((height-1)*width)*4 + 0] = bggr[(height-1)*width + 1];
129 rgba[((height-1)*width)*4 + 1] = bggr[(height-1)*width];
130 rgba[((height-1)*width)*4 + 2] = bggr[(height-2)*width];
133 rgba[((height-1)*width + width-1)*4 + 0] = bggr[height*width - 1];
134 rgba[((height-1)*width + width-1)*4 + 1] = bggr[height*width - 2];
135 rgba[((height-1)*width + width-1)*4 + 2] = bggr[(height-1)*width - 2];
138 for (
unsigned int j = 1; j < width-1; j++) {
140 rgba[j*4 + 0] =
static_cast<T
>(0.5f*bggr[width + j - 1] + 0.5f*bggr[width + j + 1]);
141 rgba[j*4 + 1] =
static_cast<T
>(0.5f*bggr[j - 1] + 0.5f*bggr[j + 1]);
142 rgba[j*4 + 2] = bggr[j];
144 rgba[j*4 + 0] = bggr[width + j];
145 rgba[j*4 + 1] = bggr[j];
146 rgba[j*4 + 2] =
static_cast<T
>(0.5f*bggr[j - 1] + 0.5f*bggr[j + 1]);
151 for (
unsigned int i = 1; i < height-1; i++) {
153 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*bggr[(i-1)*width + 1] + 0.5f*bggr[(i+1)*width + 1]);
154 rgba[i*width*4 + 1] = bggr[i*width + 1];
155 rgba[i*width*4 + 2] = bggr[i*width];
157 rgba[i*width*4 + 0] = bggr[i*width + 1];
158 rgba[i*width*4 + 1] = bggr[i*width];
159 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*bggr[(i-1)*width] + 0.5f*bggr[(i+1)*width]);
164 for (
unsigned int i = 1; i < height-1; i++) {
166 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*bggr[i*width - 1] + 0.5f*bggr[(i+2)*width - 1]);
167 rgba[(i*width + width-1)*4 + 1] = bggr[(i+1)*width - 1];
168 rgba[(i*width + width-1)*4 + 2] = bggr[(i+1)*width - 2];
170 rgba[(i*width + width-1)*4 + 0] = bggr[(i+1)*width - 1];
171 rgba[(i*width + width-1)*4 + 1] = bggr[(i+1)*width - 2];
172 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*bggr[i*width - 2] + 0.5f*bggr[(i+2)*width - 2]);
177 for (
unsigned int j = 1; j < width-1; j++) {
179 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*bggr[(height-1)*width + j - 1] + 0.5f*bggr[(height-1)*width + j + 1]);
180 rgba[((height-1)*width + j)*4 + 1] = bggr[(height-1)*width + j];
181 rgba[((height-1)*width + j)*4 + 2] = bggr[(height-2)*width + j];
183 rgba[((height-1)*width + j)*4 + 0] = bggr[(height-1)*width + j];
184 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*bggr[(height-1)*width + j - 1] + 0.5f*bggr[(height-1)*width + j + 1]);
185 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*bggr[(height-2)*width + j - 1] + 0.5f*bggr[(height-2)*width + j + 1]);
189 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 191 omp_set_num_threads(static_cast<int>(nThreads));
193 #pragma omp parallel for schedule(dynamic) 197 for (
unsigned int i = 1; i < height-1; i++) {
198 for (
unsigned int j = 1; j < width-1; j++) {
199 if (i % 2 == 0 && j % 2 == 0) {
200 rgba[(i*width + j) * 4 + 0] = demosaicCheckerBilinear(bggr, width, i, j);
201 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
202 rgba[(i*width + j) * 4 + 2] = bggr[i*width + j];
203 }
else if (i % 2 == 0 && j % 2 != 0) {
204 rgba[(i*width + j) * 4 + 0] = demosaicPhiBilinear(bggr, width, i, j);
205 rgba[(i*width + j) * 4 + 1] = bggr[i*width + j];
206 rgba[(i*width + j) * 4 + 2] = demosaicThetaBilinear(bggr, width, i, j);
207 }
else if (i % 2 != 0 && j % 2 == 0) {
208 rgba[(i*width + j) * 4 + 0] = demosaicThetaBilinear(bggr, width, i, j);
209 rgba[(i*width + j) * 4 + 1] = bggr[i*width + j];
210 rgba[(i*width + j) * 4 + 2] = demosaicPhiBilinear(bggr, width, i, j);
212 rgba[(i*width + j) * 4 + 0] = bggr[i*width + j];
213 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
214 rgba[(i*width + j) * 4 + 2] = demosaicCheckerBilinear(bggr, width, i, j);
221 void demosaicGBRGToRGBaBilinearTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
223 m_assert(
"width must be >= 4", width >= 4);
224 m_assert(
"height must be >= 4", height >= 4);
225 m_assert(
"width must be a multiple of 2", width % 2 == 0);
226 m_assert(
"height must be a multiple of 2", height % 2 == 0);
229 rgba[0] = gbrg[width];
234 rgba[(width-1)*4 + 0] = gbrg[2*width - 2];
235 rgba[(width-1)*4 + 1] = gbrg[width - 2];
236 rgba[(width-1)*4 + 2] = gbrg[width - 1];
239 rgba[((height-1)*width)*4 + 0] = gbrg[(height-1)*width];
240 rgba[((height-1)*width)*4 + 1] = gbrg[(height-1)*width + 1];
241 rgba[((height-1)*width)*4 + 2] = gbrg[(height-2)*width + 1];
244 rgba[((height-1)*width + width-1)*4 + 0] = gbrg[height*width - 2];
245 rgba[((height-1)*width + width-1)*4 + 1] = gbrg[height*width - 1];
246 rgba[((height-1)*width + width-1)*4 + 2] = gbrg[(height-1)*width - 1];
249 for (
unsigned int j = 1; j < width-1; j++) {
251 rgba[j*4 + 0] = gbrg[width + j];
252 rgba[j*4 + 1] = gbrg[j];
253 rgba[j*4 + 2] =
static_cast<T
>(0.5f*gbrg[j - 1] + 0.5f*gbrg[j + 1]);
255 rgba[j*4 + 0] =
static_cast<T
>(0.5f*gbrg[width + j - 1] + 0.5f*gbrg[width + j + 1]);
256 rgba[j*4 + 1] =
static_cast<T
>(0.5f*gbrg[j - 1] + 0.5f*gbrg[j + 1]);
257 rgba[j*4 + 2] = gbrg[j];
262 for (
unsigned int i = 1; i < height-1; i++) {
264 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*gbrg[(i-1)*width] + 0.5f*gbrg[(i+1)*width]);
265 rgba[i*width*4 + 1] = gbrg[i*width];
266 rgba[i*width*4 + 2] = gbrg[i*width + 1];
268 rgba[i*width*4 + 0] = gbrg[i*width];
269 rgba[i*width*4 + 1] =
static_cast<T
>(0.5f*gbrg[(i-1)*width] + 0.5f*gbrg[(i+1)*width]);
270 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*gbrg[(i-1)*width + 1] + 0.5f*gbrg[(i+1)*width + 1]);
275 for (
unsigned int i = 1; i < height-1; i++) {
277 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*gbrg[i*width - 2] + 0.5f*gbrg[(i+2)*width - 2]);
278 rgba[(i*width + width-1)*4 + 1] = gbrg[(i+1)*width - 2];
279 rgba[(i*width + width-1)*4 + 2] = gbrg[(i+1)*width - 1];
281 rgba[(i*width + width-1)*4 + 0] = gbrg[(i+1)*width - 2];
282 rgba[(i*width + width-1)*4 + 1] = gbrg[(i+1)*width - 1];
283 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*gbrg[i*width - 1] + 0.5f*gbrg[(i+2)*width - 1]);
288 for (
unsigned int j = 1; j < width-1; j++) {
290 rgba[((height-1)*width + j)*4 + 0] = gbrg[(height-1)*width + j];
291 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*gbrg[(height-1)*width + j - 1] + 0.5f*gbrg[(height-1)*width + j + 1]);
292 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*gbrg[(height-2)*width + j - 1] + 0.5f*gbrg[(height-2)*width + j + 1]);
294 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*gbrg[(height-1)*width + j - 1] + 0.5f*gbrg[(height-1)*width + j + 1]);
295 rgba[((height-1)*width + j)*4 + 1] = gbrg[(height-1)*width + j];
296 rgba[((height-1)*width + j)*4 + 2] = gbrg[(height-2)*width + j];
300 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 302 omp_set_num_threads(static_cast<int>(nThreads));
304 #pragma omp parallel for schedule(dynamic) 308 for (
unsigned int i = 1; i < height-1; i++) {
309 for (
unsigned int j = 1; j < width-1; j++) {
310 if (i % 2 == 0 && j % 2 == 0) {
311 rgba[(i*width + j) * 4 + 0] = demosaicPhiBilinear(gbrg, width, i, j);
312 rgba[(i*width + j) * 4 + 1] = gbrg[i*width + j];
313 rgba[(i*width + j) * 4 + 2] = demosaicThetaBilinear(gbrg, width, i, j);
314 }
else if (i % 2 == 0 && j % 2 != 0) {
315 rgba[(i*width + j) * 4 + 0] = demosaicCheckerBilinear(gbrg, width, i, j);
316 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
317 rgba[(i*width + j) * 4 + 2] = gbrg[i*width + j];
318 }
else if (i % 2 != 0 && j % 2 == 0) {
319 rgba[(i*width + j) * 4 + 0] = gbrg[i*width + j];
320 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
321 rgba[(i*width + j) * 4 + 2] = demosaicCheckerBilinear(gbrg, width, i, j);
323 rgba[(i*width + j) * 4 + 0] = demosaicThetaBilinear(gbrg, width, i, j);
324 rgba[(i*width + j) * 4 + 1] = gbrg[i*width + j];
325 rgba[(i*width + j) * 4 + 2] = demosaicPhiBilinear(gbrg, width, i, j);
332 void demosaicGRBGToRGBaBilinearTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
334 m_assert(
"width must be >= 4", width >= 4);
335 m_assert(
"height must be >= 4", height >= 4);
336 m_assert(
"width must be a multiple of 2", width % 2 == 0);
337 m_assert(
"height must be a multiple of 2", height % 2 == 0);
342 rgba[2] = grbg[width];
345 rgba[(width-1)*4 + 0] = grbg[width - 1];
346 rgba[(width-1)*4 + 1] = grbg[width - 2];
347 rgba[(width-1)*4 + 2] = grbg[2*width - 2];
350 rgba[((height-1)*width)*4 + 0] = grbg[(height-2)*width + 1];
351 rgba[((height-1)*width)*4 + 1] = grbg[(height-1)*width + 1];
352 rgba[((height-1)*width)*4 + 2] = grbg[(height-1)*width];
355 rgba[((height-1)*width + width-1)*4 + 0] = grbg[(height-1)*width - 1];
356 rgba[((height-1)*width + width-1)*4 + 1] = grbg[height*width - 1];
357 rgba[((height-1)*width + width-1)*4 + 2] = grbg[height*width - 2];
360 for (
unsigned int j = 1; j < width-1; j++) {
362 rgba[j*4 + 0] =
static_cast<T
>(0.5f*grbg[j - 1] + 0.5f*grbg[j + 1]);
363 rgba[j*4 + 1] = grbg[j];
364 rgba[j*4 + 2] = grbg[width + j];
366 rgba[j*4 + 0] = grbg[j];
367 rgba[j*4 + 1] =
static_cast<T
>(0.5f*grbg[j - 1] + 0.5f*grbg[j + 1]);
368 rgba[j*4 + 2] =
static_cast<T
>(0.5f*grbg[width + j - 1] + 0.5f*grbg[width + j + 1]);
373 for (
unsigned int i = 1; i < height-1; i++) {
375 rgba[i*width*4 + 0] = grbg[i*width + 1];
376 rgba[i*width*4 + 1] = grbg[i*width];
377 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*grbg[(i-1)*width] + 0.5f*grbg[(i+1)*width]);
379 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*grbg[(i-1)*width + 1] + 0.5f*grbg[(i+1)*width + 1]);
380 rgba[i*width*4 + 1] = grbg[i*width + 1];
381 rgba[i*width*4 + 2] = grbg[i*width];
386 for (
unsigned int i = 1; i < height-1; i++) {
388 rgba[(i*width + width-1)*4 + 0] = grbg[(i+1)*width - 1];
389 rgba[(i*width + width-1)*4 + 1] = grbg[(i+1)*width - 2];
390 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*grbg[i*width - 2] + 0.5f*grbg[(i+2)*width - 2]);
392 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*grbg[i*width - 1] + 0.5f*grbg[(i+2)*width - 1]);
393 rgba[(i*width + width-1)*4 + 1] = grbg[(i+1)*width - 1];
394 rgba[(i*width + width-1)*4 + 2] = grbg[(i+1)*width - 2];
399 for (
unsigned int j = 1; j < width-1; j++) {
401 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*grbg[(height-2)*width + j - 1] + 0.5f*grbg[(height-2)*width + j + 1]);
402 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*grbg[(height-1)*width + j - 1] + 0.5f*grbg[(height-1)*width + j + 1]);
403 rgba[((height-1)*width + j)*4 + 2] = grbg[(height-1)*width + j];
405 rgba[((height-1)*width + j)*4 + 0] = grbg[(height-2)*width + j];
406 rgba[((height-1)*width + j)*4 + 1] = grbg[(height-1)*width + j];
407 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*grbg[(height-1)*width + j - 1] + 0.5f*grbg[(height-1)*width + j + 1]);
411 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 413 omp_set_num_threads(static_cast<int>(nThreads));
415 #pragma omp parallel for schedule(dynamic) 419 for (
unsigned int i = 1; i < height-1; i++) {
420 for (
unsigned int j = 1; j < width-1; j++) {
421 if (i % 2 == 0 && j % 2 == 0) {
422 rgba[(i*width + j) * 4 + 0] = demosaicThetaBilinear(grbg, width, i, j);
423 rgba[(i*width + j) * 4 + 1] = grbg[i*width + j];
424 rgba[(i*width + j) * 4 + 2] = demosaicPhiBilinear(grbg, width, i, j);
425 }
else if (i % 2 == 0 && j % 2 != 0) {
426 rgba[(i*width + j) * 4 + 0] = grbg[i*width + j];
427 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
428 rgba[(i*width + j) * 4 + 2] = demosaicCheckerBilinear(grbg, width, i, j);
429 }
else if (i % 2 != 0 && j % 2 == 0) {
430 rgba[(i*width + j) * 4 + 0] = demosaicCheckerBilinear(grbg, width, i, j);
431 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
432 rgba[(i*width + j) * 4 + 2] = grbg[i*width + j];
434 rgba[(i*width + j) * 4 + 0] = demosaicPhiBilinear(grbg, width, i, j);
435 rgba[(i*width + j) * 4 + 1] = grbg[i*width + j];
436 rgba[(i*width + j) * 4 + 2] = demosaicThetaBilinear(grbg, width, i, j);
443 void demosaicRGGBToRGBaBilinearTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
445 m_assert(
"width must be >= 4", width >= 4);
446 m_assert(
"height must be >= 4", height >= 4);
447 m_assert(
"width must be a multiple of 2", width % 2 == 0);
448 m_assert(
"height must be a multiple of 2", height % 2 == 0);
453 rgba[2] = rggb[width + 1];
456 rgba[(width-1)*4 + 0] = rggb[width - 2];
457 rgba[(width-1)*4 + 1] = rggb[width - 1];
458 rgba[(width-1)*4 + 2] = rggb[2*width - 1];
461 rgba[((height-1)*width)*4 + 0] = rggb[(height-2)*width];
462 rgba[((height-1)*width)*4 + 1] = rggb[(height-1)*width];
463 rgba[((height-1)*width)*4 + 2] = rggb[(height-1)*width + 1];
466 rgba[((height-1)*width + width-1)*4 + 0] = rggb[(height-1)*width - 2];
467 rgba[((height-1)*width + width-1)*4 + 1] = rggb[height*width - 2];
468 rgba[((height-1)*width + width-1)*4 + 2] = rggb[height*width - 1];
471 for (
unsigned int j = 1; j < width-1; j++) {
473 rgba[j*4 + 0] = rggb[j];
474 rgba[j*4 + 1] =
static_cast<T
>(0.5f*rggb[j - 1] + 0.5f*rggb[j + 1]);
475 rgba[j*4 + 2] =
static_cast<T
>(0.5f*rggb[width + j - 1] + 0.5f*rggb[width + j + 1]);
477 rgba[j*4 + 0] =
static_cast<T
>(0.5f*rggb[j - 1] + 0.5f*rggb[j + 1]);
478 rgba[j*4 + 1] = rggb[j];
479 rgba[j*4 + 2] = rggb[width + j];
484 for (
unsigned int i = 1; i < height-1; i++) {
486 rgba[i*width*4 + 0] = rggb[i*width];
487 rgba[i*width*4 + 1] = rggb[i*width + 1];
488 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*rggb[(i-1)*width + 1] + 0.5f*rggb[(i+1)*width + 1]);
490 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*rggb[(i-1)*width] + 0.5f*rggb[(i+1)*width]);
491 rgba[i*width*4 + 1] = rggb[i*width];
492 rgba[i*width*4 + 2] = rggb[i*width + 1];
497 for (
unsigned int i = 1; i < height-1; i++) {
499 rgba[(i*width + width-1)*4 + 0] = rggb[(i+1)*width - 2];
500 rgba[(i*width + width-1)*4 + 1] = rggb[(i+1)*width - 1];
501 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*rggb[i*width - 1] + 0.5f*rggb[(i+2)*width - 1]);
503 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*rggb[i*width - 2] + 0.5f*rggb[(i+2)*width - 2]);
504 rgba[(i*width + width-1)*4 + 1] = rggb[(i+1)*width - 2];
505 rgba[(i*width + width-1)*4 + 2] = rggb[(i+1)*width - 1];
510 for (
unsigned int j = 1; j < width-1; j++) {
512 rgba[((height-1)*width + j)*4 + 0] = rggb[(height-2)*width + j];
513 rgba[((height-1)*width + j)*4 + 1] = rggb[(height-1)*width + j];
514 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*rggb[(height-1)*width + j - 1] + 0.5f*rggb[(height-1)*width + j + 1]);
516 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*rggb[(height-2)*width + j - 1] + 0.5f*rggb[(height-2)*width + j + 1]);
517 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*rggb[(height-1)*width + j - 1] + 0.5f*rggb[(height-1)*width + j + 1]);
518 rgba[((height-1)*width + j)*4 + 2] = rggb[(height-1)*width + j];
522 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 524 omp_set_num_threads(static_cast<int>(nThreads));
526 #pragma omp parallel for schedule(dynamic) 530 for (
unsigned int i = 1; i < height-1; i++) {
531 for (
unsigned int j = 1; j < width-1; j++) {
532 if (i % 2 == 0 && j % 2 == 0) {
533 rgba[(i*width + j) * 4 + 0] = rggb[i*width + j];
534 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
535 rgba[(i*width + j) * 4 + 2] = demosaicCheckerBilinear(rggb, width, i, j);
536 }
else if (i % 2 == 0 && j % 2 != 0) {
537 rgba[(i*width + j) * 4 + 0] = demosaicThetaBilinear(rggb, width, i, j);
538 rgba[(i*width + j) * 4 + 1] = rggb[i*width + j];
539 rgba[(i*width + j) * 4 + 2] = demosaicPhiBilinear(rggb, width, i, j);
540 }
else if (i % 2 != 0 && j % 2 == 0) {
541 rgba[(i*width + j) * 4 + 0] = demosaicPhiBilinear(rggb, width, i, j);
542 rgba[(i*width + j) * 4 + 1] = rggb[i*width + j];
543 rgba[(i*width + j) * 4 + 2] = demosaicThetaBilinear(rggb, width, i, j);
545 rgba[(i*width + j) * 4 + 0] = demosaicCheckerBilinear(rggb, width, i, j);
546 rgba[(i*width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
547 rgba[(i*width + j) * 4 + 2] = rggb[i*width + j];
556 void demosaicBGGRToRGBaMalvarTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
558 m_assert(
"width must be >= 4", width >= 4);
559 m_assert(
"height must be >= 4", height >= 4);
560 m_assert(
"width must be a multiple of 2", width % 2 == 0);
561 m_assert(
"height must be a multiple of 2", height % 2 == 0);
564 rgba[0] = bggr[width + 1];
569 rgba[(width-1)*4 + 0] = bggr[2*width - 1];
570 rgba[(width-1)*4 + 1] = bggr[width - 1];
571 rgba[(width-1)*4 + 2] = bggr[width - 2];
574 rgba[((height-1)*width)*4 + 0] = bggr[(height-1)*width + 1];
575 rgba[((height-1)*width)*4 + 1] = bggr[(height-1)*width];
576 rgba[((height-1)*width)*4 + 2] = bggr[(height-2)*width];
579 rgba[((height-1)*width + width-1)*4 + 0] = bggr[height*width - 1];
580 rgba[((height-1)*width + width-1)*4 + 1] = bggr[height*width - 2];
581 rgba[((height-1)*width + width-1)*4 + 2] = bggr[(height-1)*width - 2];
584 for (
unsigned int j = 1; j < width-1; j++) {
586 rgba[j*4 + 0] =
static_cast<T
>(0.5f*bggr[width + j - 1] + 0.5f*bggr[width + j + 1]);
587 rgba[j*4 + 1] =
static_cast<T
>(0.5f*bggr[j - 1] + 0.5f*bggr[j + 1]);
588 rgba[j*4 + 2] = bggr[j];
590 rgba[j*4 + 0] = bggr[width + j];
591 rgba[j*4 + 1] = bggr[j];
592 rgba[j*4 + 2] =
static_cast<T
>(0.5f*bggr[j - 1] + 0.5f*bggr[j + 1]);
597 for (
unsigned int j = 1; j < width-1; j++) {
599 rgba[(width + j)*4 + 0] = static_cast<T>(0.5f*bggr[width + j - 1] + 0.5f*bggr[width + j + 1]);
600 rgba[(width + j)*4 + 1] = bggr[width + j];
601 rgba[(width + j)*4 + 2] = static_cast<T>(0.5f*bggr[j] + 0.5f*bggr[2*width + j]);
603 rgba[(width + j)*4 + 0] = bggr[width + j];
604 rgba[(width + j)*4 + 1] = static_cast<T>(0.25f*bggr[j] + 0.25f*bggr[width + j - 1] + 0.25f*bggr[width + j + 1] + 0.25f*bggr[2*width + j]);
605 rgba[(width + j)*4 + 2] = static_cast<T>(0.25f*bggr[j - 1] + 0.25f*bggr[j + 1] + 0.25f*bggr[2*width + j - 1] + 0.25f*bggr[2*width + j + 1]);
610 for (
unsigned int i = 1; i < height-1; i++) {
612 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*bggr[(i-1)*width + 1] + 0.5f*bggr[(i+1)*width + 1]);
613 rgba[i*width*4 + 1] = bggr[i*width + 1];
614 rgba[i*width*4 + 2] = bggr[i*width];
616 rgba[i*width*4 + 0] = bggr[i*width + 1];
617 rgba[i*width*4 + 1] = bggr[i*width];
618 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*bggr[(i-1)*width] + 0.5f*bggr[(i+1)*width]);
623 for (
unsigned int i = 1; i < height-1; i++) {
625 rgba[(i*width + 1)*4 + 0] = static_cast<T>(0.5f*bggr[(i-1)*width + 1] + 0.5f*bggr[(i+1)*width + 1]);
626 rgba[(i*width + 1)*4 + 1] = bggr[i*width + 1];
627 rgba[(i*width + 1)*4 + 2] = static_cast<T>(0.5f*bggr[i*width] + 0.5f*bggr[i*width + 2]);
629 rgba[(i*width + 1)*4 + 0] = bggr[i*width + 1];
630 rgba[(i*width + 1)*4 + 1] = static_cast<T>(0.25f*bggr[(i-1)*width + 1] + 0.25f*bggr[i*width] + 0.25f*bggr[i*width + 2] + 0.25f*bggr[(i+1)*width + 1]);
631 rgba[(i*width + 1)*4 + 2] = static_cast<T>(0.25f*bggr[(i-1)*width] + 0.25f*bggr[(i-1)*width + 2] + 0.25f*bggr[(i+1)*width] + 0.25f*bggr[(i+1)*width + 2]);
636 for (
unsigned int i = 1; i < height-1; i++) {
638 rgba[(i*width + width-2)*4 + 0] = static_cast<T>(0.25f*bggr[i*width - 3] + 0.25f*bggr[i*width - 1] + 0.25f*bggr[(i+2)*width - 3] + 0.25f*bggr[(i+2)*width - 1]);
639 rgba[(i*width + width-2)*4 + 1] = static_cast<T>(0.25f*bggr[i*width - 2] + 0.25f*bggr[(i+1)*width - 3] +
640 0.25f*bggr[(i+1)*width - 1] + 0.25f*bggr[(i+2)*width - 2]);
641 rgba[(i*width + width-2)*4 + 2] = bggr[(i+1)*width - 2];
643 rgba[(i*width + width-2)*4 + 0] = static_cast<T>(0.5f*bggr[(i+1)*width - 3] + 0.5f*bggr[(i+1)*width - 1]);
644 rgba[(i*width + width-2)*4 + 1] = bggr[(i+1)*width - 2];
645 rgba[(i*width + width-2)*4 + 2] = static_cast<T>(0.5f*bggr[i*width - 2] + 0.5f*bggr[(i+2)*width - 2]);
650 for (
unsigned int i = 1; i < height-1; i++) {
652 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*bggr[i*width - 1] + 0.5f*bggr[(i+2)*width - 1]);
653 rgba[(i*width + width-1)*4 + 1] = bggr[(i+1)*width - 1];
654 rgba[(i*width + width-1)*4 + 2] = bggr[(i+1)*width - 2];
656 rgba[(i*width + width-1)*4 + 0] = bggr[(i+1)*width - 1];
657 rgba[(i*width + width-1)*4 + 1] = bggr[(i+1)*width - 2];
658 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*bggr[i*width - 2] + 0.5f*bggr[(i+2)*width - 2]);
663 for (
unsigned int j = 1; j < width-1; j++) {
665 rgba[((height-2)*width + j)*4 + 0] =
static_cast<T
>(0.25f*bggr[(height-3)*width + j - 1] + 0.25f*bggr[(height-3)*width + j + 1] +
666 0.25f*bggr[(height-1)*width + j - 1] + 0.25f*bggr[(height-1)*width + j + 1]);
667 rgba[((height-2)*width + j)*4 + 1] =
static_cast<T
>(0.5f*bggr[(height-2)*width + j - 1] + 0.5f*bggr[(height-2)*width + j + 1]);
668 rgba[((height-2)*width + j)*4 + 2] = bggr[(height-2)*width + j];
670 rgba[((height-2)*width + j)*4 + 0] =
static_cast<T
>(0.5f*bggr[(height-3)*width + j] + 0.5f*bggr[(height-1)*width + j]);
671 rgba[((height-2)*width + j)*4 + 1] = bggr[(height-2)*width + j];
672 rgba[((height-2)*width + j)*4 + 2] =
static_cast<T
>(0.5f*bggr[(height-2)*width + j - 1] + 0.5f*bggr[(height-2)*width + j + 1]);
677 for (
unsigned int j = 1; j < width-1; j++) {
679 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*bggr[(height-1)*width + j - 1] + 0.5f*bggr[(height-1)*width + j + 1]);
680 rgba[((height-1)*width + j)*4 + 1] = bggr[(height-1)*width + j];
681 rgba[((height-1)*width + j)*4 + 2] = bggr[(height-2)*width + j];
683 rgba[((height-1)*width + j)*4 + 0] = bggr[(height-1)*width + j];
684 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*bggr[(height-1)*width + j - 1] + 0.5f*bggr[(height-1)*width + j + 1]);
685 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*bggr[(height-2)*width + j - 1] + 0.5f*bggr[(height-2)*width + j + 1]);
689 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 691 omp_set_num_threads(static_cast<int>(nThreads));
693 #pragma omp parallel for schedule(dynamic) 697 for (
unsigned int i = 2; i < height-2; i++) {
698 for (
unsigned int j = 2; j < width-2; j++) {
699 if (i % 2 == 0 && j % 2 == 0) {
700 rgba[(i*width + j) * 4 + 0] = demosaicCheckerMalvar(bggr, width, i, j);
701 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
702 rgba[(i*width + j) * 4 + 2] = bggr[i*width + j];
703 }
else if (i % 2 == 0 && j % 2 != 0) {
704 rgba[(i*width + j) * 4 + 0] = demosaicPhiMalvar(bggr, width, i, j);
705 rgba[(i*width + j) * 4 + 1] = bggr[i*width + j];
706 rgba[(i*width + j) * 4 + 2] = demosaicThetaMalvar(bggr, width, i, j);
707 }
else if (i % 2 != 0 && j % 2 == 0) {
708 rgba[(i*width + j) * 4 + 0] = demosaicThetaMalvar(bggr, width, i, j);
709 rgba[(i*width + j) * 4 + 1] = bggr[i*width + j];
710 rgba[(i*width + j) * 4 + 2] = demosaicPhiMalvar(bggr, width, i, j);
712 rgba[(i*width + j) * 4 + 0] = bggr[i*width + j];
713 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
714 rgba[(i*width + j) * 4 + 2] = demosaicCheckerMalvar(bggr, width, i, j);
721 void demosaicGBRGToRGBaMalvarTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
723 m_assert(
"width must be >= 4", width >= 4);
724 m_assert(
"height must be >= 4", height >= 4);
725 m_assert(
"width must be a multiple of 2", width % 2 == 0);
726 m_assert(
"height must be a multiple of 2", height % 2 == 0);
729 rgba[0] = gbrg[width];
734 rgba[(width-1)*4 + 0] = gbrg[2*width - 2];
735 rgba[(width-1)*4 + 1] = gbrg[width - 2];
736 rgba[(width-1)*4 + 2] = gbrg[width - 1];
739 rgba[((height-1)*width)*4 + 0] = gbrg[(height-1)*width];
740 rgba[((height-1)*width)*4 + 1] = gbrg[(height-1)*width + 1];
741 rgba[((height-1)*width)*4 + 2] = gbrg[(height-2)*width + 1];
744 rgba[((height-1)*width + width-1)*4 + 0] = gbrg[height*width - 2];
745 rgba[((height-1)*width + width-1)*4 + 1] = gbrg[height*width - 1];
746 rgba[((height-1)*width + width-1)*4 + 2] = gbrg[(height-1)*width - 1];
749 for (
unsigned int j = 1; j < width-1; j++) {
751 rgba[j*4 + 0] = gbrg[width + j];
752 rgba[j*4 + 1] = gbrg[j];
753 rgba[j*4 + 2] =
static_cast<T
>(0.5f*gbrg[j - 1] + 0.5f*gbrg[j + 1]);
755 rgba[j*4 + 0] =
static_cast<T
>(0.5f*gbrg[width + j - 1] + 0.5f*gbrg[width + j + 1]);
756 rgba[j*4 + 1] =
static_cast<T
>(0.5f*gbrg[j - 1] + 0.5f*gbrg[j + 1]);
757 rgba[j*4 + 2] = gbrg[j];
762 for (
unsigned int j = 1; j < width-1; j++) {
764 rgba[(width + j)*4 + 0] = gbrg[width + j];
765 rgba[(width + j)*4 + 1] = static_cast<T>(0.25f*gbrg[j] + 0.25f*gbrg[width + j - 1] + 0.25f*gbrg[width + j + 1] + 0.25f*gbrg[2*width + j]);
766 rgba[(width + j)*4 + 2] = static_cast<T>(0.25f*gbrg[j - 1] + 0.25f*gbrg[j + 1] + 0.25f*gbrg[2*width + j - 1] + 0.25f*gbrg[2*width + j + 1]);
768 rgba[(width + j)*4 + 0] = static_cast<T>(0.5f*gbrg[width + j - 1] + 0.5f*gbrg[width + j + 1]);
769 rgba[(width + j)*4 + 1] = gbrg[width + j];
770 rgba[(width + j)*4 + 2] = static_cast<T>(0.5f*gbrg[j] + 0.5f*gbrg[2*width + j]);
775 for (
unsigned int i = 1; i < height-1; i++) {
777 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*gbrg[(i-1)*width] + 0.5f*gbrg[(i+1)*width]);
778 rgba[i*width*4 + 1] = gbrg[i*width];
779 rgba[i*width*4 + 2] = gbrg[i*width + 1];
781 rgba[i*width*4 + 0] = gbrg[i*width];
782 rgba[i*width*4 + 1] =
static_cast<T
>(0.5f*gbrg[(i-1)*width] + 0.5f*gbrg[(i+1)*width]);
783 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*gbrg[(i-1)*width + 1] + 0.5f*gbrg[(i+1)*width + 1]);
788 for (
unsigned int i = 1; i < height-1; i++) {
790 rgba[(i*width + 1)*4 + 0] = static_cast<T>(0.25f*gbrg[(i-1)*width] + 0.25f*gbrg[(i-1)*width + 2] + 0.25f*gbrg[(i+1)*width] + 0.5f*gbrg[(i+1)*width + 2]);
791 rgba[(i*width + 1)*4 + 1] = static_cast<T>(0.25f*gbrg[(i-1)*width + 1] + 0.25f*gbrg[i*width] + 0.25f*gbrg[i*width + 2] + 0.5f*gbrg[(i+1)*width + 1]);
792 rgba[(i*width + 1)*4 + 2] = gbrg[i*width + 1];
794 rgba[(i*width + 1)*4 + 0] = static_cast<T>(0.5f*gbrg[i*width] + 0.5f*gbrg[i*width + 2]);
795 rgba[(i*width + 1)*4 + 1] = gbrg[i*width + 1];
796 rgba[(i*width + 1)*4 + 2] = static_cast<T>(0.5f*gbrg[(i-1)*width + 1] + 0.5f*gbrg[(i+1)*width + 1]);
801 for (
unsigned int i = 1; i < height-1; i++) {
803 rgba[(i*width + width-2)*4 + 0] = static_cast<T>(0.5f*gbrg[i*width - 2] + 0.5f*gbrg[(i+2)*width - 2]);
804 rgba[(i*width + width-2)*4 + 1] = gbrg[(i+1)*width - 2];
805 rgba[(i*width + width-2)*4 + 2] = static_cast<T>(0.5f*gbrg[(i+1)*width - 3] + 0.5f*gbrg[(i+1)*width - 1]);
807 rgba[(i*width + width-2)*4 + 0] = gbrg[(i+1)*width - 2];
808 rgba[(i*width + width-2)*4 + 1] = static_cast<T>(0.25f*gbrg[i*width - 2] + 0.25f*gbrg[(i+1)*width - 3] +
809 0.25f*gbrg[(i+1)*width - 1] + 0.25f*gbrg[(i+2)*width - 2]);
810 rgba[(i*width + width-2)*4 + 2] = static_cast<T>(0.25f*gbrg[i*width - 3] + 0.25f*gbrg[i*width - 1] +
811 0.25f*gbrg[(i+2)*width - 3] + 0.25f*gbrg[(i+2)*width - 1]);
816 for (
unsigned int i = 1; i < height-1; i++) {
818 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*gbrg[i*width - 2] + 0.5f*gbrg[(i+2)*width - 2]);
819 rgba[(i*width + width-1)*4 + 1] = gbrg[(i+1)*width - 2];
820 rgba[(i*width + width-1)*4 + 2] = gbrg[(i+1)*width - 1];
822 rgba[(i*width + width-1)*4 + 0] = gbrg[(i+1)*width - 2];
823 rgba[(i*width + width-1)*4 + 1] = gbrg[(i+1)*width - 1];
824 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*gbrg[i*width - 1] + 0.5f*gbrg[(i+2)*width - 1]);
829 for (
unsigned int j = 1; j < width-1; j++) {
831 rgba[((height-2)*width + j)*4 + 0] =
static_cast<T
>(0.5f*gbrg[(height-3)*width + j] + 0.5f*gbrg[(height-1)*width + j]);
832 rgba[((height-2)*width + j)*4 + 1] = gbrg[(height-2)*width + j];
833 rgba[((height-2)*width + j)*4 + 2] =
static_cast<T
>(0.5f*gbrg[(height-2)*width + j - 1] + 0.5f*gbrg[(height-2)*width + j + 1]);
835 rgba[((height-2)*width + j)*4 + 0] =
static_cast<T
>(0.25f*gbrg[(height-3)*width + j - 1] + 0.25f*gbrg[(height-3)*width + j + 1] +
836 0.25f*gbrg[(height-1)*width + j - 1] + 0.25f*gbrg[(height-1)*width + j + 1]);
837 rgba[((height-2)*width + j)*4 + 1] =
static_cast<T
>(0.25f*gbrg[(height-3)*width + j] + 0.25f*gbrg[(height-2)*width + j - 1] +
838 0.25f*gbrg[(height-2)*width + j + 1] + 0.25f*gbrg[(height-1)*width + j]);
839 rgba[((height-2)*width + j)*4 + 2] = gbrg[(height-2)*width + j];
844 for (
unsigned int j = 1; j < width-1; j++) {
846 rgba[((height-1)*width + j)*4 + 0] = gbrg[(height-1)*width + j];
847 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*gbrg[(height-1)*width + j - 1] + 0.5f*gbrg[(height-1)*width + j + 1]);
848 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*gbrg[(height-2)*width + j - 1] + 0.5f*gbrg[(height-2)*width + j + 1]);
850 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*gbrg[(height-1)*width + j - 1] + 0.5f*gbrg[(height-1)*width + j + 1]);
851 rgba[((height-1)*width + j)*4 + 1] = gbrg[(height-1)*width + j];
852 rgba[((height-1)*width + j)*4 + 2] = gbrg[(height-2)*width + j];
856 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 858 omp_set_num_threads(static_cast<int>(nThreads));
860 #pragma omp parallel for schedule(dynamic) 864 for (
unsigned int i = 2; i < height-2; i++) {
865 for (
unsigned int j = 2; j < width-2; j++) {
866 if (i % 2 == 0 && j % 2 == 0) {
867 rgba[(i*width + j) * 4 + 0] = demosaicPhiMalvar(gbrg, width, i, j);
868 rgba[(i*width + j) * 4 + 1] = gbrg[i*width + j];
869 rgba[(i*width + j) * 4 + 2] = demosaicThetaMalvar(gbrg, width, i, j);
870 }
else if (i % 2 == 0 && j % 2 != 0) {
871 rgba[(i*width + j) * 4 + 0] = demosaicCheckerMalvar(gbrg, width, i, j);
872 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
873 rgba[(i*width + j) * 4 + 2] = gbrg[i*width + j];
874 }
else if (i % 2 != 0 && j % 2 == 0) {
875 rgba[(i*width + j) * 4 + 0] = gbrg[i*width + j];
876 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
877 rgba[(i*width + j) * 4 + 2] = demosaicCheckerMalvar(gbrg, width, i, j);
879 rgba[(i*width + j) * 4 + 0] = demosaicThetaMalvar(gbrg, width, i, j);
880 rgba[(i*width + j) * 4 + 1] = gbrg[i*width + j];
881 rgba[(i*width + j) * 4 + 2] = demosaicPhiMalvar(gbrg, width, i, j);
888 void demosaicGRBGToRGBaMalvarTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
890 m_assert(
"width must be >= 4", width >= 4);
891 m_assert(
"height must be >= 4", height >= 4);
892 m_assert(
"width must be a multiple of 2", width % 2 == 0);
893 m_assert(
"height must be a multiple of 2", height % 2 == 0);
898 rgba[2] = grbg[width];
901 rgba[(width-1)*4 + 0] = grbg[width - 1];
902 rgba[(width-1)*4 + 1] = grbg[width - 2];
903 rgba[(width-1)*4 + 2] = grbg[2*width - 2];
906 rgba[((height-1)*width)*4 + 0] = grbg[(height-2)*width + 1];
907 rgba[((height-1)*width)*4 + 1] = grbg[(height-1)*width + 1];
908 rgba[((height-1)*width)*4 + 2] = grbg[(height-1)*width];
911 rgba[((height-1)*width + width-1)*4 + 0] = grbg[(height-1)*width - 1];
912 rgba[((height-1)*width + width-1)*4 + 1] = grbg[height*width - 1];
913 rgba[((height-1)*width + width-1)*4 + 2] = grbg[height*width - 2];
916 for (
unsigned int j = 1; j < width-1; j++) {
918 rgba[j*4 + 0] =
static_cast<T
>(0.5f*grbg[j - 1] + 0.5f*grbg[j + 1]);
919 rgba[j*4 + 1] = grbg[j];
920 rgba[j*4 + 2] = grbg[width + j];
922 rgba[j*4 + 0] = grbg[j];
923 rgba[j*4 + 1] =
static_cast<T
>(0.5f*grbg[j - 1] + 0.5f*grbg[j + 1]);
924 rgba[j*4 + 2] =
static_cast<T
>(0.5f*grbg[width + j - 1] + 0.5f*grbg[width + j + 1]);
929 for (
unsigned int j = 1; j < width-1; j++) {
931 rgba[(width + j)*4 + 0] = static_cast<T>(0.25f*grbg[j - 1] + 0.25f*grbg[j + 1] + 0.25f*grbg[2*width + j - 1] + 0.25f*grbg[2*width + j + 1]);
932 rgba[(width + j)*4 + 1] = static_cast<T>(0.25f*grbg[j] + 0.25f*grbg[width + j - 1] + 0.25f*grbg[width + j + 1] + 0.25f*grbg[2*width + j]);
933 rgba[(width + j)*4 + 2] = grbg[width + j];
935 rgba[(width + j)*4 + 0] = static_cast<T>(0.5f*grbg[j] + 0.5f*grbg[2*width + j]);
936 rgba[(width + j)*4 + 1] = grbg[width + j];
937 rgba[(width + j)*4 + 2] = static_cast<T>(0.5f*grbg[width + j - 1] + 0.5f*grbg[width + j + 1]);
942 for (
unsigned int i = 1; i < height-1; i++) {
944 rgba[i*width*4 + 0] = grbg[i*width + 1];
945 rgba[i*width*4 + 1] = grbg[i*width];
946 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*grbg[(i-1)*width] + 0.5f*grbg[(i+1)*width]);
948 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*grbg[(i-1)*width + 1] + 0.5f*grbg[(i+1)*width + 1]);
949 rgba[i*width*4 + 1] = grbg[i*width + 1];
950 rgba[i*width*4 + 2] = grbg[i*width];
955 for (
unsigned int i = 1; i < height-1; i++) {
957 rgba[(i*width + 1)*4 + 0] = grbg[i*width + 1];
958 rgba[(i*width + 1)*4 + 1] = static_cast<T>(0.25f*grbg[(i-1)*width + 1] + 0.25f*grbg[i*width] + 0.25f*grbg[i*width + 2] + 0.25f*grbg[(i+1)*width + 1]);
959 rgba[(i*width + 1)*4 + 2] = static_cast<T>(0.25f*grbg[(i-1)*width] + 0.25f*grbg[(i-1)*width + 2] + 0.25f*grbg[(i+1)*width] + 0.25f*grbg[(i+1)*width + 2]);
961 rgba[(i*width + 1)*4 + 0] = static_cast<T>(0.5f*grbg[(i-1)*width + 1] + 0.5f*grbg[(i+1)*width + 1]);
962 rgba[(i*width + 1)*4 + 1] = grbg[i*width + 1];
963 rgba[(i*width + 1)*4 + 2] = static_cast<T>(0.5f*grbg[i*width] + 0.5f*grbg[i*width + 2]);
968 for (
unsigned int i = 1; i < height-1; i++) {
970 rgba[(i*width + width-2)*4 + 0] = static_cast<T>(0.5f*grbg[(i+1)*width - 3] + 0.5f*grbg[(i+1)*width - 1]);
971 rgba[(i*width + width-2)*4 + 1] = grbg[(i+1)*width - 2];
972 rgba[(i*width + width-2)*4 + 2] = static_cast<T>(0.5f*grbg[i*width - 2] + 0.5f*grbg[(i+2)*width - 2]);
974 rgba[(i*width + width-2)*4 + 0] = static_cast<T>(0.25f*grbg[i*width - 3] + 0.25f*grbg[i*width - 1] + 0.25f*grbg[(i+2)*width - 3] + 0.25f*grbg[(i+2)*width - 1]);
975 rgba[(i*width + width-2)*4 + 1] = static_cast<T>(0.25f*grbg[i*width - 2] + 0.25f*grbg[(i+1)*width - 3] + 0.25f*grbg[(i+1)*width - 1] + 0.25f*grbg[(i+2)*width - 2]);
976 rgba[(i*width + width-2)*4 + 2] = grbg[(i+1)*width - 2];
981 for (
unsigned int i = 1; i < height-1; i++) {
983 rgba[(i*width + width-1)*4 + 0] = grbg[(i+1)*width - 1];
984 rgba[(i*width + width-1)*4 + 1] = grbg[(i+1)*width - 2];
985 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*grbg[i*width - 2] + 0.5f*grbg[(i+2)*width - 2]);
987 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*grbg[i*width - 1] + 0.5f*grbg[(i+2)*width - 1]);
988 rgba[(i*width + width-1)*4 + 1] = grbg[(i+1)*width - 1];
989 rgba[(i*width + width-1)*4 + 2] = grbg[(i+1)*width - 2];
994 for (
unsigned int j = 1; j < width-1; j++) {
996 rgba[((height-2)*width + j)*4 + 0] =
static_cast<T
>(0.5f*grbg[(height-2)*width + j - 1] + 0.5f*grbg[(height-2)*width + j + 1]);
997 rgba[((height-2)*width + j)*4 + 1] = grbg[(height-2)*width + j];
998 rgba[((height-2)*width + j)*4 + 2] =
static_cast<T
>(0.5f*grbg[(height-3)*width + j] + 0.5f*grbg[(height-1)*width + j]);
1000 rgba[((height-2)*width + j)*4 + 0] = grbg[(height-2)*width + j];
1001 rgba[((height-2)*width + j)*4 + 1] =
static_cast<T
>(0.25f*grbg[(height-3)*width + j] + 0.25f*grbg[(height-2)*width + j - 1] +
1002 0.25f*grbg[(height-2)*width + j + 1] + 0.25f*grbg[(height-1)*width + j]);
1003 rgba[((height-2)*width + j)*4 + 2] =
static_cast<T
>(0.25f*grbg[(height-3)*width + j - 1] + 0.25f*grbg[(height-3)*width + j + 1] +
1004 0.25f*grbg[(height-1)*width + j - 1] + 0.25f*grbg[(height-1)*width + j + 1]);
1009 for (
unsigned int j = 1; j < width-1; j++) {
1011 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*grbg[(height-2)*width + j - 1] + 0.5f*grbg[(height-2)*width + j + 1]);
1012 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*grbg[(height-1)*width + j - 1] + 0.5f*grbg[(height-1)*width + j + 1]);
1013 rgba[((height-1)*width + j)*4 + 2] = grbg[(height-1)*width + j];
1015 rgba[((height-1)*width + j)*4 + 0] = grbg[(height-2)*width + j];
1016 rgba[((height-1)*width + j)*4 + 1] = grbg[(height-1)*width + j];
1017 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*grbg[(height-1)*width + j - 1] + 0.5f*grbg[(height-1)*width + j + 1]);
1021 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 1023 omp_set_num_threads(static_cast<int>(nThreads));
1025 #pragma omp parallel for schedule(dynamic) 1029 for (
unsigned int i = 2; i < height-2; i++) {
1030 for (
unsigned int j = 2; j < width-2; j++) {
1031 if (i % 2 == 0 && j % 2 == 0) {
1032 rgba[(i*width + j) * 4 + 0] = demosaicThetaMalvar(grbg, width, i, j);
1033 rgba[(i*width + j) * 4 + 1] = grbg[i*width + j];
1034 rgba[(i*width + j) * 4 + 2] = demosaicPhiMalvar(grbg, width, i, j);
1035 }
else if (i % 2 == 0 && j % 2 != 0) {
1036 rgba[(i*width + j) * 4 + 0] = grbg[i*width + j];
1037 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1038 rgba[(i*width + j) * 4 + 2] = demosaicCheckerMalvar(grbg, width, i, j);
1039 }
else if (i % 2 != 0 && j % 2 == 0) {
1040 rgba[(i*width + j) * 4 + 0] = demosaicCheckerMalvar(grbg, width, i, j);
1041 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1042 rgba[(i*width + j) * 4 + 2] = grbg[i*width + j];
1044 rgba[(i*width + j) * 4 + 0] = demosaicPhiMalvar(grbg, width, i, j);
1045 rgba[(i*width + j) * 4 + 1] = grbg[i*width + j];
1046 rgba[(i*width + j) * 4 + 2] = demosaicThetaMalvar(grbg, width, i, j);
1052 template<
typename T>
1053 void demosaicRGGBToRGBaMalvarTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1055 m_assert(
"width must be >= 4", width >= 4);
1056 m_assert(
"height must be >= 4", height >= 4);
1057 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1058 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1063 rgba[2] = rggb[width + 1];
1066 rgba[(width-1)*4 + 0] = rggb[width - 2];
1067 rgba[(width-1)*4 + 1] = rggb[width - 1];
1068 rgba[(width-1)*4 + 2] = rggb[2*width - 1];
1071 rgba[((height-1)*width)*4 + 0] = rggb[(height-2)*width];
1072 rgba[((height-1)*width)*4 + 1] = rggb[(height-1)*width];
1073 rgba[((height-1)*width)*4 + 2] = rggb[(height-1)*width + 1];
1076 rgba[((height-1)*width + width-1)*4 + 0] = rggb[(height-1)*width - 2];
1077 rgba[((height-1)*width + width-1)*4 + 1] = rggb[height*width - 2];
1078 rgba[((height-1)*width + width-1)*4 + 2] = rggb[height*width - 1];
1081 for (
unsigned int j = 1; j < width-1; j++) {
1083 rgba[j*4 + 0] = rggb[j];
1084 rgba[j*4 + 1] =
static_cast<T
>(0.5f*rggb[j - 1] + 0.5f*rggb[j + 1]);
1085 rgba[j*4 + 2] =
static_cast<T
>(0.5f*rggb[width + j - 1] + 0.5f*rggb[width + j + 1]);
1087 rgba[j*4 + 0] =
static_cast<T
>(0.5f*rggb[j - 1] + 0.5f*rggb[j + 1]);
1088 rgba[j*4 + 1] = rggb[j];
1089 rgba[j*4 + 2] = rggb[width + j];
1094 for (
unsigned int j = 1; j < width-1; j++) {
1096 rgba[(width + j)*4 + 0] = static_cast<T>(0.5f*rggb[j] + 0.5f*rggb[2*width + j]);
1097 rgba[(width + j)*4 + 1] = rggb[width + j];
1098 rgba[(width + j)*4 + 2] = static_cast<T>(0.5f*rggb[width + j - 1] + 0.5f*rggb[width + j + 1]);
1100 rgba[(width + j)*4 + 0] = static_cast<T>(0.25f*rggb[j - 1] + 0.25f*rggb[j + 1] + 0.25f*rggb[2*width + j - 1] + 0.25f*rggb[2*width + j + 1]);
1101 rgba[(width + j)*4 + 1] = static_cast<T>(0.25f*rggb[j] + 0.25f*rggb[width + j - 1] + 0.25f*rggb[width + j + 1] + 0.25f*rggb[2*width + j]);
1102 rgba[(width + j)*4 + 2] = rggb[width + j];
1107 for (
unsigned int i = 1; i < height-1; i++) {
1109 rgba[i*width*4 + 0] = rggb[i*width];
1110 rgba[i*width*4 + 1] = rggb[i*width + 1];
1111 rgba[i*width*4 + 2] =
static_cast<T
>(0.5f*rggb[(i-1)*width + 1] + 0.5f*rggb[(i+1)*width + 1]);
1113 rgba[i*width*4 + 0] =
static_cast<T
>(0.5f*rggb[(i-1)*width] + 0.5f*rggb[(i+1)*width]);
1114 rgba[i*width*4 + 1] = rggb[i*width];
1115 rgba[i*width*4 + 2] = rggb[i*width + 1];
1120 for (
unsigned int i = 1; i < height-1; i++) {
1122 rgba[(i*width + 1)*4 + 0] = static_cast<T>(0.5f*rggb[i*width] + 0.5f*rggb[i*width + 2]);
1123 rgba[(i*width + 1)*4 + 1] = rggb[i*width + 1];
1124 rgba[(i*width + 1)*4 + 2] = static_cast<T>(0.5f*rggb[(i-1)*width + 1] + 0.5f*rggb[(i+1)*width + 1]);
1126 rgba[(i*width + 1)*4 + 0] = static_cast<T>(0.25f*rggb[(i-1)*width] + 0.25f*rggb[(i-1)*width + 2] + 0.25f*rggb[(i+1)*width] + 0.25f*rggb[(i+1)*width + 2]);
1127 rgba[(i*width + 1)*4 + 1] = static_cast<T>(0.25f*rggb[(i-1)*width + 1] + 0.25f*rggb[i*width] + 0.25f*rggb[i*width + 2] + 0.25f*rggb[(i+1)*width + 1]);
1128 rgba[(i*width + 1)*4 + 2] = rggb[i*width + 1];
1133 for (
unsigned int i = 1; i < height-1; i++) {
1135 rgba[(i*width + width-2)*4 + 0] = rggb[(i+1)*width - 2];
1136 rgba[(i*width + width-2)*4 + 1] = static_cast<T>(0.25f*rggb[i*width - 2] + 0.25f*rggb[(i+1)*width - 3] + 0.25f*rggb[(i+1)*width - 1] + 0.25f*rggb[(i+2)*width - 2]);
1137 rgba[(i*width + width-2)*4 + 2] = static_cast<T>(0.25f*rggb[i*width - 3] + 0.25f*rggb[i*width - 1] + 0.25f*rggb[(i+2)*width - 3] + 0.25f*rggb[(i+2)*width - 1]);
1139 rgba[(i*width + width-2)*4 + 0] = static_cast<T>(0.5f*rggb[i*width - 2] + 0.5f*rggb[(i+2)*width - 2]);
1140 rgba[(i*width + width-2)*4 + 1] = rggb[(i+1)*width - 2];
1141 rgba[(i*width + width-2)*4 + 2] = static_cast<T>(0.5f*rggb[(i+1)*width - 3] + 0.5f*rggb[(i+1)*width - 1]);
1146 for (
unsigned int i = 1; i < height-1; i++) {
1148 rgba[(i*width + width-1)*4 + 0] = rggb[(i+1)*width - 2];
1149 rgba[(i*width + width-1)*4 + 1] = rggb[(i+1)*width - 1];
1150 rgba[(i*width + width-1)*4 + 2] = static_cast<T>(0.5f*rggb[i*width - 1] + 0.5f*rggb[(i+2)*width - 1]);
1152 rgba[(i*width + width-1)*4 + 0] = static_cast<T>(0.5f*rggb[i*width - 2] + 0.5f*rggb[(i+2)*width - 2]);
1153 rgba[(i*width + width-1)*4 + 1] = rggb[(i+1)*width - 2];
1154 rgba[(i*width + width-1)*4 + 2] = rggb[(i+1)*width - 1];
1159 for (
unsigned int j = 1; j < width-1; j++) {
1161 rgba[((height-2)*width + j)*4 + 0] = rggb[(height-2)*width + j];
1162 rgba[((height-2)*width + j)*4 + 1] =
static_cast<T
>(0.25f*rggb[(height-3)*width + j] + 0.25f*rggb[(height-2)*width + j - 1] +
1163 0.25f*rggb[(height-2)*width + j + 1] + 0.25f*rggb[(height-1)*width + j]);
1164 rgba[((height-2)*width + j)*4 + 2] =
static_cast<T
>(0.25f*rggb[(height-3)*width + j - 1] + 0.25f*rggb[(height-3)*width + j + 1] +
1165 0.25f*rggb[(height-1)*width + j - 1] + 0.25f*rggb[(height-1)*width + j + 1]);
1167 rgba[((height-2)*width + j)*4 + 0] =
static_cast<T
>(0.5f*rggb[(height-2)*width + j - 1] + 0.5f*rggb[(height-2)*width + j + 1]);
1168 rgba[((height-2)*width + j)*4 + 1] = rggb[(height-2)*width + j];
1169 rgba[((height-2)*width + j)*4 + 2] =
static_cast<T
>(0.5f*rggb[(height-3)*width + j] + 0.5f*rggb[(height-1)*width + j]);
1174 for (
unsigned int j = 1; j < width-1; j++) {
1176 rgba[((height-1)*width + j)*4 + 0] = rggb[(height-2)*width + j];
1177 rgba[((height-1)*width + j)*4 + 1] = rggb[(height-1)*width + j];
1178 rgba[((height-1)*width + j)*4 + 2] =
static_cast<T
>(0.5f*rggb[(height-1)*width + j - 1] + 0.5f*rggb[(height-1)*width + j + 1]);
1180 rgba[((height-1)*width + j)*4 + 0] =
static_cast<T
>(0.5f*rggb[(height-2)*width + j - 1] + 0.5f*rggb[(height-2)*width + j + 1]);
1181 rgba[((height-1)*width + j)*4 + 1] =
static_cast<T
>(0.5f*rggb[(height-1)*width + j - 1] + 0.5f*rggb[(height-1)*width + j + 1]);
1182 rgba[((height-1)*width + j)*4 + 2] = rggb[(height-1)*width + j];
1186 #if defined _OPENMP && _OPENMP >= 200711 // OpenMP 3.1 1188 omp_set_num_threads(static_cast<int>(nThreads));
1190 #pragma omp parallel for schedule(dynamic) 1194 for (
unsigned int i = 2; i < height-2; i++) {
1195 for (
unsigned int j = 2; j < width-2; j++) {
1196 if (i % 2 == 0 && j % 2 == 0) {
1197 rgba[(i*width + j) * 4 + 0] = rggb[i*width + j];
1198 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1199 rgba[(i*width + j) * 4 + 2] = demosaicCheckerMalvar(rggb, width, i, j);
1200 }
else if (i % 2 == 0 && j % 2 != 0) {
1201 rgba[(i*width + j) * 4 + 0] = demosaicThetaMalvar(rggb, width, i, j);
1202 rgba[(i*width + j) * 4 + 1] = rggb[i*width + j];
1203 rgba[(i*width + j) * 4 + 2] = demosaicPhiMalvar(rggb, width, i, j);
1204 }
else if (i % 2 != 0 && j % 2 == 0) {
1205 rgba[(i*width + j) * 4 + 0] = demosaicPhiMalvar(rggb, width, i, j);
1206 rgba[(i*width + j) * 4 + 1] = rggb[i*width + j];
1207 rgba[(i*width + j) * 4 + 2] = demosaicThetaMalvar(rggb, width, i, j);
1209 rgba[(i*width + j) * 4 + 0] = demosaicCheckerMalvar(rggb, width, i, j);
1210 rgba[(i*width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1211 rgba[(i*width + j) * 4 + 2] = rggb[i*width + j];