📄 dc1394_bayer.c
字号:
/* * 1394-Based Digital Camera Control Library * Bayer pattern decoding functions * Copyright (C) Damien Douxchamps <ddouxchamps@users.sf.net> * * Written by Damien Douxchamps and Frederic Devernay * * The original VNG Bayer decoding is from Dave Coffin's DCRAW. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <limits.h>#include "dc1394_conversions.h"#define CLIP(in, out)\ in = in < 0 ? 0 : in;\ in = in > 255 ? 255 : in;\ out=in; #define CLIP16(in, out, bits)\ in = in < 0 ? 0 : in;\ in = in > ((1<<bits)-1) ? ((1<<bits)-1) : in;\ out=in; voidClearBorders(uchar_t *rgb, int sx, int sy, int w){ int i, j; // black edges are added with a width w: i = 3 * sx * w - 1; j = 3 * sx * sy - 1; while (i >= 0) { rgb[i--] = 0; rgb[j--] = 0; } i = sx * (sy - 1) * 3 - 1 + w * 3; while (i > sx) { j = 6 * w; while (j > 0) { rgb[i--] = 0; j--; } i -= (sx - 2 * w) * 3; }}voidClearBorders_uint16(uint16_t * rgb, int sx, int sy, int w){ int i, j; // black edges: i = 3 * sx * w - 1; j = 3 * sx * sy - 1; while (i >= 0) { rgb[i--] = 0; rgb[j--] = 0; } i = sx * (sy - 1) * 3 - 1 + w * 3; while (i > sx) { j = 6 * w; while (j > 0) { rgb[i--] = 0; j--; } i -= (sx - 2 * w) * 3; }}/************************************************************** * Color conversion functions for cameras that can * * output raw-Bayer pattern images, such as some Basler and * * Point Grey camera. Most of the algos presented here come * * from http://www-ise.stanford.edu/~tingchen/ and have been * * converted from Matlab to C and extended to all elementary * * patterns. * **************************************************************//* 8-bits versions *//* insprired by OpenCV's Bayer decoding */voiddc1394_bayer_NearestNeighbor(const uchar_t *restrict bayer, uchar_t *restrict rgb, int sx, int sy, int tile){ const int bayerStep = sx; const int rgbStep = 3 * sx; int width = sx; int height = sy; int blue = tile == DC1394_COLOR_FILTER_BGGR || tile == DC1394_COLOR_FILTER_GBRG ? -1 : 1; int start_with_green = tile == DC1394_COLOR_FILTER_GBRG || tile == DC1394_COLOR_FILTER_GRBG; int i, imax, iinc; /* add black border */ imax = sx * sy * 3; for (i = sx * (sy - 1) * 3; i < imax; i++) { rgb[i] = 0; } iinc = (sx - 1) * 3; for (i = (sx - 1) * 3; i < imax; i += iinc) { rgb[i++] = 0; rgb[i++] = 0; rgb[i++] = 0; } rgb += 1; width -= 1; height -= 1; for (; height--; bayer += bayerStep, rgb += rgbStep) { //int t0, t1; const uchar_t *bayerEnd = bayer + width; if (start_with_green) { rgb[-blue] = bayer[1]; rgb[0] = bayer[bayerStep + 1]; rgb[blue] = bayer[bayerStep]; bayer++; rgb += 3; } if (blue > 0) { for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) { rgb[-1] = bayer[0]; rgb[0] = bayer[1]; rgb[1] = bayer[bayerStep + 1]; rgb[2] = bayer[2]; rgb[3] = bayer[bayerStep + 2]; rgb[4] = bayer[bayerStep + 1]; } } else { for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) { rgb[1] = bayer[0]; rgb[0] = bayer[1]; rgb[-1] = bayer[bayerStep + 1]; rgb[4] = bayer[2]; rgb[3] = bayer[bayerStep + 2]; rgb[2] = bayer[bayerStep + 1]; } } if (bayer < bayerEnd) { rgb[-blue] = bayer[0]; rgb[0] = bayer[1]; rgb[blue] = bayer[bayerStep + 1]; bayer++; rgb += 3; } bayer -= width; rgb -= width * 3; blue = -blue; start_with_green = !start_with_green; }}/* OpenCV's Bayer decoding */voiddc1394_bayer_Bilinear(const uchar_t *restrict bayer, uchar_t *restrict rgb, int sx, int sy, int tile){ const int bayerStep = sx; const int rgbStep = 3 * sx; int width = sx; int height = sy; /* the two letters of the OpenCV name are respectively the 4th and 3rd letters from the blinky name, and we also have to switch R and B (OpenCV is BGR) CV_BayerBG2BGR <-> DC1394_COLOR_FILTER_BGGR CV_BayerGB2BGR <-> DC1394_COLOR_FILTER_GBRG CV_BayerGR2BGR <-> DC1394_COLOR_FILTER_GRBG int blue = tile == CV_BayerBG2BGR || tile == CV_BayerGB2BGR ? -1 : 1; int start_with_green = tile == CV_BayerGB2BGR || tile == CV_BayerGR2BGR; */ int blue = tile == DC1394_COLOR_FILTER_BGGR || tile == DC1394_COLOR_FILTER_GBRG ? -1 : 1; int start_with_green = tile == DC1394_COLOR_FILTER_GBRG || tile == DC1394_COLOR_FILTER_GRBG; ClearBorders(rgb, sx, sy, 1); rgb += rgbStep + 3 + 1; height -= 2; width -= 2; for (; height--; bayer += bayerStep, rgb += rgbStep) { int t0, t1; const uchar_t *bayerEnd = bayer + width; if (start_with_green) { /* OpenCV has a bug in the next line, which was t0 = (bayer[0] + bayer[bayerStep * 2] + 1) >> 1; */ t0 = (bayer[1] + bayer[bayerStep * 2 + 1] + 1) >> 1; t1 = (bayer[bayerStep] + bayer[bayerStep + 2] + 1) >> 1; rgb[-blue] = (uchar_t) t0; rgb[0] = bayer[bayerStep + 1]; rgb[blue] = (uchar_t) t1; bayer++; rgb += 3; } if (blue > 0) { for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) { t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] + bayer[bayerStep * 2 + 2] + 2) >> 2; t1 = (bayer[1] + bayer[bayerStep] + bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] + 2) >> 2; rgb[-1] = (uchar_t) t0; rgb[0] = (uchar_t) t1; rgb[1] = bayer[bayerStep + 1]; t0 = (bayer[2] + bayer[bayerStep * 2 + 2] + 1) >> 1; t1 = (bayer[bayerStep + 1] + bayer[bayerStep + 3] + 1) >> 1; rgb[2] = (uchar_t) t0; rgb[3] = bayer[bayerStep + 2]; rgb[4] = (uchar_t) t1; } } else { for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) { t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] + bayer[bayerStep * 2 + 2] + 2) >> 2; t1 = (bayer[1] + bayer[bayerStep] + bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] + 2) >> 2; rgb[1] = (uchar_t) t0; rgb[0] = (uchar_t) t1; rgb[-1] = bayer[bayerStep + 1]; t0 = (bayer[2] + bayer[bayerStep * 2 + 2] + 1) >> 1; t1 = (bayer[bayerStep + 1] + bayer[bayerStep + 3] + 1) >> 1; rgb[4] = (uchar_t) t0; rgb[3] = bayer[bayerStep + 2]; rgb[2] = (uchar_t) t1; } } if (bayer < bayerEnd) { t0 = (bayer[0] + bayer[2] + bayer[bayerStep * 2] + bayer[bayerStep * 2 + 2] + 2) >> 2; t1 = (bayer[1] + bayer[bayerStep] + bayer[bayerStep + 2] + bayer[bayerStep * 2 + 1] + 2) >> 2; rgb[-blue] = (uchar_t) t0; rgb[0] = (uchar_t) t1; rgb[blue] = bayer[bayerStep + 1]; bayer++; rgb += 3; } bayer -= width; rgb -= width * 3; blue = -blue; start_with_green = !start_with_green; }}/* High-Quality Linear Interpolation For Demosaicing Of Bayer-Patterned Color Images, by Henrique S. Malvar, Li-wei He, and Ross Cutler, in ICASSP'04 */voiddc1394_bayer_HQLinear(const uchar_t *restrict bayer, uchar_t *restrict rgb, int sx, int sy, int tile){ const int bayerStep = sx; const int rgbStep = 3 * sx; int width = sx; int height = sy; int blue = tile == DC1394_COLOR_FILTER_BGGR || tile == DC1394_COLOR_FILTER_GBRG ? -1 : 1; int start_with_green = tile == DC1394_COLOR_FILTER_GBRG || tile == DC1394_COLOR_FILTER_GRBG; ClearBorders(rgb, sx, sy, 2); rgb += 2 * rgbStep + 6 + 1; height -= 4; width -= 4; /* We begin with a (+1 line,+1 column) offset with respect to bilinear decoding, so start_with_green is the same, but blue is opposite */ blue = -blue; for (; height--; bayer += bayerStep, rgb += rgbStep) { int t0, t1; const uchar_t *bayerEnd = bayer + width; const int bayerStep2 = bayerStep * 2; const int bayerStep3 = bayerStep * 3; const int bayerStep4 = bayerStep * 4; if (start_with_green) { /* at green pixel */ rgb[0] = bayer[bayerStep2 + 2]; t0 = rgb[0] * 5 + ((bayer[bayerStep + 2] + bayer[bayerStep3 + 2]) << 2) - bayer[2] - bayer[bayerStep + 1] - bayer[bayerStep + 3] - bayer[bayerStep3 + 1] - bayer[bayerStep3 + 3] - bayer[bayerStep4 + 2] + ((bayer[bayerStep2] + bayer[bayerStep2 + 4] + 1) >> 1); t1 = rgb[0] * 5 + ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 3]) << 2) - bayer[bayerStep2] - bayer[bayerStep + 1] - bayer[bayerStep + 3] - bayer[bayerStep3 + 1] - bayer[bayerStep3 + 3] - bayer[bayerStep2 + 4] + ((bayer[2] + bayer[bayerStep4 + 2] + 1) >> 1); t0 = (t0 + 4) >> 3; CLIP(t0, rgb[-blue]); t1 = (t1 + 4) >> 3; CLIP(t1, rgb[blue]); bayer++; rgb += 3; } if (blue > 0) { for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) { /* B at B */ rgb[1] = bayer[bayerStep2 + 2]; /* R at B */ t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] + bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1) - (((bayer[2] + bayer[bayerStep2] + bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2]) * 3 + 1) >> 1) + rgb[1] * 6; /* G at B */ t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] + bayer[bayerStep2 + 3] + bayer[bayerStep3 + 2]) << 1) - (bayer[2] + bayer[bayerStep2] + bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2]) + (rgb[1] << 2); t0 = (t0 + 4) >> 3; CLIP(t0, rgb[-1]); t1 = (t1 + 4) >> 3; CLIP(t1, rgb[0]); /* at green pixel */ rgb[3] = bayer[bayerStep2 + 3]; t0 = rgb[3] * 5 + ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2) - bayer[3] - bayer[bayerStep + 2] - bayer[bayerStep + 4] - bayer[bayerStep3 + 2] - bayer[bayerStep3 + 4] - bayer[bayerStep4 + 3] + ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] + 1) >> 1); t1 = rgb[3] * 5 + ((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2) - bayer[bayerStep2 + 1] - bayer[bayerStep + 2] - bayer[bayerStep + 4] - bayer[bayerStep3 + 2] - bayer[bayerStep3 + 4] - bayer[bayerStep2 + 5] + ((bayer[3] + bayer[bayerStep4 + 3] + 1) >> 1); t0 = (t0 + 4) >> 3; CLIP(t0, rgb[2]); t1 = (t1 + 4) >> 3; CLIP(t1, rgb[4]); } } else { for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) { /* R at R */ rgb[-1] = bayer[bayerStep2 + 2]; /* B at R */ t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] + bayer[bayerStep3 + 1] + bayer[bayerStep3 + 3]) << 1) - (((bayer[2] + bayer[bayerStep2] + bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2]) * 3 + 1) >> 1) + rgb[-1] * 6; /* G at R */ t1 = ((bayer[bayerStep + 2] + bayer[bayerStep2 + 1] + bayer[bayerStep2 + 3] + bayer[bayerStep * 3 + 2]) << 1) - (bayer[2] + bayer[bayerStep2] + bayer[bayerStep2 + 4] + bayer[bayerStep4 + 2]) + (rgb[-1] << 2); t0 = (t0 + 4) >> 3; CLIP(t0, rgb[1]); t1 = (t1 + 4) >> 3; CLIP(t1, rgb[0]); /* at green pixel */ rgb[3] = bayer[bayerStep2 + 3]; t0 = rgb[3] * 5 + ((bayer[bayerStep + 3] + bayer[bayerStep3 + 3]) << 2) - bayer[3] - bayer[bayerStep + 2] - bayer[bayerStep + 4] - bayer[bayerStep3 + 2] - bayer[bayerStep3 + 4] - bayer[bayerStep4 + 3] + ((bayer[bayerStep2 + 1] + bayer[bayerStep2 + 5] + 1) >> 1); t1 = rgb[3] * 5 + ((bayer[bayerStep2 + 2] + bayer[bayerStep2 + 4]) << 2) - bayer[bayerStep2 + 1] - bayer[bayerStep + 2] - bayer[bayerStep + 4] - bayer[bayerStep3 + 2] - bayer[bayerStep3 + 4]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -