From 7cd3ce58260bb8df55d202dfe7bf0ae48a9f9da8 Mon Sep 17 00:00:00 2001
From: Dominik Loidolt <dominik.loidolt@univie.ac.at>
Date: Tue, 7 Nov 2023 17:27:33 +0100
Subject: [PATCH] Add compression and decompression for DATA_TYPE_F_CAM_OFFSET
 and DATA_TYPE_F_CAM_BACKGROUND

---
 include/cmp_data_types.h                  |   8 +-
 include/cmp_max_used_bits.h               |   1 -
 lib/cmp_data_types.c                      |  21 +++--
 lib/cmp_entity.c                          |   5 +-
 lib/cmp_icu.c                             |  88 +++++++++++++------
 lib/cmp_io.c                              |   4 +-
 lib/cmp_max_used_bits.c                   |  24 +++---
 lib/cmp_support.c                         |  12 +--
 lib/decmp.c                               | 100 ++++++++++++++--------
 test/cmp_data_types/test_cmp_data_types.c |  38 +++++---
 test/cmp_decmp/test_cmp_decmp.c           |  46 ++++++++--
 test/cmp_entity/test_cmp_entity.c         |  10 +--
 test/cmp_icu/test_cmp_icu.c               |  22 +++--
 13 files changed, 234 insertions(+), 145 deletions(-)

diff --git a/include/cmp_data_types.h b/include/cmp_data_types.h
index 734621e..e10ae81 100644
--- a/include/cmp_data_types.h
+++ b/include/cmp_data_types.h
@@ -219,20 +219,20 @@ struct l_fx_efx_ncob_ecob {
 
 
 /**
- * @brief normal offset entry definition
+ * @brief normal and fast offset entry definition
  */
 
-struct nc_offset {
+struct offset {
 	uint32_t mean;
 	uint32_t variance;
 } __attribute__((packed));
 
 
 /**
- * @brief normal background entry definition
+ * @brief normal and fast background entry definition
  */
 
-struct nc_background {
+struct background {
 	uint32_t mean;
 	uint32_t variance;
 	uint16_t outlier_pixels;
diff --git a/include/cmp_max_used_bits.h b/include/cmp_max_used_bits.h
index ac936c7..21e7dd4 100644
--- a/include/cmp_max_used_bits.h
+++ b/include/cmp_max_used_bits.h
@@ -66,7 +66,6 @@ struct cmp_max_used_bits {
 	unsigned int fc_imagette;
 	unsigned int fc_offset_mean;
 	unsigned int fc_offset_variance;
-	unsigned int fc_offset_pixel_in_error;
 	unsigned int fc_background_mean;
 	unsigned int fc_background_variance;
 	unsigned int fc_background_outlier_pixels;
diff --git a/lib/cmp_data_types.c b/lib/cmp_data_types.c
index e3a33c6..00861cd 100644
--- a/lib/cmp_data_types.c
+++ b/lib/cmp_data_types.c
@@ -51,10 +51,12 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 		sample_size = sizeof(uint16_t);
 		break;
 	case DATA_TYPE_OFFSET:
-		sample_size = sizeof(struct nc_offset);
+	case DATA_TYPE_F_CAM_OFFSET:
+		sample_size = sizeof(struct offset);
 		break;
 	case DATA_TYPE_BACKGROUND:
-		sample_size = sizeof(struct nc_background);
+	case DATA_TYPE_F_CAM_BACKGROUND:
+		sample_size = sizeof(struct background);
 		break;
 	case DATA_TYPE_SMEARING:
 		sample_size = sizeof(struct smearing);
@@ -95,8 +97,6 @@ size_t size_of_a_sample(enum cmp_data_type data_type)
 	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		sample_size = sizeof(struct f_fx_efx_ncob_ecob);
 		break;
-	case DATA_TYPE_F_CAM_OFFSET:
-	case DATA_TYPE_F_CAM_BACKGROUND:
 	case DATA_TYPE_UNKNOWN:
 	default:
 		debug_print("Error: Compression data type is not supported.\n");
@@ -182,7 +182,7 @@ static void be_to_cpus_16(uint16_t *a, int samples)
 }
 
 
-static void be_to_cpus_nc_offset(struct nc_offset *a, int samples)
+static void be_to_cpus_offset(struct offset *a, int samples)
 {
 	int i;
 
@@ -193,7 +193,7 @@ static void be_to_cpus_nc_offset(struct nc_offset *a, int samples)
 }
 
 
-static void be_to_cpus_nc_background(struct nc_background *a, int samples)
+static void be_to_cpus_background(struct background *a, int samples)
 {
 	int i;
 
@@ -409,10 +409,12 @@ int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
 		be_to_cpus_16(data, samples);
 		break;
 	case DATA_TYPE_OFFSET:
-		be_to_cpus_nc_offset(data, samples);
+	case DATA_TYPE_F_CAM_OFFSET:
+		be_to_cpus_offset(data, samples);
 		break;
 	case DATA_TYPE_BACKGROUND:
-		be_to_cpus_nc_background(data, samples);
+	case DATA_TYPE_F_CAM_BACKGROUND:
+		be_to_cpus_background(data, samples);
 		break;
 	case DATA_TYPE_SMEARING:
 		be_to_cpus_smearing(data, samples);
@@ -453,9 +455,6 @@ int cmp_input_big_to_cpu_endianness(void *data, uint32_t data_size_byte,
 	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		be_to_cpus_f_fx_efx_ncob_ecob(data, samples);
 		break;
-	/* TODO: implement F_CAM conversion */
-	case DATA_TYPE_F_CAM_OFFSET:
-	case DATA_TYPE_F_CAM_BACKGROUND:
 	/* LCOV_EXCL_START */
 	case DATA_TYPE_UNKNOWN:
 	default:
diff --git a/lib/cmp_entity.c b/lib/cmp_entity.c
index d82a0fd..4ca1180 100644
--- a/lib/cmp_entity.c
+++ b/lib/cmp_entity.c
@@ -1859,7 +1859,9 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 			return -1;
 		break;
 	case DATA_TYPE_OFFSET:
+	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_BACKGROUND:
+	case DATA_TYPE_F_CAM_BACKGROUND:
 	case DATA_TYPE_SMEARING:
 		if (cmp_ent_set_non_ima_cmp_par1(ent, cfg->cmp_par_mean))
 			return -1;
@@ -1928,9 +1930,6 @@ int cmp_ent_write_cmp_pars(struct cmp_entity *ent, const struct cmp_cfg *cfg,
 			return -1;
 
 		break;
-	case DATA_TYPE_F_CAM_OFFSET:
-	case DATA_TYPE_F_CAM_BACKGROUND:
-		/* TODO: implement this*/
 	case DATA_TYPE_UNKNOWN:
 	default:
 		return -1;
diff --git a/lib/cmp_icu.c b/lib/cmp_icu.c
index c90fa08..2fa7e67 100644
--- a/lib/cmp_icu.c
+++ b/lib/cmp_icu.c
@@ -1880,7 +1880,7 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief compress offset data from the normal cameras
+ * @brief compress offset data from the normal and fast cameras
  *
  * @param cfg	pointer to the compression configuration structure
  * @returns the bit length of the bitstream on success; negative on error,
@@ -1888,16 +1888,16 @@ static int compress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  *	value in the bitstream
  */
 
-static int compress_nc_offset(const struct cmp_cfg *cfg)
+static int compress_offset(const struct cmp_cfg *cfg)
 {
 	int stream_len = 0;
 	size_t i;
 
-	struct nc_offset *data_buf = cfg->input_buf;
-	struct nc_offset *model_buf = cfg->model_buf;
-	struct nc_offset *up_model_buf = NULL;
-	struct nc_offset *next_model_p;
-	struct nc_offset model;
+	struct offset *data_buf = cfg->input_buf;
+	struct offset *model_buf = cfg->model_buf;
+	struct offset *up_model_buf = NULL;
+	struct offset *next_model_p;
+	struct offset model;
 	struct encoder_setupt setup_mean, setup_var;
 
 	if (model_mode_is_used(cfg->cmp_mode))
@@ -1914,10 +1914,25 @@ static int compress_nc_offset(const struct cmp_cfg *cfg)
 		next_model_p = data_buf;
 	}
 
-	configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
-				cfg->round, cfg->max_used_bits->nc_offset_mean, cfg);
-	configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
-				cfg->round, cfg->max_used_bits->nc_offset_variance, cfg);
+	{
+		unsigned int mean_bits_used, variance_bits_used;
+
+		switch (cfg->data_type) {
+		case DATA_TYPE_F_CAM_OFFSET:
+			mean_bits_used = cfg->max_used_bits->fc_offset_mean;
+			variance_bits_used = cfg->max_used_bits->fc_offset_variance;
+			break;
+		case DATA_TYPE_OFFSET:
+		default:
+			mean_bits_used = cfg->max_used_bits->nc_offset_mean;
+			variance_bits_used = cfg->max_used_bits->nc_offset_variance;
+			break;
+		}
+		configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+					cfg->round, mean_bits_used, cfg);
+		configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+					cfg->round, variance_bits_used, cfg);
+	}
 
 	for (i = 0;; i++) {
 		stream_len = encode_value(data_buf[i].mean, model.mean,
@@ -1946,7 +1961,7 @@ static int compress_nc_offset(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief compress background data from the normal cameras
+ * @brief compress background data from the normal and fast cameras
  *
  * @param cfg	pointer to the compression configuration structure
  * @returns the bit length of the bitstream on success; negative on error,
@@ -1954,16 +1969,16 @@ static int compress_nc_offset(const struct cmp_cfg *cfg)
  *	value in the bitstream
  */
 
-static int compress_nc_background(const struct cmp_cfg *cfg)
+static int compress_background(const struct cmp_cfg *cfg)
 {
 	int stream_len = 0;
 	size_t i;
 
-	struct nc_background *data_buf = cfg->input_buf;
-	struct nc_background *model_buf = cfg->model_buf;
-	struct nc_background *up_model_buf = NULL;
-	struct nc_background *next_model_p;
-	struct nc_background model;
+	struct background *data_buf = cfg->input_buf;
+	struct background *model_buf = cfg->model_buf;
+	struct background *up_model_buf = NULL;
+	struct background *next_model_p;
+	struct background model;
 	struct encoder_setupt setup_mean, setup_var, setup_pix;
 
 	if (model_mode_is_used(cfg->cmp_mode))
@@ -1980,12 +1995,29 @@ static int compress_nc_background(const struct cmp_cfg *cfg)
 		next_model_p = data_buf;
 	}
 
-	configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
-				cfg->round, cfg->max_used_bits->nc_background_mean, cfg);
-	configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
-				cfg->round, cfg->max_used_bits->nc_background_variance, cfg);
-	configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
-				cfg->round, cfg->max_used_bits->nc_background_outlier_pixels, cfg);
+	{
+		unsigned int mean_used_bits, varinace_used_bits, pixels_error_used_bits;
+
+		switch (cfg->data_type) {
+		case DATA_TYPE_F_CAM_BACKGROUND:
+			mean_used_bits = cfg->max_used_bits->fc_background_mean;
+			varinace_used_bits = cfg->max_used_bits->fc_background_variance;
+			pixels_error_used_bits = cfg->max_used_bits->fc_background_outlier_pixels;
+			break;
+		case DATA_TYPE_BACKGROUND:
+		default:
+			mean_used_bits = cfg->max_used_bits->nc_background_mean;
+			varinace_used_bits = cfg->max_used_bits->nc_background_variance;
+			pixels_error_used_bits = cfg->max_used_bits->nc_background_outlier_pixels;
+			break;
+		}
+		configure_encoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+					cfg->round, mean_used_bits, cfg);
+		configure_encoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+					cfg->round, varinace_used_bits, cfg);
+		configure_encoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+					cfg->round, pixels_error_used_bits, cfg);
+	}
 
 	for (i = 0;; i++) {
 		stream_len = encode_value(data_buf[i].mean, model.mean,
@@ -2274,17 +2306,17 @@ int icu_compress_data(const struct cmp_cfg *cfg)
 			break;
 
 		case DATA_TYPE_OFFSET:
-			bitsize = compress_nc_offset(cfg);
+		case DATA_TYPE_F_CAM_OFFSET:
+			bitsize = compress_offset(cfg);
 			break;
 		case DATA_TYPE_BACKGROUND:
-			bitsize = compress_nc_background(cfg);
+		case DATA_TYPE_F_CAM_BACKGROUND:
+			bitsize = compress_background(cfg);
 			break;
 		case DATA_TYPE_SMEARING:
 			bitsize = compress_smearing(cfg);
 			break;
 
-		case DATA_TYPE_F_CAM_OFFSET:
-		case DATA_TYPE_F_CAM_BACKGROUND:
 		/* LCOV_EXCL_START */
 		case DATA_TYPE_UNKNOWN:
 		default:
diff --git a/lib/cmp_io.c b/lib/cmp_io.c
index 57f9ec5..5e6f914 100644
--- a/lib/cmp_io.c
+++ b/lib/cmp_io.c
@@ -1683,7 +1683,8 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg)
 		fprintf(fp, "spill_variance = %" PRIu32 "\n", cfg->spill_variance);
 		fprintf(fp, "\n");
 		fprintf(fp, "#-------------------------------------------------------------------------------\n");
-		if (cfg->data_type != DATA_TYPE_OFFSET) {
+		if (cfg->data_type != DATA_TYPE_OFFSET &&
+		    cfg->data_type != DATA_TYPE_F_CAM_OFFSET) {
 			fprintf(fp, "# outlier pixels number compression parameter\n");
 			fprintf(fp, "\n");
 			fprintf(fp, "cmp_par_pixels_error = %" PRIu32 "\n", cfg->cmp_par_pixels_error);
@@ -1695,7 +1696,6 @@ static void write_cfg_internal(FILE *fp, const struct cmp_cfg *cfg)
 			fprintf(fp, "\n");
 			fprintf(fp, "#-------------------------------------------------------------------------------\n");
 		}
-		/* TODO: implemented DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */
 	}
 
 	if (cmp_fx_cob_data_type_is_used(cfg->data_type)) {
diff --git a/lib/cmp_max_used_bits.c b/lib/cmp_max_used_bits.c
index c40a961..553c0a5 100644
--- a/lib/cmp_max_used_bits.c
+++ b/lib/cmp_max_used_bits.c
@@ -89,21 +89,20 @@ const struct cmp_max_used_bits MAX_USED_BITS_SAFE = {
 	member_bit_size(struct l_fx_efx_ncob_ecob, cob_x_variance), /* l_cob_x_variance and l_cob_y_variance */
 	sizeof(uint16_t)*8, /* nc_imagette */
 	sizeof(uint16_t)*8, /* saturated_imagette */
-	member_bit_size(struct nc_offset, mean), /* nc_offset_mean */
-	member_bit_size(struct nc_offset, variance), /* nc_offset_variance */
-	member_bit_size(struct nc_background, mean), /* nc_background_mean */
-	member_bit_size(struct nc_background, variance), /* nc_background_variance */
-	member_bit_size(struct nc_background, outlier_pixels), /* nc_background_outlier_pixels */
+	member_bit_size(struct offset, mean), /* nc_offset_mean */
+	member_bit_size(struct offset, variance), /* nc_offset_variance */
+	member_bit_size(struct background, mean), /* nc_background_mean */
+	member_bit_size(struct background, variance), /* nc_background_variance */
+	member_bit_size(struct background, outlier_pixels), /* nc_background_outlier_pixels */
 	member_bit_size(struct smearing, mean), /* smearing_mean */
 	member_bit_size(struct smearing, variance_mean), /* smearing_variance_mean */
 	member_bit_size(struct smearing, outlier_pixels), /* smearing_outlier_pixels */
-	sizeof(uint16_t)*8, /* TBC */ /* fc_imagette */
-	sizeof(uint32_t)*8, /* TBC TODO: update */ /* fc_offset_mean */
-	sizeof(uint32_t)*8, /* TBC TODO: update */ /* fc_offset_variance */
-	sizeof(uint32_t)*8, /* TBC TODO: update */ /* fc_offset_pixel_in_error */
-	sizeof(uint32_t)*8, /* TBC TODO: update */ /* fc_background_mean */
-	sizeof(uint32_t)*8, /* TBC TODO: update */ /* fc_background_variance */
-	sizeof(uint32_t)*8, /* TBC TODO: update */ /* fc_background_outlier_pixels */
+	sizeof(uint16_t)*8, /* fc_imagette */
+	member_bit_size(struct offset, mean), /* fc_offset_mean */
+	member_bit_size(struct offset, variance), /* fc_offset_variance */
+	member_bit_size(struct background, mean), /* fc_background_mean */
+	member_bit_size(struct background, variance), /* fc_background_variance */
+	member_bit_size(struct background, outlier_pixels), /* fc_background_outlier_pixels */
 };
 
 
@@ -139,7 +138,6 @@ const struct cmp_max_used_bits MAX_USED_BITS_V1 = {
 	MAX_USED_FC_IMAGETTE_BITS, /* fc_imagette */
 	MAX_USED_FC_OFFSET_MEAN_BITS, /* fc_offset_mean */
 	MAX_USED_FC_OFFSET_VARIANCE_BITS, /* fc_offset_variance */
-	MAX_USED_FC_OFFSET_PIXEL_IN_ERROR_BITS, /* fc_offset_pixel_in_error */
 	MAX_USED_FC_BACKGROUND_MEAN_BITS, /* fc_background_mean */
 	MAX_USED_FC_BACKGROUND_VARIANCE_BITS, /* fc_background_variance */
 	MAX_USED_FC_BACKGROUND_OUTLIER_PIXELS_BITS /* fc_background_outlier_pixels */
diff --git a/lib/cmp_support.c b/lib/cmp_support.c
index cbad0cf..77003ac 100644
--- a/lib/cmp_support.c
+++ b/lib/cmp_support.c
@@ -69,12 +69,7 @@ int is_a_pow_of_2(unsigned int v)
 
 int cmp_data_type_is_invalid(enum cmp_data_type data_type)
 {
-	if (data_type == DATA_TYPE_F_CAM_OFFSET)
-		debug_print("Error: DATA_TYPE_F_CAM_OFFSET is TBD and not implemented yet.\n");
-	if (data_type == DATA_TYPE_F_CAM_BACKGROUND)
-		debug_print("Error: DATA_TYPE_F_CAM_BACKGROUND is TBD  and not implemented yet.\n");
-
-	if (data_type <= DATA_TYPE_UNKNOWN || data_type > DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE)
+	if (data_type <= DATA_TYPE_UNKNOWN || data_type > DATA_TYPE_F_CAM_BACKGROUND)
 		return 1;
 
 	return 0;
@@ -586,7 +581,6 @@ int cmp_cfg_icu_max_used_bits_out_of_limit(const struct cmp_max_used_bits *max_u
 	CHECK_MAX_USED_BITS_LIMIT(fc_imagette);
 	CHECK_MAX_USED_BITS_LIMIT(fc_offset_mean);
 	CHECK_MAX_USED_BITS_LIMIT(fc_offset_variance);
-	CHECK_MAX_USED_BITS_LIMIT(fc_offset_pixel_in_error);
 	CHECK_MAX_USED_BITS_LIMIT(fc_background_mean);
 	CHECK_MAX_USED_BITS_LIMIT(fc_background_variance);
 	CHECK_MAX_USED_BITS_LIMIT(fc_background_outlier_pixels);
@@ -864,7 +858,6 @@ int cmp_cfg_fx_cob_is_invalid(const struct cmp_cfg *cfg)
  *
  * @returns 0 if the auxiliary science specific parameters are valid, otherwise
  *	invalid
- * TODO: implemented DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND
  */
 
 int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg)
@@ -884,8 +877,7 @@ int cmp_cfg_aux_is_invalid(const struct cmp_cfg *cfg)
 	cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_variance, cfg->spill_variance,
 					    cfg->cmp_mode, cfg->data_type, "variance");
 
-	/* if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET) */
-	if (cfg->data_type != DATA_TYPE_OFFSET)
+	if (cfg->data_type != DATA_TYPE_OFFSET && cfg->data_type != DATA_TYPE_F_CAM_OFFSET)
 		cfg_invalid += cmp_pars_are_invalid(cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
 						    cfg->cmp_mode, cfg->data_type, "outlier pixls num");
 
diff --git a/lib/decmp.c b/lib/decmp.c
index b3a2561..eef0b71 100644
--- a/lib/decmp.c
+++ b/lib/decmp.c
@@ -1810,7 +1810,7 @@ static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
 
 
 /**
- * @brief decompress N-CAM offset data
+ * @brief decompress N-CAM and F-CAM offset data
  *
  * @param cfg	pointer to the compression configuration structure
  *
@@ -1819,17 +1819,17 @@ static int decompress_l_fx_efx_ncob_ecob(const struct cmp_cfg *cfg)
  *	buffer is too small to read the value from the bitstream
  */
 
-static int decompress_nc_offset(const struct cmp_cfg *cfg)
+static int decompress_offset(const struct cmp_cfg *cfg)
 {
 	size_t i;
 	int stream_pos = 0;
 	uint32_t decoded_value;
 	struct decoder_setup setup_mean, setup_var;
-	struct nc_offset *data_buf = cfg->input_buf;
-	struct nc_offset *model_buf = cfg->model_buf;
-	struct nc_offset *up_model_buf = NULL;
-	struct nc_offset *next_model_p;
-	struct nc_offset model;
+	struct offset *data_buf = cfg->input_buf;
+	struct offset *model_buf = cfg->model_buf;
+	struct offset *up_model_buf = NULL;
+	struct offset *next_model_p;
+	struct offset model;
 
 	if (model_mode_is_used(cfg->cmp_mode))
 		up_model_buf = cfg->icu_new_model_buf;
@@ -1845,12 +1845,27 @@ static int decompress_nc_offset(const struct cmp_cfg *cfg)
 		next_model_p = data_buf;
 	}
 
-	if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
-				    cfg->round, cfg->max_used_bits->nc_offset_mean, cfg))
-		return -1;
-	if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
-				    cfg->round, cfg->max_used_bits->nc_offset_variance, cfg))
-		return -1;
+	{
+		unsigned int mean_bits_used, variance_bits_used;
+
+		switch (cfg->data_type) {
+		case DATA_TYPE_F_CAM_OFFSET:
+			mean_bits_used = cfg->max_used_bits->fc_offset_mean;
+			variance_bits_used = cfg->max_used_bits->fc_offset_variance;
+			break;
+		case DATA_TYPE_OFFSET:
+		default:
+			mean_bits_used = cfg->max_used_bits->nc_offset_mean;
+			variance_bits_used = cfg->max_used_bits->nc_offset_variance;
+			break;
+		}
+		if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+					    cfg->round, mean_bits_used, cfg))
+			return -1;
+		if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+					    cfg->round, variance_bits_used, cfg))
+			return -1;
+	}
 
 	for (i = 0; ; i++) {
 		stream_pos = decode_value(&decoded_value, model.mean, stream_pos,
@@ -1891,17 +1906,17 @@ static int decompress_nc_offset(const struct cmp_cfg *cfg)
  *	buffer is too small to read the value from the bitstream
  */
 
-static int decompress_nc_background(const struct cmp_cfg *cfg)
+static int decompress_background(const struct cmp_cfg *cfg)
 {
 	size_t i;
 	int stream_pos = 0;
 	uint32_t decoded_value;
 	struct decoder_setup setup_mean, setup_var, setup_pix;
-	struct nc_background *data_buf = cfg->input_buf;
-	struct nc_background *model_buf = cfg->model_buf;
-	struct nc_background *up_model_buf = NULL;
-	struct nc_background *next_model_p;
-	struct nc_background model;
+	struct background *data_buf = cfg->input_buf;
+	struct background *model_buf = cfg->model_buf;
+	struct background *up_model_buf = NULL;
+	struct background *next_model_p;
+	struct background model;
 
 	if (model_mode_is_used(cfg->cmp_mode))
 		up_model_buf = cfg->icu_new_model_buf;
@@ -1916,16 +1931,33 @@ static int decompress_nc_background(const struct cmp_cfg *cfg)
 		memset(&model, 0, sizeof(model));
 		next_model_p = data_buf;
 	}
+	{
+		unsigned int mean_used_bits, variance_used_bits, outlier_pixels_used_bits;
 
-	if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
-				    cfg->round, cfg->max_used_bits->nc_background_mean, cfg))
-		return -1;
-	if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
-				    cfg->round, cfg->max_used_bits->nc_background_variance, cfg))
-		return -1;
-	if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
-				    cfg->round, cfg->max_used_bits->nc_background_outlier_pixels, cfg))
-		return -1;
+		switch (cfg->data_type) {
+		case DATA_TYPE_F_CAM_BACKGROUND:
+			mean_used_bits = cfg->max_used_bits->fc_background_mean;
+			variance_used_bits = cfg->max_used_bits->fc_background_variance;
+			outlier_pixels_used_bits = cfg->max_used_bits->fc_background_outlier_pixels;
+			break;
+		case DATA_TYPE_BACKGROUND:
+		default:
+			mean_used_bits = cfg->max_used_bits->nc_background_mean;
+			variance_used_bits = cfg->max_used_bits->nc_background_variance;
+			outlier_pixels_used_bits = cfg->max_used_bits->nc_background_outlier_pixels;
+			break;
+		}
+
+		if (configure_decoder_setup(&setup_mean, cfg->cmp_par_mean, cfg->spill_mean,
+					    cfg->round, mean_used_bits, cfg))
+			return -1;
+		if (configure_decoder_setup(&setup_var, cfg->cmp_par_variance, cfg->spill_variance,
+					    cfg->round, variance_used_bits, cfg))
+			return -1;
+		if (configure_decoder_setup(&setup_pix, cfg->cmp_par_pixels_error, cfg->spill_pixels_error,
+					    cfg->round, outlier_pixels_used_bits , cfg))
+			return -1;
+	}
 
 	for (i = 0; ; i++) {
 		stream_pos = decode_value(&decoded_value, model.mean, stream_pos,
@@ -2153,17 +2185,17 @@ static int decompressed_data_internal(struct cmp_cfg *cfg)
 			break;
 
 		case DATA_TYPE_OFFSET:
-			strem_len_bit = decompress_nc_offset(cfg);
+		case DATA_TYPE_F_CAM_OFFSET:
+			strem_len_bit = decompress_offset(cfg);
 			break;
 		case DATA_TYPE_BACKGROUND:
-			strem_len_bit = decompress_nc_background(cfg);
+		case DATA_TYPE_F_CAM_BACKGROUND:
+			strem_len_bit = decompress_background(cfg);
 			break;
 		case DATA_TYPE_SMEARING:
 			strem_len_bit = decompress_smearing(cfg);
 			break;
 
-		case DATA_TYPE_F_CAM_OFFSET:
-		case DATA_TYPE_F_CAM_BACKGROUND:
 		case DATA_TYPE_UNKNOWN:
 		default:
 			strem_len_bit = -1;
@@ -2247,7 +2279,9 @@ static int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 		cfg->golomb_par = cmp_ent_get_ima_golomb_par(ent);
 		break;
 	case DATA_TYPE_OFFSET:
+	case DATA_TYPE_F_CAM_OFFSET:
 	case DATA_TYPE_BACKGROUND:
+	case DATA_TYPE_F_CAM_BACKGROUND:
 	case DATA_TYPE_SMEARING:
 		cfg->cmp_par_mean = cmp_ent_get_non_ima_cmp_par1(ent);
 		cfg->spill_mean = cmp_ent_get_non_ima_spill1(ent);
@@ -2281,8 +2315,6 @@ static int cmp_ent_read_header(struct cmp_entity *ent, struct cmp_cfg *cfg)
 		cfg->cmp_par_fx_cob_variance = cmp_ent_get_non_ima_cmp_par6(ent);
 		cfg->spill_fx_cob_variance = cmp_ent_get_non_ima_spill6(ent);
 		break;
-	case DATA_TYPE_F_CAM_OFFSET:
-	case DATA_TYPE_F_CAM_BACKGROUND:
 	/* LCOV_EXCL_START */
 	case DATA_TYPE_UNKNOWN:
 	default:
diff --git a/test/cmp_data_types/test_cmp_data_types.c b/test/cmp_data_types/test_cmp_data_types.c
index b3461dd..ec3a8d4 100644
--- a/test/cmp_data_types/test_cmp_data_types.c
+++ b/test/cmp_data_types/test_cmp_data_types.c
@@ -30,11 +30,6 @@
 void test_size_of_a_sample(void)
 {
 	size_t size;
-	/* TODO: implied DATA_TYPE_F_CAM_OFFSET and DATA_TYPE_F_CAM_BACKGROUND DATA_TYPE_F_CAM_BACKGROUND*/
-	size = size_of_a_sample(DATA_TYPE_F_CAM_OFFSET);
-	TEST_ASSERT_EQUAL(0, size);
-	size = size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND);
-	TEST_ASSERT_EQUAL(0, size);
 
 	/* test error cases */
 	size = size_of_a_sample(DATA_TYPE_UNKNOWN);
@@ -42,13 +37,12 @@ void test_size_of_a_sample(void)
 	size = size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND+1);
 	TEST_ASSERT_EQUAL(0, size);
 
-
 	TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_IMAGETTE));
 	TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_IMAGETTE_ADAPTIVE));
 	TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_SAT_IMAGETTE));
 	TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_SAT_IMAGETTE_ADAPTIVE));
-	TEST_ASSERT_EQUAL(sizeof(struct nc_offset), size_of_a_sample(DATA_TYPE_OFFSET));
-	TEST_ASSERT_EQUAL(sizeof(struct nc_background), size_of_a_sample(DATA_TYPE_BACKGROUND));
+	TEST_ASSERT_EQUAL(sizeof(struct offset), size_of_a_sample(DATA_TYPE_OFFSET));
+	TEST_ASSERT_EQUAL(sizeof(struct background), size_of_a_sample(DATA_TYPE_BACKGROUND));
 	TEST_ASSERT_EQUAL(sizeof(struct smearing), size_of_a_sample(DATA_TYPE_SMEARING));
 	TEST_ASSERT_EQUAL(sizeof(struct s_fx), size_of_a_sample(DATA_TYPE_S_FX));
 	TEST_ASSERT_EQUAL(sizeof(struct s_fx_efx), size_of_a_sample(DATA_TYPE_S_FX_EFX));
@@ -64,8 +58,8 @@ void test_size_of_a_sample(void)
 	TEST_ASSERT_EQUAL(sizeof(struct f_fx_efx_ncob_ecob), size_of_a_sample(DATA_TYPE_F_FX_EFX_NCOB_ECOB));
 	TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_F_CAM_IMAGETTE));
 	TEST_ASSERT_EQUAL(sizeof(uint16_t), size_of_a_sample(DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE));
-	/* TODO: TEST_ASSERT_EQUAL(sizeof(struct ), size_of_a_sample(DATA_TYPE_F_CAM_OFFSET)); */
-	/* TODO: TEST_ASSERT_EQUAL(sizeof(struct ), size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND */
+	TEST_ASSERT_EQUAL(sizeof(struct offset), size_of_a_sample(DATA_TYPE_F_CAM_OFFSET));
+	TEST_ASSERT_EQUAL(sizeof(struct background), size_of_a_sample(DATA_TYPE_F_CAM_BACKGROUND));
 }
 
 
@@ -191,7 +185,7 @@ void test_cmp_input_big_to_cpu_endianness(void)
 	{
 		struct {
 			uint8_t hdr[MULTI_ENTRY_HDR_SIZE];
-			struct nc_offset entry[2];
+			struct offset entry[2];
 		} __attribute__((packed)) data = {0};
 
 		data_type = DATA_TYPE_OFFSET;
@@ -202,11 +196,20 @@ void test_cmp_input_big_to_cpu_endianness(void)
 		data.entry[1].variance = 0x0C0D0E0F;
 
 		check_endianness(&data, sizeof(data), data_type);
+
+		data_type = DATA_TYPE_F_CAM_OFFSET;
+
+		data.entry[0].mean     = 0x00010203;
+		data.entry[0].variance = 0x04050607;
+		data.entry[1].mean     = 0x08090A0B;
+		data.entry[1].variance = 0x0C0D0E0F;
+
+		check_endianness(&data, sizeof(data), data_type);
 	}
 	{
 		struct {
 			uint8_t hdr[MULTI_ENTRY_HDR_SIZE];
-			struct nc_background entry[2];
+			struct background entry[2];
 		} __attribute__((packed)) data = {0};
 
 		data_type = DATA_TYPE_BACKGROUND;
@@ -219,6 +222,17 @@ void test_cmp_input_big_to_cpu_endianness(void)
 		data.entry[1].outlier_pixels = 0x1213;
 
 		check_endianness(&data, sizeof(data), data_type);
+
+		data_type = DATA_TYPE_F_CAM_BACKGROUND;
+
+		data.entry[0].mean           = 0x00010203;
+		data.entry[0].variance       = 0x04050607;
+		data.entry[0].outlier_pixels = 0x0809;
+		data.entry[1].mean           = 0x0A0B0C0D;
+		data.entry[1].variance       = 0x0E0F1011;
+		data.entry[1].outlier_pixels = 0x1213;
+
+		check_endianness(&data, sizeof(data), data_type);
 	}
 	{
 		struct {
diff --git a/test/cmp_decmp/test_cmp_decmp.c b/test/cmp_decmp/test_cmp_decmp.c
index da53450..e2c0d24 100644
--- a/test/cmp_decmp/test_cmp_decmp.c
+++ b/test/cmp_decmp/test_cmp_decmp.c
@@ -76,8 +76,8 @@ static void gen_ima_data(uint16_t *data, uint32_t samples, const struct cmp_max_
 }
 
 
-static void gen_offset_data(struct nc_offset *data, uint32_t samples,
-			    const struct cmp_max_used_bits *max_used_bits)
+static void gen_nc_offset_data(struct offset *data, uint32_t samples,
+			       const struct cmp_max_used_bits *max_used_bits)
 {
 	uint32_t i;
 
@@ -88,7 +88,19 @@ static void gen_offset_data(struct nc_offset *data, uint32_t samples,
 }
 
 
-static void gen_background_data(struct nc_background *data, uint32_t samples,
+static void gen_fc_offset_data(struct offset *data, uint32_t samples,
+			       const struct cmp_max_used_bits *max_used_bits)
+{
+	uint32_t i;
+
+	for (i = 0; i < samples; i++) {
+		data[i].mean = cmp_rand_nbits(max_used_bits->fc_offset_mean);
+		data[i].variance = cmp_rand_nbits(max_used_bits->fc_offset_variance);
+	}
+}
+
+
+static void gen_nc_background_data(struct background *data, uint32_t samples,
 				const struct cmp_max_used_bits *max_used_bits)
 {
 	uint32_t i;
@@ -101,6 +113,19 @@ static void gen_background_data(struct nc_background *data, uint32_t samples,
 }
 
 
+static void gen_fc_background_data(struct background *data, uint32_t samples,
+				const struct cmp_max_used_bits *max_used_bits)
+{
+	uint32_t i;
+
+	for (i = 0; i < samples; i++) {
+		data[i].mean = cmp_rand_nbits(max_used_bits->fc_background_mean);
+		data[i].variance = cmp_rand_nbits(max_used_bits->fc_background_variance);
+		data[i].outlier_pixels = (__typeof__(data[i].outlier_pixels))cmp_rand_nbits(max_used_bits->fc_background_outlier_pixels);
+	}
+}
+
+
 static void gen_smearing_data(struct smearing *data, uint32_t samples,
 			      const struct cmp_max_used_bits *max_used_bits)
 {
@@ -326,10 +351,10 @@ void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type,
 		gen_ima_data(data, samples, max_used_bits);
 		break;
 	case DATA_TYPE_OFFSET:
-		gen_offset_data(data, samples, max_used_bits);
+		gen_nc_offset_data(data, samples, max_used_bits);
 		break;
 	case DATA_TYPE_BACKGROUND:
-		gen_background_data(data, samples, max_used_bits);
+		gen_nc_background_data(data, samples, max_used_bits);
 		break;
 	case DATA_TYPE_SMEARING:
 		gen_smearing_data(data, samples, max_used_bits);
@@ -370,8 +395,12 @@ void *generate_random_test_data(uint32_t samples, enum cmp_data_type data_type,
 	case DATA_TYPE_F_FX_EFX_NCOB_ECOB:
 		gen_f_fx_efx_ncob_ecob_data(data, samples, max_used_bits);
 		break;
-	case DATA_TYPE_F_CAM_OFFSET: /* TODO: implement this */
-	case DATA_TYPE_F_CAM_BACKGROUND: /* TODO: implement this */
+	case DATA_TYPE_F_CAM_OFFSET:
+		gen_fc_offset_data(data, samples, max_used_bits);
+		break;
+	case DATA_TYPE_F_CAM_BACKGROUND:
+		gen_fc_background_data(data, samples, max_used_bits);
+		break;
 	default:
 		TEST_FAIL();
 	}
@@ -540,8 +569,7 @@ void test_random_compression_decompression(void)
 	struct cmp_cfg cfg;
 	uint32_t cmp_buffer_size;
 
-	/* TODO: extend test for DATA_TYPE_F_CAM_BACKGROUND, DATA_TYPE_F_CAM_OFFSET  */
-	for (data_type = 1; data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; data_type++) {
+	for (data_type = 1; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) {
 		/* printf("%s\n", data_type2string(data_type)); */
 		/* generate random data*/
 		uint32_t samples = cmp_rand_between(1, 430179/CMP_BUFFER_FAKTOR);
diff --git a/test/cmp_entity/test_cmp_entity.c b/test/cmp_entity/test_cmp_entity.c
index 8f3f4cc..8694949 100644
--- a/test/cmp_entity/test_cmp_entity.c
+++ b/test/cmp_entity/test_cmp_entity.c
@@ -45,9 +45,7 @@ void test_cmp_ent_cal_hdr_size(void)
 
 	/* raw_mode test */
 	raw_mode_flag = 1;
-	/*TODO: implement: DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */
-	/* for (data_type = DATA_TYPE_IMAGETTE; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) { */
-	for (data_type = DATA_TYPE_IMAGETTE; data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE; data_type++) {
+	for (data_type = DATA_TYPE_IMAGETTE; data_type <= DATA_TYPE_F_CAM_BACKGROUND; data_type++) {
 		hdr_size = cmp_ent_cal_hdr_size(data_type, raw_mode_flag);
 		TEST_ASSERT_EQUAL_INT(GENERIC_HEADER_SIZE, hdr_size);
 
@@ -1295,14 +1293,14 @@ void test_ent_non_ima_cmp_par6(void)
 
 void test_cmp_ent_get_data_buf(void)
 {
-	enum cmp_data_type data_type;/*TODO: implement: DATA_TYPE_F_CAM_OFFSET, DATA_TYPE_F_CAM_BACKGROUND */
+	enum cmp_data_type data_type;
 	struct cmp_entity ent = {0};
 	char *adr;
 	uint32_t s, hdr_size;
 	int error;
 
 	for (data_type = DATA_TYPE_IMAGETTE;
-	     data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE;
+	     data_type <= DATA_TYPE_F_CAM_BACKGROUND;
 	     data_type++) {
 		s = cmp_ent_create(&ent, data_type, 0, 0);
 		TEST_ASSERT_NOT_EQUAL_INT(0, s);
@@ -1316,7 +1314,7 @@ void test_cmp_ent_get_data_buf(void)
 
 	/* RAW mode test */
 	for (data_type = DATA_TYPE_IMAGETTE;
-	     data_type <= DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE;
+	     data_type <= DATA_TYPE_F_CAM_BACKGROUND;
 	     data_type++) {
 		s = cmp_ent_create(&ent, data_type, 1, 0);
 		TEST_ASSERT_NOT_EQUAL_INT(0, s);
diff --git a/test/cmp_icu/test_cmp_icu.c b/test/cmp_icu/test_cmp_icu.c
index a51de9c..b0bf2e1 100644
--- a/test/cmp_icu/test_cmp_icu.c
+++ b/test/cmp_icu/test_cmp_icu.c
@@ -68,9 +68,7 @@ void test_cmp_cfg_icu_create(void)
 	enum cmp_data_type data_type;
 	enum cmp_mode cmp_mode;
 	uint32_t model_value, lossy_par;
-	/* TODO: change that when DATA_TYPE_BACKGROUND and
-	 * DATA_TYPE_F_CAM_BACKGROUND are implemented */
-	const enum cmp_data_type biggest_data_type = DATA_TYPE_F_CAM_IMAGETTE_ADAPTIVE;
+	const enum cmp_data_type biggest_data_type = DATA_TYPE_F_CAM_BACKGROUND;
 
 	/* wrong data type tests */
 	data_type = DATA_TYPE_UNKNOWN; /* not valid data type */
@@ -1089,9 +1087,9 @@ void test_cmp_cfg_aux(void)
 				    cmp_par_pixels_error, spillover_pixels_error);
 		if (data_type == DATA_TYPE_OFFSET ||
 		    data_type == DATA_TYPE_BACKGROUND ||
-		    data_type == DATA_TYPE_SMEARING
-		    /* data_type == DATA_TYPE_F_CAM_OFFSET || */
-		    /* data_type == DATA_TYPE_F_CAM_BACKGROUND */
+		    data_type == DATA_TYPE_SMEARING ||
+		    data_type == DATA_TYPE_F_CAM_OFFSET ||
+		    data_type == DATA_TYPE_F_CAM_BACKGROUND
 		    ) {
 			TEST_ASSERT_FALSE(error);
 			TEST_ASSERT_EQUAL_INT(data_type, cfg.data_type);
@@ -3948,10 +3946,10 @@ void test_compress_nc_offset_error_cases(void)
 	uint32_t spillover_mean = 2;
 	uint32_t cmp_par_variance = MAX_NON_IMA_GOLOMB_PAR;
 	uint32_t spillover_variance = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR);
-	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct nc_offset)] = {0};
-	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct nc_offset)] = {0};
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct offset)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct offset)] = {0};
 	struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE;
-	struct nc_offset *data_p = (struct nc_offset *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+	struct offset *data_p = (struct offset *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
 
 	cfg = cmp_cfg_icu_create(DATA_TYPE_OFFSET, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS);
 	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
@@ -4009,10 +4007,10 @@ void test_compress_nc_background_error_cases(void)
 	uint32_t spillover_variance = cmp_icu_max_spill(MAX_NON_IMA_GOLOMB_PAR);
 	uint32_t cmp_par_pixels_error = 23;
 	uint32_t spillover_pixels_error = 42;
-	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct nc_background)] = {0};
-	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct nc_background)] = {0};
+	uint8_t data_to_compress[MULTI_ENTRY_HDR_SIZE+3*sizeof(struct background)] = {0};
+	uint8_t compressed_data[MULTI_ENTRY_HDR_SIZE+1*sizeof(struct background)] = {0};
 	struct cmp_max_used_bits my_max_used_bits = MAX_USED_BITS_SAFE;
-	struct nc_background *data_p = (struct nc_background *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
+	struct background *data_p = (struct background *)&data_to_compress[MULTI_ENTRY_HDR_SIZE];
 
 	cfg = cmp_cfg_icu_create(DATA_TYPE_BACKGROUND, CMP_MODE_DIFF_MULTI, 0, CMP_LOSSLESS);
 	TEST_ASSERT(cfg.data_type != DATA_TYPE_UNKNOWN);
-- 
GitLab