@@ -18,6 +18,7 @@ namespace {
1818static const ustring pattern_us (" pattern" );
1919static const ustring algorithm_us (" algorithm" );
2020static const ustring layout_us (" layout" );
21+ static const ustring white_balance_us (" white_balance" );
2122
2223} // namespace
2324
@@ -31,7 +32,17 @@ template<class Rtype, class Atype, int size> class BayerDemosaicing {
3132 // / the source iterator.
3233 struct Row {
3334 ImageBuf::ConstIterator<Atype> iterator;
35+ float white_balance[2 ];
36+ int x_offset;
3437 float data[size];
38+
39+ float fetch ()
40+ {
41+ float result = iterator[0 ] * white_balance[x_offset];
42+ iterator++;
43+ x_offset = 1 - x_offset;
44+ return result;
45+ }
3546 };
3647
3748 std::vector<Row> rows;
@@ -46,7 +57,8 @@ template<class Rtype, class Atype, int size> class BayerDemosaicing {
4657 int src_yend;
4758 int x;
4859
49- Window (int y, int xbegin, const ImageBuf& src)
60+ Window (int y, int xbegin, const ImageBuf& src, int x_offset,
61+ int y_offset, const float white_balance[4 ])
5062 {
5163 assert (size >= 3 );
5264 assert (size % 2 == 1 );
@@ -78,12 +90,15 @@ template<class Rtype, class Atype, int size> class BayerDemosaicing {
7890 ystart = src_yend - 1 - (ystart - src_yend + 1 ) % 2 ;
7991 }
8092
81- Row row
82- = { ImageBuf::ConstIterator<Atype>(src, xstart, ystart) };
93+ int x_off = (xstart + x_offset) % 2 ;
94+ int y_off = ((ystart + y_offset) % 2 ) * 2 ;
95+
96+ Row row = { ImageBuf::ConstIterator<Atype>(src, xstart, ystart),
97+ { white_balance[y_off], white_balance[y_off + 1 ] },
98+ x_off };
8399
84100 for (int j = skip; j < size; j++) {
85- row.data [j] = row.iterator [0 ];
86- row.iterator ++;
101+ row.data [j] = row.fetch ();
87102 }
88103
89104 for (int j = 0 ; j < skip; j++) {
@@ -113,8 +128,7 @@ template<class Rtype, class Atype, int size> class BayerDemosaicing {
113128 if (x + size / 2 < src_xend) {
114129 for (int i = 0 ; i < size; i++) {
115130 Row& row = rows[i];
116- row.data [curr] = row.iterator [0 ];
117- row.iterator ++;
131+ row.data [curr] = row.fetch ();
118132 }
119133 } else {
120134 int src = column_mapping[size - 3 ];
@@ -141,7 +155,7 @@ template<class Rtype, class Atype, int size> class BayerDemosaicing {
141155
142156public:
143157 bool process (ImageBuf& dst, const ImageBuf& src, const std::string& layout,
144- ROI roi, int nthreads)
158+ const float white_balance[ 4 ], ROI roi, int nthreads)
145159 {
146160 int x_offset, y_offset;
147161
@@ -167,7 +181,7 @@ template<class Rtype, class Atype, int size> class BayerDemosaicing {
167181
168182 for (int y = roi.ybegin ; y < roi.yend ; y++) {
169183 typename BayerDemosaicing<Rtype, Atype, size>::Window window (
170- y, roi.xbegin , src);
184+ y, roi.xbegin , src, x_offset, y_offset, white_balance );
171185
172186 int r = (y_offset + y) % 2 ;
173187 Decoder calc_0 = decoders[r][(x_offset + roi.xbegin + 0 ) % 2 ];
@@ -360,20 +374,21 @@ class MHCBayerDemosaicing : public BayerDemosaicing<Rtype, Atype, size> {
360374template <class Rtype , class Atype >
361375static bool
362376bayer_demosaic_linear_impl (ImageBuf& dst, const ImageBuf& src,
363- const std::string& bayer_pattern, ROI roi,
364- int nthreads)
377+ const std::string& bayer_pattern,
378+ const float white_balance[ 4 ], ROI roi, int nthreads)
365379{
366380 LinearBayerDemosaicing<Rtype, Atype> obj;
367- return obj.process (dst, src, bayer_pattern, roi, nthreads);
381+ return obj.process (dst, src, bayer_pattern, white_balance, roi, nthreads);
368382}
369383
370384template <class Rtype , class Atype >
371385static bool
372386bayer_demosaic_MHC_impl (ImageBuf& dst, const ImageBuf& src,
373- const std::string& bayer_pattern, ROI roi, int nthreads)
387+ const std::string& bayer_pattern,
388+ const float white_balance[4 ], ROI roi, int nthreads)
374389{
375390 MHCBayerDemosaicing<Rtype, Atype> obj;
376- return obj.process (dst, src, bayer_pattern, roi, nthreads);
391+ return obj.process (dst, src, bayer_pattern, white_balance, roi, nthreads);
377392
378393 return true ;
379394}
@@ -389,6 +404,7 @@ ImageBufAlgo::demosaic(ImageBuf& dst, const ImageBuf& src, KWArgs options,
389404 std::string pattern;
390405 std::string algorithm;
391406 std::string layout;
407+ float white_balance_RGGB[4 ] = { 1 .0f , 1 .0f , 1 .0f , 1 .0f };
392408
393409 for (auto && pv : options) {
394410 if (pv.name () == pattern_us) {
@@ -409,6 +425,25 @@ ImageBufAlgo::demosaic(ImageBuf& dst, const ImageBuf& src, KWArgs options,
409425 } else {
410426 dst.errorfmt (" ImageBufAlgo::demosaic() invalid layout" );
411427 }
428+ } else if (pv.name () == white_balance_us) {
429+ if (pv.type () == TypeFloat && pv.nvalues () == 4 ) {
430+ // The order in the options is always (R,G1,B,G2)
431+ white_balance_RGGB[0 ] = pv.get_float_indexed (0 );
432+ white_balance_RGGB[1 ] = pv.get_float_indexed (1 );
433+ white_balance_RGGB[2 ] = pv.get_float_indexed (3 );
434+ white_balance_RGGB[3 ] = pv.get_float_indexed (2 );
435+
436+ if (white_balance_RGGB[2 ] == 0 )
437+ white_balance_RGGB[2 ] = white_balance_RGGB[1 ];
438+ } else if (pv.type () == TypeFloat && pv.nvalues () == 3 ) {
439+ // The order in the options is always (R,G,B)
440+ white_balance_RGGB[0 ] = pv.get_float_indexed (0 );
441+ white_balance_RGGB[1 ] = pv.get_float_indexed (1 );
442+ white_balance_RGGB[2 ] = white_balance_RGGB[1 ];
443+ white_balance_RGGB[3 ] = pv.get_float_indexed (2 );
444+ } else {
445+ dst.errorfmt (" ImageBufAlgo::demosaic() invalid white balance" );
446+ }
412447 } else {
413448 dst.errorfmt (" ImageBufAlgo::demosaic() unknown parameter {}" ,
414449 pv.name ());
@@ -418,7 +453,7 @@ ImageBufAlgo::demosaic(ImageBuf& dst, const ImageBuf& src, KWArgs options,
418453
419454 ROI dst_roi = roi;
420455 if (!dst_roi.defined ()) {
421- dst_roi = src.roi_full ();
456+ dst_roi = src.roi ();
422457 }
423458
424459 dst_roi.chbegin = 0 ;
@@ -449,12 +484,14 @@ ImageBufAlgo::demosaic(ImageBuf& dst, const ImageBuf& src, KWArgs options,
449484 OIIO_DISPATCH_COMMON_TYPES2 (ok, " bayer_demosaic_linear" ,
450485 bayer_demosaic_linear_impl,
451486 dst.spec ().format , src.spec ().format ,
452- dst, src, layout, dst_roi, nthreads);
487+ dst, src, layout, white_balance_RGGB,
488+ dst_roi, nthreads);
453489 } else if (algorithm == " MHC" ) {
454490 OIIO_DISPATCH_COMMON_TYPES2 (ok, " bayer_demosaic_MHC" ,
455491 bayer_demosaic_MHC_impl,
456492 dst.spec ().format , src.spec ().format ,
457- dst, src, layout, dst_roi, nthreads);
493+ dst, src, layout, white_balance_RGGB,
494+ dst_roi, nthreads);
458495 } else {
459496 dst.errorfmt (" ImageBufAlgo::demosaic() invalid algorithm" );
460497 }
0 commit comments