/**
* @file debayer.c
* @brief demosaicing algorithms
* @author Patrick Roth - roth@stettbacher.ch
* @version 1.0
* @date 2015-08-20
* @copyright 2012-2016 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;
}