Files
handleaiuinew/env/LMI/include/GoSdk/GoAlgorithm.c
T
2024-05-18 23:53:26 +08:00

1500 lines
51 KiB
C

/**
* @file GoAlgorithm.c
*
* @internal
* Copyright (C) 2017-2021 by LMI Technologies Inc.
* Licensed under the MIT License.
* Redistributed files must retain the above copyright notice.
*/
#include <GoSdk/GoAlgorithm.h>
#include <kApi/Data/kImage.h>
#define COPY_BAYER_ALGORITHM_FROM_KVISION 1
#ifdef COPY_BAYER_ALGORITHM_FROM_KVISION
kStatus GoAlgorithm_BayerDemosaicReduceBggr(kImage input, kImage output)
{
k32u outWidth = (k32u)kImage_Width(output);
k32u outHeight = (k32u)kImage_Height(output);
k64u* reader[2];
k64u v0, v1;
k8u* v0r = (void*)&v0;
k8u* v1r = (void*)&v1;
k32u* writer;
k32u* writerEnd;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kArgb)) ||
(kImage_Width(input) != 2 * outWidth) ||
(kImage_Height(input) != 2 * outHeight) ||
(kImage_Width(input) % 8) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
for (i = 0; i < outHeight; ++i)
{
reader[0] = (k64u*)kImage_RowAt(input, 2 * i);
reader[1] = (k64u*)kImage_RowAt(input, 2 * i + 1);
writer = (k32u*)kImage_RowAt(output, i);
writerEnd = writer + outWidth;
while (writer != writerEnd)
{
v0 = *reader[0]++;
v1 = *reader[1]++;
writer[0] = (v1r[1] << 16) | (((v0r[1] + v1r[0]) >> 1) << 8) | v0r[0];
writer[1] = (v1r[3] << 16) | (((v0r[3] + v1r[2]) >> 1) << 8) | v0r[2];
writer[2] = (v1r[5] << 16) | (((v0r[5] + v1r[4]) >> 1) << 8) | v0r[4];
writer[3] = (v1r[7] << 16) | (((v0r[7] + v1r[6]) >> 1) << 8) | v0r[6];
writer += 4;
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicReduceGbrg(kImage input, kImage output)
{
k32u outWidth = (k32u)kImage_Width(output);
k32u outHeight = (k32u)kImage_Height(output);
k64u* reader[2];
k64u v0, v1;
k8u* v0r = (void*)&v0;
k8u* v1r = (void*)&v1;
k32u* writer;
k32u* writerEnd;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kArgb)) ||
(kImage_Width(input) != 2 * outWidth) ||
(kImage_Height(input) != 2 * outHeight) ||
(kImage_Width(input) % 8) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
for (i = 0; i < outHeight; ++i)
{
reader[0] = (k64u*)kImage_RowAt(input, 2 * i);
reader[1] = (k64u*)kImage_RowAt(input, 2 * i + 1);
writer = (k32u*)kImage_RowAt(output, i);
writerEnd = writer + outWidth;
while (writer != writerEnd)
{
v0 = *reader[0]++;
v1 = *reader[1]++;
writer[0] = (v1r[0] << 16) | (((v0r[0] + v1r[1]) >> 1) << 8) | v0r[1];
writer[1] = (v1r[2] << 16) | (((v0r[2] + v1r[3]) >> 1) << 8) | v0r[3];
writer[2] = (v1r[4] << 16) | (((v0r[4] + v1r[5]) >> 1) << 8) | v0r[5];
writer[3] = (v1r[6] << 16) | (((v0r[6] + v1r[7]) >> 1) << 8) | v0r[7];
writer += 4;
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicReduceRggb(kImage input, kImage output)
{
k32u outWidth = (k32u)kImage_Width(output);
k32u outHeight = (k32u)kImage_Height(output);
k64u* reader[2];
k64u v0, v1;
k8u* v0r = (void*)&v0;
k8u* v1r = (void*)&v1;
k32u* writer;
k32u* writerEnd;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kArgb)) ||
(kImage_Width(input) != 2 * outWidth) ||
(kImage_Height(input) != 2 * outHeight) ||
(kImage_Width(input) % 8) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
for (i = 0; i < outHeight; ++i)
{
reader[0] = (k64u*)kImage_RowAt(input, 2 * i);
reader[1] = (k64u*)kImage_RowAt(input, 2 * i + 1);
writer = (k32u*)kImage_RowAt(output, i);
writerEnd = writer + outWidth;
while (writer != writerEnd)
{
v0 = *reader[0]++;
v1 = *reader[1]++;
writer[0] = (v0r[0] << 16) | (((v0r[1] + v1r[0]) >> 1) << 8) | v1r[1];
writer[1] = (v0r[2] << 16) | (((v0r[3] + v1r[2]) >> 1) << 8) | v1r[3];
writer[2] = (v0r[4] << 16) | (((v0r[5] + v1r[4]) >> 1) << 8) | v1r[5];
writer[3] = (v0r[6] << 16) | (((v0r[7] + v1r[6]) >> 1) << 8) | v1r[7];
writer += 4;
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicReduceGrbg(kImage input, kImage output)
{
k32u outWidth = (k32u)kImage_Width(output);
k32u outHeight = (k32u)kImage_Height(output);
k64u* reader[2];
k64u v0, v1;
k8u* v0r = (void*)&v0;
k8u* v1r = (void*)&v1;
k32u* writer;
k32u* writerEnd;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kArgb)) ||
(kImage_Width(input) != 2 * outWidth) ||
(kImage_Height(input) != 2 * outHeight) ||
(kImage_Width(input) % 8) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
for (i = 0; i < outHeight; ++i)
{
reader[0] = (k64u*)kImage_RowAt(input, 2 * i);
reader[1] = (k64u*)kImage_RowAt(input, 2 * i + 1);
writer = (k32u*)kImage_RowAt(output, i);
writerEnd = writer + outWidth;
while (writer != writerEnd)
{
v0 = *reader[0]++;
v1 = *reader[1]++;
writer[0] = (v0r[1] << 16) | (((v0r[0] + v1r[1]) >> 1) << 8) | v1r[0];
writer[1] = (v0r[3] << 16) | (((v0r[2] + v1r[3]) >> 1) << 8) | v1r[2];
writer[2] = (v0r[5] << 16) | (((v0r[4] + v1r[5]) >> 1) << 8) | v1r[4];
writer[3] = (v0r[7] << 16) | (((v0r[6] + v1r[7]) >> 1) << 8) | v1r[6];
writer += 4;
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicBilinearBggr(kImage input, kImage output)
{
k8u* srcp;
k8u* r0p, *r1p, *b0p, *b1p;
k32u *dstp;
k32u r, g, b;
k32s i, j;
k32s width = (k32s)kImage_Width(input);
k32s height = (k32s)kImage_Height(input);
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
((k32s)kImage_Width(output) != width) ||
((k32s)kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
srcp = kImage_AtT(input, 0, 0, k8u);
dstp = kImage_AtT(output, 0, 0, k32u);
for (i = 0; i<height; i++)
{
if ((i & 1) == 0)
{ /* Blue row */
b0p = srcp + i*width;
if (i)
{
if (i<height - 1)
{
r1p = b0p + width;
r0p = b0p - width;
}
else
{
r0p = r1p = b0p - width;
}
}
else
{
r0p = r1p = b0p + width;
}
/* First pixel */
r = (*(r0p + 1) + *(r1p + 1)) / 2;
g = (*r0p + *r1p) / 2;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{ /* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = (*(b0p - 1) + *(b0p + 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
else
{ /* Blue pixel */
r = (*(r0p - 1) + *(r0p + 1) + *(r1p - 1) + *(r1p + 1) + 1) / 4;
g = (*(b0p - 1) + *(b0p + 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
}
/* Last pixel */
if (j % 2)
{ /* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = *(b0p - 1);
*dstp++ = b | (g << 8) | (r << 16);
}
else
{ /* Blue pixel */
r = (*(r0p - 1) + *(r1p - 1)) / 2;
g = (*(b0p - 1) + *(b0p - 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
}
}
else
{ /* Red row */
r0p = srcp + i*width;
b1p = r0p + width;
if (i)
{
if (i<height - 1)
{
b1p = r0p + width;
b0p = r0p - width;
}
else
{
b0p = b1p = r0p - width;
}
}
else
{
b0p = b1p = r0p + width;
}
/* First pixel */
r = *(r0p + 1);
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{ /* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p + 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b0p + 1) + *(b1p - 1) + *(b1p + 1) + 1) / 4;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
else
{ /* Green Pixel */
r = (*(r0p - 1) + *(r0p + 1)) / 2;
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
}
/* Last pixel */
if (j % 2)
{ /* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p - 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b1p - 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
else
{ /* Green Pixel */
r = *(r0p - 1);
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicBilinearGbrg(kImage input, kImage output)
{
k8u* srcp;
k8u* r0p, *r1p, *b0p, *b1p;
k32u *dstp;
k32u r, g, b;
k32s i, j;
k32s width = (k32s)kImage_Width(input);
k32s height = (k32s)kImage_Height(input);
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
((k32s)kImage_Width(output) != width) ||
((k32s)kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
srcp = kImage_AtT(input, 0, 0, k8u);
dstp = kImage_AtT(output, 0, 0, k32u);
for (i = 0; i<height; i++)
{
if ((i & 1) == 0)
{ /* Blue row */
b0p = srcp + i*width;
if (i)
{
if (i<height - 1)
{
r1p = b0p + width;
r0p = b0p - width;
}
else
{
r0p = r1p = b0p - width;
}
}
else
{
r0p = r1p = b0p + width;
}
/* First pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = *(b0p + 1);
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{
/* Blue pixel */
r = (*(r0p - 1) + *(r0p + 1) + *(r1p - 1) + *(r1p + 1) + 1) / 4;
g = (*(b0p - 1) + *(b0p + 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
else
{
/* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = (*(b0p - 1) + *(b0p + 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
}
/* Last pixel */
if (j % 2)
{
/* Blue pixel */
r = (*(r0p - 1) + *(r1p - 1)) / 2;
g = (*(b0p - 1) + *(b0p - 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
}
else
{
/* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = *(b0p - 1);
*dstp++ = b | (g << 8) | (r << 16);
}
}
else
{ /* Red row */
r0p = srcp + i*width;
b1p = r0p + width;
if (i)
{
if (i<height - 1)
{
b1p = r0p + width;
b0p = r0p - width;
}
else
{
b0p = b1p = r0p - width;
}
}
else
{
b0p = b1p = r0p + width;
}
/* First pixel */
r = *r0p;
g = (*b0p + *b1p) / 2; // Should we take the adjacent one as well?
b = (*(b0p + 1) + *(b1p + 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{
/* Green Pixel */
r = (*(r0p - 1) + *(r0p + 1)) / 2;
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
else
{
/* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p + 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b0p + 1) + *(b1p - 1) + *(b1p + 1) + 1) / 4;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
}
/* Last pixel */
if (j % 2)
{
/* Green Pixel */
r = *(r0p - 1);
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
else
{
/* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p - 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b1p - 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicBilinearRggb(kImage input, kImage output)
{
k8u* srcp;
k8u* r0p, *r1p, *b0p, *b1p;
k32u *dstp;
k32u r, g, b;
k32s i, j;
k32s width = (k32s)kImage_Width(input);
k32s height = (k32s)kImage_Height(input);
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
((k32s)kImage_Width(output) != width) ||
((k32s)kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
srcp = kImage_AtT(input, 0, 0, k8u);
dstp = kImage_AtT(output, 0, 0, k32u);
for (i = 0; i<height; i++)
{
if ((i & 1) == 1)
{ /* Blue row */
b0p = srcp + i*width;
if (i)
{
if (i<height - 1)
{
r1p = b0p + width;
r0p = b0p - width;
}
else
{
r0p = r1p = b0p - width;
}
}
else
{
r0p = r1p = b0p + width;
}
/* First pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = *(b0p + 1);
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{
/* Blue pixel */
r = (*(r0p - 1) + *(r0p + 1) + *(r1p - 1) + *(r1p + 1) + 1) / 4;
g = (*(b0p - 1) + *(b0p + 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
else
{
/* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = (*(b0p - 1) + *(b0p + 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
}
/* Last pixel */
if (j % 2)
{
/* Blue pixel */
r = (*(r0p - 1) + *(r1p - 1)) / 2;
g = (*(b0p - 1) + *(b0p - 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
}
else
{
/* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = *(b0p - 1);
*dstp++ = b | (g << 8) | (r << 16);
}
}
else
{ /* Red row */
r0p = srcp + i*width;
b1p = r0p + width;
if (i)
{
if (i<height - 1)
{
b1p = r0p + width;
b0p = r0p - width;
}
else
{
b0p = b1p = r0p - width;
}
}
else
{
b0p = b1p = r0p + width;
}
/* First pixel */
r = *r0p;
g = (*b0p + *b1p) / 2;
b = (*(b0p + 1) + *(b1p + 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{
/* Green Pixel */
r = (*(r0p - 1) + *(r0p + 1)) / 2;
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
else
{
/* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p + 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b0p + 1) + *(b1p - 1) + *(b1p + 1) + 1) / 4;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
}
/* Last pixel */
if (j % 2)
{
/* Green Pixel */
r = *(r0p - 1);
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
else
{
/* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p - 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b1p - 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicBilinearGrbg(kImage input, kImage output)
{
k8u* srcp;
k8u* r0p, *r1p, *b0p, *b1p;
k32u *dstp;
k32u r, g, b;
k32s i, j;
k32s width = (k32s)kImage_Width(input);
k32s height = (k32s)kImage_Height(input);
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
((k32s)kImage_Width(output) != width) ||
((k32s)kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2))
{
return kERROR_PARAMETER;
}
srcp = kImage_AtT(input, 0, 0, k8u);
dstp = kImage_AtT(output, 0, 0, k32u);
for (i = 0; i<height; i++)
{
if ((i & 1) == 1)
{ /* Blue row */
b0p = srcp + i*width;
if (i)
{
if (i<height - 1)
{
r1p = b0p + width;
r0p = b0p - width;
}
else
{
r0p = r1p = b0p - width;
}
}
else
{
r0p = r1p = b0p + width;
}
/* First pixel */
r = (*(r0p + 1) + *(r1p + 1)) / 2;
g = (*r0p + *r1p) / 2;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{ /* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = (*(b0p - 1) + *(b0p + 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
else
{ /* Blue pixel */
r = (*(r0p - 1) + *(r0p + 1) + *(r1p - 1) + *(r1p + 1) + 1) / 4;
g = (*(b0p - 1) + *(b0p + 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; r1p++; b0p++;
}
}
/* Last pixel */
if (j % 2)
{ /* Green Pixel */
r = (*r0p + *r1p) / 2;
g = *b0p;
b = *(b0p - 1);
*dstp++ = b | (g << 8) | (r << 16);
}
else
{ /* Blue pixel */
r = (*(r0p - 1) + *(r1p - 1)) / 2;
g = (*(b0p - 1) + *(b0p - 1) + *r0p + *r1p + 1) / 4;
b = *b0p;
*dstp++ = b | (g << 8) | (r << 16);
}
}
else
{ /* Red row */
r0p = srcp + i*width;
b1p = r0p + width;
if (i)
{
if (i<height - 1)
{
b1p = r0p + width;
b0p = r0p - width;
}
else
{
b0p = b1p = r0p - width;
}
}
else
{
b0p = b1p = r0p + width;
}
/* First pixel */
r = *(r0p + 1);
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
for (j = 1; j<width - 1; j++)
{
if (j % 2)
{ /* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p + 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b0p + 1) + *(b1p - 1) + *(b1p + 1) + 1) / 4;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
else
{ /* Green Pixel */
r = (*(r0p - 1) + *(r0p + 1)) / 2;
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
r0p++; b0p++; b1p++;
}
}
/* Last pixel */
if (j % 2)
{ /* Red pixel */
r = *r0p;
g = (*(r0p - 1) + *(r0p - 1) + *b0p + *b1p + 1) / 4;
b = (*(b0p - 1) + *(b1p - 1)) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
else
{ /* Green Pixel */
r = *(r0p - 1);
g = *r0p;
b = (*b0p + *b1p) / 2;
*dstp++ = b | (g << 8) | (r << 16);
}
}
}
return kOK;
}
#define BAYER_GRADIENT_X(in, i) (in[2][2+i])
#define BAYER_GRADIENT_L_G(in, i) ((-1*in[0][2+i] + \
2*in[1][2+i] + \
-1*in[2][2+i] + 2*in[2][3+i] + 4*in[2][2+i] + 2*in[2][3+i] + -1*in[2][4+i] + \
2*in[3][2+i] + \
-1*in[4][2+i]) /8)
#define BAYER_GRADIENT_L_RBH(in, i) ((1*in[0][2+i]/2 + \
-1*in[1][3+i] + -1*in[1][3+i] + \
-1*in[2][2+i] + 4*in[2][3+i] + 5*in[2][2+i] + 4*in[2][3+i] + -1*in[2][4+i] + \
-1*in[3][3+i] + -1*in[3][3+i] + \
1*in[4][2+i]/2) /8)
#define BAYER_GRADIENT_L_RBV(in, i) ((-1*in[0][2+i] + \
-1*in[1][3+i] + 4*in[1][2+i] + -1*in[1][3+i] + \
1*in[2][2+i]/2 + 5*in[2][2+i] + 1*in[2][4+i]/2 + \
-1*in[3][3+i] + 4*in[3][2+i] + -1*in[3][3+i] + \
-1*in[4][2+i]) /8)
#define BAYER_GRADIENT_L_RBD(in, i) ((-3*in[0][2+i]/2 + \
2*in[1][3+i] + 2*in[1][3+i] + \
-3*in[2][2+i]/2 + 6*in[2][2+i] + -3*in[2][4+i]/2 + \
2*in[3][3+i] + 2*in[3][3+i] + \
-3*in[4][2+i]/2) /8)
#define BAYER_GRADIENT_C_G(in, i) ((-1*in[0][2+i] + \
2*in[1][2+i] + \
-1*in[2][0+i] + 2*in[2][1+i] + 4*in[2][2+i] + 2*in[2][3+i] + -1*in[2][4+i] + \
2*in[3][2+i] + \
-1*in[4][2+i]) /8)
#define BAYER_GRADIENT_C_RBH(in, i) ((1*in[0][2+i]/2 + \
-1*in[1][1+i] + -1*in[1][3+i] + \
-1*in[2][0+i] + 4*in[2][1+i] + 5*in[2][2+i] + 4*in[2][3+i] + -1*in[2][4+i] + \
-1*in[3][1+i] + -1*in[3][3+i] + \
1*in[4][2+i]/2) /8)
#define BAYER_GRADIENT_C_RBV(in, i) ((-1*in[0][2+i] + \
-1*in[1][1+i] + 4*in[1][2+i] + -1*in[1][3+i] + \
1*in[2][0+i]/2 + 5*in[2][2+i] + 1*in[2][4+i]/2 + \
-1*in[3][1+i] + 4*in[3][2+i] + -1*in[3][3+i] + \
-1*in[4][2+i]) /8)
#define BAYER_GRADIENT_C_RBD(in, i) ((-3*in[0][2+i]/2 + \
2*in[1][1+i] + 2*in[1][3+i] + \
-3*in[2][0+i]/2 + 6*in[2][2+i] + -3*in[2][4+i]/2 + \
2*in[3][1+i] + 2*in[3][3+i] + \
-3*in[4][2+i]/2) /8)
#define BAYER_GRADIENT_R_G(in, i) ((-1*in[0][2+i] + \
2*in[1][2+i] + \
-1*in[2][0+i] + 2*in[2][1+i] + 4*in[2][2+i] + 2*in[2][1+i] + -1*in[2][2+i] + \
2*in[3][2+i] + \
-1*in[4][2+i]) /8)
#define BAYER_GRADIENT_R_RBH(in, i) ((1*in[0][2+i]/2 + \
-1*in[1][1+i] + -1*in[1][1+i] + \
-1*in[2][0+i] + 4*in[2][1+i] + 5*in[2][2+i] + 4*in[2][1+i] + -1*in[2][2+i] + \
-1*in[3][1+i] + -1*in[3][1+i] + \
1*in[4][2+i]/2) /8)
#define BAYER_GRADIENT_R_RBV(in, i) ((-1*in[0][2+i] + \
-1*in[1][1+i] + 4*in[1][2+i] + -1*in[1][1+i] + \
1*in[2][0+i]/2 + 5*in[2][2+i] + 1*in[2][2+i]/2 + \
-1*in[3][1+i] + 4*in[3][2+i] + -1*in[3][1+i] + \
-1*in[4][2+i]) /8)
#define BAYER_GRADIENT_R_RBD(in, i) ((-3*in[0][2+i]/2 + \
2*in[1][1+i] + 2*in[1][1+i] + \
-3*in[2][0+i]/2 + 6*in[2][2+i] + -3*in[2][2+i]/2 + \
2*in[3][1+i] + 2*in[3][1+i] + \
-3*in[4][2+i]/2) /8)
#define BAYER_GRADIENT_ASSIGN(out, i, r, g, b) \
out[i].r = (k8u) kClamp_(r, 0, k8U_MAX); \
out[i].g = (k8u) kClamp_(g, 0, k8U_MAX); \
out[i].b = (k8u) kClamp_(b, 0, k8U_MAX)
#define BAYER_GRADIENT_ADVANCE(in, out, i) \
in[0] += i, in[1] += i, in[2] += i, in[3] += i, in[4] += i; out += i
kStatus GoAlgorithm_BayerDemosaicGradientBggr(kImage input, kImage output)
{
k32u width = (k32u)kImage_Width(input);
k32u height = (k32u)kImage_Height(input);
k32u pitch = (k32u)(kImage_Stride(input)/kImage_PixelSize(input));
k8u* base = (kImage_DataT(input, k8u)) - 2;
k8u* in[5];
k8u* end0;
kRgb* out;
k32s r, g, b;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
(kImage_Width(output) != width) ||
(kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2) ||
(kImage_Width(input) < 4) ||
(kImage_Height(input) < 4))
{
return kERROR_PARAMETER;
}
for (i = 0; i < height; ++i)
{
in[0] = (i > 1) ? &base[(i - 2)*pitch] : &base[(i)*pitch];
in[1] = (i > 0) ? &base[(i - 1)*pitch] : &base[(i + 1)*pitch];
in[2] = &base[(i)*pitch];
in[3] = (i < (height - 1)) ? &base[(i + 1)*pitch] : &base[(i - 1)*pitch];
in[4] = (i < (height - 2)) ? &base[(i + 2)*pitch] : &base[(i)*pitch];
end0 = in[0] + width - 2;
out = kImage_AtT(output, 0, i, kRgb);
if ((i & 1) == 0)
{
r = BAYER_GRADIENT_L_RBD(in, 0);
g = BAYER_GRADIENT_L_G(in, 0);
b = BAYER_GRADIENT_X(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_L_RBV(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_L_RBH(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_C_RBD(in, 0);
g = BAYER_GRADIENT_C_G(in, 0);
b = BAYER_GRADIENT_X(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_C_RBV(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_C_RBH(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_R_RBD(in, 0);
g = BAYER_GRADIENT_R_G(in, 0);
b = BAYER_GRADIENT_X(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_R_RBV(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_R_RBH(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
else
{
r = BAYER_GRADIENT_L_RBH(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_L_RBV(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_X(in, 1);
g = BAYER_GRADIENT_L_G(in, 1);
b = BAYER_GRADIENT_L_RBD(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_C_RBH(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_C_RBV(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_X(in, 1);
g = BAYER_GRADIENT_C_G(in, 1);
b = BAYER_GRADIENT_C_RBD(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_R_RBH(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_R_RBV(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_X(in, 1);
g = BAYER_GRADIENT_R_G(in, 1);
b = BAYER_GRADIENT_R_RBD(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicGradientGbrg(kImage input, kImage output)
{
k32u width = (k32u)kImage_Width(input);
k32u height = (k32u)kImage_Height(input);
k32u pitch = (k32u)(k32u)(kImage_Stride(input)/kImage_PixelSize(input));
k8u* base = (kImage_DataT(input, k8u)) - 2;
k8u* in[5];
k8u* end0;
kRgb* out;
k32s r, g, b;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
(kImage_Width(output) != width) ||
(kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2) ||
(kImage_Width(input) < 4) ||
(kImage_Height(input) < 4))
{
return kERROR_PARAMETER;
}
for (i = 0; i < height; ++i)
{
in[0] = (i > 1) ? &base[(i - 2)*pitch] : &base[(i)*pitch];
in[1] = (i > 0) ? &base[(i - 1)*pitch] : &base[(i + 1)*pitch];
in[2] = &base[(i)*pitch];
in[3] = (i < (height - 1)) ? &base[(i + 1)*pitch] : &base[(i - 1)*pitch];
in[4] = (i < (height - 2)) ? &base[(i + 2)*pitch] : &base[(i)*pitch];
end0 = in[0] + width - 2;
out = kImage_AtT(output, 0, i, kRgb);
if ((i & 1) == 1)
{
r = BAYER_GRADIENT_X(in, 0);
g = BAYER_GRADIENT_L_G(in, 0);
b = BAYER_GRADIENT_L_RBD(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_L_RBH(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_L_RBV(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_X(in, 0);
g = BAYER_GRADIENT_C_G(in, 0);
b = BAYER_GRADIENT_C_RBD(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_C_RBH(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_C_RBV(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_X(in, 0);
g = BAYER_GRADIENT_R_G(in, 0);
b = BAYER_GRADIENT_R_RBD(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_R_RBH(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_R_RBV(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
else
{
r = BAYER_GRADIENT_L_RBV(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_L_RBH(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_L_RBD(in, 1);
g = BAYER_GRADIENT_L_G(in, 1);
b = BAYER_GRADIENT_X(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_C_RBV(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_C_RBH(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_C_RBD(in, 1);
g = BAYER_GRADIENT_C_G(in, 1);
b = BAYER_GRADIENT_X(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_R_RBV(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_R_RBH(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_R_RBD(in, 1);
g = BAYER_GRADIENT_R_G(in, 1);
b = BAYER_GRADIENT_X(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicGradientRggb(kImage input, kImage output)
{
k32u width = (k32u)kImage_Width(input);
k32u height = (k32u)kImage_Height(input);
k32u pitch = (k32u)(kImage_Stride(input)/kImage_PixelSize(input));
k8u* base = (kImage_DataT(input, k8u)) - 2;
k8u* in[5];
k8u* end0;
kRgb* out;
k32s r, g, b;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
(kImage_Width(output) != width) ||
(kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2) ||
(kImage_Width(input) < 4) ||
(kImage_Height(input) < 4))
{
return kERROR_PARAMETER;
}
for (i = 0; i < height; ++i)
{
in[0] = (i > 1) ? &base[(i - 2)*pitch] : &base[(i)*pitch];
in[1] = (i > 0) ? &base[(i - 1)*pitch] : &base[(i + 1)*pitch];
in[2] = &base[(i)*pitch];
in[3] = (i < (height - 1)) ? &base[(i + 1)*pitch] : &base[(i - 1)*pitch];
in[4] = (i < (height - 2)) ? &base[(i + 2)*pitch] : &base[(i)*pitch];
end0 = in[0] + width - 2;
out = kImage_AtT(output, 0, i, kRgb);
if ((i & 1) == 0)
{
r = BAYER_GRADIENT_X(in, 0);
g = BAYER_GRADIENT_L_G(in, 0);
b = BAYER_GRADIENT_L_RBD(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_L_RBH(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_L_RBV(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_X(in, 0);
g = BAYER_GRADIENT_C_G(in, 0);
b = BAYER_GRADIENT_C_RBD(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_C_RBH(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_C_RBV(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_X(in, 0);
g = BAYER_GRADIENT_R_G(in, 0);
b = BAYER_GRADIENT_R_RBD(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_R_RBH(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_R_RBV(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
else
{
r = BAYER_GRADIENT_L_RBV(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_L_RBH(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_L_RBD(in, 1);
g = BAYER_GRADIENT_L_G(in, 1);
b = BAYER_GRADIENT_X(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_C_RBV(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_C_RBH(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_C_RBD(in, 1);
g = BAYER_GRADIENT_C_G(in, 1);
b = BAYER_GRADIENT_X(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_R_RBV(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_R_RBH(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_R_RBD(in, 1);
g = BAYER_GRADIENT_R_G(in, 1);
b = BAYER_GRADIENT_X(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicGradientGrbg(kImage input, kImage output)
{
k32u width = (k32u)kImage_Width(input);
k32u height = (k32u)kImage_Height(input);
k32u pitch = (k32u)(kImage_Stride(input)/kImage_PixelSize(input));
k8u* base = (kImage_DataT(input, k8u)) - 2;
k8u* in[5];
k8u* end0;
kRgb* out;
k32s r, g, b;
k32u i;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_PixelSize(output) != sizeof(kRgb)) ||
(kImage_Width(output) != width) ||
(kImage_Height(output) != height) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2) ||
(kImage_Width(input) < 4) ||
(kImage_Height(input) < 4))
{
return kERROR_PARAMETER;
}
for (i = 0; i < height; ++i)
{
in[0] = (i > 1) ? &base[(i - 2)*pitch] : &base[(i)*pitch];
in[1] = (i > 0) ? &base[(i - 1)*pitch] : &base[(i + 1)*pitch];
in[2] = &base[(i)*pitch];
in[3] = (i < (height - 1)) ? &base[(i + 1)*pitch] : &base[(i - 1)*pitch];
in[4] = (i < (height - 2)) ? &base[(i + 2)*pitch] : &base[(i)*pitch];
end0 = in[0] + width - 2;
out = kImage_AtT(output, 0, i, kRgb);
if ((i & 1) == 1)
{
r = BAYER_GRADIENT_L_RBD(in, 0);
g = BAYER_GRADIENT_L_G(in, 0);
b = BAYER_GRADIENT_X(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_L_RBV(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_L_RBH(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_C_RBD(in, 0);
g = BAYER_GRADIENT_C_G(in, 0);
b = BAYER_GRADIENT_X(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_C_RBV(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_C_RBH(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_R_RBD(in, 0);
g = BAYER_GRADIENT_R_G(in, 0);
b = BAYER_GRADIENT_X(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_R_RBV(in, 1);
g = BAYER_GRADIENT_X(in, 1);
b = BAYER_GRADIENT_R_RBH(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
else
{
r = BAYER_GRADIENT_L_RBH(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_L_RBV(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_X(in, 1);
g = BAYER_GRADIENT_L_G(in, 1);
b = BAYER_GRADIENT_L_RBD(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
while (in[0] != end0)
{
r = BAYER_GRADIENT_C_RBH(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_C_RBV(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_X(in, 1);
g = BAYER_GRADIENT_C_G(in, 1);
b = BAYER_GRADIENT_C_RBD(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
r = BAYER_GRADIENT_R_RBH(in, 0);
g = BAYER_GRADIENT_X(in, 0);
b = BAYER_GRADIENT_R_RBV(in, 0);
BAYER_GRADIENT_ASSIGN(out, 0, r, g, b);
r = BAYER_GRADIENT_X(in, 1);
g = BAYER_GRADIENT_R_G(in, 1);
b = BAYER_GRADIENT_R_RBD(in, 1);
BAYER_GRADIENT_ASSIGN(out, 1, r, g, b);
BAYER_GRADIENT_ADVANCE(in, out, 2);
}
}
return kOK;
}
kStatus GoAlgorithm_BayerDemosaicReduce(kImage input, kImage output)
{
switch (kImage_Cfa(input))
{
case kCFA_BAYER_BGGR: return GoAlgorithm_BayerDemosaicReduceBggr(input, output);
case kCFA_BAYER_GBRG: return GoAlgorithm_BayerDemosaicReduceGbrg(input, output);
case kCFA_BAYER_RGGB: return GoAlgorithm_BayerDemosaicReduceRggb(input, output);
case kCFA_BAYER_GRBG: return GoAlgorithm_BayerDemosaicReduceGrbg(input, output);
default: return kERROR_PARAMETER;
}
}
kStatus GoAlgorithm_BayerDemosaicBilinear(kImage input, kImage output)
{
switch (kImage_Cfa(input))
{
case kCFA_BAYER_BGGR: return GoAlgorithm_BayerDemosaicBilinearBggr(input, output);
case kCFA_BAYER_GBRG: return GoAlgorithm_BayerDemosaicBilinearGbrg(input, output);
case kCFA_BAYER_RGGB: return GoAlgorithm_BayerDemosaicBilinearRggb(input, output);
case kCFA_BAYER_GRBG: return GoAlgorithm_BayerDemosaicBilinearGrbg(input, output);
default: return kERROR_PARAMETER;
}
}
kStatus GoAlgorithm_BayerDemosaicGradient(kImage input, kImage output)
{
switch (kImage_Cfa(input))
{
case kCFA_BAYER_BGGR: return GoAlgorithm_BayerDemosaicGradientBggr(input, output);
case kCFA_BAYER_GBRG: return GoAlgorithm_BayerDemosaicGradientGbrg(input, output);
case kCFA_BAYER_RGGB: return GoAlgorithm_BayerDemosaicGradientRggb(input, output);
case kCFA_BAYER_GRBG: return GoAlgorithm_BayerDemosaicGradientGrbg(input, output);
default: return kERROR_PARAMETER;
}
}
#endif //COPY_BAYER_ALGORITHM_FROM_KVISION
GoFx(kStatus) GoAlgorithm_Demosaic(kImage input, kImage* output, GoDemosaicStyle style, kAlloc allocator)
{
kImage newImage;
kStatus exception;
kSize height, width;
if ((kImage_PixelSize(input) != sizeof(k8u)) ||
(kImage_Width(input) % 2) ||
(kImage_Height(input) % 2) ||
(kImage_Width(input) < 4) ||
(kImage_Height(input) < 4))
{
return kERROR_PARAMETER;
}
if (GO_DEMOSAIC_STYLE_REDUCE == style)
{
height = kImage_Height(input) / 2;
width = kImage_Width(input) / 2;
}
else
{
height = kImage_Height(input);
width = kImage_Width(input);
}
kCheck(kImage_Construct(&newImage, kTypeOf(kRgb), width, height, allocator));
kTry
{
switch (style)
{
case GO_DEMOSAIC_STYLE_REDUCE: kTest(GoAlgorithm_BayerDemosaicReduce(input, newImage)); break;
case GO_DEMOSAIC_STYLE_BILINEAR: kTest(GoAlgorithm_BayerDemosaicBilinear(input, newImage)); break;
case GO_DEMOSAIC_STYLE_GRADIENT: kTest(GoAlgorithm_BayerDemosaicGradient(input, newImage)); break;
default: kThrow(kERROR_PARAMETER);
}
kDestroyRef(output); //Free the image stored at the output pointer if there is already one there
//This allows them to call GoAlgorithm_Demosaic(myImage, &myImage, ...)
//Without memory leaks.
}
kCatch(&exception)
{
kDestroyRef(&newImage);
*output = kNULL;
kEndCatch(exception);
}
*output = newImage;
return kOK;
}