diff options
| author | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2013-07-04 14:40:15 +0200 | 
|---|---|---|
| committer | Matthias Vogelgesang <matthias.vogelgesang@kit.edu> | 2013-07-04 14:40:15 +0200 | 
| commit | 67d068f7c843e980141cbabad9560154024a1366 (patch) | |
| tree | 4d0ce79afee4f27f6488a3ed97a94c3922dd2390 | |
| parent | 847e0fc52cc7fc5f58373d714d67f05755004d56 (diff) | |
| download | libufodecode-67d068f7c843e980141cbabad9560154024a1366.tar.gz libufodecode-67d068f7c843e980141cbabad9560154024a1366.tar.bz2 libufodecode-67d068f7c843e980141cbabad9560154024a1366.tar.xz libufodecode-67d068f7c843e980141cbabad9560154024a1366.zip  | |
Implement simple de-mosaicking of Bayer pattern
| -rw-r--r-- | src/ufodecode.c | 81 | ||||
| -rw-r--r-- | src/ufodecode.h | 4 | ||||
| -rw-r--r-- | test/ipedec.c | 42 | 
3 files changed, 120 insertions, 7 deletions
diff --git a/src/ufodecode.c b/src/ufodecode.c index a060cdc..492be74 100644 --- a/src/ufodecode.c +++ b/src/ufodecode.c @@ -719,3 +719,84 @@ int ufo_decoder_get_next_frame(UfoDecoder     *decoder,      return 0;  } +/** + * \brief Convert Bayer pattern to RGB + * + * Convert Bayer pattern to RGB via bilinear interpolation. + * + * \param in 16 bit input data in Bayer pattern format + * \param out Location for 24 bit output data in RGB format. At + * least width x height x 3 bytes must be allocated. + * \param width Width of a frame + * \param height Height of a frame + */ +void ufo_convert_bayer_to_rgb (const uint16_t *in, +                               uint8_t *out, +                               int width, +                               int height) +{ +    /* According to the CMV docs, the pattern starts at (0,0) with +     * +     *   R G +     *   G B +     */ + +#define BY(x,y) in[(x) + width * (y)] +#define R(x,y) out[0 + 3 * ((x) + width * (y))] +#define G(x,y) out[1 + 3 * ((x) + width * (y))] +#define B(x,y) out[2 + 3 * ((x) + width * (y))] + +    double scale; +    uint16_t max = 0; + +    for (int i = 0; i < width * height; i++) { +        if (max < in[i]) +            max = in[i]; +    } + +    scale = 255. / max; + +    for (int i = 1; i < width - 1; i += 2) { +        for (int j = 1; j < height - 1; j += 2) { +            /* Top left */ +            R(i + 0, j + 0) = ((uint32_t) BY(i - 1, j - 1) + +                               (uint32_t) BY(i + 1, j - 1) + +                               (uint32_t) BY(i - 1, j + 1) + +                               (uint32_t) BY(i + 1, j + 1)) / 4 * scale; +            G(i + 0, j + 0) = ((uint32_t) BY(i - 1, j + 0) + +                               (uint32_t) BY(i + 0, j - 1) + +                               (uint32_t) BY(i + 1, j + 0) + +                               (uint32_t) BY(i + 0, j + 1)) / 4 * scale; +            B(i + 0, j + 0) = BY(i + 0, j + 0) * scale; + +            /* Top right */ +            R(i + 1, j + 0) = ((uint32_t) BY(i + 1, j - 1) + +                               (uint32_t) BY(i + 1, j + 1)) / 2 * scale; +            G(i + 1, j + 0) = BY(i + 1, j + 0) * scale; +            B(i + 1, j + 0) = ((uint32_t) BY(i + 0, j + 0) + +                               (uint32_t) BY(i + 2, j + 0)) / 2 * scale; + +            /* Lower left */ +            R(i + 0, j + 1) = ((uint32_t) BY(i - 1, j + 0) + +                               (uint32_t) BY(i + 1, j + 1)) / 2 * scale; +            G(i + 0, j + 1) = BY(i + 0, j + 1) * scale; +            B(i + 0, j + 1) = ((uint32_t) BY(i + 0, j + 0) + +                               (uint32_t) BY(i + 0, j + 2)) / 2 * scale; + +            /* Lower right */ +            R(i + 1, j + 1) = BY(i + 1, j + 1) * scale; +            G(i + 1, j + 1) = ((uint32_t) BY(i + 1, j + 0) + +                               (uint32_t) BY(i + 0, j + 1) + +                               (uint32_t) BY(i + 2, j + 1) + +                               (uint32_t) BY(i + 2, j + 1)) / 4 * scale; +            B(i + 1, j + 1) = ((uint32_t) BY(i + 0, j + 0) + +                               (uint32_t) BY(i + 2, j + 0) + +                               (uint32_t) BY(i + 0, j + 2) + +                               (uint32_t) BY(i + 2, j + 2)) / 4 * scale; +        } +    } + +#undef R +#undef G +#undef B +} diff --git a/src/ufodecode.h b/src/ufodecode.h index 228bec3..91b727a 100644 --- a/src/ufodecode.h +++ b/src/ufodecode.h @@ -91,6 +91,10 @@ void        ufo_deinterlace_weave       (const uint16_t *in1,                                           uint16_t       *out,                                            int             width,                                            int             height); +void        ufo_convert_bayer_to_rgb    (const uint16_t *in, +                                         uint8_t        *out, +                                         int             width, +                                         int             height);  #ifdef __cplusplus  } diff --git a/test/ipedec.c b/test/ipedec.c index fe3ba07..6e48c14 100644 --- a/test/ipedec.c +++ b/test/ipedec.c @@ -18,6 +18,7 @@ typedef struct {      int print_frame_rate;      int print_num_rows;      int cont; +    int convert_bayer;  } Options;  static int @@ -59,7 +60,8 @@ Options:\n\    -d, --dry-run             Do not save the frames\n\    -f, --print-frame-rate    Print frame rate on STDOUT\n\        --print-num-rows      Print number of rows on STDOUT\n\ -      --continue            Continue decoding frames even when errors occur\n"); +      --continue            Continue decoding frames even when errors occur\n\ +      --convert-bayer       Convert Bayer pattern to 24 Bit RGB\n");  }  static void @@ -146,6 +148,7 @@ process_file(const char *filename, Options *opts)      char            *buffer;      size_t           num_bytes;      uint16_t        *pixels; +    uint8_t         *rgb_pixels;      uint32_t         time_stamp, old_time_stamp;      int              n_frames;      int              error = 0; @@ -177,6 +180,9 @@ process_file(const char *filename, Options *opts)          }      } +    if (opts->convert_bayer) +        rgb_pixels = malloc (2048 * MAX_ROWS * 3); +      timer = timer_new ();      pixels = (uint16_t *) malloc(2048 * MAX_ROWS * sizeof(uint16_t));      n_frames = 0; @@ -214,16 +220,28 @@ process_file(const char *filename, Options *opts)              if (opts->clear_frame)                  memset(pixels, 0, 2048 * meta.n_rows * sizeof(uint16_t)); -            if (!opts->dry_run) -                fwrite(pixels, sizeof(uint16_t), 2048 * meta.n_rows , fp); +            if (!opts->dry_run) { +                if (opts->convert_bayer) { +                    ufo_convert_bayer_to_rgb (pixels, rgb_pixels, 2048, meta.n_rows); +                    fwrite (rgb_pixels, sizeof(uint8_t), 2048 * meta.n_rows * 3, fp); +                } +                else +                    fwrite(pixels, sizeof(uint16_t), 2048 * meta.n_rows, fp); +            }          }          else if (error != EIO) {              fprintf(stderr, "Failed to decode frame %i\n", n_frames);              if (opts->cont) {                  /* Save the frame even though we know it is corrupted */ -                if (!opts->dry_run) -                    fwrite(pixels, sizeof(uint16_t), 2048 * meta.n_rows, fp); +                if (!opts->dry_run) { +                    if (opts->convert_bayer) { +                        ufo_convert_bayer_to_rgb (pixels, rgb_pixels, 2048, meta.n_rows); +                        fwrite (rgb_pixels, sizeof(uint8_t), 2048 * meta.n_rows * 3, fp); +                    } +                    else +                        fwrite(pixels, sizeof(uint16_t), 2048 * meta.n_rows, fp); +                }              }              else                  break; @@ -238,6 +256,9 @@ process_file(const char *filename, Options *opts)          printf("Decoded %i frames in %.5fms\n", n_frames, mtime);      } +    if (opts->convert_bayer) +        free (rgb_pixels); +      free(pixels);      free(buffer);      timer_destroy (timer); @@ -258,7 +279,8 @@ int main(int argc, char const* argv[])          SET_NUM_ROWS = 'r',           VERBOSE      = 'v',          CONTINUE, -        NUM_ROWS +        NUM_ROWS, +        CONVERT_BAYER,      };      static struct option long_options[] = { @@ -270,6 +292,7 @@ int main(int argc, char const* argv[])          { "print-frame-rate",   no_argument, 0, FRAME_RATE },          { "continue",           no_argument, 0, CONTINUE },          { "print-num-rows",     no_argument, 0, NUM_ROWS }, +        { "convert-bayer",      no_argument, 0, CONVERT_BAYER },          { 0, 0, 0, 0 }      }; @@ -280,7 +303,8 @@ int main(int argc, char const* argv[])          .clear_frame = 0,          .print_frame_rate = 0,          .print_num_rows = 0, -        .cont = 0 +        .cont = 0, +        .convert_bayer = 0      };      while ((getopt_ret = getopt_long(argc, (char *const *) argv, "r:cvhdf", long_options, &index)) != -1) { @@ -308,6 +332,10 @@ int main(int argc, char const* argv[])                  break;              case NUM_ROWS:                  opts.print_num_rows = 1; +                break; +            case CONVERT_BAYER: +                opts.convert_bayer = 1; +                break;              default:                  break;          }  | 
