#include <limits.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "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;
void
ClearBorders(uint8_t *rgb, int sx, int sy, int w)
{
int i, j;
i = 3 * sx * w - 1;
j = 3 * sx * sy - 1;
while (i >= 0) {
rgb[i--] = 0;
rgb[j--] = 0;
}
int low = sx * (w - 1) * 3 - 1 + w * 3;
i = low + sx * (sy - w * 2 + 1) * 3;
while (i > low) {
j = 6 * w;
while (j > 0) {
rgb[i--] = 0;
j--;
}
i -= (sx - 2 * w) * 3;
}
}
void
ClearBorders_uint16(uint16_t * rgb, int sx, int sy, int w)
{
int i, j;
i = 3 * sx * w - 1;
j = 3 * sx * sy - 1;
while (i >= 0) {
rgb[i--] = 0;
rgb[j--] = 0;
}
int low = sx * (w - 1) * 3 - 1 + w * 3;
i = low + sx * (sy - w * 2 + 1) * 3;
while (i > low) {
j = 6 * w;
while (j > 0) {
rgb[i--] = 0;
j--;
}
i -= (sx - 2 * w) * 3;
}
}
dc1394error_t
dc1394_bayer_NearestNeighbor(const uint8_t *restrict bayer, uint8_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;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
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) {
const uint8_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;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_Bilinear(const uint8_t *restrict bayer, uint8_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;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
ClearBorders(rgb, sx, sy, 1);
rgb += rgbStep + 3 + 1;
height -= 2;
width -= 2;
for (; height--; bayer += bayerStep, rgb += rgbStep) {
int t0, t1;
const uint8_t *bayerEnd = bayer + width;
if (start_with_green) {
t0 = (bayer[1] + bayer[bayerStep * 2 + 1] + 1) >> 1;
t1 = (bayer[bayerStep] + bayer[bayerStep + 2] + 1) >> 1;
rgb[-blue] = (uint8_t) t0;
rgb[0] = bayer[bayerStep + 1];
rgb[blue] = (uint8_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] = (uint8_t) t0;
rgb[0] = (uint8_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] = (uint8_t) t0;
rgb[3] = bayer[bayerStep + 2];
rgb[4] = (uint8_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] = (uint8_t) t0;
rgb[0] = (uint8_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] = (uint8_t) t0;
rgb[3] = bayer[bayerStep + 2];
rgb[2] = (uint8_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] = (uint8_t) t0;
rgb[0] = (uint8_t) t1;
rgb[blue] = bayer[bayerStep + 1];
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_HQLinear(const uint8_t *restrict bayer, uint8_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;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
ClearBorders(rgb, sx, sy, 2);
rgb += 2 * rgbStep + 6 + 1;
height -= 4;
width -= 4;
blue = -blue;
for (; height--; bayer += bayerStep, rgb += rgbStep) {
int t0, t1;
const uint8_t *bayerEnd = bayer + width;
const int bayerStep2 = bayerStep * 2;
const int bayerStep3 = bayerStep * 3;
const int bayerStep4 = bayerStep * 4;
if (start_with_green) {
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) {
rgb[1] = bayer[bayerStep2 + 2];
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;
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]);
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) {
rgb[-1] = bayer[bayerStep2 + 2];
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;
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]);
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[4]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[2]);
}
}
if (bayer < bayerEnd) {
rgb[blue] = bayer[bayerStep2 + 2];
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[blue] * 6;
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[blue] << 2);
t0 = (t0 + 4) >> 3;
CLIP(t0, rgb[-blue]);
t1 = (t1 + 4) >> 3;
CLIP(t1, rgb[0]);
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_EdgeSense(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
return DC1394_FUNCTION_NOT_SUPPORTED;
}
dc1394error_t
dc1394_bayer_Downsample(const uint8_t *restrict bayer, uint8_t *restrict rgb, int sx, int sy, int tile)
{
uint8_t *outR, *outG, *outB;
register int i, j;
int tmp;
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[0];
outG = &rgb[1];
outB = &rgb[2];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[2];
outG = &rgb[1];
outB = &rgb[0];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_GBRG:
for (i = 0; i < sy*sx; i += (sx<<1)) {
for (j = 0; j < sx; j += 2) {
tmp = ((bayer[i + j] + bayer[i + sx + j + 1]) >> 1);
CLIP(tmp, outG[((i >> 2) + (j >> 1)) * 3]);
tmp = bayer[i + sx + j + 1];
CLIP(tmp, outR[((i >> 2) + (j >> 1)) * 3]);
tmp = bayer[i + sx + j];
CLIP(tmp, outB[((i >> 2) + (j >> 1)) * 3]);
}
}
break;
case DC1394_COLOR_FILTER_BGGR:
case DC1394_COLOR_FILTER_RGGB:
for (i = 0; i < sy*sx; i += (sx<<1)) {
for (j = 0; j < sx; j += 2) {
tmp = ((bayer[i + sx + j] + bayer[i + j + 1]) >> 1);
CLIP(tmp, outG[((i >> 2) + (j >> 1)) * 3]);
tmp = bayer[i + sx + j + 1];
CLIP(tmp, outR[((i >> 2) + (j >> 1)) * 3]);
tmp = bayer[i + j];
CLIP(tmp, outB[((i >> 2) + (j >> 1)) * 3]);
}
}
break;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_Simple(const uint8_t *restrict bayer, uint8_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;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
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) {
const uint8_t *bayerEnd = bayer + width;
if (start_with_green) {
rgb[-blue] = bayer[1];
rgb[0] = (bayer[0] + bayer[bayerStep + 1] + 1) >> 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] + bayer[bayerStep] + 1) >> 1;
rgb[1] = bayer[bayerStep + 1];
rgb[2] = bayer[2];
rgb[3] = (bayer[1] + bayer[bayerStep + 2] + 1) >> 1;
rgb[4] = bayer[bayerStep + 1];
}
} else {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
rgb[1] = bayer[0];
rgb[0] = (bayer[1] + bayer[bayerStep] + 1) >> 1;
rgb[-1] = bayer[bayerStep + 1];
rgb[4] = bayer[2];
rgb[3] = (bayer[1] + bayer[bayerStep + 2] + 1) >> 1;
rgb[2] = bayer[bayerStep + 1];
}
}
if (bayer < bayerEnd) {
rgb[-blue] = bayer[0];
rgb[0] = (bayer[1] + bayer[bayerStep] + 1) >> 1;
rgb[blue] = bayer[bayerStep + 1];
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_NearestNeighbor_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
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, iinc, imax;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
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;
height -= 1;
width -= 1;
for (; height--; bayer += bayerStep, rgb += rgbStep) {
const uint16_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;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_Bilinear_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
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;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
rgb += rgbStep + 3 + 1;
height -= 2;
width -= 2;
for (; height--; bayer += bayerStep, rgb += rgbStep) {
int t0, t1;
const uint16_t *bayerEnd = bayer + width;
if (start_with_green) {
t0 = (bayer[1] + bayer[bayerStep * 2 + 1] + 1) >> 1;
t1 = (bayer[bayerStep] + bayer[bayerStep + 2] + 1) >> 1;
rgb[-blue] = (uint16_t) t0;
rgb[0] = bayer[bayerStep + 1];
rgb[blue] = (uint16_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] = (uint16_t) t0;
rgb[0] = (uint16_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] = (uint16_t) t0;
rgb[3] = bayer[bayerStep + 2];
rgb[4] = (uint16_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] = (uint16_t) t0;
rgb[0] = (uint16_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] = (uint16_t) t0;
rgb[3] = bayer[bayerStep + 2];
rgb[2] = (uint16_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] = (uint16_t) t0;
rgb[0] = (uint16_t) t1;
rgb[blue] = bayer[bayerStep + 1];
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_HQLinear_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
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;
if ((tile>DC1394_COLOR_FILTER_MAX)||(tile<DC1394_COLOR_FILTER_MIN))
return DC1394_INVALID_COLOR_FILTER;
ClearBorders_uint16(rgb, sx, sy, 2);
rgb += 2 * rgbStep + 6 + 1;
height -= 4;
width -= 4;
blue = -blue;
for (; height--; bayer += bayerStep, rgb += rgbStep) {
int t0, t1;
const uint16_t *bayerEnd = bayer + width;
const int bayerStep2 = bayerStep * 2;
const int bayerStep3 = bayerStep * 3;
const int bayerStep4 = bayerStep * 4;
if (start_with_green) {
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;
CLIP16(t0, rgb[-blue], bits);
t1 = (t1 + 4) >> 3;
CLIP16(t1, rgb[blue], bits);
bayer++;
rgb += 3;
}
if (blue > 0) {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
rgb[1] = bayer[bayerStep2 + 2];
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;
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;
CLIP16(t0, rgb[-1], bits);
t1 = (t1 + 4) >> 3;
CLIP16(t1, rgb[0], bits);
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;
CLIP16(t0, rgb[2], bits);
t1 = (t1 + 4) >> 3;
CLIP16(t1, rgb[4], bits);
}
} else {
for (; bayer <= bayerEnd - 2; bayer += 2, rgb += 6) {
rgb[-1] = bayer[bayerStep2 + 2];
t0 = ((bayer[bayerStep + 1] + bayer[bayerStep + 3] +
bayer[bayerStep * 3 + 1] + bayer[bayerStep3 +
3]) << 1)
-
(((bayer[2] + bayer[bayerStep2] +
bayer[bayerStep2 + 4] + bayer[bayerStep4 +
2]) * 3 + 1) >> 1)
+ rgb[-1] * 6;
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;
CLIP16(t0, rgb[1], bits);
t1 = (t1 + 4) >> 3;
CLIP16(t1, rgb[0], bits);
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;
CLIP16(t0, rgb[4], bits);
t1 = (t1 + 4) >> 3;
CLIP16(t1, rgb[2], bits);
}
}
if (bayer < bayerEnd) {
rgb[blue] = bayer[bayerStep2 + 2];
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[blue] * 6;
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[blue] << 2);
t0 = (t0 + 4) >> 3;
CLIP16(t0, rgb[-blue], bits);
t1 = (t1 + 4) >> 3;
CLIP16(t1, rgb[0], bits);
bayer++;
rgb += 3;
}
bayer -= width;
rgb -= width * 3;
blue = -blue;
start_with_green = !start_with_green;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_EdgeSense_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
return DC1394_FUNCTION_NOT_SUPPORTED;
}
dc1394error_t
dc1394_bayer_Downsample_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
uint16_t *outR, *outG, *outB;
register int i, j;
int tmp;
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[0];
outG = &rgb[1];
outB = &rgb[2];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[2];
outG = &rgb[1];
outB = &rgb[0];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_GBRG:
for (i = 0; i < sy*sx; i += (sx<<1)) {
for (j = 0; j < sx; j += 2) {
tmp =
((bayer[i + j] + bayer[i + sx + j + 1]) >> 1);
CLIP16(tmp, outG[((i >> 2) + (j >> 1)) * 3], bits);
tmp = bayer[i + sx + j + 1];
CLIP16(tmp, outR[((i >> 2) + (j >> 1)) * 3], bits);
tmp = bayer[i + sx + j];
CLIP16(tmp, outB[((i >> 2) + (j >> 1)) * 3], bits);
}
}
break;
case DC1394_COLOR_FILTER_BGGR:
case DC1394_COLOR_FILTER_RGGB:
for (i = 0; i < sy*sx; i += (sx<<1)) {
for (j = 0; j < sx; j += 2) {
tmp =
((bayer[i + sx + j] + bayer[i + j + 1]) >> 1);
CLIP16(tmp, outG[((i >> 2) + (j >> 1)) * 3], bits);
tmp = bayer[i + sx + j + 1];
CLIP16(tmp, outR[((i >> 2) + (j >> 1)) * 3], bits);
tmp = bayer[i + j];
CLIP16(tmp, outB[((i >> 2) + (j >> 1)) * 3], bits);
}
}
break;
}
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_Simple_uint16(const uint16_t *restrict bayer, uint16_t *restrict rgb, int sx, int sy, int tile, int bits)
{
uint16_t *outR, *outG, *outB;
register int i, j;
int tmp, base;
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[0];
outG = &rgb[1];
outB = &rgb[2];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[2];
outG = &rgb[1];
outB = &rgb[0];
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_BGGR:
outR = &rgb[0];
outG = &rgb[1];
outB = &rgb[2];
break;
case DC1394_COLOR_FILTER_GBRG:
case DC1394_COLOR_FILTER_RGGB:
outR = &rgb[2];
outG = &rgb[1];
outB = &rgb[0];
break;
default:
outR = NULL;
outG = NULL;
outB = NULL;
break;
}
switch (tile) {
case DC1394_COLOR_FILTER_GRBG:
case DC1394_COLOR_FILTER_GBRG:
for (i = 0; i < sy - 1; i += 2) {
for (j = 0; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + sx + 1]) >> 1);
CLIP16(tmp, outG[base * 3], bits);
tmp = bayer[base + 1];
CLIP16(tmp, outR[base * 3], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outB[base * 3], bits);
}
}
for (i = 0; i < sy - 1; i += 2) {
for (j = 1; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base + 1] + bayer[base + sx]) >> 1);
CLIP16(tmp, outG[(base) * 3], bits);
tmp = bayer[base];
CLIP16(tmp, outR[(base) * 3], bits);
tmp = bayer[base + 1 + sx];
CLIP16(tmp, outB[(base) * 3], bits);
}
}
for (i = 1; i < sy - 1; i += 2) {
for (j = 0; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base + sx] + bayer[base + 1]) >> 1);
CLIP16(tmp, outG[base * 3], bits);
tmp = bayer[base + sx + 1];
CLIP16(tmp, outR[base * 3], bits);
tmp = bayer[base];
CLIP16(tmp, outB[base * 3], bits);
}
}
for (i = 1; i < sy - 1; i += 2) {
for (j = 1; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + 1 + sx]) >> 1);
CLIP16(tmp, outG[(base) * 3], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outR[(base) * 3], bits);
tmp = bayer[base + 1];
CLIP16(tmp, outB[(base) * 3], bits);
}
}
break;
case DC1394_COLOR_FILTER_BGGR:
case DC1394_COLOR_FILTER_RGGB:
for (i = 0; i < sy - 1; i += 2) {
for (j = 0; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base + sx] + bayer[base + 1]) >> 1);
CLIP16(tmp, outG[base * 3], bits);
tmp = bayer[base + sx + 1];
CLIP16(tmp, outR[base * 3], bits);
tmp = bayer[base];
CLIP16(tmp, outB[base * 3], bits);
}
}
for (i = 1; i < sy - 1; i += 2) {
for (j = 0; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + 1 + sx]) >> 1);
CLIP16(tmp, outG[(base) * 3], bits);
tmp = bayer[base + 1];
CLIP16(tmp, outR[(base) * 3], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outB[(base) * 3], bits);
}
}
for (i = 0; i < sy - 1; i += 2) {
for (j = 1; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base] + bayer[base + sx + 1]) >> 1);
CLIP16(tmp, outG[base * 3], bits);
tmp = bayer[base + sx];
CLIP16(tmp, outR[base * 3], bits);
tmp = bayer[base + 1];
CLIP16(tmp, outB[base * 3], bits);
}
}
for (i = 1; i < sy - 1; i += 2) {
for (j = 1; j < sx - 1; j += 2) {
base = i * sx + j;
tmp = ((bayer[base + 1] + bayer[base + sx]) >> 1);
CLIP16(tmp, outG[(base) * 3], bits);
tmp = bayer[base];
CLIP16(tmp, outR[(base) * 3], bits);
tmp = bayer[base + 1 + sx];
CLIP16(tmp, outB[(base) * 3], bits);
}
}
break;
}
for (i = sx * (sy - 1) * 3; i < sx * sy * 3; i++) {
rgb[i] = 0;
}
for (i = (sx - 1) * 3; i < sx * sy * 3; i += (sx - 1) * 3) {
rgb[i++] = 0;
rgb[i++] = 0;
rgb[i++] = 0;
}
return DC1394_SUCCESS;
}
#define FORC3 for (c=0; c < 3; c++)
#define SQR(x) ((x)*(x))
#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
#define LIM(x,min,max) MAX(min,MIN(x,max))
#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
#define FC(row,col) \
(filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
static const signed char bayervng_terms[] = {
-2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
-2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
-2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
-2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
-2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
-1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
-1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
-1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
-1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
-1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
-1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
-1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
-1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+1,+0,+2,+1,0,0x10
}, bayervng_chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
dc1394error_t
dc1394_bayer_VNG(const uint8_t *restrict bayer,
uint8_t *restrict dst, int sx, int sy,
dc1394color_filter_t pattern)
{
const int height = sy, width = sx;
static const signed char *cp;
uint8_t (*brow[5])[3], *pix;
int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4];
int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
int g, diff, thold, num, c;
uint32_t filters;
dc1394_bayer_Bilinear(bayer, dst, sx, sy, pattern);
switch(pattern) {
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
for (row=0; row < 8; row++) {
for (col=0; col < 2; col++) {
ip = code[row][col];
for (cp=bayervng_terms, t=0; t < 64; t++) {
y1 = *cp++; x1 = *cp++;
y2 = *cp++; x2 = *cp++;
weight = *cp++;
grads = *cp++;
color = FC(row+y1,col+x1);
if (FC(row+y2,col+x2) != color) continue;
diag = (FC(row,col+1) == color && FC(row+1,col) == color) ? 2:1;
if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
*ip++ = (y1*width + x1)*3 + color;
*ip++ = (y2*width + x2)*3 + color;
*ip++ = weight;
for (g=0; g < 8; g++)
if (grads & 1<<g) *ip++ = g;
*ip++ = -1;
}
*ip++ = INT_MAX;
for (cp=bayervng_chood, g=0; g < 8; g++) {
y = *cp++; x = *cp++;
*ip++ = (y*width + x) * 3;
color = FC(row,col);
if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color)
*ip++ = (y*width + x) * 6 + color;
else
*ip++ = 0;
}
}
}
brow[4] = calloc (width*3, sizeof **brow);
for (row=0; row < 3; row++)
brow[row] = brow[4] + row*width;
for (row=2; row < height-2; row++) {
for (col=2; col < width-2; col++) {
pix = dst + (row*width+col)*3;
ip = code[row & 7][col & 1];
memset (gval, 0, sizeof gval);
while ((g = ip[0]) != INT_MAX) {
diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
gval[ip[3]] += diff;
ip += 5;
if ((g = ip[-1]) == -1) continue;
gval[g] += diff;
while ((g = *ip++) != -1)
gval[g] += diff;
}
ip++;
gmin = gmax = gval[0];
for (g=1; g < 8; g++) {
if (gmin > gval[g]) gmin = gval[g];
if (gmax < gval[g]) gmax = gval[g];
}
if (gmax == 0) {
memcpy (brow[2][col], pix, 3 * sizeof *dst);
continue;
}
thold = gmin + (gmax >> 1);
memset (sum, 0, sizeof sum);
color = FC(row,col);
for (num=g=0; g < 8; g++,ip+=2) {
if (gval[g] <= thold) {
for (c=0; c < 3; c++)
if (c == color && ip[1])
sum[c] += (pix[c] + pix[ip[1]]) >> 1;
else
sum[c] += pix[ip[0] + c];
num++;
}
}
for (c=0; c < 3; c++) {
t = pix[color];
if (c != color)
t += (sum[c] - sum[color]) / num;
CLIP(t,brow[2][col][c]);
}
}
if (row > 3)
memcpy (dst + 3*((row-2)*width+2), brow[0]+2, (width-4)*3*sizeof *dst);
for (g=0; g < 4; g++)
brow[(g-1) & 3] = brow[g];
}
memcpy (dst + 3*((row-2)*width+2), brow[0]+2, (width-4)*3*sizeof *dst);
memcpy (dst + 3*((row-1)*width+2), brow[1]+2, (width-4)*3*sizeof *dst);
free (brow[4]);
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_VNG_uint16(const uint16_t *restrict bayer,
uint16_t *restrict dst, int sx, int sy,
dc1394color_filter_t pattern, int bits)
{
const int height = sy, width = sx;
static const signed char *cp;
uint16_t (*brow[5])[3], *pix;
int code[8][2][320], *ip, gval[8], gmin, gmax, sum[4];
int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
int g, diff, thold, num, c;
uint32_t filters;
dc1394_bayer_Bilinear_uint16(bayer, dst, sx, sy, pattern, bits);
switch(pattern) {
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
for (row=0; row < 8; row++) {
for (col=0; col < 2; col++) {
ip = code[row][col];
for (cp=bayervng_terms, t=0; t < 64; t++) {
y1 = *cp++; x1 = *cp++;
y2 = *cp++; x2 = *cp++;
weight = *cp++;
grads = *cp++;
color = FC(row+y1,col+x1);
if (FC(row+y2,col+x2) != color) continue;
diag = (FC(row,col+1) == color && FC(row+1,col) == color) ? 2:1;
if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
*ip++ = (y1*width + x1)*3 + color;
*ip++ = (y2*width + x2)*3 + color;
*ip++ = weight;
for (g=0; g < 8; g++)
if (grads & 1<<g) *ip++ = g;
*ip++ = -1;
}
*ip++ = INT_MAX;
for (cp=bayervng_chood, g=0; g < 8; g++) {
y = *cp++; x = *cp++;
*ip++ = (y*width + x) * 3;
color = FC(row,col);
if (FC(row+y,col+x) != color && FC(row+y*2,col+x*2) == color)
*ip++ = (y*width + x) * 6 + color;
else
*ip++ = 0;
}
}
}
brow[4] = calloc (width*3, sizeof **brow);
for (row=0; row < 3; row++)
brow[row] = brow[4] + row*width;
for (row=2; row < height-2; row++) {
for (col=2; col < width-2; col++) {
pix = dst + (row*width+col)*3;
ip = code[row & 7][col & 1];
memset (gval, 0, sizeof gval);
while ((g = ip[0]) != INT_MAX) {
diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
gval[ip[3]] += diff;
ip += 5;
if ((g = ip[-1]) == -1) continue;
gval[g] += diff;
while ((g = *ip++) != -1)
gval[g] += diff;
}
ip++;
gmin = gmax = gval[0];
for (g=1; g < 8; g++) {
if (gmin > gval[g]) gmin = gval[g];
if (gmax < gval[g]) gmax = gval[g];
}
if (gmax == 0) {
memcpy (brow[2][col], pix, 3 * sizeof *dst);
continue;
}
thold = gmin + (gmax >> 1);
memset (sum, 0, sizeof sum);
color = FC(row,col);
for (num=g=0; g < 8; g++,ip+=2) {
if (gval[g] <= thold) {
for (c=0; c < 3; c++)
if (c == color && ip[1])
sum[c] += (pix[c] + pix[ip[1]]) >> 1;
else
sum[c] += pix[ip[0] + c];
num++;
}
}
for (c=0; c < 3; c++) {
t = pix[color];
if (c != color)
t += (sum[c] - sum[color]) / num;
CLIP16(t,brow[2][col][c],bits);
}
}
if (row > 3)
memcpy (dst + 3*((row-2)*width+2), brow[0]+2, (width-4)*3*sizeof *dst);
for (g=0; g < 4; g++)
brow[(g-1) & 3] = brow[g];
}
memcpy (dst + 3*((row-2)*width+2), brow[0]+2, (width-4)*3*sizeof *dst);
memcpy (dst + 3*((row-1)*width+2), brow[1]+2, (width-4)*3*sizeof *dst);
free (brow[4]);
return DC1394_SUCCESS;
}
static dc1394bool_t ahd_inited = DC1394_FALSE;
#define CLIPOUT(x) LIM(x,0,255)
#define CLIPOUT16(x,bits) LIM(x,0,((1<<bits)-1))
static const double xyz_rgb[3][3] = {
{ 0.412453, 0.357580, 0.180423 },
{ 0.212671, 0.715160, 0.072169 },
{ 0.019334, 0.119193, 0.950227 } };
static const float d65_white[3] = { 0.950456, 1, 1.088754 };
static void cam_to_cielab (uint16_t cam[3], float lab[3])
{
int c, i, j;
float r, xyz[3];
static float cbrt[0x10000], xyz_cam[3][4];
if (cam == NULL) {
for (i=0; i < 0x10000; i++) {
r = i / 65535.0;
cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
}
for (i=0; i < 3; i++)
for (j=0; j < 3; j++)
xyz_cam[i][j] = xyz_rgb[i][j] / d65_white[i];
} else {
xyz[0] = xyz[1] = xyz[2] = 0.5;
FORC3 {
xyz[0] += xyz_cam[0][c] * cam[c];
xyz[1] += xyz_cam[1][c] * cam[c];
xyz[2] += xyz_cam[2][c] * cam[c];
}
xyz[0] = cbrt[CLIPOUT16((int) xyz[0],16)];
xyz[1] = cbrt[CLIPOUT16((int) xyz[1],16)];
xyz[2] = cbrt[CLIPOUT16((int) xyz[2],16)];
lab[0] = 116 * xyz[1] - 16;
lab[1] = 500 * (xyz[0] - xyz[1]);
lab[2] = 200 * (xyz[1] - xyz[2]);
}
}
#define TS 256
dc1394error_t
dc1394_bayer_AHD(const uint8_t *restrict bayer,
uint8_t *restrict dst, int sx, int sy,
dc1394color_filter_t pattern)
{
int i, j, top, left, row, col, tr, tc, fc, c, d, val, hm[2];
uint8_t (*pix)[3], (*rix)[3];
uint16_t rix16[3];
static const int dir[4] = { -1, 1, -TS, TS };
unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
float flab[3];
uint8_t (*rgb)[TS][TS][3];
short (*lab)[TS][TS][3];
char (*homo)[TS][TS], *buffer;
uint32_t filters;
const int height = sy, width = sx;
int x, y;
if (ahd_inited==DC1394_FALSE) {
cam_to_cielab (NULL,NULL);
ahd_inited = DC1394_TRUE;
}
switch(pattern) {
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int channel = FC(y,x);
dst[(y*width+x)*3 + channel] = bayer[y*width+x];
}
}
{
int border = 3;
unsigned row, col, y, x, f, c, sum[8];
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
if (col==border && row >= border && row < height-border)
col = width-border;
memset (sum, 0, sizeof sum);
for (y=row-1; y != row+2; y++)
for (x=col-1; x != col+2; x++)
if (y < height && x < width) {
f = FC(y,x);
sum[f] += dst[(y*width+x)*3 + f];
sum[f+4]++;
}
f = FC(row,col);
FORC3 if (c != f && sum[c+4])
dst[(row*width+col)*3 + c] = sum[c] / sum[c+4];
}
}
buffer = (char *) malloc (26*TS*TS);
rgb = (uint8_t(*)[TS][TS][3]) buffer;
lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
for (top=0; top < height; top += TS-6)
for (left=0; left < width; left += TS-6) {
memset (rgb, 0, 12*TS*TS);
for (row = top < 2 ? 2:top; row < top+TS && row < height-2; row++) {
col = left + (FC(row,left) == 1);
if (col < 2) col += 2;
for (fc = FC(row,col); col < left+TS && col < width-2; col+=2) {
pix = (uint8_t (*)[3])dst + (row*width+col);
val = ((pix[-1][1] + pix[0][fc] + pix[1][1]) * 2
- pix[-2][fc] - pix[2][fc]) >> 2;
rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
val = ((pix[-width][1] + pix[0][fc] + pix[width][1]) * 2
- pix[-2*width][fc] - pix[2*width][fc]) >> 2;
rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
}
}
for (d=0; d < 2; d++)
for (row=top+1; row < top+TS-1 && row < height-1; row++)
for (col=left+1; col < left+TS-1 && col < width-1; col++) {
pix = (uint8_t (*)[3])dst + (row*width+col);
rix = &rgb[d][row-top][col-left];
if ((c = 2 - FC(row,col)) == 1) {
c = FC(row+1,col);
val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
- rix[-1][1] - rix[1][1] ) >> 1);
rix[0][2-c] = CLIPOUT(val);
val = pix[0][1] + (( pix[-width][c] + pix[width][c]
- rix[-TS][1] - rix[TS][1] ) >> 1);
} else
val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+ pix[+width-1][c] + pix[+width+1][c]
- rix[-TS-1][1] - rix[-TS+1][1]
- rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
rix[0][c] = CLIPOUT(val);
c = FC(row,col);
rix[0][c] = pix[0][c];
rix16[0] = rix[0][0];
rix16[1] = rix[0][1];
rix16[2] = rix[0][2];
cam_to_cielab (rix16, flab);
FORC3 lab[d][row-top][col-left][c] = 64*flab[c];
}
memset (homo, 0, 2*TS*TS);
for (row=top+2; row < top+TS-2 && row < height; row++) {
tr = row-top;
for (col=left+2; col < left+TS-2 && col < width; col++) {
tc = col-left;
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
ldiff[d][i] = ABS(lab[d][tr][tc][0]-lab[d][tr][tc+dir[i]][0]);
leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
MAX(ldiff[1][2],ldiff[1][3]));
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
if (i >> 1 == d || ldiff[d][i] <= leps)
abdiff[d][i] = SQR(lab[d][tr][tc][1]-lab[d][tr][tc+dir[i]][1])
+ SQR(lab[d][tr][tc][2]-lab[d][tr][tc+dir[i]][2]);
abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
MAX(abdiff[1][2],abdiff[1][3]));
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
homo[d][tr][tc]++;
}
}
for (row=top+3; row < top+TS-3 && row < height-3; row++) {
tr = row-top;
for (col=left+3; col < left+TS-3 && col < width-3; col++) {
tc = col-left;
for (d=0; d < 2; d++)
for (hm[d]=0, i=tr-1; i <= tr+1; i++)
for (j=tc-1; j <= tc+1; j++)
hm[d] += homo[d][i][j];
if (hm[0] != hm[1])
FORC3 dst[(row*width+col)*3 + c] = CLIPOUT(rgb[hm[1] > hm[0]][tr][tc][c]);
else
FORC3 dst[(row*width+col)*3 + c] =
CLIPOUT((rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1);
}
}
}
free (buffer);
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_AHD_uint16(const uint16_t *restrict bayer,
uint16_t *restrict dst, int sx, int sy,
dc1394color_filter_t pattern, int bits)
{
int i, j, top, left, row, col, tr, tc, fc, c, d, val, hm[2];
uint16_t (*pix)[3], (*rix)[3];
static const int dir[4] = { -1, 1, -TS, TS };
unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
float flab[3];
uint16_t (*rgb)[TS][TS][3];
short (*lab)[TS][TS][3];
char (*homo)[TS][TS], *buffer;
uint32_t filters;
const int height = sy, width = sx;
int x, y;
if (ahd_inited==DC1394_FALSE) {
cam_to_cielab (NULL,NULL);
ahd_inited = DC1394_TRUE;
}
switch(pattern) {
case DC1394_COLOR_FILTER_BGGR:
filters = 0x16161616;
break;
case DC1394_COLOR_FILTER_GRBG:
filters = 0x61616161;
break;
case DC1394_COLOR_FILTER_RGGB:
filters = 0x94949494;
break;
case DC1394_COLOR_FILTER_GBRG:
filters = 0x49494949;
break;
default:
return DC1394_INVALID_COLOR_FILTER;
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
int channel = FC(y,x);
dst[(y*width+x)*3 + channel] = bayer[y*width+x];
}
}
{
int border = 3;
unsigned row, col, y, x, f, c, sum[8];
for (row=0; row < height; row++)
for (col=0; col < width; col++) {
if (col==border && row >= border && row < height-border)
col = width-border;
memset (sum, 0, sizeof sum);
for (y=row-1; y != row+2; y++)
for (x=col-1; x != col+2; x++)
if (y < height && x < width) {
f = FC(y,x);
sum[f] += dst[(y*width+x)*3 + f];
sum[f+4]++;
}
f = FC(row,col);
FORC3 if (c != f && sum[c+4])
dst[(row*width+col)*3 + c] = sum[c] / sum[c+4];
}
}
buffer = (char *) malloc (26*TS*TS);
rgb = (uint16_t(*)[TS][TS][3]) buffer;
lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
for (top=0; top < height; top += TS-6)
for (left=0; left < width; left += TS-6) {
memset (rgb, 0, 12*TS*TS);
for (row = top < 2 ? 2:top; row < top+TS && row < height-2; row++) {
col = left + (FC(row,left) == 1);
if (col < 2) col += 2;
for (fc = FC(row,col); col < left+TS && col < width-2; col+=2) {
pix = (uint16_t (*)[3])dst + (row*width+col);
val = ((pix[-1][1] + pix[0][fc] + pix[1][1]) * 2
- pix[-2][fc] - pix[2][fc]) >> 2;
rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
val = ((pix[-width][1] + pix[0][fc] + pix[width][1]) * 2
- pix[-2*width][fc] - pix[2*width][fc]) >> 2;
rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
}
}
for (d=0; d < 2; d++)
for (row=top+1; row < top+TS-1 && row < height-1; row++)
for (col=left+1; col < left+TS-1 && col < width-1; col++) {
pix = (uint16_t (*)[3])dst + (row*width+col);
rix = &rgb[d][row-top][col-left];
if ((c = 2 - FC(row,col)) == 1) {
c = FC(row+1,col);
val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
- rix[-1][1] - rix[1][1] ) >> 1);
rix[0][2-c] = CLIPOUT16(val, bits);
val = pix[0][1] + (( pix[-width][c] + pix[width][c]
- rix[-TS][1] - rix[TS][1] ) >> 1);
} else
val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+ pix[+width-1][c] + pix[+width+1][c]
- rix[-TS-1][1] - rix[-TS+1][1]
- rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
rix[0][c] = CLIPOUT16(val, bits);
c = FC(row,col);
rix[0][c] = pix[0][c];
cam_to_cielab (rix[0], flab);
FORC3 lab[d][row-top][col-left][c] = 64*flab[c];
}
memset (homo, 0, 2*TS*TS);
for (row=top+2; row < top+TS-2 && row < height; row++) {
tr = row-top;
for (col=left+2; col < left+TS-2 && col < width; col++) {
tc = col-left;
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
ldiff[d][i] = ABS(lab[d][tr][tc][0]-lab[d][tr][tc+dir[i]][0]);
leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
MAX(ldiff[1][2],ldiff[1][3]));
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
if (i >> 1 == d || ldiff[d][i] <= leps)
abdiff[d][i] = SQR(lab[d][tr][tc][1]-lab[d][tr][tc+dir[i]][1])
+ SQR(lab[d][tr][tc][2]-lab[d][tr][tc+dir[i]][2]);
abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
MAX(abdiff[1][2],abdiff[1][3]));
for (d=0; d < 2; d++)
for (i=0; i < 4; i++)
if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
homo[d][tr][tc]++;
}
}
for (row=top+3; row < top+TS-3 && row < height-3; row++) {
tr = row-top;
for (col=left+3; col < left+TS-3 && col < width-3; col++) {
tc = col-left;
for (d=0; d < 2; d++)
for (hm[d]=0, i=tr-1; i <= tr+1; i++)
for (j=tc-1; j <= tc+1; j++)
hm[d] += homo[d][i][j];
if (hm[0] != hm[1])
FORC3 dst[(row*width+col)*3 + c] = CLIPOUT16(rgb[hm[1] > hm[0]][tr][tc][c], bits);
else
FORC3 dst[(row*width+col)*3 + c] =
CLIPOUT16((rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1, bits);
}
}
}
free (buffer);
return DC1394_SUCCESS;
}
dc1394error_t
dc1394_bayer_decoding_8bit(const uint8_t *restrict bayer, uint8_t *restrict rgb, uint32_t sx, uint32_t sy, dc1394color_filter_t tile, dc1394bayer_method_t method)
{
switch (method) {
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG(bayer, rgb, sx, sy, tile);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD(bayer, rgb, sx, sy, tile);
default:
return DC1394_INVALID_BAYER_METHOD;
}
}
dc1394error_t
dc1394_bayer_decoding_16bit(const uint16_t *restrict bayer, uint16_t *restrict rgb, uint32_t sx, uint32_t sy, dc1394color_filter_t tile, dc1394bayer_method_t method, uint32_t bits)
{
switch (method) {
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG_uint16(bayer, rgb, sx, sy, tile, bits);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD_uint16(bayer, rgb, sx, sy, tile, bits);
default:
return DC1394_INVALID_BAYER_METHOD;
}
}
void
Adapt_buffer_bayer(dc1394video_frame_t *in, dc1394video_frame_t *out, dc1394bayer_method_t method)
{
uint32_t bpp;
out->size[0]=in->size[0];
out->size[1]=in->size[1];
if (method == DC1394_BAYER_METHOD_DOWNSAMPLE) {
out->size[0]/=2;
out->size[1]/=2;
}
out->position[0]=in->position[0];
out->position[1]=in->position[1];
if (method == DC1394_BAYER_METHOD_DOWNSAMPLE) {
out->position[0]/=2;
out->position[1]/=2;
}
if (in->color_coding==DC1394_COLOR_CODING_RAW16)
out->color_coding=DC1394_COLOR_CODING_RGB16;
else
out->color_coding=DC1394_COLOR_CODING_RGB8;
out->color_filter=in->color_filter;
if (in->color_coding==DC1394_COLOR_CODING_RAW16)
out->data_depth=in->data_depth;
else
out->data_depth=8;
out->video_mode = in->video_mode;
out->padding_bytes = in->padding_bytes;
dc1394_get_color_coding_bit_size(out->color_coding, &bpp);
out->image_bytes=(out->size[0]*out->size[1]*bpp)/8;
out->total_bytes = out->image_bytes + out->padding_bytes;
out->packet_size = in->packet_size;
out->packets_per_frame = in->packets_per_frame;
out->timestamp = in->timestamp;
out->frames_behind = in->frames_behind;
out->camera = in->camera;
out->id = in->id;
if (out->total_bytes>out->allocated_image_bytes) {
free(out->image);
out->image=(uint8_t*)malloc(out->total_bytes*sizeof(uint8_t));
}
memcpy(&(out->image[out->image_bytes]),&(in->image[in->image_bytes]),out->padding_bytes);
out->little_endian=0;
out->data_in_padding=0;
}
dc1394error_t
02110 dc1394_debayer_frames(dc1394video_frame_t *in, dc1394video_frame_t *out, dc1394bayer_method_t method)
{
if ((method<DC1394_BAYER_METHOD_MIN)||(method>DC1394_BAYER_METHOD_MAX))
return DC1394_INVALID_BAYER_METHOD;
switch (in->color_coding) {
case DC1394_COLOR_CODING_RAW8:
case DC1394_COLOR_CODING_MONO8:
Adapt_buffer_bayer(in,out,method);
switch (method) {
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG(in->image, out->image, in->size[0], in->size[1], in->color_filter);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD(in->image, out->image, in->size[0], in->size[1], in->color_filter);
}
break;
case DC1394_COLOR_CODING_MONO16:
case DC1394_COLOR_CODING_RAW16:
Adapt_buffer_bayer(in,out,method);
switch (method) {
case DC1394_BAYER_METHOD_NEAREST:
return dc1394_bayer_NearestNeighbor_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_SIMPLE:
return dc1394_bayer_Simple_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_BILINEAR:
return dc1394_bayer_Bilinear_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_HQLINEAR:
return dc1394_bayer_HQLinear_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_DOWNSAMPLE:
return dc1394_bayer_Downsample_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_EDGESENSE:
return dc1394_bayer_EdgeSense_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_VNG:
return dc1394_bayer_VNG_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
case DC1394_BAYER_METHOD_AHD:
return dc1394_bayer_AHD_uint16((uint16_t*)in->image, (uint16_t*)out->image, in->size[0], in->size[1], in->color_filter, in->data_depth);
}
break;
default:
return DC1394_FUNCTION_NOT_SUPPORTED;
}
return DC1394_SUCCESS;
}