41#ifndef vpBAYERCONVERSION_H
42#define vpBAYERCONVERSION_H
46#include <visp3/core/vpMath.h>
50#define m_assert(msg, expr) assert(((void)(msg), (expr)))
53template <
typename T> T demosaicPhiBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
55 return static_cast<T
>(0.5f * bayer[(i - 1) * width + j] + 0.5f * bayer[(i + 1) * width + j]);
58template <
typename T> T demosaicThetaBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
60 return static_cast<T
>(0.5f * bayer[i * width + j - 1] + 0.5f * bayer[i * width + j + 1]);
63template <
typename T> T demosaicCheckerBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
65 return static_cast<T
>(0.25f * bayer[(i - 1) * width + j - 1] + 0.25f * bayer[(i - 1) * width + j + 1] +
66 0.25f * bayer[(i + 1) * width + j - 1] + 0.25f * bayer[(i + 1) * width + j + 1]);
69template <
typename T> T demosaicCrossBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
71 return static_cast<T
>(0.25f * bayer[(i - 1) * width + j] + 0.25f * bayer[i * width + j - 1] +
72 0.25f * bayer[i * width + j + 1] + 0.25f * bayer[(i + 1) * width + j]);
76template <
typename T> T demosaicPhiMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
79 (-bayer[(i - 2) * width + j] - bayer[(i - 1) * width + j - 1] + 4 * bayer[(i - 1) * width + j] -
80 bayer[(i - 1) * width + j + 1] + 0.5f * bayer[i * width + j - 2] + 5 * bayer[i * width + j] +
81 0.5f * bayer[i * width + j + 2] - bayer[(i + 1) * width + j - 1] + 4 * bayer[(i + 1) * width + j] -
82 bayer[(i + 1) * width + j + 1] - bayer[(i + 2) * width + j]) *
86template <
typename T> T demosaicThetaMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
88 return vpMath::saturate<T>((0.5f * bayer[(i - 2) * width + j] - bayer[(i - 1) * width + j - 1] -
89 bayer[(i - 1) * width + j + 1] - bayer[i * width + j - 2] + 4 * bayer[i * width + j - 1] +
90 5 * bayer[i * width + j] + 4 * bayer[i * width + j + 1] - bayer[i * width + j + 2] -
91 bayer[(i + 1) * width + j - 1] - bayer[(i + 1) * width + j + 1] +
92 0.5f * bayer[(i + 2) * width + j]) *
96template <
typename T> T demosaicCheckerMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
99 (-1.5f * bayer[(i - 2) * width + j] + 2 * bayer[(i - 1) * width + j - 1] + 2 * bayer[(i - 1) * width + j + 1] -
100 1.5f * bayer[i * width + j - 2] + 6 * bayer[i * width + j] - 1.5f * bayer[i * width + j + 2] +
101 2 * bayer[(i + 1) * width + j - 1] + 2 * bayer[(i + 1) * width + j + 1] - 1.5f * bayer[(i + 2) * width + j]) *
105template <
typename T> T demosaicCrossMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
107 return vpMath::saturate<T>((-bayer[(i - 2) * width + j] + 2 * bayer[(i - 1) * width + j] - bayer[i * width + j - 2] +
108 2 * bayer[i * width + j - 1] + 4 * bayer[i * width + j] + 2 * bayer[i * width + j + 1] -
109 bayer[i * width + j + 2] + 2 * bayer[(i + 1) * width + j] - bayer[(i + 2) * width + j]) *
114void demosaicBGGRToRGBaBilinearTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
115 unsigned int nThreads)
117 m_assert(
"width must be >= 4", width >= 4);
118 m_assert(
"height must be >= 4", height >= 4);
119 m_assert(
"width must be a multiple of 2", width % 2 == 0);
120 m_assert(
"height must be a multiple of 2", height % 2 == 0);
123 rgba[0] = bggr[width + 1];
128 rgba[(width - 1) * 4 + 0] = bggr[2 * width - 1];
129 rgba[(width - 1) * 4 + 1] = bggr[width - 1];
130 rgba[(width - 1) * 4 + 2] = bggr[width - 2];
133 rgba[((height - 1) * width) * 4 + 0] = bggr[(height - 1) * width + 1];
134 rgba[((height - 1) * width) * 4 + 1] = bggr[(height - 1) * width];
135 rgba[((height - 1) * width) * 4 + 2] = bggr[(height - 2) * width];
138 rgba[((height - 1) * width + width - 1) * 4 + 0] = bggr[height * width - 1];
139 rgba[((height - 1) * width + width - 1) * 4 + 1] = bggr[height * width - 2];
140 rgba[((height - 1) * width + width - 1) * 4 + 2] = bggr[(height - 1) * width - 2];
143 for (
unsigned int j = 1; j < width - 1; j++) {
145 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
146 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
147 rgba[j * 4 + 2] = bggr[j];
149 rgba[j * 4 + 0] = bggr[width + j];
150 rgba[j * 4 + 1] = bggr[j];
151 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
156 for (
unsigned int i = 1; i < height - 1; i++) {
158 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
159 rgba[i * width * 4 + 1] = bggr[i * width + 1];
160 rgba[i * width * 4 + 2] = bggr[i * width];
162 rgba[i * width * 4 + 0] = bggr[i * width + 1];
163 rgba[i * width * 4 + 1] = bggr[i * width];
164 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(i - 1) * width] + 0.5f * bggr[(i + 1) * width]);
169 for (
unsigned int i = 1; i < height - 1; i++) {
171 rgba[(i * width + width - 1) * 4 + 0] =
172 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
173 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 1];
174 rgba[(i * width + width - 1) * 4 + 2] = bggr[(i + 1) * width - 2];
176 rgba[(i * width + width - 1) * 4 + 0] = bggr[(i + 1) * width - 1];
177 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 2];
178 rgba[(i * width + width - 1) * 4 + 2] =
179 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
184 for (
unsigned int j = 1; j < width - 1; j++) {
186 rgba[((height - 1) * width + j) * 4 + 0] =
187 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
188 rgba[((height - 1) * width + j) * 4 + 1] = bggr[(height - 1) * width + j];
189 rgba[((height - 1) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
191 rgba[((height - 1) * width + j) * 4 + 0] = bggr[(height - 1) * width + j];
192 rgba[((height - 1) * width + j) * 4 + 1] =
193 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
194 rgba[((height - 1) * width + j) * 4 + 2] =
195 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
199#if defined _OPENMP && _OPENMP >= 200711
201 omp_set_num_threads(
static_cast<int>(nThreads));
203#pragma omp parallel for schedule(dynamic)
207 for (
unsigned int i = 1; i < height - 1; i++) {
208 for (
unsigned int j = 1; j < width - 1; j++) {
209 if (i % 2 == 0 && j % 2 == 0) {
210 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(bggr, width, i, j);
211 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
212 rgba[(i * width + j) * 4 + 2] = bggr[i * width + j];
213 }
else if (i % 2 == 0 && j % 2 != 0) {
214 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(bggr, width, i, j);
215 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
216 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(bggr, width, i, j);
217 }
else if (i % 2 != 0 && j % 2 == 0) {
218 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(bggr, width, i, j);
219 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
220 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(bggr, width, i, j);
222 rgba[(i * width + j) * 4 + 0] = bggr[i * width + j];
223 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
224 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(bggr, width, i, j);
231void demosaicGBRGToRGBaBilinearTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
232 unsigned int nThreads)
234 m_assert(
"width must be >= 4", width >= 4);
235 m_assert(
"height must be >= 4", height >= 4);
236 m_assert(
"width must be a multiple of 2", width % 2 == 0);
237 m_assert(
"height must be a multiple of 2", height % 2 == 0);
240 rgba[0] = gbrg[width];
245 rgba[(width - 1) * 4 + 0] = gbrg[2 * width - 2];
246 rgba[(width - 1) * 4 + 1] = gbrg[width - 2];
247 rgba[(width - 1) * 4 + 2] = gbrg[width - 1];
250 rgba[((height - 1) * width) * 4 + 0] = gbrg[(height - 1) * width];
251 rgba[((height - 1) * width) * 4 + 1] = gbrg[(height - 1) * width + 1];
252 rgba[((height - 1) * width) * 4 + 2] = gbrg[(height - 2) * width + 1];
255 rgba[((height - 1) * width + width - 1) * 4 + 0] = gbrg[height * width - 2];
256 rgba[((height - 1) * width + width - 1) * 4 + 1] = gbrg[height * width - 1];
257 rgba[((height - 1) * width + width - 1) * 4 + 2] = gbrg[(height - 1) * width - 1];
260 for (
unsigned int j = 1; j < width - 1; j++) {
262 rgba[j * 4 + 0] = gbrg[width + j];
263 rgba[j * 4 + 1] = gbrg[j];
264 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
266 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
267 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
268 rgba[j * 4 + 2] = gbrg[j];
273 for (
unsigned int i = 1; i < height - 1; i++) {
275 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
276 rgba[i * width * 4 + 1] = gbrg[i * width];
277 rgba[i * width * 4 + 2] = gbrg[i * width + 1];
279 rgba[i * width * 4 + 0] = gbrg[i * width];
280 rgba[i * width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
281 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
286 for (
unsigned int i = 1; i < height - 1; i++) {
288 rgba[(i * width + width - 1) * 4 + 0] =
289 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
290 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 2];
291 rgba[(i * width + width - 1) * 4 + 2] = gbrg[(i + 1) * width - 1];
293 rgba[(i * width + width - 1) * 4 + 0] = gbrg[(i + 1) * width - 2];
294 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 1];
295 rgba[(i * width + width - 1) * 4 + 2] =
296 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
301 for (
unsigned int j = 1; j < width - 1; j++) {
303 rgba[((height - 1) * width + j) * 4 + 0] = gbrg[(height - 1) * width + j];
304 rgba[((height - 1) * width + j) * 4 + 1] =
305 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
306 rgba[((height - 1) * width + j) * 4 + 2] =
307 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
309 rgba[((height - 1) * width + j) * 4 + 0] =
310 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
311 rgba[((height - 1) * width + j) * 4 + 1] = gbrg[(height - 1) * width + j];
312 rgba[((height - 1) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
316#if defined _OPENMP && _OPENMP >= 200711
318 omp_set_num_threads(
static_cast<int>(nThreads));
320#pragma omp parallel for schedule(dynamic)
324 for (
unsigned int i = 1; i < height - 1; i++) {
325 for (
unsigned int j = 1; j < width - 1; j++) {
326 if (i % 2 == 0 && j % 2 == 0) {
327 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(gbrg, width, i, j);
328 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
329 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(gbrg, width, i, j);
330 }
else if (i % 2 == 0 && j % 2 != 0) {
331 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(gbrg, width, i, j);
332 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
333 rgba[(i * width + j) * 4 + 2] = gbrg[i * width + j];
334 }
else if (i % 2 != 0 && j % 2 == 0) {
335 rgba[(i * width + j) * 4 + 0] = gbrg[i * width + j];
336 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
337 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(gbrg, width, i, j);
339 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(gbrg, width, i, j);
340 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
341 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(gbrg, width, i, j);
348void demosaicGRBGToRGBaBilinearTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
349 unsigned int nThreads)
351 m_assert(
"width must be >= 4", width >= 4);
352 m_assert(
"height must be >= 4", height >= 4);
353 m_assert(
"width must be a multiple of 2", width % 2 == 0);
354 m_assert(
"height must be a multiple of 2", height % 2 == 0);
359 rgba[2] = grbg[width];
362 rgba[(width - 1) * 4 + 0] = grbg[width - 1];
363 rgba[(width - 1) * 4 + 1] = grbg[width - 2];
364 rgba[(width - 1) * 4 + 2] = grbg[2 * width - 2];
367 rgba[((height - 1) * width) * 4 + 0] = grbg[(height - 2) * width + 1];
368 rgba[((height - 1) * width) * 4 + 1] = grbg[(height - 1) * width + 1];
369 rgba[((height - 1) * width) * 4 + 2] = grbg[(height - 1) * width];
372 rgba[((height - 1) * width + width - 1) * 4 + 0] = grbg[(height - 1) * width - 1];
373 rgba[((height - 1) * width + width - 1) * 4 + 1] = grbg[height * width - 1];
374 rgba[((height - 1) * width + width - 1) * 4 + 2] = grbg[height * width - 2];
377 for (
unsigned int j = 1; j < width - 1; j++) {
379 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
380 rgba[j * 4 + 1] = grbg[j];
381 rgba[j * 4 + 2] = grbg[width + j];
383 rgba[j * 4 + 0] = grbg[j];
384 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
385 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
390 for (
unsigned int i = 1; i < height - 1; i++) {
392 rgba[i * width * 4 + 0] = grbg[i * width + 1];
393 rgba[i * width * 4 + 1] = grbg[i * width];
394 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(i - 1) * width] + 0.5f * grbg[(i + 1) * width]);
396 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
397 rgba[i * width * 4 + 1] = grbg[i * width + 1];
398 rgba[i * width * 4 + 2] = grbg[i * width];
403 for (
unsigned int i = 1; i < height - 1; i++) {
405 rgba[(i * width + width - 1) * 4 + 0] = grbg[(i + 1) * width - 1];
406 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 2];
407 rgba[(i * width + width - 1) * 4 + 2] =
408 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
410 rgba[(i * width + width - 1) * 4 + 0] =
411 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
412 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 1];
413 rgba[(i * width + width - 1) * 4 + 2] = grbg[(i + 1) * width - 2];
418 for (
unsigned int j = 1; j < width - 1; j++) {
420 rgba[((height - 1) * width + j) * 4 + 0] =
421 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
422 rgba[((height - 1) * width + j) * 4 + 1] =
423 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
424 rgba[((height - 1) * width + j) * 4 + 2] = grbg[(height - 1) * width + j];
426 rgba[((height - 1) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
427 rgba[((height - 1) * width + j) * 4 + 1] = grbg[(height - 1) * width + j];
428 rgba[((height - 1) * width + j) * 4 + 2] =
429 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
433#if defined _OPENMP && _OPENMP >= 200711
435 omp_set_num_threads(
static_cast<int>(nThreads));
437#pragma omp parallel for schedule(dynamic)
441 for (
unsigned int i = 1; i < height - 1; i++) {
442 for (
unsigned int j = 1; j < width - 1; j++) {
443 if (i % 2 == 0 && j % 2 == 0) {
444 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(grbg, width, i, j);
445 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
446 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(grbg, width, i, j);
447 }
else if (i % 2 == 0 && j % 2 != 0) {
448 rgba[(i * width + j) * 4 + 0] = grbg[i * width + j];
449 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
450 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(grbg, width, i, j);
451 }
else if (i % 2 != 0 && j % 2 == 0) {
452 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(grbg, width, i, j);
453 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
454 rgba[(i * width + j) * 4 + 2] = grbg[i * width + j];
456 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(grbg, width, i, j);
457 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
458 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(grbg, width, i, j);
465void demosaicRGGBToRGBaBilinearTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
466 unsigned int nThreads)
468 m_assert(
"width must be >= 4", width >= 4);
469 m_assert(
"height must be >= 4", height >= 4);
470 m_assert(
"width must be a multiple of 2", width % 2 == 0);
471 m_assert(
"height must be a multiple of 2", height % 2 == 0);
476 rgba[2] = rggb[width + 1];
479 rgba[(width - 1) * 4 + 0] = rggb[width - 2];
480 rgba[(width - 1) * 4 + 1] = rggb[width - 1];
481 rgba[(width - 1) * 4 + 2] = rggb[2 * width - 1];
484 rgba[((height - 1) * width) * 4 + 0] = rggb[(height - 2) * width];
485 rgba[((height - 1) * width) * 4 + 1] = rggb[(height - 1) * width];
486 rgba[((height - 1) * width) * 4 + 2] = rggb[(height - 1) * width + 1];
489 rgba[((height - 1) * width + width - 1) * 4 + 0] = rggb[(height - 1) * width - 2];
490 rgba[((height - 1) * width + width - 1) * 4 + 1] = rggb[height * width - 2];
491 rgba[((height - 1) * width + width - 1) * 4 + 2] = rggb[height * width - 1];
494 for (
unsigned int j = 1; j < width - 1; j++) {
496 rgba[j * 4 + 0] = rggb[j];
497 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
498 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
500 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
501 rgba[j * 4 + 1] = rggb[j];
502 rgba[j * 4 + 2] = rggb[width + j];
507 for (
unsigned int i = 1; i < height - 1; i++) {
509 rgba[i * width * 4 + 0] = rggb[i * width];
510 rgba[i * width * 4 + 1] = rggb[i * width + 1];
511 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
513 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(i - 1) * width] + 0.5f * rggb[(i + 1) * width]);
514 rgba[i * width * 4 + 1] = rggb[i * width];
515 rgba[i * width * 4 + 2] = rggb[i * width + 1];
520 for (
unsigned int i = 1; i < height - 1; i++) {
522 rgba[(i * width + width - 1) * 4 + 0] = rggb[(i + 1) * width - 2];
523 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 1];
524 rgba[(i * width + width - 1) * 4 + 2] =
525 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
527 rgba[(i * width + width - 1) * 4 + 0] =
528 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
529 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 2];
530 rgba[(i * width + width - 1) * 4 + 2] = rggb[(i + 1) * width - 1];
535 for (
unsigned int j = 1; j < width - 1; j++) {
537 rgba[((height - 1) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
538 rgba[((height - 1) * width + j) * 4 + 1] = rggb[(height - 1) * width + j];
539 rgba[((height - 1) * width + j) * 4 + 2] =
540 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
542 rgba[((height - 1) * width + j) * 4 + 0] =
543 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
544 rgba[((height - 1) * width + j) * 4 + 1] =
545 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
546 rgba[((height - 1) * width + j) * 4 + 2] = rggb[(height - 1) * width + j];
550#if defined _OPENMP && _OPENMP >= 200711
552 omp_set_num_threads(
static_cast<int>(nThreads));
554#pragma omp parallel for schedule(dynamic)
558 for (
unsigned int i = 1; i < height - 1; i++) {
559 for (
unsigned int j = 1; j < width - 1; j++) {
560 if (i % 2 == 0 && j % 2 == 0) {
561 rgba[(i * width + j) * 4 + 0] = rggb[i * width + j];
562 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
563 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(rggb, width, i, j);
564 }
else if (i % 2 == 0 && j % 2 != 0) {
565 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(rggb, width, i, j);
566 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
567 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(rggb, width, i, j);
568 }
else if (i % 2 != 0 && j % 2 == 0) {
569 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(rggb, width, i, j);
570 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
571 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(rggb, width, i, j);
573 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(rggb, width, i, j);
574 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
575 rgba[(i * width + j) * 4 + 2] = rggb[i * width + j];
584void demosaicBGGRToRGBaMalvarTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
586 m_assert(
"width must be >= 4", width >= 4);
587 m_assert(
"height must be >= 4", height >= 4);
588 m_assert(
"width must be a multiple of 2", width % 2 == 0);
589 m_assert(
"height must be a multiple of 2", height % 2 == 0);
592 rgba[0] = bggr[width + 1];
597 rgba[(width - 1) * 4 + 0] = bggr[2 * width - 1];
598 rgba[(width - 1) * 4 + 1] = bggr[width - 1];
599 rgba[(width - 1) * 4 + 2] = bggr[width - 2];
602 rgba[((height - 1) * width) * 4 + 0] = bggr[(height - 1) * width + 1];
603 rgba[((height - 1) * width) * 4 + 1] = bggr[(height - 1) * width];
604 rgba[((height - 1) * width) * 4 + 2] = bggr[(height - 2) * width];
607 rgba[((height - 1) * width + width - 1) * 4 + 0] = bggr[height * width - 1];
608 rgba[((height - 1) * width + width - 1) * 4 + 1] = bggr[height * width - 2];
609 rgba[((height - 1) * width + width - 1) * 4 + 2] = bggr[(height - 1) * width - 2];
612 for (
unsigned int j = 1; j < width - 1; j++) {
614 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
615 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
616 rgba[j * 4 + 2] = bggr[j];
618 rgba[j * 4 + 0] = bggr[width + j];
619 rgba[j * 4 + 1] = bggr[j];
620 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
625 for (
unsigned int j = 1; j < width - 1; j++) {
627 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
628 rgba[(width + j) * 4 + 1] = bggr[width + j];
629 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * bggr[j] + 0.5f * bggr[2 * width + j]);
631 rgba[(width + j) * 4 + 0] = bggr[width + j];
632 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * bggr[j] + 0.25f * bggr[width + j - 1] +
633 0.25f * bggr[width + j + 1] + 0.25f * bggr[2 * width + j]);
634 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.25f * bggr[j - 1] + 0.25f * bggr[j + 1] +
635 0.25f * bggr[2 * width + j - 1] + 0.25f * bggr[2 * width + j + 1]);
640 for (
unsigned int i = 1; i < height - 1; i++) {
642 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
643 rgba[i * width * 4 + 1] = bggr[i * width + 1];
644 rgba[i * width * 4 + 2] = bggr[i * width];
646 rgba[i * width * 4 + 0] = bggr[i * width + 1];
647 rgba[i * width * 4 + 1] = bggr[i * width];
648 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(i - 1) * width] + 0.5f * bggr[(i + 1) * width]);
653 for (
unsigned int i = 1; i < height - 1; i++) {
655 rgba[(i * width + 1) * 4 + 0] =
656 static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
657 rgba[(i * width + 1) * 4 + 1] = bggr[i * width + 1];
658 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.5f * bggr[i * width] + 0.5f * bggr[i * width + 2]);
660 rgba[(i * width + 1) * 4 + 0] = bggr[i * width + 1];
661 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * bggr[(i - 1) * width + 1] + 0.25f * bggr[i * width] +
662 0.25f * bggr[i * width + 2] + 0.25f * bggr[(i + 1) * width + 1]);
663 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.25f * bggr[(i - 1) * width] + 0.25f * bggr[(i - 1) * width + 2] +
664 0.25f * bggr[(i + 1) * width] + 0.25f * bggr[(i + 1) * width + 2]);
669 for (
unsigned int i = 1; i < height - 1; i++) {
671 rgba[(i * width + width - 2) * 4 + 0] =
672 static_cast<T
>(0.25f * bggr[i * width - 3] + 0.25f * bggr[i * width - 1] + 0.25f * bggr[(i + 2) * width - 3] +
673 0.25f * bggr[(i + 2) * width - 1]);
674 rgba[(i * width + width - 2) * 4 + 1] =
675 static_cast<T
>(0.25f * bggr[i * width - 2] + 0.25f * bggr[(i + 1) * width - 3] +
676 0.25f * bggr[(i + 1) * width - 1] + 0.25f * bggr[(i + 2) * width - 2]);
677 rgba[(i * width + width - 2) * 4 + 2] = bggr[(i + 1) * width - 2];
679 rgba[(i * width + width - 2) * 4 + 0] =
680 static_cast<T
>(0.5f * bggr[(i + 1) * width - 3] + 0.5f * bggr[(i + 1) * width - 1]);
681 rgba[(i * width + width - 2) * 4 + 1] = bggr[(i + 1) * width - 2];
682 rgba[(i * width + width - 2) * 4 + 2] =
683 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
688 for (
unsigned int i = 1; i < height - 1; i++) {
690 rgba[(i * width + width - 1) * 4 + 0] =
691 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
692 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 1];
693 rgba[(i * width + width - 1) * 4 + 2] = bggr[(i + 1) * width - 2];
695 rgba[(i * width + width - 1) * 4 + 0] = bggr[(i + 1) * width - 1];
696 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 2];
697 rgba[(i * width + width - 1) * 4 + 2] =
698 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
703 for (
unsigned int j = 1; j < width - 1; j++) {
705 rgba[((height - 2) * width + j) * 4 + 0] =
706 static_cast<T
>(0.25f * bggr[(height - 3) * width + j - 1] + 0.25f * bggr[(height - 3) * width + j + 1] +
707 0.25f * bggr[(height - 1) * width + j - 1] + 0.25f * bggr[(height - 1) * width + j + 1]);
708 rgba[((height - 2) * width + j) * 4 + 1] =
709 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
710 rgba[((height - 2) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
712 rgba[((height - 2) * width + j) * 4 + 0] =
713 static_cast<T
>(0.5f * bggr[(height - 3) * width + j] + 0.5f * bggr[(height - 1) * width + j]);
714 rgba[((height - 2) * width + j) * 4 + 1] = bggr[(height - 2) * width + j];
715 rgba[((height - 2) * width + j) * 4 + 2] =
716 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
721 for (
unsigned int j = 1; j < width - 1; j++) {
723 rgba[((height - 1) * width + j) * 4 + 0] =
724 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
725 rgba[((height - 1) * width + j) * 4 + 1] = bggr[(height - 1) * width + j];
726 rgba[((height - 1) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
728 rgba[((height - 1) * width + j) * 4 + 0] = bggr[(height - 1) * width + j];
729 rgba[((height - 1) * width + j) * 4 + 1] =
730 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
731 rgba[((height - 1) * width + j) * 4 + 2] =
732 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
736#if defined _OPENMP && _OPENMP >= 200711
738 omp_set_num_threads(
static_cast<int>(nThreads));
740#pragma omp parallel for schedule(dynamic)
744 for (
unsigned int i = 2; i < height - 2; i++) {
745 for (
unsigned int j = 2; j < width - 2; j++) {
746 if (i % 2 == 0 && j % 2 == 0) {
747 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(bggr, width, i, j);
748 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
749 rgba[(i * width + j) * 4 + 2] = bggr[i * width + j];
750 }
else if (i % 2 == 0 && j % 2 != 0) {
751 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(bggr, width, i, j);
752 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
753 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(bggr, width, i, j);
754 }
else if (i % 2 != 0 && j % 2 == 0) {
755 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(bggr, width, i, j);
756 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
757 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(bggr, width, i, j);
759 rgba[(i * width + j) * 4 + 0] = bggr[i * width + j];
760 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
761 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(bggr, width, i, j);
768void demosaicGBRGToRGBaMalvarTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
770 m_assert(
"width must be >= 4", width >= 4);
771 m_assert(
"height must be >= 4", height >= 4);
772 m_assert(
"width must be a multiple of 2", width % 2 == 0);
773 m_assert(
"height must be a multiple of 2", height % 2 == 0);
776 rgba[0] = gbrg[width];
781 rgba[(width - 1) * 4 + 0] = gbrg[2 * width - 2];
782 rgba[(width - 1) * 4 + 1] = gbrg[width - 2];
783 rgba[(width - 1) * 4 + 2] = gbrg[width - 1];
786 rgba[((height - 1) * width) * 4 + 0] = gbrg[(height - 1) * width];
787 rgba[((height - 1) * width) * 4 + 1] = gbrg[(height - 1) * width + 1];
788 rgba[((height - 1) * width) * 4 + 2] = gbrg[(height - 2) * width + 1];
791 rgba[((height - 1) * width + width - 1) * 4 + 0] = gbrg[height * width - 2];
792 rgba[((height - 1) * width + width - 1) * 4 + 1] = gbrg[height * width - 1];
793 rgba[((height - 1) * width + width - 1) * 4 + 2] = gbrg[(height - 1) * width - 1];
796 for (
unsigned int j = 1; j < width - 1; j++) {
798 rgba[j * 4 + 0] = gbrg[width + j];
799 rgba[j * 4 + 1] = gbrg[j];
800 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
802 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
803 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
804 rgba[j * 4 + 2] = gbrg[j];
809 for (
unsigned int j = 1; j < width - 1; j++) {
811 rgba[(width + j) * 4 + 0] = gbrg[width + j];
812 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[j] + 0.25f * gbrg[width + j - 1] +
813 0.25f * gbrg[width + j + 1] + 0.25f * gbrg[2 * width + j]);
814 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.25f * gbrg[j - 1] + 0.25f * gbrg[j + 1] +
815 0.25f * gbrg[2 * width + j - 1] + 0.25f * gbrg[2 * width + j + 1]);
817 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
818 rgba[(width + j) * 4 + 1] = gbrg[width + j];
819 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j] + 0.5f * gbrg[2 * width + j]);
824 for (
unsigned int i = 1; i < height - 1; i++) {
826 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
827 rgba[i * width * 4 + 1] = gbrg[i * width];
828 rgba[i * width * 4 + 2] = gbrg[i * width + 1];
830 rgba[i * width * 4 + 0] = gbrg[i * width];
831 rgba[i * width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
832 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
837 for (
unsigned int i = 1; i < height - 1; i++) {
839 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width] + 0.25f * gbrg[(i - 1) * width + 2] +
840 0.25f * gbrg[(i + 1) * width] + 0.5f * gbrg[(i + 1) * width + 2]);
841 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width + 1] + 0.25f * gbrg[i * width] +
842 0.25f * gbrg[i * width + 2] + 0.5f * gbrg[(i + 1) * width + 1]);
843 rgba[(i * width + 1) * 4 + 2] = gbrg[i * width + 1];
845 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[i * width] + 0.5f * gbrg[i * width + 2]);
846 rgba[(i * width + 1) * 4 + 1] = gbrg[i * width + 1];
847 rgba[(i * width + 1) * 4 + 2] =
848 static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
853 for (
unsigned int i = 1; i < height - 1; i++) {
855 rgba[(i * width + width - 2) * 4 + 0] =
856 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
857 rgba[(i * width + width - 2) * 4 + 1] = gbrg[(i + 1) * width - 2];
858 rgba[(i * width + width - 2) * 4 + 2] =
859 static_cast<T
>(0.5f * gbrg[(i + 1) * width - 3] + 0.5f * gbrg[(i + 1) * width - 1]);
861 rgba[(i * width + width - 2) * 4 + 0] = gbrg[(i + 1) * width - 2];
862 rgba[(i * width + width - 2) * 4 + 1] =
863 static_cast<T
>(0.25f * gbrg[i * width - 2] + 0.25f * gbrg[(i + 1) * width - 3] +
864 0.25f * gbrg[(i + 1) * width - 1] + 0.25f * gbrg[(i + 2) * width - 2]);
865 rgba[(i * width + width - 2) * 4 + 2] =
866 static_cast<T
>(0.25f * gbrg[i * width - 3] + 0.25f * gbrg[i * width - 1] + 0.25f * gbrg[(i + 2) * width - 3] +
867 0.25f * gbrg[(i + 2) * width - 1]);
872 for (
unsigned int i = 1; i < height - 1; i++) {
874 rgba[(i * width + width - 1) * 4 + 0] =
875 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
876 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 2];
877 rgba[(i * width + width - 1) * 4 + 2] = gbrg[(i + 1) * width - 1];
879 rgba[(i * width + width - 1) * 4 + 0] = gbrg[(i + 1) * width - 2];
880 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 1];
881 rgba[(i * width + width - 1) * 4 + 2] =
882 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
887 for (
unsigned int j = 1; j < width - 1; j++) {
889 rgba[((height - 2) * width + j) * 4 + 0] =
890 static_cast<T
>(0.5f * gbrg[(height - 3) * width + j] + 0.5f * gbrg[(height - 1) * width + j]);
891 rgba[((height - 2) * width + j) * 4 + 1] = gbrg[(height - 2) * width + j];
892 rgba[((height - 2) * width + j) * 4 + 2] =
893 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
895 rgba[((height - 2) * width + j) * 4 + 0] =
896 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j - 1] + 0.25f * gbrg[(height - 3) * width + j + 1] +
897 0.25f * gbrg[(height - 1) * width + j - 1] + 0.25f * gbrg[(height - 1) * width + j + 1]);
898 rgba[((height - 2) * width + j) * 4 + 1] =
899 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j] + 0.25f * gbrg[(height - 2) * width + j - 1] +
900 0.25f * gbrg[(height - 2) * width + j + 1] + 0.25f * gbrg[(height - 1) * width + j]);
901 rgba[((height - 2) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
906 for (
unsigned int j = 1; j < width - 1; j++) {
908 rgba[((height - 1) * width + j) * 4 + 0] = gbrg[(height - 1) * width + j];
909 rgba[((height - 1) * width + j) * 4 + 1] =
910 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
911 rgba[((height - 1) * width + j) * 4 + 2] =
912 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
914 rgba[((height - 1) * width + j) * 4 + 0] =
915 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
916 rgba[((height - 1) * width + j) * 4 + 1] = gbrg[(height - 1) * width + j];
917 rgba[((height - 1) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
921#if defined _OPENMP && _OPENMP >= 200711
923 omp_set_num_threads(
static_cast<int>(nThreads));
925#pragma omp parallel for schedule(dynamic)
929 for (
unsigned int i = 2; i < height - 2; i++) {
930 for (
unsigned int j = 2; j < width - 2; j++) {
931 if (i % 2 == 0 && j % 2 == 0) {
932 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(gbrg, width, i, j);
933 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
934 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(gbrg, width, i, j);
935 }
else if (i % 2 == 0 && j % 2 != 0) {
936 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(gbrg, width, i, j);
937 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
938 rgba[(i * width + j) * 4 + 2] = gbrg[i * width + j];
939 }
else if (i % 2 != 0 && j % 2 == 0) {
940 rgba[(i * width + j) * 4 + 0] = gbrg[i * width + j];
941 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
942 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(gbrg, width, i, j);
944 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(gbrg, width, i, j);
945 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
946 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(gbrg, width, i, j);
953void demosaicGRBGToRGBaMalvarTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
955 m_assert(
"width must be >= 4", width >= 4);
956 m_assert(
"height must be >= 4", height >= 4);
957 m_assert(
"width must be a multiple of 2", width % 2 == 0);
958 m_assert(
"height must be a multiple of 2", height % 2 == 0);
963 rgba[2] = grbg[width];
966 rgba[(width - 1) * 4 + 0] = grbg[width - 1];
967 rgba[(width - 1) * 4 + 1] = grbg[width - 2];
968 rgba[(width - 1) * 4 + 2] = grbg[2 * width - 2];
971 rgba[((height - 1) * width) * 4 + 0] = grbg[(height - 2) * width + 1];
972 rgba[((height - 1) * width) * 4 + 1] = grbg[(height - 1) * width + 1];
973 rgba[((height - 1) * width) * 4 + 2] = grbg[(height - 1) * width];
976 rgba[((height - 1) * width + width - 1) * 4 + 0] = grbg[(height - 1) * width - 1];
977 rgba[((height - 1) * width + width - 1) * 4 + 1] = grbg[height * width - 1];
978 rgba[((height - 1) * width + width - 1) * 4 + 2] = grbg[height * width - 2];
981 for (
unsigned int j = 1; j < width - 1; j++) {
983 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
984 rgba[j * 4 + 1] = grbg[j];
985 rgba[j * 4 + 2] = grbg[width + j];
987 rgba[j * 4 + 0] = grbg[j];
988 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
989 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
994 for (
unsigned int j = 1; j < width - 1; j++) {
996 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.25f * grbg[j - 1] + 0.25f * grbg[j + 1] +
997 0.25f * grbg[2 * width + j - 1] + 0.25f * grbg[2 * width + j + 1]);
998 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * grbg[j] + 0.25f * grbg[width + j - 1] +
999 0.25f * grbg[width + j + 1] + 0.25f * grbg[2 * width + j]);
1000 rgba[(width + j) * 4 + 2] = grbg[width + j];
1002 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * grbg[j] + 0.5f * grbg[2 * width + j]);
1003 rgba[(width + j) * 4 + 1] = grbg[width + j];
1004 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
1009 for (
unsigned int i = 1; i < height - 1; i++) {
1011 rgba[i * width * 4 + 0] = grbg[i * width + 1];
1012 rgba[i * width * 4 + 1] = grbg[i * width];
1013 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(i - 1) * width] + 0.5f * grbg[(i + 1) * width]);
1015 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1016 rgba[i * width * 4 + 1] = grbg[i * width + 1];
1017 rgba[i * width * 4 + 2] = grbg[i * width];
1022 for (
unsigned int i = 1; i < height - 1; i++) {
1024 rgba[(i * width + 1) * 4 + 0] = grbg[i * width + 1];
1025 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * grbg[(i - 1) * width + 1] + 0.25f * grbg[i * width] +
1026 0.25f * grbg[i * width + 2] + 0.25f * grbg[(i + 1) * width + 1]);
1027 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.25f * grbg[(i - 1) * width] + 0.25f * grbg[(i - 1) * width + 2] +
1028 0.25f * grbg[(i + 1) * width] + 0.25f * grbg[(i + 1) * width + 2]);
1030 rgba[(i * width + 1) * 4 + 0] =
1031 static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1032 rgba[(i * width + 1) * 4 + 1] = grbg[i * width + 1];
1033 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.5f * grbg[i * width] + 0.5f * grbg[i * width + 2]);
1038 for (
unsigned int i = 1; i < height - 1; i++) {
1040 rgba[(i * width + width - 2) * 4 + 0] =
1041 static_cast<T
>(0.5f * grbg[(i + 1) * width - 3] + 0.5f * grbg[(i + 1) * width - 1]);
1042 rgba[(i * width + width - 2) * 4 + 1] = grbg[(i + 1) * width - 2];
1043 rgba[(i * width + width - 2) * 4 + 2] =
1044 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1046 rgba[(i * width + width - 2) * 4 + 0] =
1047 static_cast<T
>(0.25f * grbg[i * width - 3] + 0.25f * grbg[i * width - 1] + 0.25f * grbg[(i + 2) * width - 3] +
1048 0.25f * grbg[(i + 2) * width - 1]);
1049 rgba[(i * width + width - 2) * 4 + 1] =
1050 static_cast<T
>(0.25f * grbg[i * width - 2] + 0.25f * grbg[(i + 1) * width - 3] +
1051 0.25f * grbg[(i + 1) * width - 1] + 0.25f * grbg[(i + 2) * width - 2]);
1052 rgba[(i * width + width - 2) * 4 + 2] = grbg[(i + 1) * width - 2];
1057 for (
unsigned int i = 1; i < height - 1; i++) {
1059 rgba[(i * width + width - 1) * 4 + 0] = grbg[(i + 1) * width - 1];
1060 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 2];
1061 rgba[(i * width + width - 1) * 4 + 2] =
1062 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1064 rgba[(i * width + width - 1) * 4 + 0] =
1065 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
1066 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 1];
1067 rgba[(i * width + width - 1) * 4 + 2] = grbg[(i + 1) * width - 2];
1072 for (
unsigned int j = 1; j < width - 1; j++) {
1074 rgba[((height - 2) * width + j) * 4 + 0] =
1075 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1076 rgba[((height - 2) * width + j) * 4 + 1] = grbg[(height - 2) * width + j];
1077 rgba[((height - 2) * width + j) * 4 + 2] =
1078 static_cast<T
>(0.5f * grbg[(height - 3) * width + j] + 0.5f * grbg[(height - 1) * width + j]);
1080 rgba[((height - 2) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
1081 rgba[((height - 2) * width + j) * 4 + 1] =
1082 static_cast<T
>(0.25f * grbg[(height - 3) * width + j] + 0.25f * grbg[(height - 2) * width + j - 1] +
1083 0.25f * grbg[(height - 2) * width + j + 1] + 0.25f * grbg[(height - 1) * width + j]);
1084 rgba[((height - 2) * width + j) * 4 + 2] =
1085 static_cast<T
>(0.25f * grbg[(height - 3) * width + j - 1] + 0.25f * grbg[(height - 3) * width + j + 1] +
1086 0.25f * grbg[(height - 1) * width + j - 1] + 0.25f * grbg[(height - 1) * width + j + 1]);
1091 for (
unsigned int j = 1; j < width - 1; j++) {
1093 rgba[((height - 1) * width + j) * 4 + 0] =
1094 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1095 rgba[((height - 1) * width + j) * 4 + 1] =
1096 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1097 rgba[((height - 1) * width + j) * 4 + 2] = grbg[(height - 1) * width + j];
1099 rgba[((height - 1) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
1100 rgba[((height - 1) * width + j) * 4 + 1] = grbg[(height - 1) * width + j];
1101 rgba[((height - 1) * width + j) * 4 + 2] =
1102 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1106#if defined _OPENMP && _OPENMP >= 200711
1108 omp_set_num_threads(
static_cast<int>(nThreads));
1110#pragma omp parallel for schedule(dynamic)
1114 for (
unsigned int i = 2; i < height - 2; i++) {
1115 for (
unsigned int j = 2; j < width - 2; j++) {
1116 if (i % 2 == 0 && j % 2 == 0) {
1117 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(grbg, width, i, j);
1118 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
1119 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(grbg, width, i, j);
1120 }
else if (i % 2 == 0 && j % 2 != 0) {
1121 rgba[(i * width + j) * 4 + 0] = grbg[i * width + j];
1122 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1123 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(grbg, width, i, j);
1124 }
else if (i % 2 != 0 && j % 2 == 0) {
1125 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(grbg, width, i, j);
1126 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1127 rgba[(i * width + j) * 4 + 2] = grbg[i * width + j];
1129 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(grbg, width, i, j);
1130 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
1131 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(grbg, width, i, j);
1137template <
typename T>
1138void demosaicRGGBToRGBaMalvarTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1140 m_assert(
"width must be >= 4", width >= 4);
1141 m_assert(
"height must be >= 4", height >= 4);
1142 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1143 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1148 rgba[2] = rggb[width + 1];
1151 rgba[(width - 1) * 4 + 0] = rggb[width - 2];
1152 rgba[(width - 1) * 4 + 1] = rggb[width - 1];
1153 rgba[(width - 1) * 4 + 2] = rggb[2 * width - 1];
1156 rgba[((height - 1) * width) * 4 + 0] = rggb[(height - 2) * width];
1157 rgba[((height - 1) * width) * 4 + 1] = rggb[(height - 1) * width];
1158 rgba[((height - 1) * width) * 4 + 2] = rggb[(height - 1) * width + 1];
1161 rgba[((height - 1) * width + width - 1) * 4 + 0] = rggb[(height - 1) * width - 2];
1162 rgba[((height - 1) * width + width - 1) * 4 + 1] = rggb[height * width - 2];
1163 rgba[((height - 1) * width + width - 1) * 4 + 2] = rggb[height * width - 1];
1166 for (
unsigned int j = 1; j < width - 1; j++) {
1168 rgba[j * 4 + 0] = rggb[j];
1169 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
1170 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1172 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
1173 rgba[j * 4 + 1] = rggb[j];
1174 rgba[j * 4 + 2] = rggb[width + j];
1179 for (
unsigned int j = 1; j < width - 1; j++) {
1181 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * rggb[j] + 0.5f * rggb[2 * width + j]);
1182 rgba[(width + j) * 4 + 1] = rggb[width + j];
1183 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1185 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.25f * rggb[j - 1] + 0.25f * rggb[j + 1] +
1186 0.25f * rggb[2 * width + j - 1] + 0.25f * rggb[2 * width + j + 1]);
1187 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * rggb[j] + 0.25f * rggb[width + j - 1] +
1188 0.25f * rggb[width + j + 1] + 0.25f * rggb[2 * width + j]);
1189 rgba[(width + j) * 4 + 2] = rggb[width + j];
1194 for (
unsigned int i = 1; i < height - 1; i++) {
1196 rgba[i * width * 4 + 0] = rggb[i * width];
1197 rgba[i * width * 4 + 1] = rggb[i * width + 1];
1198 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1200 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(i - 1) * width] + 0.5f * rggb[(i + 1) * width]);
1201 rgba[i * width * 4 + 1] = rggb[i * width];
1202 rgba[i * width * 4 + 2] = rggb[i * width + 1];
1207 for (
unsigned int i = 1; i < height - 1; i++) {
1209 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.5f * rggb[i * width] + 0.5f * rggb[i * width + 2]);
1210 rgba[(i * width + 1) * 4 + 1] = rggb[i * width + 1];
1211 rgba[(i * width + 1) * 4 + 2] =
1212 static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1214 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.25f * rggb[(i - 1) * width] + 0.25f * rggb[(i - 1) * width + 2] +
1215 0.25f * rggb[(i + 1) * width] + 0.25f * rggb[(i + 1) * width + 2]);
1216 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * rggb[(i - 1) * width + 1] + 0.25f * rggb[i * width] +
1217 0.25f * rggb[i * width + 2] + 0.25f * rggb[(i + 1) * width + 1]);
1218 rgba[(i * width + 1) * 4 + 2] = rggb[i * width + 1];
1223 for (
unsigned int i = 1; i < height - 1; i++) {
1225 rgba[(i * width + width - 2) * 4 + 0] = rggb[(i + 1) * width - 2];
1226 rgba[(i * width + width - 2) * 4 + 1] =
1227 static_cast<T
>(0.25f * rggb[i * width - 2] + 0.25f * rggb[(i + 1) * width - 3] +
1228 0.25f * rggb[(i + 1) * width - 1] + 0.25f * rggb[(i + 2) * width - 2]);
1229 rgba[(i * width + width - 2) * 4 + 2] =
1230 static_cast<T
>(0.25f * rggb[i * width - 3] + 0.25f * rggb[i * width - 1] + 0.25f * rggb[(i + 2) * width - 3] +
1231 0.25f * rggb[(i + 2) * width - 1]);
1233 rgba[(i * width + width - 2) * 4 + 0] =
1234 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1235 rgba[(i * width + width - 2) * 4 + 1] = rggb[(i + 1) * width - 2];
1236 rgba[(i * width + width - 2) * 4 + 2] =
1237 static_cast<T
>(0.5f * rggb[(i + 1) * width - 3] + 0.5f * rggb[(i + 1) * width - 1]);
1242 for (
unsigned int i = 1; i < height - 1; i++) {
1244 rgba[(i * width + width - 1) * 4 + 0] = rggb[(i + 1) * width - 2];
1245 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 1];
1246 rgba[(i * width + width - 1) * 4 + 2] =
1247 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
1249 rgba[(i * width + width - 1) * 4 + 0] =
1250 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1251 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 2];
1252 rgba[(i * width + width - 1) * 4 + 2] = rggb[(i + 1) * width - 1];
1257 for (
unsigned int j = 1; j < width - 1; j++) {
1259 rgba[((height - 2) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
1260 rgba[((height - 2) * width + j) * 4 + 1] =
1261 static_cast<T
>(0.25f * rggb[(height - 3) * width + j] + 0.25f * rggb[(height - 2) * width + j - 1] +
1262 0.25f * rggb[(height - 2) * width + j + 1] + 0.25f * rggb[(height - 1) * width + j]);
1263 rgba[((height - 2) * width + j) * 4 + 2] =
1264 static_cast<T
>(0.25f * rggb[(height - 3) * width + j - 1] + 0.25f * rggb[(height - 3) * width + j + 1] +
1265 0.25f * rggb[(height - 1) * width + j - 1] + 0.25f * rggb[(height - 1) * width + j + 1]);
1267 rgba[((height - 2) * width + j) * 4 + 0] =
1268 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1269 rgba[((height - 2) * width + j) * 4 + 1] = rggb[(height - 2) * width + j];
1270 rgba[((height - 2) * width + j) * 4 + 2] =
1271 static_cast<T
>(0.5f * rggb[(height - 3) * width + j] + 0.5f * rggb[(height - 1) * width + j]);
1276 for (
unsigned int j = 1; j < width - 1; j++) {
1278 rgba[((height - 1) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
1279 rgba[((height - 1) * width + j) * 4 + 1] = rggb[(height - 1) * width + j];
1280 rgba[((height - 1) * width + j) * 4 + 2] =
1281 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1283 rgba[((height - 1) * width + j) * 4 + 0] =
1284 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1285 rgba[((height - 1) * width + j) * 4 + 1] =
1286 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1287 rgba[((height - 1) * width + j) * 4 + 2] = rggb[(height - 1) * width + j];
1291#if defined _OPENMP && _OPENMP >= 200711
1293 omp_set_num_threads(
static_cast<int>(nThreads));
1295#pragma omp parallel for schedule(dynamic)
1299 for (
unsigned int i = 2; i < height - 2; i++) {
1300 for (
unsigned int j = 2; j < width - 2; j++) {
1301 if (i % 2 == 0 && j % 2 == 0) {
1302 rgba[(i * width + j) * 4 + 0] = rggb[i * width + j];
1303 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1304 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(rggb, width, i, j);
1305 }
else if (i % 2 == 0 && j % 2 != 0) {
1306 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(rggb, width, i, j);
1307 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
1308 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(rggb, width, i, j);
1309 }
else if (i % 2 != 0 && j % 2 == 0) {
1310 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(rggb, width, i, j);
1311 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
1312 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(rggb, width, i, j);
1314 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(rggb, width, i, j);
1315 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1316 rgba[(i * width + j) * 4 + 2] = rggb[i * width + j];
static _Tp saturate(unsigned char v)