/** * @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 #include #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 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; }