From bf4018f5bd93efb78c7cd518991709a5b80636c1 Mon Sep 17 00:00:00 2001 From: Shahram Najm Date: Wed, 22 Jun 2022 14:44:20 +0100 Subject: [PATCH] ECC-1414: GRIB: Nearest neighbour does not work for PNG packing --- src/grib_accessor_class_data_png_packing.c | 96 ++++++++++++++++++++-- tests/grib_png.sh | 17 +++- 2 files changed, 103 insertions(+), 10 deletions(-) diff --git a/src/grib_accessor_class_data_png_packing.c b/src/grib_accessor_class_data_png_packing.c index ce4c872a7..3444893db 100644 --- a/src/grib_accessor_class_data_png_packing.c +++ b/src/grib_accessor_class_data_png_packing.c @@ -21,6 +21,7 @@ IMPLEMENTS = unpack_double IMPLEMENTS = pack_double IMPLEMENTS = value_count + IMPLEMENTS = unpack_double_element;unpack_double_element_set MEMBERS=const char* number_of_values MEMBERS=const char* reference_value MEMBERS=const char* binary_scale_factor @@ -51,6 +52,8 @@ static int unpack_double(grib_accessor*, double* val, size_t* len); static int value_count(grib_accessor*, long*); static void init(grib_accessor*, const long, grib_arguments*); static void init_class(grib_accessor_class*); +static int unpack_double_element(grib_accessor*, size_t i, double* val); +static int unpack_double_element_set(grib_accessor*, const size_t* index_array, size_t len, double* val_array); typedef struct grib_accessor_data_png_packing { @@ -114,8 +117,8 @@ static grib_accessor_class _grib_accessor_class_data_png_packing = { 0, /* nearest_smaller_value */ 0, /* next accessor */ 0, /* compare vs. another accessor */ - 0, /* unpack only ith value */ - 0, /* unpack a given set of elements */ + &unpack_double_element, /* unpack only ith value */ + &unpack_double_element_set, /* unpack a given set of elements */ 0, /* unpack a subarray */ 0, /* clear */ 0, /* clone accessor */ @@ -152,8 +155,6 @@ static void init_class(grib_accessor_class* c) c->nearest_smaller_value = (*(c->super))->nearest_smaller_value; c->next = (*(c->super))->next; c->compare = (*(c->super))->compare; - c->unpack_double_element = (*(c->super))->unpack_double_element; - c->unpack_double_element_set = (*(c->super))->unpack_double_element_set; c->unpack_double_subarray = (*(c->super))->unpack_double_subarray; c->clear = (*(c->super))->clear; c->make_clone = (*(c->super))->make_clone; @@ -219,7 +220,6 @@ static void png_flush_callback(png_structp png) /* Empty */ } - static int unpack_double(grib_accessor* a, double* val, size_t* len) { grib_accessor_data_png_packing* self = (grib_accessor_data_png_packing*)a; @@ -324,7 +324,6 @@ static int unpack_double(grib_accessor* a, double* val, size_t* len) Assert(callback_data.offset == callback_data.length); - rows = png_get_rows(png, info); png_get_IHDR(png, info, @@ -432,14 +431,13 @@ static int pack_double(grib_accessor* a, const double* val, size_t* len) return err; /* Special case */ - if (*len == 0) { grib_buffer_replace(a, NULL, 0, 1, 1); return GRIB_SUCCESS; } is_constant_field = is_constant(val, n_vals); - if (!is_constant_field && bits_per_value==0) { + if (!is_constant_field && bits_per_value == 0) { /* A non-constant field with bitsPerValue==0! */ bits_per_value = 24; /* Set sane value */ } @@ -660,6 +658,88 @@ cleanup: return err; } + +static int unpack_double_element(grib_accessor* a, size_t idx, double* val) +{ + /* The index idx relates to codedValues NOT values! */ + grib_accessor_data_png_packing* self = (grib_accessor_data_png_packing*)a; + grib_handle* hand = grib_handle_of_accessor(a); + int err = 0; + size_t size = 0; + double reference_value = 0; + long bits_per_value = 0; + double* values = NULL; + + if ((err = grib_get_long_internal(hand, self->bits_per_value, &bits_per_value)) != GRIB_SUCCESS) + return err; + if ((err = grib_get_double_internal(hand, self->reference_value, &reference_value)) != GRIB_SUCCESS) + return err; + + /* Special case of constant field */ + if (bits_per_value == 0) { + *val = reference_value; + return GRIB_SUCCESS; + } + err = grib_get_size(hand, "codedValues", &size); + if (err) return err; + if (idx > size) return GRIB_INVALID_ARGUMENT; + + values = (double*)grib_context_malloc_clear(a->context, size * sizeof(double)); + err = grib_get_double_array(hand, "codedValues", values, &size); + if (err) { + grib_context_free(a->context, values); + return err; + } + *val = values[idx]; + grib_context_free(a->context, values); + return GRIB_SUCCESS; +} + +static int unpack_double_element_set(grib_accessor* a, const size_t* index_array, size_t len, double* val_array) +{ + /* The index idx relates to codedValues NOT values! */ + grib_accessor_data_png_packing* self = (grib_accessor_data_png_packing*)a; + grib_handle* hand = grib_handle_of_accessor(a); + int err = 0; + size_t size = 0, i = 0; + double reference_value = 0; + long bits_per_value = 0; + double* values = NULL; + + if ((err = grib_get_long_internal(hand, self->bits_per_value, &bits_per_value)) != GRIB_SUCCESS) + return err; + if ((err = grib_get_double_internal(hand, self->reference_value, &reference_value)) != GRIB_SUCCESS) + return err; + + /* Special case of constant field */ + if (bits_per_value == 0) { + for (i = 0; i < len; i++) { + val_array[i] = reference_value; + } + return GRIB_SUCCESS; + } + + err = grib_get_size(grib_handle_of_accessor(a), "codedValues", &size); + if (err) + return err; + + for (i = 0; i < len; i++) { + if (index_array[i] > size) return GRIB_INVALID_ARGUMENT; + } + + values = (double*)grib_context_malloc_clear(a->context, size * sizeof(double)); + err = grib_get_double_array(grib_handle_of_accessor(a), "codedValues", values, &size); + if (err) { + grib_context_free(a->context, values); + return err; + } + for (i = 0; i < len; i++) { + val_array[i] = values[index_array[i]]; + } + grib_context_free(a->context, values); + return GRIB_SUCCESS; +} + #else static int unpack_double(grib_accessor* a, double* val, size_t* len) diff --git a/tests/grib_png.sh b/tests/grib_png.sh index 4fc5c5821..6acf763e9 100755 --- a/tests/grib_png.sh +++ b/tests/grib_png.sh @@ -10,7 +10,6 @@ . ./include.ctest.sh -REDIRECT=/dev/null label="grib_png" temp=${label}".grib.tmp" temp1=${label}".1.tmp" @@ -23,7 +22,7 @@ files=" " if [ $HAVE_JPEG -eq 1 ]; then - files="multi.grib2 v.grib2"$files + files="v.grib2"$files fi # TODO: For the following the PNG packing fails with an assert! @@ -43,7 +42,20 @@ for file in $files; do rm -f $temp $temp1 $temp2 done + +# Nearest neighbour +# ---------------------- +infile=${data_dir}/reduced_gaussian_model_level.grib2 +${tools_dir}/grib_set -r -s packingType=grid_png $infile $temp +${tools_dir}/grib_get -F%.6g -l 48.835,327.600,1 $temp > $temp1 +grep -q "224.455" $temp1 + +${tools_dir}/grib_ls -F%.6g -l 48.835,327.600 $temp > $temp1 +grep -q "Grid Point chosen #4 index=936 " $temp1 + + # Conversion from IEEE to PNG +# ---------------------------- infile=${data_dir}/grid_ieee.grib ${tools_dir}/grib_set -r -s packingType=grid_png $infile $temp # TODO: check results @@ -51,4 +63,5 @@ grib_check_key_equals $temp packingType grid_png grib_check_key_equals $temp accuracy 0 +# Clean up rm -f $temp