41 #ifndef vpBAYERCONVERSION_H
42 #define vpBAYERCONVERSION_H
44 #include <visp3/core/vpConfig.h>
46 #ifndef VISP_SKIP_BAYER_CONVERSION
50 #include <visp3/core/vpMath.h>
54 #define m_assert(msg, expr) assert(((void)(msg), (expr)))
57 template <
typename T> T demosaicPhiBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
59 return static_cast<T
>(0.5f * bayer[(i - 1) * width + j] + 0.5f * bayer[(i + 1) * width + j]);
62 template <
typename T> T demosaicThetaBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
64 return static_cast<T
>(0.5f * bayer[i * width + j - 1] + 0.5f * bayer[i * width + j + 1]);
67 template <
typename T> T demosaicCheckerBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
69 return static_cast<T
>(0.25f * bayer[(i - 1) * width + j - 1] + 0.25f * bayer[(i - 1) * width + j + 1] +
70 0.25f * bayer[(i + 1) * width + j - 1] + 0.25f * bayer[(i + 1) * width + j + 1]);
73 template <
typename T> T demosaicCrossBilinear(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
75 return static_cast<T
>(0.25f * bayer[(i - 1) * width + j] + 0.25f * bayer[i * width + j - 1] +
76 0.25f * bayer[i * width + j + 1] + 0.25f * bayer[(i + 1) * width + j]);
80 template <
typename T> T demosaicPhiMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
82 return VISP_NAMESPACE_ADDRESSING vpMath::saturate<T>(
83 (-bayer[(i - 2) * width + j] - bayer[(i - 1) * width + j - 1] + 4 * bayer[(i - 1) * width + j] -
84 bayer[(i - 1) * width + j + 1] + 0.5f * bayer[i * width + j - 2] + 5 * bayer[i * width + j] +
85 0.5f * bayer[i * width + j + 2] - bayer[(i + 1) * width + j - 1] + 4 * bayer[(i + 1) * width + j] -
86 bayer[(i + 1) * width + j + 1] - bayer[(i + 2) * width + j]) *
90 template <
typename T> T demosaicThetaMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
92 return VISP_NAMESPACE_ADDRESSING vpMath::saturate<T>((0.5f * bayer[(i - 2) * width + j] - bayer[(i - 1) * width + j - 1] -
93 bayer[(i - 1) * width + j + 1] - bayer[i * width + j - 2] + 4 * bayer[i * width + j - 1] +
94 5 * bayer[i * width + j] + 4 * bayer[i * width + j + 1] - bayer[i * width + j + 2] -
95 bayer[(i + 1) * width + j - 1] - bayer[(i + 1) * width + j + 1] +
96 0.5f * bayer[(i + 2) * width + j]) *
100 template <
typename T> T demosaicCheckerMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
102 return VISP_NAMESPACE_ADDRESSING vpMath::saturate<T>(
103 (-1.5f * bayer[(i - 2) * width + j] + 2 * bayer[(i - 1) * width + j - 1] + 2 * bayer[(i - 1) * width + j + 1] -
104 1.5f * bayer[i * width + j - 2] + 6 * bayer[i * width + j] - 1.5f * bayer[i * width + j + 2] +
105 2 * bayer[(i + 1) * width + j - 1] + 2 * bayer[(i + 1) * width + j + 1] - 1.5f * bayer[(i + 2) * width + j]) *
109 template <
typename T> T demosaicCrossMalvar(
const T *bayer,
unsigned int width,
unsigned int i,
unsigned int j)
111 return VISP_NAMESPACE_ADDRESSING vpMath::saturate<T>((-bayer[(i - 2) * width + j] + 2 * bayer[(i - 1) * width + j] - bayer[i * width + j - 2] +
112 2 * bayer[i * width + j - 1] + 4 * bayer[i * width + j] + 2 * bayer[i * width + j + 1] -
113 bayer[i * width + j + 2] + 2 * bayer[(i + 1) * width + j] - bayer[(i + 2) * width + j]) *
117 template <
typename T>
118 void demosaicBGGRToRGBaBilinearTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
119 unsigned int nThreads)
121 m_assert(
"width must be >= 4", width >= 4);
122 m_assert(
"height must be >= 4", height >= 4);
123 m_assert(
"width must be a multiple of 2", width % 2 == 0);
124 m_assert(
"height must be a multiple of 2", height % 2 == 0);
127 rgba[0] = bggr[width + 1];
132 rgba[(width - 1) * 4 + 0] = bggr[2 * width - 1];
133 rgba[(width - 1) * 4 + 1] = bggr[width - 1];
134 rgba[(width - 1) * 4 + 2] = bggr[width - 2];
137 rgba[((height - 1) * width) * 4 + 0] = bggr[(height - 1) * width + 1];
138 rgba[((height - 1) * width) * 4 + 1] = bggr[(height - 1) * width];
139 rgba[((height - 1) * width) * 4 + 2] = bggr[(height - 2) * width];
142 rgba[((height - 1) * width + width - 1) * 4 + 0] = bggr[height * width - 1];
143 rgba[((height - 1) * width + width - 1) * 4 + 1] = bggr[height * width - 2];
144 rgba[((height - 1) * width + width - 1) * 4 + 2] = bggr[(height - 1) * width - 2];
147 for (
unsigned int j = 1; j < width - 1; ++j) {
149 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
150 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
151 rgba[j * 4 + 2] = bggr[j];
154 rgba[j * 4 + 0] = bggr[width + j];
155 rgba[j * 4 + 1] = bggr[j];
156 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
161 for (
unsigned int i = 1; i < height - 1; ++i) {
163 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
164 rgba[i * width * 4 + 1] = bggr[i * width + 1];
165 rgba[i * width * 4 + 2] = bggr[i * width];
168 rgba[i * width * 4 + 0] = bggr[i * width + 1];
169 rgba[i * width * 4 + 1] = bggr[i * width];
170 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(i - 1) * width] + 0.5f * bggr[(i + 1) * width]);
175 for (
unsigned int i = 1; i < height - 1; ++i) {
177 rgba[(i * width + width - 1) * 4 + 0] =
178 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
179 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 1];
180 rgba[(i * width + width - 1) * 4 + 2] = bggr[(i + 1) * width - 2];
183 rgba[(i * width + width - 1) * 4 + 0] = bggr[(i + 1) * width - 1];
184 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 2];
185 rgba[(i * width + width - 1) * 4 + 2] =
186 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
191 for (
unsigned int j = 1; j < width - 1; ++j) {
193 rgba[((height - 1) * width + j) * 4 + 0] =
194 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
195 rgba[((height - 1) * width + j) * 4 + 1] = bggr[(height - 1) * width + j];
196 rgba[((height - 1) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
199 rgba[((height - 1) * width + j) * 4 + 0] = bggr[(height - 1) * width + j];
200 rgba[((height - 1) * width + j) * 4 + 1] =
201 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
202 rgba[((height - 1) * width + j) * 4 + 2] =
203 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
207 #if defined(_OPENMP) && (_OPENMP >= 200711)
209 omp_set_num_threads(
static_cast<int>(nThreads));
211 #pragma omp parallel for schedule(dynamic)
215 for (
unsigned int i = 1; i < height - 1; ++i) {
216 for (
unsigned int j = 1; j < width - 1; ++j) {
217 if (i % 2 == 0 && j % 2 == 0) {
218 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(bggr, width, i, j);
219 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
220 rgba[(i * width + j) * 4 + 2] = bggr[i * width + j];
222 else if (i % 2 == 0 && j % 2 != 0) {
223 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(bggr, width, i, j);
224 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
225 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(bggr, width, i, j);
227 else if (i % 2 != 0 && j % 2 == 0) {
228 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(bggr, width, i, j);
229 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
230 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(bggr, width, i, j);
233 rgba[(i * width + j) * 4 + 0] = bggr[i * width + j];
234 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(bggr, width, i, j);
235 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(bggr, width, i, j);
241 template <
typename T>
242 void demosaicGBRGToRGBaBilinearTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
243 unsigned int nThreads)
245 m_assert(
"width must be >= 4", width >= 4);
246 m_assert(
"height must be >= 4", height >= 4);
247 m_assert(
"width must be a multiple of 2", width % 2 == 0);
248 m_assert(
"height must be a multiple of 2", height % 2 == 0);
251 rgba[0] = gbrg[width];
256 rgba[(width - 1) * 4 + 0] = gbrg[2 * width - 2];
257 rgba[(width - 1) * 4 + 1] = gbrg[width - 2];
258 rgba[(width - 1) * 4 + 2] = gbrg[width - 1];
261 rgba[((height - 1) * width) * 4 + 0] = gbrg[(height - 1) * width];
262 rgba[((height - 1) * width) * 4 + 1] = gbrg[(height - 1) * width + 1];
263 rgba[((height - 1) * width) * 4 + 2] = gbrg[(height - 2) * width + 1];
266 rgba[((height - 1) * width + width - 1) * 4 + 0] = gbrg[height * width - 2];
267 rgba[((height - 1) * width + width - 1) * 4 + 1] = gbrg[height * width - 1];
268 rgba[((height - 1) * width + width - 1) * 4 + 2] = gbrg[(height - 1) * width - 1];
271 for (
unsigned int j = 1; j < width - 1; ++j) {
273 rgba[j * 4 + 0] = gbrg[width + j];
274 rgba[j * 4 + 1] = gbrg[j];
275 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
278 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
279 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
280 rgba[j * 4 + 2] = gbrg[j];
285 for (
unsigned int i = 1; i < height - 1; ++i) {
287 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
288 rgba[i * width * 4 + 1] = gbrg[i * width];
289 rgba[i * width * 4 + 2] = gbrg[i * width + 1];
292 rgba[i * width * 4 + 0] = gbrg[i * width];
293 rgba[i * width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
294 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
299 for (
unsigned int i = 1; i < height - 1; ++i) {
301 rgba[(i * width + width - 1) * 4 + 0] =
302 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
303 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 2];
304 rgba[(i * width + width - 1) * 4 + 2] = gbrg[(i + 1) * width - 1];
307 rgba[(i * width + width - 1) * 4 + 0] = gbrg[(i + 1) * width - 2];
308 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 1];
309 rgba[(i * width + width - 1) * 4 + 2] =
310 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
315 for (
unsigned int j = 1; j < width - 1; ++j) {
317 rgba[((height - 1) * width + j) * 4 + 0] = gbrg[(height - 1) * width + j];
318 rgba[((height - 1) * width + j) * 4 + 1] =
319 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
320 rgba[((height - 1) * width + j) * 4 + 2] =
321 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
324 rgba[((height - 1) * width + j) * 4 + 0] =
325 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
326 rgba[((height - 1) * width + j) * 4 + 1] = gbrg[(height - 1) * width + j];
327 rgba[((height - 1) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
331 #if defined(_OPENMP) && (_OPENMP >= 200711)
333 omp_set_num_threads(
static_cast<int>(nThreads));
335 #pragma omp parallel for schedule(dynamic)
339 for (
unsigned int i = 1; i < height - 1; ++i) {
340 for (
unsigned int j = 1; j < width - 1; ++j) {
341 if (i % 2 == 0 && j % 2 == 0) {
342 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(gbrg, width, i, j);
343 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
344 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(gbrg, width, i, j);
346 else if (i % 2 == 0 && j % 2 != 0) {
347 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(gbrg, width, i, j);
348 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
349 rgba[(i * width + j) * 4 + 2] = gbrg[i * width + j];
351 else if (i % 2 != 0 && j % 2 == 0) {
352 rgba[(i * width + j) * 4 + 0] = gbrg[i * width + j];
353 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(gbrg, width, i, j);
354 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(gbrg, width, i, j);
357 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(gbrg, width, i, j);
358 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
359 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(gbrg, width, i, j);
365 template <
typename T>
366 void demosaicGRBGToRGBaBilinearTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
367 unsigned int nThreads)
369 m_assert(
"width must be >= 4", width >= 4);
370 m_assert(
"height must be >= 4", height >= 4);
371 m_assert(
"width must be a multiple of 2", width % 2 == 0);
372 m_assert(
"height must be a multiple of 2", height % 2 == 0);
377 rgba[2] = grbg[width];
380 rgba[(width - 1) * 4 + 0] = grbg[width - 1];
381 rgba[(width - 1) * 4 + 1] = grbg[width - 2];
382 rgba[(width - 1) * 4 + 2] = grbg[2 * width - 2];
385 rgba[((height - 1) * width) * 4 + 0] = grbg[(height - 2) * width + 1];
386 rgba[((height - 1) * width) * 4 + 1] = grbg[(height - 1) * width + 1];
387 rgba[((height - 1) * width) * 4 + 2] = grbg[(height - 1) * width];
390 rgba[((height - 1) * width + width - 1) * 4 + 0] = grbg[(height - 1) * width - 1];
391 rgba[((height - 1) * width + width - 1) * 4 + 1] = grbg[height * width - 1];
392 rgba[((height - 1) * width + width - 1) * 4 + 2] = grbg[height * width - 2];
395 for (
unsigned int j = 1; j < width - 1; ++j) {
397 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
398 rgba[j * 4 + 1] = grbg[j];
399 rgba[j * 4 + 2] = grbg[width + j];
402 rgba[j * 4 + 0] = grbg[j];
403 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
404 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
409 for (
unsigned int i = 1; i < height - 1; ++i) {
411 rgba[i * width * 4 + 0] = grbg[i * width + 1];
412 rgba[i * width * 4 + 1] = grbg[i * width];
413 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(i - 1) * width] + 0.5f * grbg[(i + 1) * width]);
416 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
417 rgba[i * width * 4 + 1] = grbg[i * width + 1];
418 rgba[i * width * 4 + 2] = grbg[i * width];
423 for (
unsigned int i = 1; i < height - 1; ++i) {
425 rgba[(i * width + width - 1) * 4 + 0] = grbg[(i + 1) * width - 1];
426 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 2];
427 rgba[(i * width + width - 1) * 4 + 2] =
428 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
431 rgba[(i * width + width - 1) * 4 + 0] =
432 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
433 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 1];
434 rgba[(i * width + width - 1) * 4 + 2] = grbg[(i + 1) * width - 2];
439 for (
unsigned int j = 1; j < width - 1; ++j) {
441 rgba[((height - 1) * width + j) * 4 + 0] =
442 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
443 rgba[((height - 1) * width + j) * 4 + 1] =
444 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
445 rgba[((height - 1) * width + j) * 4 + 2] = grbg[(height - 1) * width + j];
448 rgba[((height - 1) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
449 rgba[((height - 1) * width + j) * 4 + 1] = grbg[(height - 1) * width + j];
450 rgba[((height - 1) * width + j) * 4 + 2] =
451 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
455 #if defined(_OPENMP) && (_OPENMP >= 200711)
457 omp_set_num_threads(
static_cast<int>(nThreads));
459 #pragma omp parallel for schedule(dynamic)
463 for (
unsigned int i = 1; i < height - 1; ++i) {
464 for (
unsigned int j = 1; j < width - 1; ++j) {
465 if (i % 2 == 0 && j % 2 == 0) {
466 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(grbg, width, i, j);
467 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
468 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(grbg, width, i, j);
470 else if (i % 2 == 0 && j % 2 != 0) {
471 rgba[(i * width + j) * 4 + 0] = grbg[i * width + j];
472 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
473 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(grbg, width, i, j);
475 else if (i % 2 != 0 && j % 2 == 0) {
476 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(grbg, width, i, j);
477 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(grbg, width, i, j);
478 rgba[(i * width + j) * 4 + 2] = grbg[i * width + j];
481 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(grbg, width, i, j);
482 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
483 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(grbg, width, i, j);
489 template <
typename T>
490 void demosaicRGGBToRGBaBilinearTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
491 unsigned int nThreads)
493 m_assert(
"width must be >= 4", width >= 4);
494 m_assert(
"height must be >= 4", height >= 4);
495 m_assert(
"width must be a multiple of 2", width % 2 == 0);
496 m_assert(
"height must be a multiple of 2", height % 2 == 0);
501 rgba[2] = rggb[width + 1];
504 rgba[(width - 1) * 4 + 0] = rggb[width - 2];
505 rgba[(width - 1) * 4 + 1] = rggb[width - 1];
506 rgba[(width - 1) * 4 + 2] = rggb[2 * width - 1];
509 rgba[((height - 1) * width) * 4 + 0] = rggb[(height - 2) * width];
510 rgba[((height - 1) * width) * 4 + 1] = rggb[(height - 1) * width];
511 rgba[((height - 1) * width) * 4 + 2] = rggb[(height - 1) * width + 1];
514 rgba[((height - 1) * width + width - 1) * 4 + 0] = rggb[(height - 1) * width - 2];
515 rgba[((height - 1) * width + width - 1) * 4 + 1] = rggb[height * width - 2];
516 rgba[((height - 1) * width + width - 1) * 4 + 2] = rggb[height * width - 1];
519 for (
unsigned int j = 1; j < width - 1; ++j) {
521 rgba[j * 4 + 0] = rggb[j];
522 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
523 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
526 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
527 rgba[j * 4 + 1] = rggb[j];
528 rgba[j * 4 + 2] = rggb[width + j];
533 for (
unsigned int i = 1; i < height - 1; ++i) {
535 rgba[i * width * 4 + 0] = rggb[i * width];
536 rgba[i * width * 4 + 1] = rggb[i * width + 1];
537 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
540 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(i - 1) * width] + 0.5f * rggb[(i + 1) * width]);
541 rgba[i * width * 4 + 1] = rggb[i * width];
542 rgba[i * width * 4 + 2] = rggb[i * width + 1];
547 for (
unsigned int i = 1; i < height - 1; ++i) {
549 rgba[(i * width + width - 1) * 4 + 0] = rggb[(i + 1) * width - 2];
550 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 1];
551 rgba[(i * width + width - 1) * 4 + 2] =
552 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
555 rgba[(i * width + width - 1) * 4 + 0] =
556 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
557 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 2];
558 rgba[(i * width + width - 1) * 4 + 2] = rggb[(i + 1) * width - 1];
563 for (
unsigned int j = 1; j < width - 1; ++j) {
565 rgba[((height - 1) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
566 rgba[((height - 1) * width + j) * 4 + 1] = rggb[(height - 1) * width + j];
567 rgba[((height - 1) * width + j) * 4 + 2] =
568 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 + 0] =
572 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
573 rgba[((height - 1) * width + j) * 4 + 1] =
574 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
575 rgba[((height - 1) * width + j) * 4 + 2] = rggb[(height - 1) * width + j];
579 #if defined(_OPENMP) && (_OPENMP >= 200711)
581 omp_set_num_threads(
static_cast<int>(nThreads));
583 #pragma omp parallel for schedule(dynamic)
587 for (
unsigned int i = 1; i < height - 1; ++i) {
588 for (
unsigned int j = 1; j < width - 1; ++j) {
589 if (i % 2 == 0 && j % 2 == 0) {
590 rgba[(i * width + j) * 4 + 0] = rggb[i * width + j];
591 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
592 rgba[(i * width + j) * 4 + 2] = demosaicCheckerBilinear(rggb, width, i, j);
594 else if (i % 2 == 0 && j % 2 != 0) {
595 rgba[(i * width + j) * 4 + 0] = demosaicThetaBilinear(rggb, width, i, j);
596 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
597 rgba[(i * width + j) * 4 + 2] = demosaicPhiBilinear(rggb, width, i, j);
599 else if (i % 2 != 0 && j % 2 == 0) {
600 rgba[(i * width + j) * 4 + 0] = demosaicPhiBilinear(rggb, width, i, j);
601 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
602 rgba[(i * width + j) * 4 + 2] = demosaicThetaBilinear(rggb, width, i, j);
605 rgba[(i * width + j) * 4 + 0] = demosaicCheckerBilinear(rggb, width, i, j);
606 rgba[(i * width + j) * 4 + 1] = demosaicCrossBilinear(rggb, width, i, j);
607 rgba[(i * width + j) * 4 + 2] = rggb[i * width + j];
615 template <
typename T>
616 void demosaicBGGRToRGBaMalvarTpl(
const T *bggr, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
618 m_assert(
"width must be >= 4", width >= 4);
619 m_assert(
"height must be >= 4", height >= 4);
620 m_assert(
"width must be a multiple of 2", width % 2 == 0);
621 m_assert(
"height must be a multiple of 2", height % 2 == 0);
624 rgba[0] = bggr[width + 1];
629 rgba[(width - 1) * 4 + 0] = bggr[2 * width - 1];
630 rgba[(width - 1) * 4 + 1] = bggr[width - 1];
631 rgba[(width - 1) * 4 + 2] = bggr[width - 2];
634 rgba[((height - 1) * width) * 4 + 0] = bggr[(height - 1) * width + 1];
635 rgba[((height - 1) * width) * 4 + 1] = bggr[(height - 1) * width];
636 rgba[((height - 1) * width) * 4 + 2] = bggr[(height - 2) * width];
639 rgba[((height - 1) * width + width - 1) * 4 + 0] = bggr[height * width - 1];
640 rgba[((height - 1) * width + width - 1) * 4 + 1] = bggr[height * width - 2];
641 rgba[((height - 1) * width + width - 1) * 4 + 2] = bggr[(height - 1) * width - 2];
644 for (
unsigned int j = 1; j < width - 1; ++j) {
646 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
647 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
648 rgba[j * 4 + 2] = bggr[j];
651 rgba[j * 4 + 0] = bggr[width + j];
652 rgba[j * 4 + 1] = bggr[j];
653 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * bggr[j - 1] + 0.5f * bggr[j + 1]);
658 for (
unsigned int j = 1; j < width - 1; ++j) {
660 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * bggr[width + j - 1] + 0.5f * bggr[width + j + 1]);
661 rgba[(width + j) * 4 + 1] = bggr[width + j];
662 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * bggr[j] + 0.5f * bggr[2 * width + j]);
665 rgba[(width + j) * 4 + 0] = bggr[width + j];
666 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * bggr[j] + 0.25f * bggr[width + j - 1] +
667 0.25f * bggr[width + j + 1] + 0.25f * bggr[2 * width + j]);
668 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.25f * bggr[j - 1] + 0.25f * bggr[j + 1] +
669 0.25f * bggr[2 * width + j - 1] + 0.25f * bggr[2 * width + j + 1]);
674 for (
unsigned int i = 1; i < height - 1; ++i) {
676 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
677 rgba[i * width * 4 + 1] = bggr[i * width + 1];
678 rgba[i * width * 4 + 2] = bggr[i * width];
681 rgba[i * width * 4 + 0] = bggr[i * width + 1];
682 rgba[i * width * 4 + 1] = bggr[i * width];
683 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * bggr[(i - 1) * width] + 0.5f * bggr[(i + 1) * width]);
688 for (
unsigned int i = 1; i < height - 1; ++i) {
690 rgba[(i * width + 1) * 4 + 0] =
691 static_cast<T
>(0.5f * bggr[(i - 1) * width + 1] + 0.5f * bggr[(i + 1) * width + 1]);
692 rgba[(i * width + 1) * 4 + 1] = bggr[i * width + 1];
693 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.5f * bggr[i * width] + 0.5f * bggr[i * width + 2]);
696 rgba[(i * width + 1) * 4 + 0] = bggr[i * width + 1];
697 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * bggr[(i - 1) * width + 1] + 0.25f * bggr[i * width] +
698 0.25f * bggr[i * width + 2] + 0.25f * bggr[(i + 1) * width + 1]);
699 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.25f * bggr[(i - 1) * width] + 0.25f * bggr[(i - 1) * width + 2] +
700 0.25f * bggr[(i + 1) * width] + 0.25f * bggr[(i + 1) * width + 2]);
705 for (
unsigned int i = 1; i < height - 1; ++i) {
707 rgba[(i * width + width - 2) * 4 + 0] =
708 static_cast<T
>(0.25f * bggr[i * width - 3] + 0.25f * bggr[i * width - 1] + 0.25f * bggr[(i + 2) * width - 3] +
709 0.25f * bggr[(i + 2) * width - 1]);
710 rgba[(i * width + width - 2) * 4 + 1] =
711 static_cast<T
>(0.25f * bggr[i * width - 2] + 0.25f * bggr[(i + 1) * width - 3] +
712 0.25f * bggr[(i + 1) * width - 1] + 0.25f * bggr[(i + 2) * width - 2]);
713 rgba[(i * width + width - 2) * 4 + 2] = bggr[(i + 1) * width - 2];
716 rgba[(i * width + width - 2) * 4 + 0] =
717 static_cast<T
>(0.5f * bggr[(i + 1) * width - 3] + 0.5f * bggr[(i + 1) * width - 1]);
718 rgba[(i * width + width - 2) * 4 + 1] = bggr[(i + 1) * width - 2];
719 rgba[(i * width + width - 2) * 4 + 2] =
720 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
725 for (
unsigned int i = 1; i < height - 1; ++i) {
727 rgba[(i * width + width - 1) * 4 + 0] =
728 static_cast<T
>(0.5f * bggr[i * width - 1] + 0.5f * bggr[(i + 2) * width - 1]);
729 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 1];
730 rgba[(i * width + width - 1) * 4 + 2] = bggr[(i + 1) * width - 2];
733 rgba[(i * width + width - 1) * 4 + 0] = bggr[(i + 1) * width - 1];
734 rgba[(i * width + width - 1) * 4 + 1] = bggr[(i + 1) * width - 2];
735 rgba[(i * width + width - 1) * 4 + 2] =
736 static_cast<T
>(0.5f * bggr[i * width - 2] + 0.5f * bggr[(i + 2) * width - 2]);
741 for (
unsigned int j = 1; j < width - 1; ++j) {
743 rgba[((height - 2) * width + j) * 4 + 0] =
744 static_cast<T
>(0.25f * bggr[(height - 3) * width + j - 1] + 0.25f * bggr[(height - 3) * width + j + 1] +
745 0.25f * bggr[(height - 1) * width + j - 1] + 0.25f * bggr[(height - 1) * width + j + 1]);
746 rgba[((height - 2) * width + j) * 4 + 1] =
747 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
748 rgba[((height - 2) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
751 rgba[((height - 2) * width + j) * 4 + 0] =
752 static_cast<T
>(0.5f * bggr[(height - 3) * width + j] + 0.5f * bggr[(height - 1) * width + j]);
753 rgba[((height - 2) * width + j) * 4 + 1] = bggr[(height - 2) * width + j];
754 rgba[((height - 2) * width + j) * 4 + 2] =
755 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
760 for (
unsigned int j = 1; j < width - 1; ++j) {
762 rgba[((height - 1) * width + j) * 4 + 0] =
763 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
764 rgba[((height - 1) * width + j) * 4 + 1] = bggr[(height - 1) * width + j];
765 rgba[((height - 1) * width + j) * 4 + 2] = bggr[(height - 2) * width + j];
768 rgba[((height - 1) * width + j) * 4 + 0] = bggr[(height - 1) * width + j];
769 rgba[((height - 1) * width + j) * 4 + 1] =
770 static_cast<T
>(0.5f * bggr[(height - 1) * width + j - 1] + 0.5f * bggr[(height - 1) * width + j + 1]);
771 rgba[((height - 1) * width + j) * 4 + 2] =
772 static_cast<T
>(0.5f * bggr[(height - 2) * width + j - 1] + 0.5f * bggr[(height - 2) * width + j + 1]);
776 #if defined(_OPENMP) && (_OPENMP >= 200711)
778 omp_set_num_threads(
static_cast<int>(nThreads));
780 #pragma omp parallel for schedule(dynamic)
784 for (
unsigned int i = 2; i < height - 2; ++i) {
785 for (
unsigned int j = 2; j < width - 2; ++j) {
786 if (i % 2 == 0 && j % 2 == 0) {
787 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(bggr, width, i, j);
788 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
789 rgba[(i * width + j) * 4 + 2] = bggr[i * width + j];
791 else if (i % 2 == 0 && j % 2 != 0) {
792 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(bggr, width, i, j);
793 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
794 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(bggr, width, i, j);
796 else if (i % 2 != 0 && j % 2 == 0) {
797 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(bggr, width, i, j);
798 rgba[(i * width + j) * 4 + 1] = bggr[i * width + j];
799 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(bggr, width, i, j);
802 rgba[(i * width + j) * 4 + 0] = bggr[i * width + j];
803 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(bggr, width, i, j);
804 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(bggr, width, i, j);
810 template <
typename T>
811 void demosaicGBRGToRGBaMalvarTpl(
const T *gbrg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
813 m_assert(
"width must be >= 4", width >= 4);
814 m_assert(
"height must be >= 4", height >= 4);
815 m_assert(
"width must be a multiple of 2", width % 2 == 0);
816 m_assert(
"height must be a multiple of 2", height % 2 == 0);
819 rgba[0] = gbrg[width];
824 rgba[(width - 1) * 4 + 0] = gbrg[2 * width - 2];
825 rgba[(width - 1) * 4 + 1] = gbrg[width - 2];
826 rgba[(width - 1) * 4 + 2] = gbrg[width - 1];
829 rgba[((height - 1) * width) * 4 + 0] = gbrg[(height - 1) * width];
830 rgba[((height - 1) * width) * 4 + 1] = gbrg[(height - 1) * width + 1];
831 rgba[((height - 1) * width) * 4 + 2] = gbrg[(height - 2) * width + 1];
834 rgba[((height - 1) * width + width - 1) * 4 + 0] = gbrg[height * width - 2];
835 rgba[((height - 1) * width + width - 1) * 4 + 1] = gbrg[height * width - 1];
836 rgba[((height - 1) * width + width - 1) * 4 + 2] = gbrg[(height - 1) * width - 1];
839 for (
unsigned int j = 1; j < width - 1; ++j) {
841 rgba[j * 4 + 0] = gbrg[width + j];
842 rgba[j * 4 + 1] = gbrg[j];
843 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
846 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
847 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * gbrg[j - 1] + 0.5f * gbrg[j + 1]);
848 rgba[j * 4 + 2] = gbrg[j];
853 for (
unsigned int j = 1; j < width - 1; ++j) {
855 rgba[(width + j) * 4 + 0] = gbrg[width + j];
856 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[j] + 0.25f * gbrg[width + j - 1] +
857 0.25f * gbrg[width + j + 1] + 0.25f * gbrg[2 * width + j]);
858 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.25f * gbrg[j - 1] + 0.25f * gbrg[j + 1] +
859 0.25f * gbrg[2 * width + j - 1] + 0.25f * gbrg[2 * width + j + 1]);
862 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[width + j - 1] + 0.5f * gbrg[width + j + 1]);
863 rgba[(width + j) * 4 + 1] = gbrg[width + j];
864 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * gbrg[j] + 0.5f * gbrg[2 * width + j]);
869 for (
unsigned int i = 1; i < height - 1; ++i) {
871 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
872 rgba[i * width * 4 + 1] = gbrg[i * width];
873 rgba[i * width * 4 + 2] = gbrg[i * width + 1];
876 rgba[i * width * 4 + 0] = gbrg[i * width];
877 rgba[i * width * 4 + 1] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width] + 0.5f * gbrg[(i + 1) * width]);
878 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
883 for (
unsigned int i = 1; i < height - 1; ++i) {
885 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width] + 0.25f * gbrg[(i - 1) * width + 2] +
886 0.25f * gbrg[(i + 1) * width] + 0.5f * gbrg[(i + 1) * width + 2]);
887 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * gbrg[(i - 1) * width + 1] + 0.25f * gbrg[i * width] +
888 0.25f * gbrg[i * width + 2] + 0.5f * gbrg[(i + 1) * width + 1]);
889 rgba[(i * width + 1) * 4 + 2] = gbrg[i * width + 1];
892 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.5f * gbrg[i * width] + 0.5f * gbrg[i * width + 2]);
893 rgba[(i * width + 1) * 4 + 1] = gbrg[i * width + 1];
894 rgba[(i * width + 1) * 4 + 2] =
895 static_cast<T
>(0.5f * gbrg[(i - 1) * width + 1] + 0.5f * gbrg[(i + 1) * width + 1]);
900 for (
unsigned int i = 1; i < height - 1; ++i) {
902 rgba[(i * width + width - 2) * 4 + 0] =
903 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
904 rgba[(i * width + width - 2) * 4 + 1] = gbrg[(i + 1) * width - 2];
905 rgba[(i * width + width - 2) * 4 + 2] =
906 static_cast<T
>(0.5f * gbrg[(i + 1) * width - 3] + 0.5f * gbrg[(i + 1) * width - 1]);
909 rgba[(i * width + width - 2) * 4 + 0] = gbrg[(i + 1) * width - 2];
910 rgba[(i * width + width - 2) * 4 + 1] =
911 static_cast<T
>(0.25f * gbrg[i * width - 2] + 0.25f * gbrg[(i + 1) * width - 3] +
912 0.25f * gbrg[(i + 1) * width - 1] + 0.25f * gbrg[(i + 2) * width - 2]);
913 rgba[(i * width + width - 2) * 4 + 2] =
914 static_cast<T
>(0.25f * gbrg[i * width - 3] + 0.25f * gbrg[i * width - 1] + 0.25f * gbrg[(i + 2) * width - 3] +
915 0.25f * gbrg[(i + 2) * width - 1]);
920 for (
unsigned int i = 1; i < height - 1; ++i) {
922 rgba[(i * width + width - 1) * 4 + 0] =
923 static_cast<T
>(0.5f * gbrg[i * width - 2] + 0.5f * gbrg[(i + 2) * width - 2]);
924 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 2];
925 rgba[(i * width + width - 1) * 4 + 2] = gbrg[(i + 1) * width - 1];
928 rgba[(i * width + width - 1) * 4 + 0] = gbrg[(i + 1) * width - 2];
929 rgba[(i * width + width - 1) * 4 + 1] = gbrg[(i + 1) * width - 1];
930 rgba[(i * width + width - 1) * 4 + 2] =
931 static_cast<T
>(0.5f * gbrg[i * width - 1] + 0.5f * gbrg[(i + 2) * width - 1]);
936 for (
unsigned int j = 1; j < width - 1; ++j) {
938 rgba[((height - 2) * width + j) * 4 + 0] =
939 static_cast<T
>(0.5f * gbrg[(height - 3) * width + j] + 0.5f * gbrg[(height - 1) * width + j]);
940 rgba[((height - 2) * width + j) * 4 + 1] = gbrg[(height - 2) * width + j];
941 rgba[((height - 2) * width + j) * 4 + 2] =
942 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
945 rgba[((height - 2) * width + j) * 4 + 0] =
946 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j - 1] + 0.25f * gbrg[(height - 3) * width + j + 1] +
947 0.25f * gbrg[(height - 1) * width + j - 1] + 0.25f * gbrg[(height - 1) * width + j + 1]);
948 rgba[((height - 2) * width + j) * 4 + 1] =
949 static_cast<T
>(0.25f * gbrg[(height - 3) * width + j] + 0.25f * gbrg[(height - 2) * width + j - 1] +
950 0.25f * gbrg[(height - 2) * width + j + 1] + 0.25f * gbrg[(height - 1) * width + j]);
951 rgba[((height - 2) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
956 for (
unsigned int j = 1; j < width - 1; ++j) {
958 rgba[((height - 1) * width + j) * 4 + 0] = gbrg[(height - 1) * width + j];
959 rgba[((height - 1) * width + j) * 4 + 1] =
960 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
961 rgba[((height - 1) * width + j) * 4 + 2] =
962 static_cast<T
>(0.5f * gbrg[(height - 2) * width + j - 1] + 0.5f * gbrg[(height - 2) * width + j + 1]);
965 rgba[((height - 1) * width + j) * 4 + 0] =
966 static_cast<T
>(0.5f * gbrg[(height - 1) * width + j - 1] + 0.5f * gbrg[(height - 1) * width + j + 1]);
967 rgba[((height - 1) * width + j) * 4 + 1] = gbrg[(height - 1) * width + j];
968 rgba[((height - 1) * width + j) * 4 + 2] = gbrg[(height - 2) * width + j];
972 #if defined(_OPENMP) && (_OPENMP >= 200711)
974 omp_set_num_threads(
static_cast<int>(nThreads));
976 #pragma omp parallel for schedule(dynamic)
980 for (
unsigned int i = 2; i < height - 2; ++i) {
981 for (
unsigned int j = 2; j < width - 2; ++j) {
982 if (i % 2 == 0 && j % 2 == 0) {
983 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(gbrg, width, i, j);
984 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
985 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(gbrg, width, i, j);
987 else if (i % 2 == 0 && j % 2 != 0) {
988 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(gbrg, width, i, j);
989 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
990 rgba[(i * width + j) * 4 + 2] = gbrg[i * width + j];
992 else if (i % 2 != 0 && j % 2 == 0) {
993 rgba[(i * width + j) * 4 + 0] = gbrg[i * width + j];
994 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(gbrg, width, i, j);
995 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(gbrg, width, i, j);
998 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(gbrg, width, i, j);
999 rgba[(i * width + j) * 4 + 1] = gbrg[i * width + j];
1000 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(gbrg, width, i, j);
1006 template <
typename T>
1007 void demosaicGRBGToRGBaMalvarTpl(
const T *grbg, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1009 m_assert(
"width must be >= 4", width >= 4);
1010 m_assert(
"height must be >= 4", height >= 4);
1011 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1012 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1017 rgba[2] = grbg[width];
1020 rgba[(width - 1) * 4 + 0] = grbg[width - 1];
1021 rgba[(width - 1) * 4 + 1] = grbg[width - 2];
1022 rgba[(width - 1) * 4 + 2] = grbg[2 * width - 2];
1025 rgba[((height - 1) * width) * 4 + 0] = grbg[(height - 2) * width + 1];
1026 rgba[((height - 1) * width) * 4 + 1] = grbg[(height - 1) * width + 1];
1027 rgba[((height - 1) * width) * 4 + 2] = grbg[(height - 1) * width];
1030 rgba[((height - 1) * width + width - 1) * 4 + 0] = grbg[(height - 1) * width - 1];
1031 rgba[((height - 1) * width + width - 1) * 4 + 1] = grbg[height * width - 1];
1032 rgba[((height - 1) * width + width - 1) * 4 + 2] = grbg[height * width - 2];
1035 for (
unsigned int j = 1; j < width - 1; ++j) {
1037 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
1038 rgba[j * 4 + 1] = grbg[j];
1039 rgba[j * 4 + 2] = grbg[width + j];
1042 rgba[j * 4 + 0] = grbg[j];
1043 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * grbg[j - 1] + 0.5f * grbg[j + 1]);
1044 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
1049 for (
unsigned int j = 1; j < width - 1; ++j) {
1051 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.25f * grbg[j - 1] + 0.25f * grbg[j + 1] +
1052 0.25f * grbg[2 * width + j - 1] + 0.25f * grbg[2 * width + j + 1]);
1053 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * grbg[j] + 0.25f * grbg[width + j - 1] +
1054 0.25f * grbg[width + j + 1] + 0.25f * grbg[2 * width + j]);
1055 rgba[(width + j) * 4 + 2] = grbg[width + j];
1058 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * grbg[j] + 0.5f * grbg[2 * width + j]);
1059 rgba[(width + j) * 4 + 1] = grbg[width + j];
1060 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * grbg[width + j - 1] + 0.5f * grbg[width + j + 1]);
1065 for (
unsigned int i = 1; i < height - 1; ++i) {
1067 rgba[i * width * 4 + 0] = grbg[i * width + 1];
1068 rgba[i * width * 4 + 1] = grbg[i * width];
1069 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * grbg[(i - 1) * width] + 0.5f * grbg[(i + 1) * width]);
1072 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1073 rgba[i * width * 4 + 1] = grbg[i * width + 1];
1074 rgba[i * width * 4 + 2] = grbg[i * width];
1079 for (
unsigned int i = 1; i < height - 1; ++i) {
1081 rgba[(i * width + 1) * 4 + 0] = grbg[i * width + 1];
1082 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * grbg[(i - 1) * width + 1] + 0.25f * grbg[i * width] +
1083 0.25f * grbg[i * width + 2] + 0.25f * grbg[(i + 1) * width + 1]);
1084 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.25f * grbg[(i - 1) * width] + 0.25f * grbg[(i - 1) * width + 2] +
1085 0.25f * grbg[(i + 1) * width] + 0.25f * grbg[(i + 1) * width + 2]);
1088 rgba[(i * width + 1) * 4 + 0] =
1089 static_cast<T
>(0.5f * grbg[(i - 1) * width + 1] + 0.5f * grbg[(i + 1) * width + 1]);
1090 rgba[(i * width + 1) * 4 + 1] = grbg[i * width + 1];
1091 rgba[(i * width + 1) * 4 + 2] =
static_cast<T
>(0.5f * grbg[i * width] + 0.5f * grbg[i * width + 2]);
1096 for (
unsigned int i = 1; i < height - 1; ++i) {
1098 rgba[(i * width + width - 2) * 4 + 0] =
1099 static_cast<T
>(0.5f * grbg[(i + 1) * width - 3] + 0.5f * grbg[(i + 1) * width - 1]);
1100 rgba[(i * width + width - 2) * 4 + 1] = grbg[(i + 1) * width - 2];
1101 rgba[(i * width + width - 2) * 4 + 2] =
1102 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1105 rgba[(i * width + width - 2) * 4 + 0] =
1106 static_cast<T
>(0.25f * grbg[i * width - 3] + 0.25f * grbg[i * width - 1] + 0.25f * grbg[(i + 2) * width - 3] +
1107 0.25f * grbg[(i + 2) * width - 1]);
1108 rgba[(i * width + width - 2) * 4 + 1] =
1109 static_cast<T
>(0.25f * grbg[i * width - 2] + 0.25f * grbg[(i + 1) * width - 3] +
1110 0.25f * grbg[(i + 1) * width - 1] + 0.25f * grbg[(i + 2) * width - 2]);
1111 rgba[(i * width + width - 2) * 4 + 2] = grbg[(i + 1) * width - 2];
1116 for (
unsigned int i = 1; i < height - 1; ++i) {
1118 rgba[(i * width + width - 1) * 4 + 0] = grbg[(i + 1) * width - 1];
1119 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 2];
1120 rgba[(i * width + width - 1) * 4 + 2] =
1121 static_cast<T
>(0.5f * grbg[i * width - 2] + 0.5f * grbg[(i + 2) * width - 2]);
1124 rgba[(i * width + width - 1) * 4 + 0] =
1125 static_cast<T
>(0.5f * grbg[i * width - 1] + 0.5f * grbg[(i + 2) * width - 1]);
1126 rgba[(i * width + width - 1) * 4 + 1] = grbg[(i + 1) * width - 1];
1127 rgba[(i * width + width - 1) * 4 + 2] = grbg[(i + 1) * width - 2];
1132 for (
unsigned int j = 1; j < width - 1; ++j) {
1134 rgba[((height - 2) * width + j) * 4 + 0] =
1135 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1136 rgba[((height - 2) * width + j) * 4 + 1] = grbg[(height - 2) * width + j];
1137 rgba[((height - 2) * width + j) * 4 + 2] =
1138 static_cast<T
>(0.5f * grbg[(height - 3) * width + j] + 0.5f * grbg[(height - 1) * width + j]);
1141 rgba[((height - 2) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
1142 rgba[((height - 2) * width + j) * 4 + 1] =
1143 static_cast<T
>(0.25f * grbg[(height - 3) * width + j] + 0.25f * grbg[(height - 2) * width + j - 1] +
1144 0.25f * grbg[(height - 2) * width + j + 1] + 0.25f * grbg[(height - 1) * width + j]);
1145 rgba[((height - 2) * width + j) * 4 + 2] =
1146 static_cast<T
>(0.25f * grbg[(height - 3) * width + j - 1] + 0.25f * grbg[(height - 3) * width + j + 1] +
1147 0.25f * grbg[(height - 1) * width + j - 1] + 0.25f * grbg[(height - 1) * width + j + 1]);
1152 for (
unsigned int j = 1; j < width - 1; ++j) {
1154 rgba[((height - 1) * width + j) * 4 + 0] =
1155 static_cast<T
>(0.5f * grbg[(height - 2) * width + j - 1] + 0.5f * grbg[(height - 2) * width + j + 1]);
1156 rgba[((height - 1) * width + j) * 4 + 1] =
1157 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1158 rgba[((height - 1) * width + j) * 4 + 2] = grbg[(height - 1) * width + j];
1161 rgba[((height - 1) * width + j) * 4 + 0] = grbg[(height - 2) * width + j];
1162 rgba[((height - 1) * width + j) * 4 + 1] = grbg[(height - 1) * width + j];
1163 rgba[((height - 1) * width + j) * 4 + 2] =
1164 static_cast<T
>(0.5f * grbg[(height - 1) * width + j - 1] + 0.5f * grbg[(height - 1) * width + j + 1]);
1168 #if defined(_OPENMP) && (_OPENMP >= 200711)
1170 omp_set_num_threads(
static_cast<int>(nThreads));
1172 #pragma omp parallel for schedule(dynamic)
1176 for (
unsigned int i = 2; i < height - 2; ++i) {
1177 for (
unsigned int j = 2; j < width - 2; ++j) {
1178 if (i % 2 == 0 && j % 2 == 0) {
1179 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(grbg, width, i, j);
1180 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
1181 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(grbg, width, i, j);
1183 else if (i % 2 == 0 && j % 2 != 0) {
1184 rgba[(i * width + j) * 4 + 0] = grbg[i * width + j];
1185 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1186 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(grbg, width, i, j);
1188 else if (i % 2 != 0 && j % 2 == 0) {
1189 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(grbg, width, i, j);
1190 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(grbg, width, i, j);
1191 rgba[(i * width + j) * 4 + 2] = grbg[i * width + j];
1194 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(grbg, width, i, j);
1195 rgba[(i * width + j) * 4 + 1] = grbg[i * width + j];
1196 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(grbg, width, i, j);
1202 template <
typename T>
1203 void demosaicRGGBToRGBaMalvarTpl(
const T *rggb, T *rgba,
unsigned int width,
unsigned int height,
unsigned int nThreads)
1205 m_assert(
"width must be >= 4", width >= 4);
1206 m_assert(
"height must be >= 4", height >= 4);
1207 m_assert(
"width must be a multiple of 2", width % 2 == 0);
1208 m_assert(
"height must be a multiple of 2", height % 2 == 0);
1213 rgba[2] = rggb[width + 1];
1216 rgba[(width - 1) * 4 + 0] = rggb[width - 2];
1217 rgba[(width - 1) * 4 + 1] = rggb[width - 1];
1218 rgba[(width - 1) * 4 + 2] = rggb[2 * width - 1];
1221 rgba[((height - 1) * width) * 4 + 0] = rggb[(height - 2) * width];
1222 rgba[((height - 1) * width) * 4 + 1] = rggb[(height - 1) * width];
1223 rgba[((height - 1) * width) * 4 + 2] = rggb[(height - 1) * width + 1];
1226 rgba[((height - 1) * width + width - 1) * 4 + 0] = rggb[(height - 1) * width - 2];
1227 rgba[((height - 1) * width + width - 1) * 4 + 1] = rggb[height * width - 2];
1228 rgba[((height - 1) * width + width - 1) * 4 + 2] = rggb[height * width - 1];
1231 for (
unsigned int j = 1; j < width - 1; ++j) {
1233 rgba[j * 4 + 0] = rggb[j];
1234 rgba[j * 4 + 1] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
1235 rgba[j * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1238 rgba[j * 4 + 0] =
static_cast<T
>(0.5f * rggb[j - 1] + 0.5f * rggb[j + 1]);
1239 rgba[j * 4 + 1] = rggb[j];
1240 rgba[j * 4 + 2] = rggb[width + j];
1245 for (
unsigned int j = 1; j < width - 1; ++j) {
1247 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.5f * rggb[j] + 0.5f * rggb[2 * width + j]);
1248 rgba[(width + j) * 4 + 1] = rggb[width + j];
1249 rgba[(width + j) * 4 + 2] =
static_cast<T
>(0.5f * rggb[width + j - 1] + 0.5f * rggb[width + j + 1]);
1252 rgba[(width + j) * 4 + 0] =
static_cast<T
>(0.25f * rggb[j - 1] + 0.25f * rggb[j + 1] +
1253 0.25f * rggb[2 * width + j - 1] + 0.25f * rggb[2 * width + j + 1]);
1254 rgba[(width + j) * 4 + 1] =
static_cast<T
>(0.25f * rggb[j] + 0.25f * rggb[width + j - 1] +
1255 0.25f * rggb[width + j + 1] + 0.25f * rggb[2 * width + j]);
1256 rgba[(width + j) * 4 + 2] = rggb[width + j];
1261 for (
unsigned int i = 1; i < height - 1; ++i) {
1263 rgba[i * width * 4 + 0] = rggb[i * width];
1264 rgba[i * width * 4 + 1] = rggb[i * width + 1];
1265 rgba[i * width * 4 + 2] =
static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1268 rgba[i * width * 4 + 0] =
static_cast<T
>(0.5f * rggb[(i - 1) * width] + 0.5f * rggb[(i + 1) * width]);
1269 rgba[i * width * 4 + 1] = rggb[i * width];
1270 rgba[i * width * 4 + 2] = rggb[i * width + 1];
1275 for (
unsigned int i = 1; i < height - 1; ++i) {
1277 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.5f * rggb[i * width] + 0.5f * rggb[i * width + 2]);
1278 rgba[(i * width + 1) * 4 + 1] = rggb[i * width + 1];
1279 rgba[(i * width + 1) * 4 + 2] =
1280 static_cast<T
>(0.5f * rggb[(i - 1) * width + 1] + 0.5f * rggb[(i + 1) * width + 1]);
1283 rgba[(i * width + 1) * 4 + 0] =
static_cast<T
>(0.25f * rggb[(i - 1) * width] + 0.25f * rggb[(i - 1) * width + 2] +
1284 0.25f * rggb[(i + 1) * width] + 0.25f * rggb[(i + 1) * width + 2]);
1285 rgba[(i * width + 1) * 4 + 1] =
static_cast<T
>(0.25f * rggb[(i - 1) * width + 1] + 0.25f * rggb[i * width] +
1286 0.25f * rggb[i * width + 2] + 0.25f * rggb[(i + 1) * width + 1]);
1287 rgba[(i * width + 1) * 4 + 2] = rggb[i * width + 1];
1292 for (
unsigned int i = 1; i < height - 1; ++i) {
1294 rgba[(i * width + width - 2) * 4 + 0] = rggb[(i + 1) * width - 2];
1295 rgba[(i * width + width - 2) * 4 + 1] =
1296 static_cast<T
>(0.25f * rggb[i * width - 2] + 0.25f * rggb[(i + 1) * width - 3] +
1297 0.25f * rggb[(i + 1) * width - 1] + 0.25f * rggb[(i + 2) * width - 2]);
1298 rgba[(i * width + width - 2) * 4 + 2] =
1299 static_cast<T
>(0.25f * rggb[i * width - 3] + 0.25f * rggb[i * width - 1] + 0.25f * rggb[(i + 2) * width - 3] +
1300 0.25f * rggb[(i + 2) * width - 1]);
1303 rgba[(i * width + width - 2) * 4 + 0] =
1304 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1305 rgba[(i * width + width - 2) * 4 + 1] = rggb[(i + 1) * width - 2];
1306 rgba[(i * width + width - 2) * 4 + 2] =
1307 static_cast<T
>(0.5f * rggb[(i + 1) * width - 3] + 0.5f * rggb[(i + 1) * width - 1]);
1312 for (
unsigned int i = 1; i < height - 1; ++i) {
1314 rgba[(i * width + width - 1) * 4 + 0] = rggb[(i + 1) * width - 2];
1315 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 1];
1316 rgba[(i * width + width - 1) * 4 + 2] =
1317 static_cast<T
>(0.5f * rggb[i * width - 1] + 0.5f * rggb[(i + 2) * width - 1]);
1320 rgba[(i * width + width - 1) * 4 + 0] =
1321 static_cast<T
>(0.5f * rggb[i * width - 2] + 0.5f * rggb[(i + 2) * width - 2]);
1322 rgba[(i * width + width - 1) * 4 + 1] = rggb[(i + 1) * width - 2];
1323 rgba[(i * width + width - 1) * 4 + 2] = rggb[(i + 1) * width - 1];
1328 for (
unsigned int j = 1; j < width - 1; ++j) {
1330 rgba[((height - 2) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
1331 rgba[((height - 2) * width + j) * 4 + 1] =
1332 static_cast<T
>(0.25f * rggb[(height - 3) * width + j] + 0.25f * rggb[(height - 2) * width + j - 1] +
1333 0.25f * rggb[(height - 2) * width + j + 1] + 0.25f * rggb[(height - 1) * width + j]);
1334 rgba[((height - 2) * width + j) * 4 + 2] =
1335 static_cast<T
>(0.25f * rggb[(height - 3) * width + j - 1] + 0.25f * rggb[(height - 3) * width + j + 1] +
1336 0.25f * rggb[(height - 1) * width + j - 1] + 0.25f * rggb[(height - 1) * width + j + 1]);
1339 rgba[((height - 2) * width + j) * 4 + 0] =
1340 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1341 rgba[((height - 2) * width + j) * 4 + 1] = rggb[(height - 2) * width + j];
1342 rgba[((height - 2) * width + j) * 4 + 2] =
1343 static_cast<T
>(0.5f * rggb[(height - 3) * width + j] + 0.5f * rggb[(height - 1) * width + j]);
1348 for (
unsigned int j = 1; j < width - 1; ++j) {
1350 rgba[((height - 1) * width + j) * 4 + 0] = rggb[(height - 2) * width + j];
1351 rgba[((height - 1) * width + j) * 4 + 1] = rggb[(height - 1) * width + j];
1352 rgba[((height - 1) * width + j) * 4 + 2] =
1353 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 + 0] =
1357 static_cast<T
>(0.5f * rggb[(height - 2) * width + j - 1] + 0.5f * rggb[(height - 2) * width + j + 1]);
1358 rgba[((height - 1) * width + j) * 4 + 1] =
1359 static_cast<T
>(0.5f * rggb[(height - 1) * width + j - 1] + 0.5f * rggb[(height - 1) * width + j + 1]);
1360 rgba[((height - 1) * width + j) * 4 + 2] = rggb[(height - 1) * width + j];
1364 #if defined(_OPENMP) && (_OPENMP >= 200711)
1366 omp_set_num_threads(
static_cast<int>(nThreads));
1368 #pragma omp parallel for schedule(dynamic)
1372 for (
unsigned int i = 2; i < height - 2; ++i) {
1373 for (
unsigned int j = 2; j < width - 2; ++j) {
1374 if (i % 2 == 0 && j % 2 == 0) {
1375 rgba[(i * width + j) * 4 + 0] = rggb[i * width + j];
1376 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1377 rgba[(i * width + j) * 4 + 2] = demosaicCheckerMalvar(rggb, width, i, j);
1379 else if (i % 2 == 0 && j % 2 != 0) {
1380 rgba[(i * width + j) * 4 + 0] = demosaicThetaMalvar(rggb, width, i, j);
1381 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
1382 rgba[(i * width + j) * 4 + 2] = demosaicPhiMalvar(rggb, width, i, j);
1384 else if (i % 2 != 0 && j % 2 == 0) {
1385 rgba[(i * width + j) * 4 + 0] = demosaicPhiMalvar(rggb, width, i, j);
1386 rgba[(i * width + j) * 4 + 1] = rggb[i * width + j];
1387 rgba[(i * width + j) * 4 + 2] = demosaicThetaMalvar(rggb, width, i, j);
1390 rgba[(i * width + j) * 4 + 0] = demosaicCheckerMalvar(rggb, width, i, j);
1391 rgba[(i * width + j) * 4 + 1] = demosaicCrossMalvar(rggb, width, i, j);
1392 rgba[(i * width + j) * 4 + 2] = rggb[i * width + j];