41 #ifndef vpBAYERCONVERSION_H
42 #define vpBAYERCONVERSION_H
46 #include <visp3/core/vpMath.h>
50 #define m_assert(msg, expr) assert(((void)(msg), (expr)))
53 template <
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]);
58 template <
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]);
63 template <
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]);
69 template <
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]);
76 template <
typename T> T demosaicPhiMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
78 return vpMath::saturate<T>(
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]) *
86 template <
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]) *
96 template <
typename T> T demosaicCheckerMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
98 return vpMath::saturate<T>(
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]) *
105 template <
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]) *
113 template <
typename T>
114 void 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];
150 rgba[j * 4 + 0] = bggr[width + j];
151 rgba[j * 4 + 1] = bggr[j];
152 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
157 for (
unsigned int i = 1; i < height - 1; ++i) {
159 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
160 rgba[i * width * 4 + 1] = bggr[i * width + 1];
161 rgba[i * width * 4 + 2] = bggr[i * width];
164 rgba[i * width * 4 + 0] = bggr[i * width + 1];
165 rgba[i * width * 4 + 1] = bggr[i * width];
166 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(i - 1) * width] + 0.5f * bggr[(i + 1) * width]);
171 for (
unsigned int i = 1; i < height - 1; ++i) {
173 rgba[(i * width + width - 1) * 4 + 0] =
174 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
175 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 1];
176 rgba[(i * width + width - 1) * 4 + 2] = bggr[(i + 1) * width - 2];
179 rgba[(i * width + width - 1) * 4 + 0] = bggr[(i + 1) * width - 1];
180 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 2];
181 rgba[(i * width + width - 1) * 4 + 2] =
182 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
187 for (
unsigned int j = 1; j < width - 1; ++j) {
189 rgba[((height - 1) * width + j) * 4 + 0] =
190 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
191 rgba[((height - 1) * width + j) * 4 + 1] = bggr[(height - 1) * width + j];
192 rgba[((height - 1) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
195 rgba[((height - 1) * width + j) * 4 + 0] = bggr[(height - 1) * width + j];
196 rgba[((height - 1) * width + j) * 4 + 1] =
197 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
198 rgba[((height - 1) * width + j) * 4 + 2] =
199 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
203 #if defined(_OPENMP) && (_OPENMP >= 200711)
205 omp_set_num_threads(
static_cast<int>(nThreads));
207 #pragma omp parallel for schedule(dynamic)
211 for (
unsigned int i = 1; i < height - 1; ++i) {
212 for (
unsigned int j = 1; j < width - 1; ++j) {
213 if (i % 2 == 0 && j % 2 == 0) {
214 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(bggr, width, i, j);
215 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
216 rgba[(i * width + j) * 4 + 2] = bggr[i * width + j];
218 else if (i % 2 == 0 && j % 2 != 0) {
219 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(bggr, width, i, j);
220 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
221 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(bggr, width, i, j);
223 else if (i % 2 != 0 && j % 2 == 0) {
224 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(bggr, width, i, j);
225 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
226 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(bggr, width, i, j);
229 rgba[(i * width + j) * 4 + 0] = bggr[i * width + j];
230 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
231 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(bggr, width, i, j);
237 template <
typename T>
238 void demosaicGBRGToRGBaBilinearTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
239 unsigned int nThreads)
241 m_assert(
"width must be >= 4", width >= 4);
242 m_assert(
"height must be >= 4", height >= 4);
243 m_assert(
"width must be a multiple of 2", width % 2 == 0);
244 m_assert(
"height must be a multiple of 2", height % 2 == 0);
247 rgba[0] = gbrg[width];
252 rgba[(width - 1) * 4 + 0] = gbrg[2 * width - 2];
253 rgba[(width - 1) * 4 + 1] = gbrg[width - 2];
254 rgba[(width - 1) * 4 + 2] = gbrg[width - 1];
257 rgba[((height - 1) * width) * 4 + 0] = gbrg[(height - 1) * width];
258 rgba[((height - 1) * width) * 4 + 1] = gbrg[(height - 1) * width + 1];
259 rgba[((height - 1) * width) * 4 + 2] = gbrg[(height - 2) * width + 1];
262 rgba[((height - 1) * width + width - 1) * 4 + 0] = gbrg[height * width - 2];
263 rgba[((height - 1) * width + width - 1) * 4 + 1] = gbrg[height * width - 1];
264 rgba[((height - 1) * width + width - 1) * 4 + 2] = gbrg[(height - 1) * width - 1];
267 for (
unsigned int j = 1; j < width - 1; ++j) {
269 rgba[j * 4 + 0] = gbrg[width + j];
270 rgba[j * 4 + 1] = gbrg[j];
271 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
274 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
275 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
276 rgba[j * 4 + 2] = gbrg[j];
281 for (
unsigned int i = 1; i < height - 1; ++i) {
283 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
284 rgba[i * width * 4 + 1] = gbrg[i * width];
285 rgba[i * width * 4 + 2] = gbrg[i * width + 1];
288 rgba[i * width * 4 + 0] = gbrg[i * width];
289 rgba[i * width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
290 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
295 for (
unsigned int i = 1; i < height - 1; ++i) {
297 rgba[(i * width + width - 1) * 4 + 0] =
298 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
299 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 2];
300 rgba[(i * width + width - 1) * 4 + 2] = gbrg[(i + 1) * width - 1];
303 rgba[(i * width + width - 1) * 4 + 0] = gbrg[(i + 1) * width - 2];
304 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 1];
305 rgba[(i * width + width - 1) * 4 + 2] =
306 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
311 for (
unsigned int j = 1; j < width - 1; ++j) {
313 rgba[((height - 1) * width + j) * 4 + 0] = gbrg[(height - 1) * width + j];
314 rgba[((height - 1) * width + j) * 4 + 1] =
315 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
316 rgba[((height - 1) * width + j) * 4 + 2] =
317 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
320 rgba[((height - 1) * width + j) * 4 + 0] =
321 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
322 rgba[((height - 1) * width + j) * 4 + 1] = gbrg[(height - 1) * width + j];
323 rgba[((height - 1) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
327 #if defined(_OPENMP) && (_OPENMP >= 200711)
329 omp_set_num_threads(
static_cast<int>(nThreads));
331 #pragma omp parallel for schedule(dynamic)
335 for (
unsigned int i = 1; i < height - 1; ++i) {
336 for (
unsigned int j = 1; j < width - 1; ++j) {
337 if (i % 2 == 0 && j % 2 == 0) {
338 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(gbrg, width, i, j);
339 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
340 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(gbrg, width, i, j);
342 else if (i % 2 == 0 && j % 2 != 0) {
343 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(gbrg, width, i, j);
344 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
345 rgba[(i * width + j) * 4 + 2] = gbrg[i * width + j];
347 else if (i % 2 != 0 && j % 2 == 0) {
348 rgba[(i * width + j) * 4 + 0] = gbrg[i * width + j];
349 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
350 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(gbrg, width, i, j);
353 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(gbrg, width, i, j);
354 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
355 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(gbrg, width, i, j);
361 template <
typename T>
362 void demosaicGRBGToRGBaBilinearTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
363 unsigned int nThreads)
365 m_assert(
"width must be >= 4", width >= 4);
366 m_assert(
"height must be >= 4", height >= 4);
367 m_assert(
"width must be a multiple of 2", width % 2 == 0);
368 m_assert(
"height must be a multiple of 2", height % 2 == 0);
373 rgba[2] = grbg[width];
376 rgba[(width - 1) * 4 + 0] = grbg[width - 1];
377 rgba[(width - 1) * 4 + 1] = grbg[width - 2];
378 rgba[(width - 1) * 4 + 2] = grbg[2 * width - 2];
381 rgba[((height - 1) * width) * 4 + 0] = grbg[(height - 2) * width + 1];
382 rgba[((height - 1) * width) * 4 + 1] = grbg[(height - 1) * width + 1];
383 rgba[((height - 1) * width) * 4 + 2] = grbg[(height - 1) * width];
386 rgba[((height - 1) * width + width - 1) * 4 + 0] = grbg[(height - 1) * width - 1];
387 rgba[((height - 1) * width + width - 1) * 4 + 1] = grbg[height * width - 1];
388 rgba[((height - 1) * width + width - 1) * 4 + 2] = grbg[height * width - 2];
391 for (
unsigned int j = 1; j < width - 1; ++j) {
393 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
394 rgba[j * 4 + 1] = grbg[j];
395 rgba[j * 4 + 2] = grbg[width + j];
398 rgba[j * 4 + 0] = grbg[j];
399 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
400 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
405 for (
unsigned int i = 1; i < height - 1; ++i) {
407 rgba[i * width * 4 + 0] = grbg[i * width + 1];
408 rgba[i * width * 4 + 1] = grbg[i * width];
409 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(i - 1) * width] + 0.5f * grbg[(i + 1) * width]);
412 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
413 rgba[i * width * 4 + 1] = grbg[i * width + 1];
414 rgba[i * width * 4 + 2] = grbg[i * width];
419 for (
unsigned int i = 1; i < height - 1; ++i) {
421 rgba[(i * width + width - 1) * 4 + 0] = grbg[(i + 1) * width - 1];
422 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 2];
423 rgba[(i * width + width - 1) * 4 + 2] =
424 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
427 rgba[(i * width + width - 1) * 4 + 0] =
428 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
429 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 1];
430 rgba[(i * width + width - 1) * 4 + 2] = grbg[(i + 1) * width - 2];
435 for (
unsigned int j = 1; j < width - 1; ++j) {
437 rgba[((height - 1) * width + j) * 4 + 0] =
438 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
439 rgba[((height - 1) * width + j) * 4 + 1] =
440 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
441 rgba[((height - 1) * width + j) * 4 + 2] = grbg[(height - 1) * width + j];
444 rgba[((height - 1) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
445 rgba[((height - 1) * width + j) * 4 + 1] = grbg[(height - 1) * width + j];
446 rgba[((height - 1) * width + j) * 4 + 2] =
447 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
451 #if defined(_OPENMP) && (_OPENMP >= 200711)
453 omp_set_num_threads(
static_cast<int>(nThreads));
455 #pragma omp parallel for schedule(dynamic)
459 for (
unsigned int i = 1; i < height - 1; ++i) {
460 for (
unsigned int j = 1; j < width - 1; ++j) {
461 if (i % 2 == 0 && j % 2 == 0) {
462 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(grbg, width, i, j);
463 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
464 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(grbg, width, i, j);
466 else if (i % 2 == 0 && j % 2 != 0) {
467 rgba[(i * width + j) * 4 + 0] = grbg[i * width + j];
468 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
469 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(grbg, width, i, j);
471 else if (i % 2 != 0 && j % 2 == 0) {
472 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(grbg, width, i, j);
473 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
474 rgba[(i * width + j) * 4 + 2] = grbg[i * width + j];
477 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(grbg, width, i, j);
478 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
479 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(grbg, width, i, j);
485 template <
typename T>
486 void demosaicRGGBToRGBaBilinearTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
487 unsigned int nThreads)
489 m_assert(
"width must be >= 4", width >= 4);
490 m_assert(
"height must be >= 4", height >= 4);
491 m_assert(
"width must be a multiple of 2", width % 2 == 0);
492 m_assert(
"height must be a multiple of 2", height % 2 == 0);
497 rgba[2] = rggb[width + 1];
500 rgba[(width - 1) * 4 + 0] = rggb[width - 2];
501 rgba[(width - 1) * 4 + 1] = rggb[width - 1];
502 rgba[(width - 1) * 4 + 2] = rggb[2 * width - 1];
505 rgba[((height - 1) * width) * 4 + 0] = rggb[(height - 2) * width];
506 rgba[((height - 1) * width) * 4 + 1] = rggb[(height - 1) * width];
507 rgba[((height - 1) * width) * 4 + 2] = rggb[(height - 1) * width + 1];
510 rgba[((height - 1) * width + width - 1) * 4 + 0] = rggb[(height - 1) * width - 2];
511 rgba[((height - 1) * width + width - 1) * 4 + 1] = rggb[height * width - 2];
512 rgba[((height - 1) * width + width - 1) * 4 + 2] = rggb[height * width - 1];
515 for (
unsigned int j = 1; j < width - 1; ++j) {
517 rgba[j * 4 + 0] = rggb[j];
518 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
519 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
522 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
523 rgba[j * 4 + 1] = rggb[j];
524 rgba[j * 4 + 2] = rggb[width + j];
529 for (
unsigned int i = 1; i < height - 1; ++i) {
531 rgba[i * width * 4 + 0] = rggb[i * width];
532 rgba[i * width * 4 + 1] = rggb[i * width + 1];
533 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
536 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(i - 1) * width] + 0.5f * rggb[(i + 1) * width]);
537 rgba[i * width * 4 + 1] = rggb[i * width];
538 rgba[i * width * 4 + 2] = rggb[i * width + 1];
543 for (
unsigned int i = 1; i < height - 1; ++i) {
545 rgba[(i * width + width - 1) * 4 + 0] = rggb[(i + 1) * width - 2];
546 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 1];
547 rgba[(i * width + width - 1) * 4 + 2] =
548 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
551 rgba[(i * width + width - 1) * 4 + 0] =
552 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
553 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 2];
554 rgba[(i * width + width - 1) * 4 + 2] = rggb[(i + 1) * width - 1];
559 for (
unsigned int j = 1; j < width - 1; ++j) {
561 rgba[((height - 1) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
562 rgba[((height - 1) * width + j) * 4 + 1] = rggb[(height - 1) * width + j];
563 rgba[((height - 1) * width + j) * 4 + 2] =
564 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
567 rgba[((height - 1) * width + j) * 4 + 0] =
568 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
569 rgba[((height - 1) * width + j) * 4 + 1] =
570 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
571 rgba[((height - 1) * width + j) * 4 + 2] = rggb[(height - 1) * width + j];
575 #if defined(_OPENMP) && (_OPENMP >= 200711)
577 omp_set_num_threads(
static_cast<int>(nThreads));
579 #pragma omp parallel for schedule(dynamic)
583 for (
unsigned int i = 1; i < height - 1; ++i) {
584 for (
unsigned int j = 1; j < width - 1; ++j) {
585 if (i % 2 == 0 && j % 2 == 0) {
586 rgba[(i * width + j) * 4 + 0] = rggb[i * width + j];
587 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
588 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(rggb, width, i, j);
590 else if (i % 2 == 0 && j % 2 != 0) {
591 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(rggb, width, i, j);
592 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
593 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(rggb, width, i, j);
595 else if (i % 2 != 0 && j % 2 == 0) {
596 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(rggb, width, i, j);
597 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
598 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(rggb, width, i, j);
601 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(rggb, width, i, j);
602 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
603 rgba[(i * width + j) * 4 + 2] = rggb[i * width + j];
611 template <
typename T>
612 void demosaicBGGRToRGBaMalvarTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
614 m_assert(
"width must be >= 4", width >= 4);
615 m_assert(
"height must be >= 4", height >= 4);
616 m_assert(
"width must be a multiple of 2", width % 2 == 0);
617 m_assert(
"height must be a multiple of 2", height % 2 == 0);
620 rgba[0] = bggr[width + 1];
625 rgba[(width - 1) * 4 + 0] = bggr[2 * width - 1];
626 rgba[(width - 1) * 4 + 1] = bggr[width - 1];
627 rgba[(width - 1) * 4 + 2] = bggr[width - 2];
630 rgba[((height - 1) * width) * 4 + 0] = bggr[(height - 1) * width + 1];
631 rgba[((height - 1) * width) * 4 + 1] = bggr[(height - 1) * width];
632 rgba[((height - 1) * width) * 4 + 2] = bggr[(height - 2) * width];
635 rgba[((height - 1) * width + width - 1) * 4 + 0] = bggr[height * width - 1];
636 rgba[((height - 1) * width + width - 1) * 4 + 1] = bggr[height * width - 2];
637 rgba[((height - 1) * width + width - 1) * 4 + 2] = bggr[(height - 1) * width - 2];
640 for (
unsigned int j = 1; j < width - 1; ++j) {
642 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
643 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
644 rgba[j * 4 + 2] = bggr[j];
647 rgba[j * 4 + 0] = bggr[width + j];
648 rgba[j * 4 + 1] = bggr[j];
649 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
654 for (
unsigned int j = 1; j < width - 1; ++j) {
656 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
657 rgba[(width + j) * 4 + 1] = bggr[width + j];
658 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * bggr[j] + 0.5f * bggr[2 * width + j]);
661 rgba[(width + j) * 4 + 0] = bggr[width + j];
662 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * bggr[j] + 0.25f * bggr[width + j - 1] +
663 0.25f * bggr[width + j + 1] + 0.25f * bggr[2 * width + j]);
664 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.25f * bggr[j - 1] + 0.25f * bggr[j + 1] +
665 0.25f * bggr[2 * width + j - 1] + 0.25f * bggr[2 * width + j + 1]);
670 for (
unsigned int i = 1; i < height - 1; ++i) {
672 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
673 rgba[i * width * 4 + 1] = bggr[i * width + 1];
674 rgba[i * width * 4 + 2] = bggr[i * width];
677 rgba[i * width * 4 + 0] = bggr[i * width + 1];
678 rgba[i * width * 4 + 1] = bggr[i * width];
679 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(i - 1) * width] + 0.5f * bggr[(i + 1) * width]);
684 for (
unsigned int i = 1; i < height - 1; ++i) {
686 rgba[(i * width + 1) * 4 + 0] =
687 static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
688 rgba[(i * width + 1) * 4 + 1] = bggr[i * width + 1];
689 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.5f * bggr[i * width] + 0.5f * bggr[i * width + 2]);
692 rgba[(i * width + 1) * 4 + 0] = bggr[i * width + 1];
693 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * bggr[(i - 1) * width + 1] + 0.25f * bggr[i * width] +
694 0.25f * bggr[i * width + 2] + 0.25f * bggr[(i + 1) * width + 1]);
695 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.25f * bggr[(i - 1) * width] + 0.25f * bggr[(i - 1) * width + 2] +
696 0.25f * bggr[(i + 1) * width] + 0.25f * bggr[(i + 1) * width + 2]);
701 for (
unsigned int i = 1; i < height - 1; ++i) {
703 rgba[(i * width + width - 2) * 4 + 0] =
704 static_cast<T
>(0.25f * bggr[i * width - 3] + 0.25f * bggr[i * width - 1] + 0.25f * bggr[(i + 2) * width - 3] +
705 0.25f * bggr[(i + 2) * width - 1]);
706 rgba[(i * width + width - 2) * 4 + 1] =
707 static_cast<T
>(0.25f * bggr[i * width - 2] + 0.25f * bggr[(i + 1) * width - 3] +
708 0.25f * bggr[(i + 1) * width - 1] + 0.25f * bggr[(i + 2) * width - 2]);
709 rgba[(i * width + width - 2) * 4 + 2] = bggr[(i + 1) * width - 2];
712 rgba[(i * width + width - 2) * 4 + 0] =
713 static_cast<T
>(0.5f * bggr[(i + 1) * width - 3] + 0.5f * bggr[(i + 1) * width - 1]);
714 rgba[(i * width + width - 2) * 4 + 1] = bggr[(i + 1) * width - 2];
715 rgba[(i * width + width - 2) * 4 + 2] =
716 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
721 for (
unsigned int i = 1; i < height - 1; ++i) {
723 rgba[(i * width + width - 1) * 4 + 0] =
724 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
725 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 1];
726 rgba[(i * width + width - 1) * 4 + 2] = bggr[(i + 1) * width - 2];
729 rgba[(i * width + width - 1) * 4 + 0] = bggr[(i + 1) * width - 1];
730 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 2];
731 rgba[(i * width + width - 1) * 4 + 2] =
732 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
737 for (
unsigned int j = 1; j < width - 1; ++j) {
739 rgba[((height - 2) * width + j) * 4 + 0] =
740 static_cast<T
>(0.25f * bggr[(height - 3) * width + j - 1] + 0.25f * bggr[(height - 3) * width + j + 1] +
741 0.25f * bggr[(height - 1) * width + j - 1] + 0.25f * bggr[(height - 1) * width + j + 1]);
742 rgba[((height - 2) * width + j) * 4 + 1] =
743 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
744 rgba[((height - 2) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
747 rgba[((height - 2) * width + j) * 4 + 0] =
748 static_cast<T
>(0.5f * bggr[(height - 3) * width + j] + 0.5f * bggr[(height - 1) * width + j]);
749 rgba[((height - 2) * width + j) * 4 + 1] = bggr[(height - 2) * width + j];
750 rgba[((height - 2) * width + j) * 4 + 2] =
751 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
756 for (
unsigned int j = 1; j < width - 1; ++j) {
758 rgba[((height - 1) * width + j) * 4 + 0] =
759 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
760 rgba[((height - 1) * width + j) * 4 + 1] = bggr[(height - 1) * width + j];
761 rgba[((height - 1) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
764 rgba[((height - 1) * width + j) * 4 + 0] = bggr[(height - 1) * width + j];
765 rgba[((height - 1) * width + j) * 4 + 1] =
766 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
767 rgba[((height - 1) * width + j) * 4 + 2] =
768 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
772 #if defined(_OPENMP) && (_OPENMP >= 200711)
774 omp_set_num_threads(
static_cast<int>(nThreads));
776 #pragma omp parallel for schedule(dynamic)
780 for (
unsigned int i = 2; i < height - 2; ++i) {
781 for (
unsigned int j = 2; j < width - 2; ++j) {
782 if (i % 2 == 0 && j % 2 == 0) {
783 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(bggr, width, i, j);
784 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
785 rgba[(i * width + j) * 4 + 2] = bggr[i * width + j];
787 else if (i % 2 == 0 && j % 2 != 0) {
788 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(bggr, width, i, j);
789 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
790 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(bggr, width, i, j);
792 else if (i % 2 != 0 && j % 2 == 0) {
793 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(bggr, width, i, j);
794 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
795 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(bggr, width, i, j);
798 rgba[(i * width + j) * 4 + 0] = bggr[i * width + j];
799 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
800 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(bggr, width, i, j);
806 template <
typename T>
807 void demosaicGBRGToRGBaMalvarTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
809 m_assert(
"width must be >= 4", width >= 4);
810 m_assert(
"height must be >= 4", height >= 4);
811 m_assert(
"width must be a multiple of 2", width % 2 == 0);
812 m_assert(
"height must be a multiple of 2", height % 2 == 0);
815 rgba[0] = gbrg[width];
820 rgba[(width - 1) * 4 + 0] = gbrg[2 * width - 2];
821 rgba[(width - 1) * 4 + 1] = gbrg[width - 2];
822 rgba[(width - 1) * 4 + 2] = gbrg[width - 1];
825 rgba[((height - 1) * width) * 4 + 0] = gbrg[(height - 1) * width];
826 rgba[((height - 1) * width) * 4 + 1] = gbrg[(height - 1) * width + 1];
827 rgba[((height - 1) * width) * 4 + 2] = gbrg[(height - 2) * width + 1];
830 rgba[((height - 1) * width + width - 1) * 4 + 0] = gbrg[height * width - 2];
831 rgba[((height - 1) * width + width - 1) * 4 + 1] = gbrg[height * width - 1];
832 rgba[((height - 1) * width + width - 1) * 4 + 2] = gbrg[(height - 1) * width - 1];
835 for (
unsigned int j = 1; j < width - 1; ++j) {
837 rgba[j * 4 + 0] = gbrg[width + j];
838 rgba[j * 4 + 1] = gbrg[j];
839 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
842 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
843 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
844 rgba[j * 4 + 2] = gbrg[j];
849 for (
unsigned int j = 1; j < width - 1; ++j) {
851 rgba[(width + j) * 4 + 0] = gbrg[width + j];
852 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[j] + 0.25f * gbrg[width + j - 1] +
853 0.25f * gbrg[width + j + 1] + 0.25f * gbrg[2 * width + j]);
854 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.25f * gbrg[j - 1] + 0.25f * gbrg[j + 1] +
855 0.25f * gbrg[2 * width + j - 1] + 0.25f * gbrg[2 * width + j + 1]);
858 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
859 rgba[(width + j) * 4 + 1] = gbrg[width + j];
860 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j] + 0.5f * gbrg[2 * width + j]);
865 for (
unsigned int i = 1; i < height - 1; ++i) {
867 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
868 rgba[i * width * 4 + 1] = gbrg[i * width];
869 rgba[i * width * 4 + 2] = gbrg[i * width + 1];
872 rgba[i * width * 4 + 0] = gbrg[i * width];
873 rgba[i * width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
874 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
879 for (
unsigned int i = 1; i < height - 1; ++i) {
881 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width] + 0.25f * gbrg[(i - 1) * width + 2] +
882 0.25f * gbrg[(i + 1) * width] + 0.5f * gbrg[(i + 1) * width + 2]);
883 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width + 1] + 0.25f * gbrg[i * width] +
884 0.25f * gbrg[i * width + 2] + 0.5f * gbrg[(i + 1) * width + 1]);
885 rgba[(i * width + 1) * 4 + 2] = gbrg[i * width + 1];
888 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[i * width] + 0.5f * gbrg[i * width + 2]);
889 rgba[(i * width + 1) * 4 + 1] = gbrg[i * width + 1];
890 rgba[(i * width + 1) * 4 + 2] =
891 static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
896 for (
unsigned int i = 1; i < height - 1; ++i) {
898 rgba[(i * width + width - 2) * 4 + 0] =
899 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
900 rgba[(i * width + width - 2) * 4 + 1] = gbrg[(i + 1) * width - 2];
901 rgba[(i * width + width - 2) * 4 + 2] =
902 static_cast<T
>(0.5f * gbrg[(i + 1) * width - 3] + 0.5f * gbrg[(i + 1) * width - 1]);
905 rgba[(i * width + width - 2) * 4 + 0] = gbrg[(i + 1) * width - 2];
906 rgba[(i * width + width - 2) * 4 + 1] =
907 static_cast<T
>(0.25f * gbrg[i * width - 2] + 0.25f * gbrg[(i + 1) * width - 3] +
908 0.25f * gbrg[(i + 1) * width - 1] + 0.25f * gbrg[(i + 2) * width - 2]);
909 rgba[(i * width + width - 2) * 4 + 2] =
910 static_cast<T
>(0.25f * gbrg[i * width - 3] + 0.25f * gbrg[i * width - 1] + 0.25f * gbrg[(i + 2) * width - 3] +
911 0.25f * gbrg[(i + 2) * width - 1]);
916 for (
unsigned int i = 1; i < height - 1; ++i) {
918 rgba[(i * width + width - 1) * 4 + 0] =
919 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
920 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 2];
921 rgba[(i * width + width - 1) * 4 + 2] = gbrg[(i + 1) * width - 1];
924 rgba[(i * width + width - 1) * 4 + 0] = gbrg[(i + 1) * width - 2];
925 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 1];
926 rgba[(i * width + width - 1) * 4 + 2] =
927 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
932 for (
unsigned int j = 1; j < width - 1; ++j) {
934 rgba[((height - 2) * width + j) * 4 + 0] =
935 static_cast<T
>(0.5f * gbrg[(height - 3) * width + j] + 0.5f * gbrg[(height - 1) * width + j]);
936 rgba[((height - 2) * width + j) * 4 + 1] = gbrg[(height - 2) * width + j];
937 rgba[((height - 2) * width + j) * 4 + 2] =
938 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
941 rgba[((height - 2) * width + j) * 4 + 0] =
942 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j - 1] + 0.25f * gbrg[(height - 3) * width + j + 1] +
943 0.25f * gbrg[(height - 1) * width + j - 1] + 0.25f * gbrg[(height - 1) * width + j + 1]);
944 rgba[((height - 2) * width + j) * 4 + 1] =
945 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j] + 0.25f * gbrg[(height - 2) * width + j - 1] +
946 0.25f * gbrg[(height - 2) * width + j + 1] + 0.25f * gbrg[(height - 1) * width + j]);
947 rgba[((height - 2) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
952 for (
unsigned int j = 1; j < width - 1; ++j) {
954 rgba[((height - 1) * width + j) * 4 + 0] = gbrg[(height - 1) * width + j];
955 rgba[((height - 1) * width + j) * 4 + 1] =
956 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
957 rgba[((height - 1) * width + j) * 4 + 2] =
958 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
961 rgba[((height - 1) * width + j) * 4 + 0] =
962 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
963 rgba[((height - 1) * width + j) * 4 + 1] = gbrg[(height - 1) * width + j];
964 rgba[((height - 1) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
968 #if defined(_OPENMP) && (_OPENMP >= 200711)
970 omp_set_num_threads(
static_cast<int>(nThreads));
972 #pragma omp parallel for schedule(dynamic)
976 for (
unsigned int i = 2; i < height - 2; ++i) {
977 for (
unsigned int j = 2; j < width - 2; ++j) {
978 if (i % 2 == 0 && j % 2 == 0) {
979 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(gbrg, width, i, j);
980 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
981 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(gbrg, width, i, j);
983 else if (i % 2 == 0 && j % 2 != 0) {
984 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(gbrg, width, i, j);
985 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
986 rgba[(i * width + j) * 4 + 2] = gbrg[i * width + j];
988 else if (i % 2 != 0 && j % 2 == 0) {
989 rgba[(i * width + j) * 4 + 0] = gbrg[i * width + j];
990 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
991 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(gbrg, width, i, j);
994 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(gbrg, width, i, j);
995 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
996 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(gbrg, width, i, j);
1002 template <
typename T>
1003 void demosaicGRBGToRGBaMalvarTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1005 m_assert(
"width must be >= 4", width >= 4);
1006 m_assert(
"height must be >= 4", height >= 4);
1007 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1008 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1013 rgba[2] = grbg[width];
1016 rgba[(width - 1) * 4 + 0] = grbg[width - 1];
1017 rgba[(width - 1) * 4 + 1] = grbg[width - 2];
1018 rgba[(width - 1) * 4 + 2] = grbg[2 * width - 2];
1021 rgba[((height - 1) * width) * 4 + 0] = grbg[(height - 2) * width + 1];
1022 rgba[((height - 1) * width) * 4 + 1] = grbg[(height - 1) * width + 1];
1023 rgba[((height - 1) * width) * 4 + 2] = grbg[(height - 1) * width];
1026 rgba[((height - 1) * width + width - 1) * 4 + 0] = grbg[(height - 1) * width - 1];
1027 rgba[((height - 1) * width + width - 1) * 4 + 1] = grbg[height * width - 1];
1028 rgba[((height - 1) * width + width - 1) * 4 + 2] = grbg[height * width - 2];
1031 for (
unsigned int j = 1; j < width - 1; ++j) {
1033 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
1034 rgba[j * 4 + 1] = grbg[j];
1035 rgba[j * 4 + 2] = grbg[width + j];
1038 rgba[j * 4 + 0] = grbg[j];
1039 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
1040 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
1045 for (
unsigned int j = 1; j < width - 1; ++j) {
1047 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.25f * grbg[j - 1] + 0.25f * grbg[j + 1] +
1048 0.25f * grbg[2 * width + j - 1] + 0.25f * grbg[2 * width + j + 1]);
1049 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * grbg[j] + 0.25f * grbg[width + j - 1] +
1050 0.25f * grbg[width + j + 1] + 0.25f * grbg[2 * width + j]);
1051 rgba[(width + j) * 4 + 2] = grbg[width + j];
1054 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * grbg[j] + 0.5f * grbg[2 * width + j]);
1055 rgba[(width + j) * 4 + 1] = grbg[width + j];
1056 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
1061 for (
unsigned int i = 1; i < height - 1; ++i) {
1063 rgba[i * width * 4 + 0] = grbg[i * width + 1];
1064 rgba[i * width * 4 + 1] = grbg[i * width];
1065 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(i - 1) * width] + 0.5f * grbg[(i + 1) * width]);
1068 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1069 rgba[i * width * 4 + 1] = grbg[i * width + 1];
1070 rgba[i * width * 4 + 2] = grbg[i * width];
1075 for (
unsigned int i = 1; i < height - 1; ++i) {
1077 rgba[(i * width + 1) * 4 + 0] = grbg[i * width + 1];
1078 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * grbg[(i - 1) * width + 1] + 0.25f * grbg[i * width] +
1079 0.25f * grbg[i * width + 2] + 0.25f * grbg[(i + 1) * width + 1]);
1080 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.25f * grbg[(i - 1) * width] + 0.25f * grbg[(i - 1) * width + 2] +
1081 0.25f * grbg[(i + 1) * width] + 0.25f * grbg[(i + 1) * width + 2]);
1084 rgba[(i * width + 1) * 4 + 0] =
1085 static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1086 rgba[(i * width + 1) * 4 + 1] = grbg[i * width + 1];
1087 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.5f * grbg[i * width] + 0.5f * grbg[i * width + 2]);
1092 for (
unsigned int i = 1; i < height - 1; ++i) {
1094 rgba[(i * width + width - 2) * 4 + 0] =
1095 static_cast<T
>(0.5f * grbg[(i + 1) * width - 3] + 0.5f * grbg[(i + 1) * width - 1]);
1096 rgba[(i * width + width - 2) * 4 + 1] = grbg[(i + 1) * width - 2];
1097 rgba[(i * width + width - 2) * 4 + 2] =
1098 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1101 rgba[(i * width + width - 2) * 4 + 0] =
1102 static_cast<T
>(0.25f * grbg[i * width - 3] + 0.25f * grbg[i * width - 1] + 0.25f * grbg[(i + 2) * width - 3] +
1103 0.25f * grbg[(i + 2) * width - 1]);
1104 rgba[(i * width + width - 2) * 4 + 1] =
1105 static_cast<T
>(0.25f * grbg[i * width - 2] + 0.25f * grbg[(i + 1) * width - 3] +
1106 0.25f * grbg[(i + 1) * width - 1] + 0.25f * grbg[(i + 2) * width - 2]);
1107 rgba[(i * width + width - 2) * 4 + 2] = grbg[(i + 1) * width - 2];
1112 for (
unsigned int i = 1; i < height - 1; ++i) {
1114 rgba[(i * width + width - 1) * 4 + 0] = grbg[(i + 1) * width - 1];
1115 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 2];
1116 rgba[(i * width + width - 1) * 4 + 2] =
1117 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1120 rgba[(i * width + width - 1) * 4 + 0] =
1121 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
1122 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 1];
1123 rgba[(i * width + width - 1) * 4 + 2] = grbg[(i + 1) * width - 2];
1128 for (
unsigned int j = 1; j < width - 1; ++j) {
1130 rgba[((height - 2) * width + j) * 4 + 0] =
1131 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1132 rgba[((height - 2) * width + j) * 4 + 1] = grbg[(height - 2) * width + j];
1133 rgba[((height - 2) * width + j) * 4 + 2] =
1134 static_cast<T
>(0.5f * grbg[(height - 3) * width + j] + 0.5f * grbg[(height - 1) * width + j]);
1137 rgba[((height - 2) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
1138 rgba[((height - 2) * width + j) * 4 + 1] =
1139 static_cast<T
>(0.25f * grbg[(height - 3) * width + j] + 0.25f * grbg[(height - 2) * width + j - 1] +
1140 0.25f * grbg[(height - 2) * width + j + 1] + 0.25f * grbg[(height - 1) * width + j]);
1141 rgba[((height - 2) * width + j) * 4 + 2] =
1142 static_cast<T
>(0.25f * grbg[(height - 3) * width + j - 1] + 0.25f * grbg[(height - 3) * width + j + 1] +
1143 0.25f * grbg[(height - 1) * width + j - 1] + 0.25f * grbg[(height - 1) * width + j + 1]);
1148 for (
unsigned int j = 1; j < width - 1; ++j) {
1150 rgba[((height - 1) * width + j) * 4 + 0] =
1151 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1152 rgba[((height - 1) * width + j) * 4 + 1] =
1153 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1154 rgba[((height - 1) * width + j) * 4 + 2] = grbg[(height - 1) * width + j];
1157 rgba[((height - 1) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
1158 rgba[((height - 1) * width + j) * 4 + 1] = grbg[(height - 1) * width + j];
1159 rgba[((height - 1) * width + j) * 4 + 2] =
1160 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1164 #if defined(_OPENMP) && (_OPENMP >= 200711)
1166 omp_set_num_threads(
static_cast<int>(nThreads));
1168 #pragma omp parallel for schedule(dynamic)
1172 for (
unsigned int i = 2; i < height - 2; ++i) {
1173 for (
unsigned int j = 2; j < width - 2; ++j) {
1174 if (i % 2 == 0 && j % 2 == 0) {
1175 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(grbg, width, i, j);
1176 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
1177 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(grbg, width, i, j);
1179 else if (i % 2 == 0 && j % 2 != 0) {
1180 rgba[(i * width + j) * 4 + 0] = grbg[i * width + j];
1181 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1182 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(grbg, width, i, j);
1184 else if (i % 2 != 0 && j % 2 == 0) {
1185 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(grbg, width, i, j);
1186 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1187 rgba[(i * width + j) * 4 + 2] = grbg[i * width + j];
1190 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(grbg, width, i, j);
1191 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
1192 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(grbg, width, i, j);
1198 template <
typename T>
1199 void demosaicRGGBToRGBaMalvarTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1201 m_assert(
"width must be >= 4", width >= 4);
1202 m_assert(
"height must be >= 4", height >= 4);
1203 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1204 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1209 rgba[2] = rggb[width + 1];
1212 rgba[(width - 1) * 4 + 0] = rggb[width - 2];
1213 rgba[(width - 1) * 4 + 1] = rggb[width - 1];
1214 rgba[(width - 1) * 4 + 2] = rggb[2 * width - 1];
1217 rgba[((height - 1) * width) * 4 + 0] = rggb[(height - 2) * width];
1218 rgba[((height - 1) * width) * 4 + 1] = rggb[(height - 1) * width];
1219 rgba[((height - 1) * width) * 4 + 2] = rggb[(height - 1) * width + 1];
1222 rgba[((height - 1) * width + width - 1) * 4 + 0] = rggb[(height - 1) * width - 2];
1223 rgba[((height - 1) * width + width - 1) * 4 + 1] = rggb[height * width - 2];
1224 rgba[((height - 1) * width + width - 1) * 4 + 2] = rggb[height * width - 1];
1227 for (
unsigned int j = 1; j < width - 1; ++j) {
1229 rgba[j * 4 + 0] = rggb[j];
1230 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
1231 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1234 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
1235 rgba[j * 4 + 1] = rggb[j];
1236 rgba[j * 4 + 2] = rggb[width + j];
1241 for (
unsigned int j = 1; j < width - 1; ++j) {
1243 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * rggb[j] + 0.5f * rggb[2 * width + j]);
1244 rgba[(width + j) * 4 + 1] = rggb[width + j];
1245 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1248 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.25f * rggb[j - 1] + 0.25f * rggb[j + 1] +
1249 0.25f * rggb[2 * width + j - 1] + 0.25f * rggb[2 * width + j + 1]);
1250 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * rggb[j] + 0.25f * rggb[width + j - 1] +
1251 0.25f * rggb[width + j + 1] + 0.25f * rggb[2 * width + j]);
1252 rgba[(width + j) * 4 + 2] = rggb[width + j];
1257 for (
unsigned int i = 1; i < height - 1; ++i) {
1259 rgba[i * width * 4 + 0] = rggb[i * width];
1260 rgba[i * width * 4 + 1] = rggb[i * width + 1];
1261 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1264 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(i - 1) * width] + 0.5f * rggb[(i + 1) * width]);
1265 rgba[i * width * 4 + 1] = rggb[i * width];
1266 rgba[i * width * 4 + 2] = rggb[i * width + 1];
1271 for (
unsigned int i = 1; i < height - 1; ++i) {
1273 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.5f * rggb[i * width] + 0.5f * rggb[i * width + 2]);
1274 rgba[(i * width + 1) * 4 + 1] = rggb[i * width + 1];
1275 rgba[(i * width + 1) * 4 + 2] =
1276 static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1279 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.25f * rggb[(i - 1) * width] + 0.25f * rggb[(i - 1) * width + 2] +
1280 0.25f * rggb[(i + 1) * width] + 0.25f * rggb[(i + 1) * width + 2]);
1281 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * rggb[(i - 1) * width + 1] + 0.25f * rggb[i * width] +
1282 0.25f * rggb[i * width + 2] + 0.25f * rggb[(i + 1) * width + 1]);
1283 rgba[(i * width + 1) * 4 + 2] = rggb[i * width + 1];
1288 for (
unsigned int i = 1; i < height - 1; ++i) {
1290 rgba[(i * width + width - 2) * 4 + 0] = rggb[(i + 1) * width - 2];
1291 rgba[(i * width + width - 2) * 4 + 1] =
1292 static_cast<T
>(0.25f * rggb[i * width - 2] + 0.25f * rggb[(i + 1) * width - 3] +
1293 0.25f * rggb[(i + 1) * width - 1] + 0.25f * rggb[(i + 2) * width - 2]);
1294 rgba[(i * width + width - 2) * 4 + 2] =
1295 static_cast<T
>(0.25f * rggb[i * width - 3] + 0.25f * rggb[i * width - 1] + 0.25f * rggb[(i + 2) * width - 3] +
1296 0.25f * rggb[(i + 2) * width - 1]);
1299 rgba[(i * width + width - 2) * 4 + 0] =
1300 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1301 rgba[(i * width + width - 2) * 4 + 1] = rggb[(i + 1) * width - 2];
1302 rgba[(i * width + width - 2) * 4 + 2] =
1303 static_cast<T
>(0.5f * rggb[(i + 1) * width - 3] + 0.5f * rggb[(i + 1) * width - 1]);
1308 for (
unsigned int i = 1; i < height - 1; ++i) {
1310 rgba[(i * width + width - 1) * 4 + 0] = rggb[(i + 1) * width - 2];
1311 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 1];
1312 rgba[(i * width + width - 1) * 4 + 2] =
1313 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
1316 rgba[(i * width + width - 1) * 4 + 0] =
1317 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1318 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 2];
1319 rgba[(i * width + width - 1) * 4 + 2] = rggb[(i + 1) * width - 1];
1324 for (
unsigned int j = 1; j < width - 1; ++j) {
1326 rgba[((height - 2) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
1327 rgba[((height - 2) * width + j) * 4 + 1] =
1328 static_cast<T
>(0.25f * rggb[(height - 3) * width + j] + 0.25f * rggb[(height - 2) * width + j - 1] +
1329 0.25f * rggb[(height - 2) * width + j + 1] + 0.25f * rggb[(height - 1) * width + j]);
1330 rgba[((height - 2) * width + j) * 4 + 2] =
1331 static_cast<T
>(0.25f * rggb[(height - 3) * width + j - 1] + 0.25f * rggb[(height - 3) * width + j + 1] +
1332 0.25f * rggb[(height - 1) * width + j - 1] + 0.25f * rggb[(height - 1) * width + j + 1]);
1335 rgba[((height - 2) * width + j) * 4 + 0] =
1336 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1337 rgba[((height - 2) * width + j) * 4 + 1] = rggb[(height - 2) * width + j];
1338 rgba[((height - 2) * width + j) * 4 + 2] =
1339 static_cast<T
>(0.5f * rggb[(height - 3) * width + j] + 0.5f * rggb[(height - 1) * width + j]);
1344 for (
unsigned int j = 1; j < width - 1; ++j) {
1346 rgba[((height - 1) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
1347 rgba[((height - 1) * width + j) * 4 + 1] = rggb[(height - 1) * width + j];
1348 rgba[((height - 1) * width + j) * 4 + 2] =
1349 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1352 rgba[((height - 1) * width + j) * 4 + 0] =
1353 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1354 rgba[((height - 1) * width + j) * 4 + 1] =
1355 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1356 rgba[((height - 1) * width + j) * 4 + 2] = rggb[(height - 1) * width + j];
1360 #if defined(_OPENMP) && (_OPENMP >= 200711)
1362 omp_set_num_threads(
static_cast<int>(nThreads));
1364 #pragma omp parallel for schedule(dynamic)
1368 for (
unsigned int i = 2; i < height - 2; ++i) {
1369 for (
unsigned int j = 2; j < width - 2; ++j) {
1370 if (i % 2 == 0 && j % 2 == 0) {
1371 rgba[(i * width + j) * 4 + 0] = rggb[i * width + j];
1372 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1373 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(rggb, width, i, j);
1375 else if (i % 2 == 0 && j % 2 != 0) {
1376 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(rggb, width, i, j);
1377 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
1378 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(rggb, width, i, j);
1380 else if (i % 2 != 0 && j % 2 == 0) {
1381 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(rggb, width, i, j);
1382 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
1383 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(rggb, width, i, j);
1386 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(rggb, width, i, j);
1387 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1388 rgba[(i * width + j) * 4 + 2] = rggb[i * width + j];