Skip to content
Browse files

Added slightly faster bayer pattern to rgb conversion

Signed-off-by: Jochen Kerdels <jochen@kerdels.de>
  • Loading branch information...
1 parent 5dcf307 commit bac69ea85c73f9f25b5a024dec589a7b6f750b6a @jkerdels jkerdels committed
Showing with 146 additions and 48 deletions.
  1. +146 −48 src/cameras.c
View
194 src/cameras.c
@@ -256,7 +256,7 @@ static void depth_process(freenect_device *dev, uint8_t *pkt, int len)
static void rgb_process(freenect_device *dev, uint8_t *pkt, int len)
{
freenect_context *ctx = dev->parent;
- int x,y,i;
+ int x,y;
if (len == 0)
return;
@@ -282,61 +282,159 @@ static void rgb_process(freenect_device *dev, uint8_t *pkt, int len)
* B G B G B G B G
* G R G R G R G R
* B G B G B G B G
+ *
+ * To convert a Bayer-pattern into RGB you have to handle four pattern
+ * configurations:
+ * 1) 2) 3) 4)
+ * B1 B1 G1 B2 R1 G1 R2 R1 <- previous line
+ * R1 G1 R2 G2 R1 G3 G2 B1 G3 B1 G1 B2 <- current line
+ * B2 B3 G4 B4 R3 G4 R4 R2 <- next line
+ * ^ ^ ^
+ * | | next pixel
+ * | current pixel
+ * previous pixel
+ *
+ * The RGB values (r,g,b) for each configuration are calculated as
+ * follows:
+ *
+ * 1) r = (R1 + R2) / 2
+ * g = G1
+ * b = (B1 + B2) / 2
+ *
+ * 2) r = R1
+ * g = (G1 + G2 + G3 + G4) / 4
+ * b = (B1 + B2 + B3 + B4) / 4
+ *
+ * 3) r = (R1 + R2 + R3 + R4) / 4
+ * g = (G1 + G2 + G3 + G4) / 4
+ * b = B1
+ *
+ * 4) r = (R1 + R2) / 2
+ * g = G1
+ * b = (B1 + B2) / 2
+ *
+ * To efficiently calculate these values, two 32bit integers are used
+ * as "shift-buffers". One integer to store the 3 horizontal bayer pixel
+ * values (previous, current, next) of the current line. The other
+ * integer to store the vertical average value of the bayer pixels
+ * (previous, current, next) of the previous and next line.
+ *
+ * The boundary conditions for the first and last line and the first
+ * and last column are solved via mirroring the second and second last
+ * line and the second and second last column.
+ *
+ * To reduce slow memory access, the values of a rgb pixel are packet
+ * into a 32bit variable and transfered together.
*/
- for (y=0; y<480; y++) {
- for (x=0; x<640; x++) {
- i = (y*640+x);
- if ((y&1) == 0) {
- if ((x&1) == 0) {
- // topleft G pixel
- uint8_t rr = raw_buf[i+1];
- uint8_t rl = x == 0 ? rr : raw_buf[i-1];
- uint8_t bb = raw_buf[i+640];
- uint8_t bt = y == 0 ? bb : raw_buf[i-640];
- proc_buf[3*i+0] = (rl+rr)>>1;
- proc_buf[3*i+1] = raw_buf[i];
- proc_buf[3*i+2] = (bt+bb)>>1;
+
+ uint8_t *dst = proc_buf; // pointer to destination
+
+ uint8_t *prevLine; // pointer to previous, current and next line
+ uint8_t *curLine; // of the source bayer pattern
+ uint8_t *nextLine;
+
+ // storing horizontal values in hVals:
+ // previous << 16, current << 8, next
+ uint32_t hVals;
+ // storing vertical averages in vSums:
+ // previous << 16, current << 8, next
+ uint32_t vSums;
+
+ // init curLine and nextLine pointers
+ curLine = raw_buf;
+ nextLine = curLine + 640;
+ for (y = 0; y < 480; ++y) {
+
+ if ((y > 0) && (y < 479))
+ prevLine = curLine - 640; // normal case
+ else if (y == 0)
+ prevLine = nextLine; // top boundary case
+ else
+ nextLine = prevLine; // bottom boundary case
+
+ // init horizontal shift-buffer with current value
+ hVals = (*(curLine++) << 8);
+ // handle left column boundary case
+ hVals |= (*curLine << 16);
+ // init vertical average shift-buffer with current values average
+ vSums = ((*(prevLine++) + *(nextLine++)) << 7) & 0xFF00;
+ // handle left column boundary case
+ vSums |= ((*prevLine + *nextLine) << 15) & 0xFF0000;
+
+ // store if line is odd or not
+ uint8_t yOdd = y & 1;
+ // the right column boundary case is not handled inside this loop
+ // thus the "639"
+ for (x = 0; x < 639; ++x) {
+ // place next value in shift buffers
+ hVals |= *(curLine++);
+ vSums |= (*(prevLine++) + *(nextLine++)) >> 1;
+
+ // calculate the horizontal sum as this sum is needed in
+ // any configuration
+ uint8_t hSum = ((uint8_t)(hVals >> 16) + (uint8_t)(hVals)) >> 1;
+
+ if (yOdd == 0) {
+ if ((x & 1) == 0) {
+ // Configuration 1
+ *(dst++) = hSum; // r
+ *(dst++) = hVals >> 8; // g
+ *(dst++) = vSums >> 8; // b
} else {
- // R pixel
- uint8_t gl = raw_buf[i-1];
- uint8_t gr = x == 639 ? gl : raw_buf[i+1];
- uint8_t gb = raw_buf[i+640];
- uint8_t gt = y == 0 ? gb : raw_buf[i-640];
- uint8_t bbl = raw_buf[i+639];
- uint8_t btl = y == 0 ? bbl : raw_buf[i-641];
- uint8_t bbr = x == 639 ? bbl : raw_buf[i+641];
- uint8_t btr = x == 639 ? btl : y == 0 ? bbr : raw_buf[i-639];
- proc_buf[3*i+0] = raw_buf[i];
- proc_buf[3*i+1] = (gl+gr+gb+gt)>>2;
- proc_buf[3*i+2] = (bbl+btl+bbr+btr)>>2;
+ // Configuration 2
+ *(dst++) = hVals >> 8;
+ *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1;
+ *(dst++) = ((uint8_t)(vSums >> 16) + (uint8_t)(vSums)) >> 1;
}
} else {
- if ((x&1) == 0) {
- // B pixel
- uint8_t gr = raw_buf[i+1];
- uint8_t gl = x == 0 ? gr : raw_buf[i-1];
- uint8_t gt = raw_buf[i-640];
- uint8_t gb = y == 479 ? gt : raw_buf[i+640];
- uint8_t rtr = raw_buf[i-639];
- uint8_t rbr = y == 479 ? rtr : raw_buf[i+641];
- uint8_t rtl = x == 0 ? rtr : raw_buf[i-641];
- uint8_t rbl = x == 0 ? rbr : y == 479 ? rtl : raw_buf[i+639];
- proc_buf[3*i+0] = (rbl+rtl+rbr+rtr)>>2;
- proc_buf[3*i+1] = (gl+gr+gb+gt)>>2;
- proc_buf[3*i+2] = raw_buf[i];
+ if ((x & 1) == 0) {
+ // Configuration 3
+ *(dst++) = ((uint8_t)(vSums >> 16) + (uint8_t)(vSums)) >> 1;
+ *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1;
+ *(dst++) = hVals >> 8;
} else {
- // botright G pixel
- uint8_t bl = raw_buf[i-1];
- uint8_t br = x == 639 ? bl : raw_buf[i+1];
- uint8_t rt = raw_buf[i-640];
- uint8_t rb = y == 479 ? rt : raw_buf[i+640];
- proc_buf[3*i+0] = (rt+rb)>>1;
- proc_buf[3*i+1] = raw_buf[i];
- proc_buf[3*i+2] = (bl+br)>>1;
+ // Configuration 4
+ *(dst++) = vSums >> 8;
+ *(dst++) = hVals >> 8;
+ *(dst++) = hSum;
}
}
+
+ // shift the shift-buffers
+ hVals <<= 8;
+ vSums <<= 8;
+ } // end of for x loop
+ // right column boundary case, mirroring second last column
+ hVals |= (uint8_t)(hVals >> 16);
+ vSums |= (uint8_t)(vSums >> 16);
+
+ // the horizontal sum simplifies to the second last column value
+ uint8_t hSum = (uint8_t)(hVals);
+
+ if (yOdd == 0) {
+ if ((x & 1) == 0) {
+ *(dst++) = hSum;
+ *(dst++) = hVals >> 8;
+ *(dst++) = vSums >> 8;
+ } else {
+ *(dst++) = hVals >> 8;
+ *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1;
+ *(dst++) = vSums;
+ }
+ } else {
+ if ((x & 1) == 0) {
+ *(dst++) = vSums;
+ *(dst++) = (hSum + (uint8_t)(vSums >> 8)) >> 1;
+ *(dst++) = hVals >> 8;
+ } else {
+ *(dst++) = vSums >> 8;
+ *(dst++) = hVals >> 8;
+ *(dst++) = hSum;
+ }
}
- }
+
+ } // end of for y loop
+
}
if (dev->rgb_cb)

0 comments on commit bac69ea

Please sign in to comment.
Something went wrong with that request. Please try again.