39#ifndef vpBAYERCONVERSION_H
40#define vpBAYERCONVERSION_H
42#include <visp3/core/vpConfig.h>
44#ifndef VISP_SKIP_BAYER_CONVERSION
48#include <visp3/core/vpMath.h>
52#define m_assert(msg, expr) assert(((void)(msg), (expr)))
55template <
typename T> T demosaicPhiBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
57 return static_cast<T
>(0.5f * bayer[(
i - 1) *
width +
j] + 0.5f * bayer[(
i + 1) *
width +
j]);
60template <
typename T> 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]);
65template <
typename T> T demosaicCheckerBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
67 return static_cast<T
>(0.25f * bayer[(
i - 1) *
width +
j - 1] + 0.25f * bayer[(
i - 1) *
width +
j + 1] +
68 0.25f * bayer[(
i + 1) *
width +
j - 1] + 0.25f * bayer[(
i + 1) *
width +
j + 1]);
71template <
typename T> T demosaicCrossBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
73 return static_cast<T
>(0.25f * bayer[(
i - 1) *
width +
j] + 0.25f * bayer[
i *
width +
j - 1] +
74 0.25f * bayer[
i *
width +
j + 1] + 0.25f * bayer[(
i + 1) *
width +
j]);
78template <
typename T> T demosaicPhiMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
81 (-bayer[(i - 2) * width + j] - bayer[(i - 1) * width + j - 1] + 4 * bayer[(i - 1) * width + j] -
82 bayer[(i - 1) * width + j + 1] + 0.5f * bayer[i * width + j - 2] + 5 * bayer[i * width + j] +
83 0.5f * bayer[i * width + j + 2] - bayer[(i + 1) * width + j - 1] + 4 * bayer[(i + 1) * width + j] -
84 bayer[(i + 1) * width + j + 1] - bayer[(i + 2) * width + j]) *
88template <
typename T> T demosaicThetaMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
90 return VISP_NAMESPACE_ADDRESSING
vpMath::saturate<T>((0.5f * bayer[(i - 2) * width + j] - bayer[(i - 1) * width + j - 1] -
91 bayer[(i - 1) * width + j + 1] - bayer[i * width + j - 2] + 4 * bayer[i * width + j - 1] +
92 5 * bayer[i * width + j] + 4 * bayer[i * width + j + 1] - bayer[i * width + j + 2] -
93 bayer[(i + 1) * width + j - 1] - bayer[(i + 1) * width + j + 1] +
94 0.5f * bayer[(i + 2) * width + j]) *
98template <
typename T> T demosaicCheckerMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
101 (-1.5f * bayer[(i - 2) * width + j] + 2 * bayer[(i - 1) * width + j - 1] + 2 * bayer[(i - 1) * width + j + 1] -
102 1.5f * bayer[i * width + j - 2] + 6 * bayer[i * width + j] - 1.5f * bayer[i * width + j + 2] +
103 2 * bayer[(i + 1) * width + j - 1] + 2 * bayer[(i + 1) * width + j + 1] - 1.5f * bayer[(i + 2) * width + j]) *
107template <
typename T> T demosaicCrossMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
109 return VISP_NAMESPACE_ADDRESSING
vpMath::saturate<T>((-bayer[(i - 2) * width + j] + 2 * bayer[(i - 1) * width + j] - bayer[i * width + j - 2] +
110 2 * bayer[i * width + j - 1] + 4 * bayer[i * width + j] + 2 * bayer[i * width + j + 1] -
111 bayer[i * width + j + 2] + 2 * bayer[(i + 1) * width + j] - bayer[(i + 2) * width + j]) *
116void demosaicBGGRToRGBaBilinearTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
117 unsigned int nThreads)
119 m_assert(
"width must be >= 4", width >= 4);
120 m_assert(
"height must be >= 4", height >= 4);
121 m_assert(
"width must be a multiple of 2", width % 2 == 0);
122 m_assert(
"height must be a multiple of 2", height % 2 == 0);
125 rgba[0] = bggr[
width + 1];
130 rgba[(
width - 1) * 4 + 0] = bggr[2 * width - 1];
131 rgba[(
width - 1) * 4 + 1] = bggr[width - 1];
132 rgba[(
width - 1) * 4 + 2] = bggr[width - 2];
140 rgba[((
height - 1) *
width +
width - 1) * 4 + 0] = bggr[height * width - 1];
141 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = bggr[height * width - 2];
145 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
147 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * bggr[
width +
j - 1] + 0.5f * bggr[
width +
j + 1]);
148 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * bggr[
j - 1] + 0.5f * bggr[
j + 1]);
149 rgba[
j * 4 + 2] = bggr[
j];
152 rgba[
j * 4 + 0] = bggr[
width +
j];
153 rgba[
j * 4 + 1] = bggr[
j];
154 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * bggr[
j - 1] + 0.5f * bggr[
j + 1]);
159 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
161 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(
i - 1) *
width + 1] + 0.5f * bggr[(
i + 1) *
width + 1]);
168 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(
i - 1) *
width] + 0.5f * bggr[(
i + 1) *
width]);
173 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
176 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
184 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
189 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
192 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
199 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
201 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
205#if defined(_OPENMP) && (_OPENMP >= 200711)
207 omp_set_num_threads(
static_cast<int>(nThreads));
209#pragma omp parallel for schedule(dynamic)
213 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
214 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
215 if (i % 2 == 0 && j % 2 == 0) {
216 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerBilinear(bggr, width, i, j);
217 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
218 rgba[(
i *
width +
j) * 4 + 2] = bggr[i * width + j];
220 else if (i % 2 == 0 && j % 2 != 0) {
221 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiBilinear(bggr, width, i, j);
222 rgba[(
i *
width +
j) * 4 + 1] = bggr[i * width + j];
223 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaBilinear(bggr, width, i, j);
225 else if (i % 2 != 0 && j % 2 == 0) {
226 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaBilinear(bggr, width, i, j);
227 rgba[(
i *
width +
j) * 4 + 1] = bggr[i * width + j];
228 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiBilinear(bggr, width, i, j);
231 rgba[(
i *
width +
j) * 4 + 0] = bggr[i * width + j];
232 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
233 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerBilinear(bggr, width, i, j);
240void demosaicGBRGToRGBaBilinearTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
241 unsigned int nThreads)
243 m_assert(
"width must be >= 4", width >= 4);
244 m_assert(
"height must be >= 4", height >= 4);
245 m_assert(
"width must be a multiple of 2", width % 2 == 0);
246 m_assert(
"height must be a multiple of 2", height % 2 == 0);
249 rgba[0] = gbrg[
width];
254 rgba[(
width - 1) * 4 + 0] = gbrg[2 * width - 2];
255 rgba[(
width - 1) * 4 + 1] = gbrg[width - 2];
256 rgba[(
width - 1) * 4 + 2] = gbrg[width - 1];
264 rgba[((
height - 1) *
width +
width - 1) * 4 + 0] = gbrg[height * width - 2];
265 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = gbrg[height * width - 1];
269 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
271 rgba[
j * 4 + 0] = gbrg[
width +
j];
272 rgba[
j * 4 + 1] = gbrg[
j];
273 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[
j - 1] + 0.5f * gbrg[
j + 1]);
276 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[
width +
j - 1] + 0.5f * gbrg[
width +
j + 1]);
277 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[
j - 1] + 0.5f * gbrg[
j + 1]);
278 rgba[
j * 4 + 2] = gbrg[
j];
283 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
285 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(
i - 1) *
width] + 0.5f * gbrg[(
i + 1) *
width]);
291 rgba[
i *
width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(
i - 1) *
width] + 0.5f * gbrg[(
i + 1) *
width]);
292 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(
i - 1) *
width + 1] + 0.5f * gbrg[(
i + 1) *
width + 1]);
297 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
300 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
308 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
313 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
317 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
319 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
323 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
329#if defined(_OPENMP) && (_OPENMP >= 200711)
331 omp_set_num_threads(
static_cast<int>(nThreads));
333#pragma omp parallel for schedule(dynamic)
337 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
338 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
339 if (i % 2 == 0 && j % 2 == 0) {
340 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiBilinear(gbrg, width, i, j);
341 rgba[(
i *
width +
j) * 4 + 1] = gbrg[i * width + j];
342 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaBilinear(gbrg, width, i, j);
344 else if (i % 2 == 0 && j % 2 != 0) {
345 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerBilinear(gbrg, width, i, j);
346 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
347 rgba[(
i *
width +
j) * 4 + 2] = gbrg[i * width + j];
349 else if (i % 2 != 0 && j % 2 == 0) {
350 rgba[(
i *
width +
j) * 4 + 0] = gbrg[i * width + j];
351 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
352 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerBilinear(gbrg, width, i, j);
355 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaBilinear(gbrg, width, i, j);
356 rgba[(
i *
width +
j) * 4 + 1] = gbrg[i * width + j];
357 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiBilinear(gbrg, width, i, j);
364void demosaicGRBGToRGBaBilinearTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
365 unsigned int nThreads)
367 m_assert(
"width must be >= 4", width >= 4);
368 m_assert(
"height must be >= 4", height >= 4);
369 m_assert(
"width must be a multiple of 2", width % 2 == 0);
370 m_assert(
"height must be a multiple of 2", height % 2 == 0);
375 rgba[2] = grbg[
width];
378 rgba[(
width - 1) * 4 + 0] = grbg[width - 1];
379 rgba[(
width - 1) * 4 + 1] = grbg[width - 2];
380 rgba[(
width - 1) * 4 + 2] = grbg[2 * width - 2];
389 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = grbg[height * width - 1];
390 rgba[((
height - 1) *
width +
width - 1) * 4 + 2] = grbg[height * width - 2];
393 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
395 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * grbg[
j - 1] + 0.5f * grbg[
j + 1]);
396 rgba[
j * 4 + 1] = grbg[
j];
397 rgba[
j * 4 + 2] = grbg[
width +
j];
400 rgba[
j * 4 + 0] = grbg[
j];
401 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * grbg[
j - 1] + 0.5f * grbg[
j + 1]);
402 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * grbg[
width +
j - 1] + 0.5f * grbg[
width +
j + 1]);
407 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
411 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(
i - 1) *
width] + 0.5f * grbg[(
i + 1) *
width]);
414 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(
i - 1) *
width + 1] + 0.5f * grbg[(
i + 1) *
width + 1]);
421 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
426 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
430 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
437 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
440 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
442 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
449 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
453#if defined(_OPENMP) && (_OPENMP >= 200711)
455 omp_set_num_threads(
static_cast<int>(nThreads));
457#pragma omp parallel for schedule(dynamic)
461 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
462 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
463 if (i % 2 == 0 && j % 2 == 0) {
464 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaBilinear(grbg, width, i, j);
465 rgba[(
i *
width +
j) * 4 + 1] = grbg[i * width + j];
466 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiBilinear(grbg, width, i, j);
468 else if (i % 2 == 0 && j % 2 != 0) {
469 rgba[(
i *
width +
j) * 4 + 0] = grbg[i * width + j];
470 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
471 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerBilinear(grbg, width, i, j);
473 else if (i % 2 != 0 && j % 2 == 0) {
474 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerBilinear(grbg, width, i, j);
475 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
476 rgba[(
i *
width +
j) * 4 + 2] = grbg[i * width + j];
479 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiBilinear(grbg, width, i, j);
480 rgba[(
i *
width +
j) * 4 + 1] = grbg[i * width + j];
481 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaBilinear(grbg, width, i, j);
488void demosaicRGGBToRGBaBilinearTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
489 unsigned int nThreads)
491 m_assert(
"width must be >= 4", width >= 4);
492 m_assert(
"height must be >= 4", height >= 4);
493 m_assert(
"width must be a multiple of 2", width % 2 == 0);
494 m_assert(
"height must be a multiple of 2", height % 2 == 0);
499 rgba[2] = rggb[
width + 1];
502 rgba[(
width - 1) * 4 + 0] = rggb[width - 2];
503 rgba[(
width - 1) * 4 + 1] = rggb[width - 1];
504 rgba[(
width - 1) * 4 + 2] = rggb[2 * width - 1];
513 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = rggb[height * width - 2];
514 rgba[((
height - 1) *
width +
width - 1) * 4 + 2] = rggb[height * width - 1];
517 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
519 rgba[
j * 4 + 0] = rggb[
j];
520 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * rggb[
j - 1] + 0.5f * rggb[
j + 1]);
521 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * rggb[
width +
j - 1] + 0.5f * rggb[
width +
j + 1]);
524 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * rggb[
j - 1] + 0.5f * rggb[
j + 1]);
525 rgba[
j * 4 + 1] = rggb[
j];
526 rgba[
j * 4 + 2] = rggb[
width +
j];
531 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
535 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(
i - 1) *
width + 1] + 0.5f * rggb[(
i + 1) *
width + 1]);
538 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(
i - 1) *
width] + 0.5f * rggb[(
i + 1) *
width]);
545 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
550 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
554 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
561 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
566 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
570 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
572 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
577#if defined(_OPENMP) && (_OPENMP >= 200711)
579 omp_set_num_threads(
static_cast<int>(nThreads));
581#pragma omp parallel for schedule(dynamic)
585 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
586 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
587 if (i % 2 == 0 && j % 2 == 0) {
588 rgba[(
i *
width +
j) * 4 + 0] = rggb[i * width + j];
589 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
590 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerBilinear(rggb, width, i, j);
592 else if (i % 2 == 0 && j % 2 != 0) {
593 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaBilinear(rggb, width, i, j);
594 rgba[(
i *
width +
j) * 4 + 1] = rggb[i * width + j];
595 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiBilinear(rggb, width, i, j);
597 else if (i % 2 != 0 && j % 2 == 0) {
598 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiBilinear(rggb, width, i, j);
599 rgba[(
i *
width +
j) * 4 + 1] = rggb[i * width + j];
600 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaBilinear(rggb, width, i, j);
603 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerBilinear(rggb, width, i, j);
604 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
605 rgba[(
i *
width +
j) * 4 + 2] = rggb[i * width + j];
614void demosaicBGGRToRGBaMalvarTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
616 m_assert(
"width must be >= 4", width >= 4);
617 m_assert(
"height must be >= 4", height >= 4);
618 m_assert(
"width must be a multiple of 2", width % 2 == 0);
619 m_assert(
"height must be a multiple of 2", height % 2 == 0);
622 rgba[0] = bggr[
width + 1];
627 rgba[(
width - 1) * 4 + 0] = bggr[2 * width - 1];
628 rgba[(
width - 1) * 4 + 1] = bggr[width - 1];
629 rgba[(
width - 1) * 4 + 2] = bggr[width - 2];
637 rgba[((
height - 1) *
width +
width - 1) * 4 + 0] = bggr[height * width - 1];
638 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = bggr[height * width - 2];
642 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
644 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * bggr[
width +
j - 1] + 0.5f * bggr[
width +
j + 1]);
645 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * bggr[
j - 1] + 0.5f * bggr[
j + 1]);
646 rgba[
j * 4 + 2] = bggr[
j];
649 rgba[
j * 4 + 0] = bggr[
width +
j];
650 rgba[
j * 4 + 1] = bggr[
j];
651 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * bggr[
j - 1] + 0.5f * bggr[
j + 1]);
656 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
658 rgba[(
width +
j) * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
659 rgba[(
width +
j) * 4 + 1] = bggr[width + j];
660 rgba[(
width +
j) * 4 + 2] =
static_cast<T
>(0.5f * bggr[j] + 0.5f * bggr[2 * width + j]);
663 rgba[(
width +
j) * 4 + 0] = bggr[width + j];
664 rgba[(
width +
j) * 4 + 1] =
static_cast<T
>(0.25f * bggr[j] + 0.25f * bggr[width + j - 1] +
665 0.25f * bggr[width + j + 1] + 0.25f * bggr[2 * width + j]);
666 rgba[(
width +
j) * 4 + 2] =
static_cast<T
>(0.25f * bggr[j - 1] + 0.25f * bggr[j + 1] +
667 0.25f * bggr[2 * width + j - 1] + 0.25f * bggr[2 * width + j + 1]);
672 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
674 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(
i - 1) *
width + 1] + 0.5f * bggr[(
i + 1) *
width + 1]);
681 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(
i - 1) *
width] + 0.5f * bggr[(
i + 1) *
width]);
686 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
688 rgba[(
i *
width + 1) * 4 + 0] =
689 static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
690 rgba[(
i *
width + 1) * 4 + 1] = bggr[i * width + 1];
691 rgba[(
i *
width + 1) * 4 + 2] =
static_cast<T
>(0.5f * bggr[i * width] + 0.5f * bggr[i * width + 2]);
694 rgba[(
i *
width + 1) * 4 + 0] = bggr[i * width + 1];
695 rgba[(
i *
width + 1) * 4 + 1] =
static_cast<T
>(0.25f * bggr[(i - 1) * width + 1] + 0.25f * bggr[i * width] +
696 0.25f * bggr[i * width + 2] + 0.25f * bggr[(i + 1) * width + 1]);
697 rgba[(
i *
width + 1) * 4 + 2] =
static_cast<T
>(0.25f * bggr[(i - 1) * width] + 0.25f * bggr[(i - 1) * width + 2] +
698 0.25f * bggr[(i + 1) * width] + 0.25f * bggr[(i + 1) * width + 2]);
703 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
706 static_cast<T
>(0.25f * bggr[i * width - 3] + 0.25f * bggr[i * width - 1] + 0.25f * bggr[(i + 2) * width - 3] +
707 0.25f * bggr[(i + 2) * width - 1]);
709 static_cast<T
>(0.25f * bggr[i * width - 2] + 0.25f * bggr[(i + 1) * width - 3] +
710 0.25f * bggr[(i + 1) * width - 1] + 0.25f * bggr[(i + 2) * width - 2]);
715 static_cast<T
>(0.5f * bggr[(i + 1) * width - 3] + 0.5f * bggr[(i + 1) * width - 1]);
718 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
723 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
726 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
734 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
739 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
742 static_cast<T
>(0.25f * bggr[(height - 3) * width + j - 1] + 0.25f * bggr[(height - 3) * width + j + 1] +
743 0.25f * bggr[(height - 1) * width + j - 1] + 0.25f * bggr[(height - 1) * width + j + 1]);
745 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
750 static_cast<T
>(0.5f * bggr[(height - 3) * width + j] + 0.5f * bggr[(height - 1) * width + j]);
753 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
758 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
761 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
768 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
770 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
774#if defined(_OPENMP) && (_OPENMP >= 200711)
776 omp_set_num_threads(
static_cast<int>(nThreads));
778#pragma omp parallel for schedule(dynamic)
782 for (
unsigned int i = 2;
i <
height - 2; ++
i) {
783 for (
unsigned int j = 2;
j <
width - 2; ++
j) {
784 if (i % 2 == 0 && j % 2 == 0) {
785 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerMalvar(bggr, width, i, j);
786 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
787 rgba[(
i *
width +
j) * 4 + 2] = bggr[i * width + j];
789 else if (i % 2 == 0 && j % 2 != 0) {
790 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiMalvar(bggr, width, i, j);
791 rgba[(
i *
width +
j) * 4 + 1] = bggr[i * width + j];
792 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaMalvar(bggr, width, i, j);
794 else if (i % 2 != 0 && j % 2 == 0) {
795 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaMalvar(bggr, width, i, j);
796 rgba[(
i *
width +
j) * 4 + 1] = bggr[i * width + j];
797 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiMalvar(bggr, width, i, j);
800 rgba[(
i *
width +
j) * 4 + 0] = bggr[i * width + j];
801 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
802 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerMalvar(bggr, width, i, j);
809void demosaicGBRGToRGBaMalvarTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
811 m_assert(
"width must be >= 4", width >= 4);
812 m_assert(
"height must be >= 4", height >= 4);
813 m_assert(
"width must be a multiple of 2", width % 2 == 0);
814 m_assert(
"height must be a multiple of 2", height % 2 == 0);
817 rgba[0] = gbrg[
width];
822 rgba[(
width - 1) * 4 + 0] = gbrg[2 * width - 2];
823 rgba[(
width - 1) * 4 + 1] = gbrg[width - 2];
824 rgba[(
width - 1) * 4 + 2] = gbrg[width - 1];
832 rgba[((
height - 1) *
width +
width - 1) * 4 + 0] = gbrg[height * width - 2];
833 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = gbrg[height * width - 1];
837 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
839 rgba[
j * 4 + 0] = gbrg[
width +
j];
840 rgba[
j * 4 + 1] = gbrg[
j];
841 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[
j - 1] + 0.5f * gbrg[
j + 1]);
844 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[
width +
j - 1] + 0.5f * gbrg[
width +
j + 1]);
845 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[
j - 1] + 0.5f * gbrg[
j + 1]);
846 rgba[
j * 4 + 2] = gbrg[
j];
851 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
853 rgba[(
width +
j) * 4 + 0] = gbrg[width + j];
854 rgba[(
width +
j) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[j] + 0.25f * gbrg[width + j - 1] +
855 0.25f * gbrg[width + j + 1] + 0.25f * gbrg[2 * width + j]);
856 rgba[(
width +
j) * 4 + 2] =
static_cast<T
>(0.25f * gbrg[j - 1] + 0.25f * gbrg[j + 1] +
857 0.25f * gbrg[2 * width + j - 1] + 0.25f * gbrg[2 * width + j + 1]);
860 rgba[(
width +
j) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
861 rgba[(
width +
j) * 4 + 1] = gbrg[width + j];
862 rgba[(
width +
j) * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j] + 0.5f * gbrg[2 * width + j]);
867 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
869 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(
i - 1) *
width] + 0.5f * gbrg[(
i + 1) *
width]);
875 rgba[
i *
width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(
i - 1) *
width] + 0.5f * gbrg[(
i + 1) *
width]);
876 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(
i - 1) *
width + 1] + 0.5f * gbrg[(
i + 1) *
width + 1]);
881 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
883 rgba[(
i *
width + 1) * 4 + 0] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width] + 0.25f * gbrg[(i - 1) * width + 2] +
884 0.25f * gbrg[(i + 1) * width] + 0.5f * gbrg[(i + 1) * width + 2]);
885 rgba[(
i *
width + 1) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width + 1] + 0.25f * gbrg[i * width] +
886 0.25f * gbrg[i * width + 2] + 0.5f * gbrg[(i + 1) * width + 1]);
887 rgba[(
i *
width + 1) * 4 + 2] = gbrg[i * width + 1];
890 rgba[(
i *
width + 1) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[i * width] + 0.5f * gbrg[i * width + 2]);
891 rgba[(
i *
width + 1) * 4 + 1] = gbrg[i * width + 1];
892 rgba[(
i *
width + 1) * 4 + 2] =
893 static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
898 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
901 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
904 static_cast<T
>(0.5f * gbrg[(i + 1) * width - 3] + 0.5f * gbrg[(i + 1) * width - 1]);
909 static_cast<T
>(0.25f * gbrg[i * width - 2] + 0.25f * gbrg[(i + 1) * width - 3] +
910 0.25f * gbrg[(i + 1) * width - 1] + 0.25f * gbrg[(i + 2) * width - 2]);
912 static_cast<T
>(0.25f * gbrg[i * width - 3] + 0.25f * gbrg[i * width - 1] + 0.25f * gbrg[(i + 2) * width - 3] +
913 0.25f * gbrg[(i + 2) * width - 1]);
918 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
921 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
929 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
934 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
937 static_cast<T
>(0.5f * gbrg[(height - 3) * width + j] + 0.5f * gbrg[(height - 1) * width + j]);
940 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
944 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j - 1] + 0.25f * gbrg[(height - 3) * width + j + 1] +
945 0.25f * gbrg[(height - 1) * width + j - 1] + 0.25f * gbrg[(height - 1) * width + j + 1]);
947 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j] + 0.25f * gbrg[(height - 2) * width + j - 1] +
948 0.25f * gbrg[(height - 2) * width + j + 1] + 0.25f * gbrg[(height - 1) * width + j]);
954 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
958 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
960 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
964 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
970#if defined(_OPENMP) && (_OPENMP >= 200711)
972 omp_set_num_threads(
static_cast<int>(nThreads));
974#pragma omp parallel for schedule(dynamic)
978 for (
unsigned int i = 2;
i <
height - 2; ++
i) {
979 for (
unsigned int j = 2;
j <
width - 2; ++
j) {
980 if (i % 2 == 0 && j % 2 == 0) {
981 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiMalvar(gbrg, width, i, j);
982 rgba[(
i *
width +
j) * 4 + 1] = gbrg[i * width + j];
983 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaMalvar(gbrg, width, i, j);
985 else if (i % 2 == 0 && j % 2 != 0) {
986 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerMalvar(gbrg, width, i, j);
987 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
988 rgba[(
i *
width +
j) * 4 + 2] = gbrg[i * width + j];
990 else if (i % 2 != 0 && j % 2 == 0) {
991 rgba[(
i *
width +
j) * 4 + 0] = gbrg[i * width + j];
992 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
993 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerMalvar(gbrg, width, i, j);
996 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaMalvar(gbrg, width, i, j);
997 rgba[(
i *
width +
j) * 4 + 1] = gbrg[i * width + j];
998 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiMalvar(gbrg, width, i, j);
1004template <
typename T>
1005void demosaicGRBGToRGBaMalvarTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1007 m_assert(
"width must be >= 4", width >= 4);
1008 m_assert(
"height must be >= 4", height >= 4);
1009 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1010 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1015 rgba[2] = grbg[
width];
1018 rgba[(
width - 1) * 4 + 0] = grbg[width - 1];
1019 rgba[(
width - 1) * 4 + 1] = grbg[width - 2];
1020 rgba[(
width - 1) * 4 + 2] = grbg[2 * width - 2];
1029 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = grbg[height * width - 1];
1030 rgba[((
height - 1) *
width +
width - 1) * 4 + 2] = grbg[height * width - 2];
1033 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1035 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * grbg[
j - 1] + 0.5f * grbg[
j + 1]);
1036 rgba[
j * 4 + 1] = grbg[
j];
1037 rgba[
j * 4 + 2] = grbg[
width +
j];
1040 rgba[
j * 4 + 0] = grbg[
j];
1041 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * grbg[
j - 1] + 0.5f * grbg[
j + 1]);
1042 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * grbg[
width +
j - 1] + 0.5f * grbg[
width +
j + 1]);
1047 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1049 rgba[(
width +
j) * 4 + 0] =
static_cast<T
>(0.25f * grbg[j - 1] + 0.25f * grbg[j + 1] +
1050 0.25f * grbg[2 * width + j - 1] + 0.25f * grbg[2 * width + j + 1]);
1051 rgba[(
width +
j) * 4 + 1] =
static_cast<T
>(0.25f * grbg[j] + 0.25f * grbg[width + j - 1] +
1052 0.25f * grbg[width + j + 1] + 0.25f * grbg[2 * width + j]);
1053 rgba[(
width +
j) * 4 + 2] = grbg[width + j];
1056 rgba[(
width +
j) * 4 + 0] =
static_cast<T
>(0.5f * grbg[j] + 0.5f * grbg[2 * width + j]);
1057 rgba[(
width +
j) * 4 + 1] = grbg[width + j];
1058 rgba[(
width +
j) * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
1063 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1067 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(
i - 1) *
width] + 0.5f * grbg[(
i + 1) *
width]);
1070 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(
i - 1) *
width + 1] + 0.5f * grbg[(
i + 1) *
width + 1]);
1077 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1079 rgba[(
i *
width + 1) * 4 + 0] = grbg[i * width + 1];
1080 rgba[(
i *
width + 1) * 4 + 1] =
static_cast<T
>(0.25f * grbg[(i - 1) * width + 1] + 0.25f * grbg[i * width] +
1081 0.25f * grbg[i * width + 2] + 0.25f * grbg[(i + 1) * width + 1]);
1082 rgba[(
i *
width + 1) * 4 + 2] =
static_cast<T
>(0.25f * grbg[(i - 1) * width] + 0.25f * grbg[(i - 1) * width + 2] +
1083 0.25f * grbg[(i + 1) * width] + 0.25f * grbg[(i + 1) * width + 2]);
1086 rgba[(
i *
width + 1) * 4 + 0] =
1087 static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1088 rgba[(
i *
width + 1) * 4 + 1] = grbg[i * width + 1];
1089 rgba[(
i *
width + 1) * 4 + 2] =
static_cast<T
>(0.5f * grbg[i * width] + 0.5f * grbg[i * width + 2]);
1094 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1097 static_cast<T
>(0.5f * grbg[(i + 1) * width - 3] + 0.5f * grbg[(i + 1) * width - 1]);
1100 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1104 static_cast<T
>(0.25f * grbg[i * width - 3] + 0.25f * grbg[i * width - 1] + 0.25f * grbg[(i + 2) * width - 3] +
1105 0.25f * grbg[(i + 2) * width - 1]);
1107 static_cast<T
>(0.25f * grbg[i * width - 2] + 0.25f * grbg[(i + 1) * width - 3] +
1108 0.25f * grbg[(i + 1) * width - 1] + 0.25f * grbg[(i + 2) * width - 2]);
1114 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1119 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1123 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
1130 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1133 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1136 static_cast<T
>(0.5f * grbg[(height - 3) * width + j] + 0.5f * grbg[(height - 1) * width + j]);
1141 static_cast<T
>(0.25f * grbg[(height - 3) * width + j] + 0.25f * grbg[(height - 2) * width + j - 1] +
1142 0.25f * grbg[(height - 2) * width + j + 1] + 0.25f * grbg[(height - 1) * width + j]);
1144 static_cast<T
>(0.25f * grbg[(height - 3) * width + j - 1] + 0.25f * grbg[(height - 3) * width + j + 1] +
1145 0.25f * grbg[(height - 1) * width + j - 1] + 0.25f * grbg[(height - 1) * width + j + 1]);
1150 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1153 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1155 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1162 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1166#if defined(_OPENMP) && (_OPENMP >= 200711)
1168 omp_set_num_threads(
static_cast<int>(nThreads));
1170#pragma omp parallel for schedule(dynamic)
1174 for (
unsigned int i = 2;
i <
height - 2; ++
i) {
1175 for (
unsigned int j = 2;
j <
width - 2; ++
j) {
1176 if (i % 2 == 0 && j % 2 == 0) {
1177 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaMalvar(grbg, width, i, j);
1178 rgba[(
i *
width +
j) * 4 + 1] = grbg[i * width + j];
1179 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiMalvar(grbg, width, i, j);
1181 else if (i % 2 == 0 && j % 2 != 0) {
1182 rgba[(
i *
width +
j) * 4 + 0] = grbg[i * width + j];
1183 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1184 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerMalvar(grbg, width, i, j);
1186 else if (i % 2 != 0 && j % 2 == 0) {
1187 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerMalvar(grbg, width, i, j);
1188 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1189 rgba[(
i *
width +
j) * 4 + 2] = grbg[i * width + j];
1192 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiMalvar(grbg, width, i, j);
1193 rgba[(
i *
width +
j) * 4 + 1] = grbg[i * width + j];
1194 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaMalvar(grbg, width, i, j);
1200template <
typename T>
1201void demosaicRGGBToRGBaMalvarTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1203 m_assert(
"width must be >= 4", width >= 4);
1204 m_assert(
"height must be >= 4", height >= 4);
1205 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1206 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1211 rgba[2] = rggb[
width + 1];
1214 rgba[(
width - 1) * 4 + 0] = rggb[width - 2];
1215 rgba[(
width - 1) * 4 + 1] = rggb[width - 1];
1216 rgba[(
width - 1) * 4 + 2] = rggb[2 * width - 1];
1225 rgba[((
height - 1) *
width +
width - 1) * 4 + 1] = rggb[height * width - 2];
1226 rgba[((
height - 1) *
width +
width - 1) * 4 + 2] = rggb[height * width - 1];
1229 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1231 rgba[
j * 4 + 0] = rggb[
j];
1232 rgba[
j * 4 + 1] =
static_cast<T
>(0.5f * rggb[
j - 1] + 0.5f * rggb[
j + 1]);
1233 rgba[
j * 4 + 2] =
static_cast<T
>(0.5f * rggb[
width +
j - 1] + 0.5f * rggb[
width +
j + 1]);
1236 rgba[
j * 4 + 0] =
static_cast<T
>(0.5f * rggb[
j - 1] + 0.5f * rggb[
j + 1]);
1237 rgba[
j * 4 + 1] = rggb[
j];
1238 rgba[
j * 4 + 2] = rggb[
width +
j];
1243 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1245 rgba[(
width +
j) * 4 + 0] =
static_cast<T
>(0.5f * rggb[j] + 0.5f * rggb[2 * width + j]);
1246 rgba[(
width +
j) * 4 + 1] = rggb[width + j];
1247 rgba[(
width +
j) * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1250 rgba[(
width +
j) * 4 + 0] =
static_cast<T
>(0.25f * rggb[j - 1] + 0.25f * rggb[j + 1] +
1251 0.25f * rggb[2 * width + j - 1] + 0.25f * rggb[2 * width + j + 1]);
1252 rgba[(
width +
j) * 4 + 1] =
static_cast<T
>(0.25f * rggb[j] + 0.25f * rggb[width + j - 1] +
1253 0.25f * rggb[width + j + 1] + 0.25f * rggb[2 * width + j]);
1254 rgba[(
width +
j) * 4 + 2] = rggb[width + j];
1259 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1263 rgba[
i *
width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(
i - 1) *
width + 1] + 0.5f * rggb[(
i + 1) *
width + 1]);
1266 rgba[
i *
width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(
i - 1) *
width] + 0.5f * rggb[(
i + 1) *
width]);
1273 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1275 rgba[(
i *
width + 1) * 4 + 0] =
static_cast<T
>(0.5f * rggb[i * width] + 0.5f * rggb[i * width + 2]);
1276 rgba[(
i *
width + 1) * 4 + 1] = rggb[i * width + 1];
1277 rgba[(
i *
width + 1) * 4 + 2] =
1278 static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1281 rgba[(
i *
width + 1) * 4 + 0] =
static_cast<T
>(0.25f * rggb[(i - 1) * width] + 0.25f * rggb[(i - 1) * width + 2] +
1282 0.25f * rggb[(i + 1) * width] + 0.25f * rggb[(i + 1) * width + 2]);
1283 rgba[(
i *
width + 1) * 4 + 1] =
static_cast<T
>(0.25f * rggb[(i - 1) * width + 1] + 0.25f * rggb[i * width] +
1284 0.25f * rggb[i * width + 2] + 0.25f * rggb[(i + 1) * width + 1]);
1285 rgba[(
i *
width + 1) * 4 + 2] = rggb[i * width + 1];
1290 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1294 static_cast<T
>(0.25f * rggb[i * width - 2] + 0.25f * rggb[(i + 1) * width - 3] +
1295 0.25f * rggb[(i + 1) * width - 1] + 0.25f * rggb[(i + 2) * width - 2]);
1297 static_cast<T
>(0.25f * rggb[i * width - 3] + 0.25f * rggb[i * width - 1] + 0.25f * rggb[(i + 2) * width - 3] +
1298 0.25f * rggb[(i + 2) * width - 1]);
1302 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1305 static_cast<T
>(0.5f * rggb[(i + 1) * width - 3] + 0.5f * rggb[(i + 1) * width - 1]);
1310 for (
unsigned int i = 1;
i <
height - 1; ++
i) {
1315 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
1319 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1326 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1330 static_cast<T
>(0.25f * rggb[(height - 3) * width + j] + 0.25f * rggb[(height - 2) * width + j - 1] +
1331 0.25f * rggb[(height - 2) * width + j + 1] + 0.25f * rggb[(height - 1) * width + j]);
1333 static_cast<T
>(0.25f * rggb[(height - 3) * width + j - 1] + 0.25f * rggb[(height - 3) * width + j + 1] +
1334 0.25f * rggb[(height - 1) * width + j - 1] + 0.25f * rggb[(height - 1) * width + j + 1]);
1338 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1341 static_cast<T
>(0.5f * rggb[(height - 3) * width + j] + 0.5f * rggb[(height - 1) * width + j]);
1346 for (
unsigned int j = 1;
j <
width - 1; ++
j) {
1351 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1355 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1357 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1362#if defined(_OPENMP) && (_OPENMP >= 200711)
1364 omp_set_num_threads(
static_cast<int>(nThreads));
1366#pragma omp parallel for schedule(dynamic)
1370 for (
unsigned int i = 2;
i <
height - 2; ++
i) {
1371 for (
unsigned int j = 2;
j <
width - 2; ++
j) {
1372 if (i % 2 == 0 && j % 2 == 0) {
1373 rgba[(
i *
width +
j) * 4 + 0] = rggb[i * width + j];
1374 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1375 rgba[(
i *
width +
j) * 4 + 2] = demosaicCheckerMalvar(rggb, width, i, j);
1377 else if (i % 2 == 0 && j % 2 != 0) {
1378 rgba[(
i *
width +
j) * 4 + 0] = demosaicThetaMalvar(rggb, width, i, j);
1379 rgba[(
i *
width +
j) * 4 + 1] = rggb[i * width + j];
1380 rgba[(
i *
width +
j) * 4 + 2] = demosaicPhiMalvar(rggb, width, i, j);
1382 else if (i % 2 != 0 && j % 2 == 0) {
1383 rgba[(
i *
width +
j) * 4 + 0] = demosaicPhiMalvar(rggb, width, i, j);
1384 rgba[(
i *
width +
j) * 4 + 1] = rggb[i * width + j];
1385 rgba[(
i *
width +
j) * 4 + 2] = demosaicThetaMalvar(rggb, width, i, j);
1388 rgba[(
i *
width +
j) * 4 + 0] = demosaicCheckerMalvar(rggb, width, i, j);
1389 rgba[(
i *
width +
j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1390 rgba[(
i *
width +
j) * 4 + 2] = rggb[i * width + j];
static Tp saturate(unsigned char v)