[vlc-devel] Request for SBGGR8->x colorspace conversions

Luca Risolia luca.risolia at studio.unibo.it
Mon Nov 15 05:08:34 CET 2004


Hello,
 could you integrate the SBGGR8 pixel format in VLC, which is defined by
the V4L2 API (in videodev2.h)? This way I could write and test a simple v4l2 
input module for webcams (and video capture devices in general) in 1 day.

The functions below that I wrote for xawtv might help. I think they are 
already clear enough to be mostly copied and placed in the right place 
without any problems. The code is released under GPL.

Thanks.

#define RED 0
#define GREEN 1
#define BLUE 2

#define avg2(x,y) ((((int)(x)) + ((int)(y))) / 2)
#define avg3(x,y,z) ((((int)(x)) + ((int)(y)) + ((int)(z))) / 3)
#define avg4(w,x,y,z) ((((int)(w)) + ((int)(x)) + ((int)(y)) + ((int)(z))) / 
4)

/* ------------------------------------------------------------------- */
/* bayer bgbg...grgr...to rgb24                                        */

/*
 bgbgbg
 grgrgr
 bgbgbg
 grgrgr
*/

static void
sbggr8_to_rgb24(void *h, struct ng_video_buf *out, struct ng_video_buf *in)
{
    unsigned char *restrict s, *restrict d;
    unsigned long x, y, i, j;

    d = out->data;
    s = in->data;
    x  = in->fmt.width;
    y  = in->fmt.height;

    /* upper left corner */
    d[0 + RED] = s[x + 1];
    d[0 + BLUE] = s[0];
    d[0 + GREEN] = ((int)s[1] + (int)s[x]) / 2;

    /* top line (minus corners) */
    i = 1;
    while (i < x - 2) {
 d[i * 3 + RED] = s[x + i];
 d[i * 3 + GREEN] = s[i];
 d[i * 3 + BLUE] = avg2(s[i - 1], s[i + 1]);

 i++;

 d[i * 3 + RED] = avg2(s[x + i - 1], s[x + i + 1]);
 d[i * 3 + GREEN] = avg3(s[i - 1], s[i + 1], s[x + 1]);
 d[i * 3 + BLUE] = s[i];

 i++;
    }

    /* upper right corner */
    d[i * 3 + RED] = s[x + i];
    d[i * 3 + GREEN] = s[i];
    d[i * 3 + BLUE] = s[i - 1];

    /* middle lines */
    j = 1;
    while (j < y - 2) {
 d[j * x * 3 + RED] = s[j * x + 1];
 d[j * x * 3 + GREEN] = s[j * x];
 d[j * x * 3 + BLUE] = avg2(s[(j - 1) * x], s[(j + 1) * x]);

 i = 1;
 while (i < x - 2) {
     d[(j * x + i) * 3 + RED] = s[j * x + i];
     d[(j * x + i) * 3 + GREEN] = avg4(s[(j - 1) * x + i],
           s[j * x + i - 1],
           s[j * x + i + 1],
           s[(j + 1) * x + i]);
     d[(j * x + i) * 3 + BLUE] = avg4(s[(j - 1) * x + i - 1],
          s[(j - 1) * x + i + 1],
          s[(j + 1) * x + i - 1],
          s[(j + 1) * x + i + 1]);

     i++;

     d[(j * x + i) * 3 + RED] = avg2(s[j * x + i - 1],
         s[j * x + i + 1]);
     d[(j * x + i) * 3 + GREEN] = s[j * x + i];
     d[(j * x + i) * 3 + BLUE] = avg2(s[(j - 1) * x + i],
          s[(j + 1) * x + i]);

     i++;
 }

 d[(j * x + i) * 3 + RED] = s[j * x + i];
 d[(j * x + i) * 3 + BLUE] = avg2(s[(j - 1) * x + i - 1],
      s[(j + 1) * x + i - 1]);
 d[(j * x + i) * 3 + GREEN] = avg2(s[(j - 1) * x + i],
       s[(j + 1) * x + i]);

 j++;

 d[(j * x + i) * 3 + RED] = avg2(s[(j - 1) * x + i + 1],
     s[(j + 1) * x + i + 1]);
 d[(j * x + i) * 3 + BLUE] = s[j * x + i];
 d[(j * x + i) * 3 + GREEN] = avg3(s[(j - 1) * x + i],
       s[j * x + i + 1],
       s[(j + 1) * x + i]);

 i = 1;
 while (i < x - 2) {
     d[(j * x + i) * 3 + RED] = avg2(s[(j - 1) * x + i],
         s[(j + 1) * x + i]);
     d[(j * x + i) * 3 + GREEN] = s[j * x + i];
     d[(j * x + i) * 3 + BLUE] = avg2(s[j * x + i - 1],
          s[j * x + i + 1]);

     i++;

     d[(j * x + i) * 3 + RED] = avg4(s[(j - 1) * x + i - 1],
         s[(j - 1) * x + i + 1],
         s[(j + 1) * x + i - 1],
         s[(j + 1) * x + i + 1]);
     d[(j * x + i) * 3 + GREEN] = avg4(s[(j - 1) * x + i],
           s[j * x + i - 1],
           s[j * x + i + 1],
           s[(j + 1) * x + i]);
     d[(j * x + i) * 3 + BLUE] = s[j * x + i];

     i++;
 }

 j++;
    }

    /* lower left corner */
    d[(j * x) * 3 + RED] = s[j * x + 1];
    d[(j * x) * 3 + GREEN] = s[j * x];
    d[(j * x) * 3 + BLUE] = s[(j - 1) * x];

    /* bottom line */
    i = 1;
    while (i < x - 2) {
 d[(j * x + i) * 3 + RED] = s[j * x + i];
 d[(j * x + i) * 3 + GREEN] = avg2(s[j * x + i - 1],  s[j * x + i + 1]);
 d[(j * x + i) * 3 + BLUE] = avg2(s[(j - 1) * x + i - 1],
      s[(j - 1) * x + i + 1]);

 i++;

 d[(j * x + i) * 3 + RED] = avg2(s[j * x + i - 1], s[j * x + i + 1]);
 d[(j * x + i) * 3 + GREEN] = s[j * x + i];
 d[(j * x + i) * 3 + BLUE] = s[(j - 1) * x + i];

 i++;
    }

    /* lower right corner */
    d[(j * x + i) * 3 + RED] = s[j * x + i];
    d[(j * x + i) * 3 + GREEN] = avg2(s[(j - 1) * x + i], s[j * x + i - 1]);
    d[(j * x + i) * 3 + BLUE] = s[(j - 1) * x + i - 1];
}

/* ------------------------------------------------------------------- */
/* bayer bgbg...grgr...to rgb16                                        */

static void
sbggr8_to_rgb16(void *p, struct ng_video_buf *out, struct ng_video_buf *in)
{
 unsigned char *restrict s;
 uint16_t *d1, *d2;
 unsigned long i, j, x, y, w, h;
 unsigned char r, g1, g2, b, g;

 s = in->data;
 w  = in->fmt.width;
 h  = in->fmt.height;
 d1 = (uint16_t *)out->data;
 d2 = d1 + w;
 i = 0;
 j = w;

 for (y = 0; y < h; y += 2, i += w * 2, j += w * 2, d1 += w, d2 += w) {
  for (x = 0; x < w; x += 2) {

   b = s[i + x] ;
   g1 = s[i + 1 + x];
   g2 = s[j + x];
   r = s[j + 1 + x];

   g = (g1 >> 1) + (g2 >> 1);

   *d1++ = (((b) & 0xF8) >> 3 |
         (((g1) & 0xFC) << 3) |
         (((r) & 0xF8) << 8)) ;

   *d1++ = (((b) & 0xF8) >> 3 |
         (((g) & 0xFC) << 3) |
         (((r) & 0xF8) << 8)) ;

   *d2++ = (((b) & 0xF8) >> 3 |
         (((g) & 0xFC) << 3) |
         (((r) & 0xF8) << 8)) ;

   *d2++ = (((b) & 0xF8) >> 3 |
         (((g2) & 0xFC) << 3) |
         (((r) & 0xF8) << 8)) ;

  }
 }
}

static void
sbggr8_to_rgb32(void *p, struct ng_video_buf *out, struct ng_video_buf *in)
{
 unsigned char *restrict s;
 unsigned char *d1, *d2;
 unsigned long i, j, x, y, w, h;
 unsigned char r, g1, g2, b, g;

 s = in->data;
 w  = in->fmt.width;
 h  = in->fmt.height;
 d1 = out->data;
 d2 = d1 + 4*w;
 i = 0;
 j = w;

 for (y = 0; y < h; y += 2, i += w * 2, j += w * 2, d1 += 4*w, d2 += 4*w) {
  for (x = 0; x < w; x += 2) {

   b = s[i + x] ;
   g1 = s[i + 1 + x];
   g2 = s[j + x];
   r = s[j + 1 + x];
   g = (g1 >> 1) + (g2 >> 1);

   d1[0] = (r);
   d1[1] = (g1);
   d1[2] = (b);
   d1 += 4;

   d1[0] = (r);
   d1[1] = (g);
   d1[2] = (b);
   d1 += 4;

   d2[0] = (r);
   d2[1] = (g);
   d2[2] = (b);
   d2 += 4;

   d2[0] = (r);
   d2[1] = (g2);
   d2[2] = (b);
   d2 += 4;

  }
 }
}

static void
sbggr8_to_yuv420p(void *p, struct ng_video_buf *out, struct ng_video_buf *in)
{
 unsigned char *restrict s;
 unsigned char *d1, *d2, *U, *V;
 unsigned long i, j, x, y, w, h;
 unsigned char tr, tb, r, g1, g2, b, g, y1, y2, y3, y4;
 int u, v;

 #define CLIP(color) ((color > 0xff) ? 0xff : ((color < 0) ? 0 : color))

 s = in->data;
 w  = in->fmt.width;
 h  = in->fmt.height;
 d1 = out->data;
 d2 = d1 + w;
 i = 0;
 j = w;
 U = d1 + w*h;
 V = U + ((w*h) >> 2);

 for (y = 0; y < h; y += 2, i += w * 2, j += w * 2, d1 += w, d2 += w) {
  for (x = 0; x < w; x += 2) {

   tb = s[i + x] ;
   g1 = s[i + 1 + x];
   g2 = s[j + x];
   tr = s[j + 1 + x];

   g = (g1 >> 1) + (g2 >> 1);
   r = ((tr << 8) - (tr << 4) - (tr << 3)) >> 10;
   b = ((tb << 7) >> 10);
   g1 = ((g1 << 9) + (g1 << 7) + (g1 << 5)) >> 10;
   g2 = ((g2 << 9) + (g2 << 7) + (g2 << 5)) >> 10;
   g = ((g << 9) + (g << 7) + (g << 5)) >> 10;

   y1 = CLIP((r + g1 + b));
   y2 = CLIP((r + g + b));
   y3 =  CLIP((r + g + b));
   y4 =  CLIP((r + g2 + b));

   *d1++ = y1;
   *d1++ = y2;
   *d2++ = y3;
   *d2++ = y4;

   v = tr - ((y1 + y2 + y3 + y4) >> 2);
   u = ((v << 9) + (v << 7) + (v << 5)) >> 10;
   v = (tb - ((y1 + y2 + y3 + y4) >> 2)) >> 1;

   *U++ = 128 + v;
   *V++ = 128 + u;

  }
 }
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20041115/469384f0/attachment.html>


More information about the vlc-devel mailing list