/** * @file debayer.c * @brief demosaicing algorithms * @author Patrick Roth - roth@stettbacher.ch * @copyright Stettbacher Signal Processing AG * * @remarks * *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* 
* */ #include #include "color_pipe_private.h" /** * Return bayer pattern type of next line. * * @param pattern current pattern type * @param offset_height height offset in number of lines * @param offset_width width offset in numbers of rows * @return pattern type of next line */ static inline enum enumBayerPattern_t getBayerType(enum enumBayerPattern_t pattern, int offset_height, int offset_width) { int offset_y = offset_height%2; int offset_x = offset_width%2; if(offset_y == 0 && offset_x == 0) { // do nothing } else if(offset_y == 0 && offset_x == 1) { if(pattern == BP_GR) { pattern = BP_RG; } else if(pattern == BP_RG) { pattern = BP_GR; } else if(pattern == BP_BG) { pattern = BP_GB; } else if(pattern == BP_GB) { pattern = BP_BG; } } else if(offset_y == 1 && offset_x == 0) { if(pattern == BP_GR) { pattern = BP_BG; } else if(pattern == BP_RG) { pattern = BP_GB; } else if(pattern == BP_BG) { pattern = BP_GR; } else if(pattern == BP_GB) { pattern = BP_RG; } } else if(offset_y == 1 && offset_x == 1) { if(pattern == BP_GR) { pattern = BP_GB; } else if(pattern == BP_RG) { pattern = BP_BG; } else if(pattern == BP_BG) { pattern = BP_RG; } else if(pattern == BP_GB) { pattern = BP_GR; } } return pattern; } /** * Calculate RGB value depening on 9 pixel value from bayer pattern. * * @param p11 upper left pixel * @param p12 upper center pixel * @param p13 upper right pixel * @param p21 center left pixel * @param p22 center center pixel * @param p23 center right pixel * @param p31 lower left pixel * @param p32 lower center pixel * @param p33 lower right pixel * @param pattern current bayer pattern type, this value is adjusted to next expected type after return * @param red On return: red pixel value * @param green On return: green pixel value * @param blue On return: blue pixel value */ static inline void calc_bilinear(int p11, int p12, int p13, int p21, int p22, int p23, int p31, int p32, int p33, enum enumBayerPattern_t *pattern, int *red, int *green, int *blue) { switch(*pattern) { case BP_GR: // green-red-green-red-... *red = (p21 + p23) >> 1; *green = (p11 + p13 + p22*4 + p31 + p33) >> 3; *blue = (p12 + p32) >> 1; *pattern = BP_RG; break; case BP_RG: // red-green-red-green-... *red = p22; *green = (p12 + p21 + p23 + p32) >> 2; *blue = (p11 + p13 + p31 + p33) >> 2; *pattern = BP_GR; break; case BP_BG: // blue-green-blue-green-... *red = (p11 + p13 + p31 + p33) >> 2; *green = (p12 + p21 + p23 + p32) >> 2; *blue = p22; *pattern = BP_GB; break; case BP_GB: // green-blue-green-blue-... *red = (p12 + p32) >> 1; *green = (p11 + p13 + p22*4 + p31 + p33) >> 3; *blue = (p21 + p23) >> 1; *pattern = BP_BG; break; } } /** * Bilinear demosaicing algorithm for RGB image (16 bit per color channel). * * @param img_rgb On return: RGB image in R-G-B order * @param img_bayer bayer image * @param height image height in number of pixels * @param width image width in number of pixels * @param bayer_pattern first pixel starts with this pixel * @return 0 on success otherwise -1 */ static void bilinear16(uint16_t *img_rgb, const uint16_t *img_bayer, const int height, const int width, const enum enumBayerPattern_t bayer_pattern) #include "alg_debayer_bilinear.h" /** * Bilinear demosaicing algorithm for RGB image (8 bit per color channel). * * @param img_rgb On return: RGB image in R-G-B order * @param img_bayer bayer image * @param height image height in number of pixels * @param width image width in number of pixels * @param bayer_pattern first pixel starts with this pixel * @return 0 on success otherwise -1 */ static void bilinear8(uint8_t *img_rgb, const uint8_t *img_bayer, const int height, const int width, const enum enumBayerPattern_t bayer_pattern) #include "alg_debayer_bilinear.h" /** * Bilinear demosaicing wrapper function used to select pixel-bit-depth dependet algrotihm. * * @param img_rgb On return: RGB image in R-G-B order * @param img_bayer bayer image * @param height image height in number of pixels * @param width image width in number of pixels * @param data_format image data format * @param bayer_pattern first pixel starts with this pixel * @return 0 on success otherwise -1 */ static int bilinear_wrapper(void *img_rgb, const void *img_bayer, const int height, const int width, const enum enumDataFormat_t data_format, const enum enumBayerPattern_t bayer_pattern) { if(data_format == DF_RAW_BAYER_8) { bilinear8(img_rgb, img_bayer, height, width, bayer_pattern); } else if(data_format == DF_RAW_BAYER_12 || data_format == DF_HDR_BAYER_20_COMP) { bilinear16(img_rgb, img_bayer, height, width, bayer_pattern); } else { printf("%s: image data format %d unknown\n", __func__, data_format); return -1; } return 0; } /** * Bayer to RGB image conversion algrithm (demosaicing) * * @param debayer_data required data for debayering * @return 0 on success otherwise -1 */ int debayer(struct debayer_data_t *debayer_data) { void *img_rgb, *img_raw; int ret, height, width; enum enumDataFormat_t data_format; enum enumBayerPattern_t bayer_pattern; enum bayer_alg_t alg; ret = 0; img_rgb = debayer_data->img_rgb; img_raw = debayer_data->img_raw; height = debayer_data->height; width = debayer_data->width; data_format = debayer_data->format; bayer_pattern = debayer_data->start_pattern; alg = debayer_data->alg; if(data_format == DF_RAW_MONO_8 || data_format == DF_RAW_MONO_12 || data_format == DF_HDR_MONO_20_COMP) { printf("%s: No debayering is done on monochrome image (image data format %d)\n", __func__, data_format); return -1; } switch(alg) { case BAYER_ALG_BILINEAR: ret = bilinear_wrapper(img_rgb, img_raw, height, width, data_format, bayer_pattern); break; default: printf("%s: Debayer algorithm %d not implemented yet\n", __func__, alg); ret = -1; } return ret; }