mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
commit
86e01445fd
@ -420,6 +420,9 @@ void imlib_bayer_to_rgb565(image_t *img, int w, int h, int xoffs, int yoffs, uin
|
||||
{
|
||||
int r, g, b;
|
||||
for (int y=yoffs; y<yoffs+h; y++) {
|
||||
// The faster routine needs to start on an even column
|
||||
// and not next to the top or bottom edge to avoid boundary checks on each pixel
|
||||
if (xoffs & 1 || y == 0 || y >= yoffs+h-1) {
|
||||
for (int x=xoffs; x<xoffs+w; x++) {
|
||||
if ((y % 2) == 0) { // Even row
|
||||
if ((x % 2) == 0) { // Even col
|
||||
@ -471,8 +474,97 @@ void imlib_bayer_to_rgb565(image_t *img, int w, int h, int xoffs, int yoffs, uin
|
||||
g = IM_G826(g);
|
||||
b = IM_B825(b);
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
}
|
||||
}
|
||||
} // for x
|
||||
} else { // faster way
|
||||
//
|
||||
// Theory of operation:
|
||||
// The Bayer pattern from the sensor looks like this:
|
||||
// +---+---+---+---+---+---+
|
||||
// | B | G | B | G | B | G |
|
||||
// +---+---+---+---+---+---+
|
||||
// | G |*R*|*G*| R | G | R | * = Example of current pair of pixels being processed
|
||||
// +---+---+---+---+---+---+ Each iteration below will advance 2 pixels to the right
|
||||
// | B | G | B | G | B | G |
|
||||
// +---+---+---+---+---+---+
|
||||
// | G | R | G | R | G | R |
|
||||
// +---+---+---+---+---+---+
|
||||
// Each of the color stimuli above is stored as 1 byte
|
||||
// The slower algorithm above reads each byte around the current pixel individually to
|
||||
// average the colors together to simulate the colors not present at the current pixel
|
||||
// e.g. At location 0,0, only the blue value is present; red and green must be estimated from
|
||||
// neighboring pixels
|
||||
//
|
||||
// The optimized algorithm below minimizes memory accesses by reading 2 bytes at a time
|
||||
// and re-using the last pair as it progresses from left to right. Since the ARM CPU enforces a
|
||||
// memory policy of generating an exception on unaligned reads, we read 16-bits at a time and
|
||||
// OR them into a 32-bit variable to hold on to the pixels left and right of the current pair.
|
||||
// This way we can work on 2 pixels at a time from 3 32-bit variables containing 3 lines of 4 pixels.
|
||||
// The variables l0,l1,l2 hold the 4 pixels (left, current left, current_right, right)
|
||||
// in lines above the current (l0), current (l1) and below (l2)
|
||||
// This algorithm assumes that the starting x is 0 (it doesn't have to be).
|
||||
// The starting and ending pixel are treated like absolute sensor edges, so they are less accurate
|
||||
// than the middle pixels.
|
||||
//
|
||||
uint32_t l0,l1,l2; // 3 lines we're working with
|
||||
uint16_t *s = (uint16_t *)&img->pixels[(y * img->w) + xoffs];
|
||||
uint32_t r, g, b, w2 = img->w/2;
|
||||
l0 = s[-w2]; l1 = s[0]; l2 = s[w2];
|
||||
s++;
|
||||
// For each pixel, the R8 G8 B8 values are directly shifted into R5 G6 B5
|
||||
// to save a step when creating the RGB565 output
|
||||
if (y & 1) { // odd lines (G R G R G R)
|
||||
b = ((l0 & 0xff) + (l2 & 0xff)) >> 4; // left edge pixel
|
||||
g = (l1 & 0xff) >> 2;
|
||||
r = (l1 & 0xff00) >> 11;
|
||||
*rgbbuf++ = IM_RGB565(r, g, b); // first col is treated differently
|
||||
for (int x = xoffs+1; x < xoffs+w-1; x+=2) { // 'middle' pixels can use neighbors from 3x3 grid
|
||||
l0 |= (s[-w2] << 16); // shift last pixel pairs into upper 16 bits
|
||||
l1 |= (s[0] << 16); // of the 3 line variables
|
||||
l2 |= (s[w2] << 16);
|
||||
s++; // advance source pointer one pair of pixels
|
||||
r = (l1 & 0xff00) >> 11; // (1, 0) red pixel at current-left
|
||||
g = (((l1 >> 16) & 0xff) + (l1 & 0xff) + ((l0 >> 8) & 0xff) + ((l2 >> 8) & 0xff)) >> 4;
|
||||
b = ((l0 & 0xff) + (l2 & 0xff) + ((l0 >> 16) & 0xff) + ((l2 >> 16) & 0xff)) >> 5;
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
g = (l1 & 0xff0000) >> 18; // (0,0) green pixel at current-right
|
||||
b = (((l0 >> 16) & 0xff) + ((l2 >> 16) & 0xff)) >> 4;
|
||||
r = (((l1 >> 8) & 0xff) + (l1 >> 24)) >> 4;
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
// prepare for the next set of source pixels
|
||||
l0 >>= 16; l1 >>= 16; l2 >>= 16; // L-CL-CR-R becomes L-CL-0-0
|
||||
} // for x
|
||||
// last col
|
||||
g = ((l0 >> 8) + (l2 >> 8)) >> 3; // re-use blue from last pixel in loop
|
||||
r = (l1 >> 11);
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
} else { // even lines (B G B G B G)
|
||||
b = (l1 & 0xff) >> 3;
|
||||
g = ((l0 & 0xff) + (l2 & 0xff)) >> 3;
|
||||
r = ((l0 & 0xff00) + (l2 & 0xff00)) >> 12; // first pixel is different
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
for (int x = xoffs+1; x < xoffs+w-1; x+=2) { // middle part
|
||||
l0 |= (s[-w2] << 16); // grab 3 more pairs of pixels and put in upper 16-bits
|
||||
l1 |= (s[0] << 16);
|
||||
l2 |= (s[w2] << 16);
|
||||
s++;
|
||||
g = (l1 & 0xff00) >> 10; // (1, 0) green pixel at current-left
|
||||
b = ((l1 & 0xff) + ((l1 >> 16) & 0xff)) >> 4;
|
||||
r = ((l0 & 0xff00) + (l2 & 0xff00)) >> 12;
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
b = (l1 & 0xff0000) >> 19; // (0,0) blue pixel at current-right
|
||||
g = (((l1 >> 8) & 0xff) + (l1 >> 24) + ((l0 >> 16) & 0xff) + ((l2 >> 16) & 0xff)) >> 4;
|
||||
r = (((l0 >> 8) & 0xff) + (l0 >> 24) + ((l2 >> 8) & 0xff) + (l2 >> 24)) >> 5;
|
||||
*rgbbuf++ = IM_RGB565(r, g, b);
|
||||
// prepare for the next set of source pixels
|
||||
l0 >>= 16; l1 >>= 16; l2 >>= 16; // L-CL-CR-R becomes L-CL-0-0
|
||||
} // for x
|
||||
// last col
|
||||
g = (l1 >> 10); // re-use blue pixel from last column of loop
|
||||
r = ((l0 >> 8) + (l2 >> 8)) >> 4;
|
||||
*rgbbuf++ = IM_RGB565(r, g, b); // last pixel
|
||||
} // even lines
|
||||
} // faster way
|
||||
} // for y
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user