summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ufodecode.c81
-rw-r--r--src/ufodecode.h4
-rw-r--r--test/ipedec.c42
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;
}