aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/source/GImage_bayer.cpp
diff options
context:
space:
mode:
authorclick <none@none>2010-08-27 01:52:05 +0200
committerclick <none@none>2010-08-27 01:52:05 +0200
commit7686d6ee57038e848f75130563fc78c1adebc1a2 (patch)
tree258a7a6db03e3479a0219ace8cfc3ec3ba53a1be /dep/g3dlite/source/GImage_bayer.cpp
parent1d3deae555f0ec523d77875bd5a307ab9bd19742 (diff)
Core/Dependency: Upgrade G3d-library to v8.0-release (patched version!)
Note: Due to issues with G3D (normally requiring X11 and the ZIP-library), the sourcetree version contains a modified version. The applied patch is commited to the repository for future reference. --HG-- branch : trunk
Diffstat (limited to 'dep/g3dlite/source/GImage_bayer.cpp')
-rw-r--r--dep/g3dlite/source/GImage_bayer.cpp298
1 files changed, 298 insertions, 0 deletions
diff --git a/dep/g3dlite/source/GImage_bayer.cpp b/dep/g3dlite/source/GImage_bayer.cpp
new file mode 100644
index 00000000000..3d08e8ade5f
--- /dev/null
+++ b/dep/g3dlite/source/GImage_bayer.cpp
@@ -0,0 +1,298 @@
+/**
+ @file GImage_bayer.cpp
+ @author Morgan McGuire, http://graphics.cs.williams.edu
+ @created 2002-05-27
+ @edited 2006-05-10
+ */
+#include "G3D/platform.h"
+#include "G3D/GImage.h"
+
+namespace G3D {
+
+void GImage::BAYER_G8B8_R8G8_to_Quarter_R8G8B8(int width, int height, const uint8* in, uint8* out) {
+ debugAssert(in != out);
+
+ int halfHeight = height / 2;
+ int halfWidth = width / 2;
+
+ int dst_off = 0;
+ for (int y = 0; y < halfHeight; ++y) {
+ for (int x = 0; x < halfWidth; ++x) {
+ // GBRG
+ int src_off = x*2 + y*2*width;
+ out[dst_off] = in[src_off+width]; // red
+ out[dst_off+1] = ((int)in[src_off] + (int)in[src_off+width+1])/2; // green
+ out[dst_off+2] = in[src_off+1]; // blue
+
+ dst_off = dst_off + 3;
+ }
+ }
+}
+
+
+void GImage::Quarter_R8G8B8_to_BAYER_G8B8_R8G8(int inWidth, int inHeight, const uint8* in, uint8* out) {
+ // Undo quarter-size Bayer as best we can. This code isn't very efficient, but it
+ // also isn't used very frequently.
+
+ debugAssert(out != in);
+
+ int outWidth = 2 * inWidth;
+ int outHeight = 2 * inHeight;
+
+ for (int y = 0; y < outHeight; ++y) {
+ for (int x = 0; x < outWidth; ++x) {
+ const Color3uint8* inp = ((const Color3uint8*)in) + ((x/2) + (y/2)* inWidth);
+ uint8* outp = out + x + y * outWidth;
+
+ if (isEven(y)) {
+ // GB row
+ if (isEven(x)) {
+ // Green
+ *outp = inp->g;
+ } else {
+ // Blue
+ *outp = inp->b;
+ }
+ } else {
+ // RG row
+ if (isEven(x)) {
+ // Red
+ *outp = inp->r;
+ } else {
+ // Green
+ *outp = inp->g;
+ }
+ }
+ }
+ }
+}
+
+
+/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */
+static uint8 applyFilter(
+ const uint8* I,
+ int x,
+ int y,
+ int w,
+ int h,
+ const float filter[5][5]) {
+
+ debugAssert(isEven(w));
+ debugAssert(isEven(h));
+
+ float sum = 0.0f;
+ float denom = 0.0f;
+
+ for (int dy = 0; dy < 5; ++dy) {
+ int offset = ((y + dy + h - 2) % h) * w;
+
+ for (int dx = 0; dx < 5; ++dx) {
+ float f = filter[dy][dx];
+ sum += f * I[((x + dx + w - 2) % w) + offset];
+ denom += f;
+ }
+ }
+
+ return (uint8)iClamp(iRound(sum / denom), 0, 255);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// Bayer conversions
+//
+
+// There are two kinds of rows (GR and BG).
+// In each row, there are two kinds of pixels (G/R, B/G).
+// We express the four kinds of INPUT pixels as:
+// GRG, GRG, BGB, BGG
+//
+// There are three kinds of OUTPUT pixels: R, G, B.
+// Thus there are nominally 12 different I/O combinations,
+// but several are impulses because needed output at that
+// location *is* the input (e.g., G_GRG and G_BGG).
+//
+// The following 5x5 row-major filters are named as output_input.
+
+// Green
+static const float G_GRR[5][5] =
+{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
+{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
+{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f},
+{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
+{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
+
+static const float G_BGB[5][5] =
+{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
+{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
+{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f},
+{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
+{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
+
+// Red
+//(the caption in the paper is wrong for this case:
+// "R row B column really means R row G column"
+static const float R_GRG[5][5] =
+{{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f},
+{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f},
+{ -1.0f, 4.0f, 5.0f, 4.0f, -1.0f},
+{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f},
+{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}};
+
+static const float R_BGG[5][5] =
+{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
+{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f},
+{ 0.5f, 0.0f, 5.0f, 0.0f, 0.5f},
+{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f},
+{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
+
+static const float R_BGB[5][5] =
+{{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f},
+{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f},
+{-3.0f/2.0f, 0.0f, 6.0f, 0.0f, -3.0f/2.0f},
+{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f},
+{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}};
+
+
+// Blue
+//(the caption in the paper is wrong for this case:
+// "B row R column really means B row G column")
+#define B_BGG R_GRG
+#define B_GRG R_BGG
+#define B_GRR R_BGB
+
+
+void GImage::BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
+ debugAssert(in != _out);
+
+ Color3uint8* out = (Color3uint8*)_out;
+
+ for (int y = 0; y < h; ++y) {
+
+ // Row beginning in the input array.
+ int offset = y * w;
+
+ // RG row
+ for (int x = 0; x < w; ++x, ++out) {
+ // R pixel
+ {
+ out->r = in[x + offset];
+ out->g = applyFilter(in, x, y, w, h, G_GRR);
+ out->b = applyFilter(in, x, y, w, h, B_GRR);
+ }
+ ++x; ++out;
+
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_GRG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_GRG);
+ }
+ }
+
+ ++y;
+ offset += w;
+
+ // GB row
+ for (int x = 0; x < w; ++x, ++out) {
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_BGG);
+ }
+ ++x; ++out;
+
+ // B pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGB);
+ out->g = applyFilter(in, x, y, w, h, G_BGB);
+ out->b = in[x + offset];
+ }
+ }
+ }
+}
+
+static void swapRedAndBlue(int N, Color3uint8* out) {
+ for (int i = N - 1; i >= 0; --i) {
+ uint8 tmp = out[i].r;
+ out[i].r = out[i].b;
+ out[i].b = tmp;
+ }
+}
+
+void GImage::BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
+ // Run the equivalent function for red
+ BAYER_G8B8_R8G8_to_R8G8B8_MHC(w, h, in, _out);
+
+ // Now swap red and blue
+ swapRedAndBlue(w * h, (Color3uint8*)_out);
+}
+
+
+void GImage::BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
+ // Run the equivalent function for red
+ BAYER_R8G8_G8B8_to_R8G8B8_MHC(w, h, in, _out);
+
+ // Now swap red and blue
+ swapRedAndBlue(w * h, (Color3uint8*)_out);
+}
+
+
+void GImage::BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
+
+ debugAssert(in != _out);
+
+ Color3uint8* out = (Color3uint8*)_out;
+
+ for (int y = 0; y < h; ++y) {
+
+ // Row beginning in the input array.
+ int offset = y * w;
+
+ // GB row
+ for (int x = 0; x < w; ++x, ++out) {
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_BGG);
+ }
+ ++x; ++out;
+
+ // B pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGB);
+ out->g = applyFilter(in, x, y, w, h, G_BGB);
+ out->b = in[x + offset];
+ }
+ }
+
+ ++y;
+ offset += w;
+
+ // RG row
+ for (int x = 0; x < w; ++x, ++out) {
+ // R pixel
+ {
+ out->r = in[x + offset];
+ out->g = applyFilter(in, x, y, w, h, G_GRR);
+ out->b = applyFilter(in, x, y, w, h, B_GRR);
+ }
+ ++x; ++out;
+
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_GRG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_GRG);
+ }
+ }
+ }
+
+}
+
+#undef B_BGG
+#undef B_GRG
+#undef B_GRR
+
+}