Browse Source

Support defining the pixel format

Martijn Braam 1 year ago
parent
commit
48856f1c7a
6 changed files with 214 additions and 2 deletions
  1. 1 1
      CMakeLists.txt
  2. 3 0
      include/libdng.h
  3. 18 0
      src/libdng.c
  4. 152 0
      src/mode.c
  5. 23 0
      src/mode.h
  6. 17 1
      util/makedng.c

+ 1 - 1
CMakeLists.txt

@@ -6,7 +6,7 @@ set(LIBRARY_VERSION_MAJOR 0)
 set(LIBRARY_VERSION_STRING 0.1)
 set(CMAKE_C_VISIBILITY_PRESET hidden)
 
-add_library(libdng SHARED include/libdng.h src/libdng.c src/dng.h)
+add_library(libdng SHARED include/libdng.h src/libdng.c src/dng.h src/mode.c)
 
 set_target_properties(libdng PROPERTIES
         VERSION ${LIBRARY_VERSION_STRING}

+ 3 - 0
include/libdng.h

@@ -32,6 +32,9 @@ libdng_new(libdng_info *dng);
 EXPORT void
 libdng_free(libdng_info *dng);
 
+EXPORT int
+libdng_set_mode_from_name(libdng_info *dng, const char *name);
+
 EXPORT int
 libdng_write(libdng_info *dng, const char *path, unsigned int width, unsigned int height, uint8_t *data,
 	size_t length);

+ 18 - 0
src/libdng.c

@@ -1,5 +1,6 @@
 #include "libdng.h"
 #include "dng.h"
+#include "mode.h"
 
 #include <stdio.h>
 #include <tiffio.h>
@@ -49,6 +50,23 @@ libdng_new(libdng_info *dng)
 	dng->cfapattern[3] = 2;
 }
 
+int
+libdng_set_mode_from_name(libdng_info *dng, const char *name)
+{
+	int index = dng_mode_from_name(name);
+	if (index == 0) {
+		fprintf(stderr, "Invalid mode '%s'\n", name);
+		return 0;
+	}
+
+	uint32_t cfa = dng_cfa_from_mode(index);
+	dng->cfapattern[0] = (cfa >> 24) & 0xFF;
+	dng->cfapattern[1] = (cfa >> 16) & 0xFF;
+	dng->cfapattern[2] = (cfa >> 8) & 0xFF;
+	dng->cfapattern[3] = (cfa >> 0) & 0xFF;
+	return 1;
+}
+
 int
 libdng_set_make_model(libdng_info *dng, char *make, char *model)
 {

+ 152 - 0
src/mode.c

@@ -0,0 +1,152 @@
+#include <string.h>
+#include "mode.h"
+
+static struct pixelformat pixelformat_lut[] = {
+	{
+		.fourcc = "",
+		.name = "unsupported",
+		.cfa = CFA_NONE,
+		.bits_per_sample = 0,
+	},
+	{
+		.fourcc = "RGGB",
+		.name = "SRRGB8",
+		.cfa = CFA_RGGB,
+		.bits_per_sample = 8,
+	},
+	{
+		.fourcc = "GRBG",
+		.name = "SGRBG8",
+		.cfa = CFA_GRBG,
+		.bits_per_sample = 8,
+	},
+	{
+		.fourcc = "GBRG",
+		.name = "SGBR8",
+		.cfa = CFA_GBRG,
+		.bits_per_sample = 8,
+	},
+	{
+		.fourcc = "BGGR",
+		.name = "SBGGR8",
+		.cfa = CFA_BGGR,
+		.bits_per_sample = 8,
+	},
+	{
+		.fourcc = "RG10",
+		.name = "SRGGB10",
+		.cfa = CFA_RGGB,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "BA10",
+		.name = "SGRBG10",
+		.cfa = CFA_GRBG,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "GB10",
+		.name = "SGBR10",
+		.cfa = CFA_GBRG,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "BG10",
+		.name = "SBGGR10",
+		.cfa = CFA_BGGR,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "pRAA",
+		.name = "SRGGB10P",
+		.cfa = CFA_RGGB,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "pgAA",
+		.name = "SGRBG10P",
+		.cfa = CFA_GRBG,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "pGAA",
+		.name = "SGBR10P",
+		.cfa = CFA_GBRG,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "pBAA",
+		.name = "SBGGR10P",
+		.cfa = CFA_BGGR,
+		.bits_per_sample = 10,
+	},
+	{
+		.fourcc = "RG12",
+		.name = "SRGGB12",
+		.cfa = CFA_RGGB,
+		.bits_per_sample = 12,
+	},
+	{
+		.fourcc = "BA12",
+		.name = "SGRBG12",
+		.cfa = CFA_GRBG,
+		.bits_per_sample = 12,
+	},
+	{
+		.fourcc = "GB12",
+		.name = "SGBR12",
+		.cfa = CFA_GBRG,
+		.bits_per_sample = 12,
+	},
+	{
+		.fourcc = "BG12",
+		.name = "SBGGR12",
+		.cfa = CFA_BGGR,
+		.bits_per_sample = 12,
+	},
+	{
+		.fourcc = "RG16",
+		.name = "SRGGB16",
+		.cfa = CFA_RGGB,
+		.bits_per_sample = 16,
+	},
+	{
+		.fourcc = "GR16",
+		.name = "SGRBG16",
+		.cfa = CFA_GRBG,
+		.bits_per_sample = 16,
+	},
+	{
+		.fourcc = "GB16",
+		.name = "SGBR16",
+		.cfa = CFA_GBRG,
+		.bits_per_sample = 16,
+	},
+	{
+		.fourcc = "BYR2",
+		.name = "SBGGR16",
+		.cfa = CFA_BGGR,
+		.bits_per_sample = 16,
+	},
+};
+
+int
+dng_mode_from_name(const char *name)
+{
+	int count = sizeof(pixelformat_lut) / sizeof(pixelformat_lut[0]);
+	for (int i = 0; i < count; i++) {
+		if (strcmp(pixelformat_lut[i].name, name) == 0) {
+			return i;
+		}
+		if (strcmp(pixelformat_lut[i].fourcc, name) == 0) {
+			return i;
+		}
+	}
+	return 0;
+}
+
+uint32_t
+dng_cfa_from_mode(int index)
+{
+	return pixelformat_lut[index].cfa;
+}

+ 23 - 0
src/mode.h

@@ -0,0 +1,23 @@
+#include <stdint.h>
+
+#pragma once
+
+#define CFA_NONE 0
+#define CFA_BGGR '\002\001\001\000'
+#define CFA_GBRG '\001\002\001\000'
+#define CFA_GRBG '\001\000\002\001'
+#define CFA_RGGB '\000\001\001\002'
+
+
+struct pixelformat {
+		char *fourcc;
+		char *name;
+		uint32_t cfa;
+		int bits_per_sample;
+};
+
+int
+dng_mode_from_name(const char *name);
+
+uint32_t
+dng_cfa_from_mode(int index);

+ 17 - 1
util/makedng.c

@@ -14,6 +14,7 @@ usage(char *name)
 	fprintf(stderr, "Arguments:\n");
 	fprintf(stderr, "  -w width    Source data width\n");
 	fprintf(stderr, "  -h height   Source data height\n");
+	fprintf(stderr, "  -p fmt      Source data pixelformat\n");
 }
 
 int
@@ -29,8 +30,9 @@ main(int argc, char *argv[])
 	libdng_new(&info);
 	unsigned int width = 0;
 	unsigned int height = 0;
+	char *pixelfmt = NULL;
 
-	while ((c = getopt(argc, argv, "w:h:")) != -1) {
+	while ((c = getopt(argc, argv, "w:h:p:")) != -1) {
 		switch (c) {
 			case 'w':
 				val = strtol(optarg, &end, 10);
@@ -40,6 +42,9 @@ main(int argc, char *argv[])
 				val = strtol(optarg, &end, 10);
 				height = (unsigned int) val;
 				break;
+			case 'p':
+				pixelfmt = optarg;
+				break;
 			case '?':
 				if (optopt == 'd' || optopt == 'l') {
 					fprintf(stderr, "Option -%c requires an argument.\n", optopt);
@@ -66,6 +71,17 @@ main(int argc, char *argv[])
 		return 1;
 	}
 
+	if (pixelfmt == NULL) {
+		fprintf(stderr, "The pixel format argument is required\n");
+		usage(argv[0]);
+		return 1;
+	}
+	if (!libdng_set_mode_from_name(&info, pixelfmt)) {
+		fprintf(stderr, "Invalid pixel format supplied\n");
+		usage(argv[0]);
+		return 1;
+	}
+
 	printf("Reading %s...\n", argv[optind]);
 	FILE *src = fopen(argv[optind], "r");
 	if (src == NULL) {