Skip to content

Commit

Permalink
Added slightly faster bayer pattern to rgb conversion
Browse files Browse the repository at this point in the history
Signed-off-by: Jochen Kerdels <jochen@kerdels.de>
  • Loading branch information
jkerdels committed Nov 28, 2010
1 parent 5dcf307 commit bac69ea
Showing 1 changed file with 146 additions and 48 deletions.
194 changes: 146 additions & 48 deletions src/cameras.c
Expand Up @@ -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;
Expand All @@ -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)
Expand Down

0 comments on commit bac69ea

Please sign in to comment.