Ticket #188: rt_hasnodata.patch

File rt_hasnodata.patch, 16.8 KB (added by dzwarg, 2 years ago)

Implementation of hasnodata flag in the c api.

  • test/core/testwkb.c

     
    165165"0A000000"         /* SRID (int32 10) */ 
    166166"0100"             /* width (uint16 1) */ 
    167167"0100"             /* height (uint16 1) */ 
    168 "00"               /* First band type (1BB, in memory) */ 
     168"40"               /* First band type (1BB, in memory, hasnodata) */ 
    169169"00"               /* nodata value (0) */ 
    170170"01"               /* pix(0,0) == 1 */ 
    171171    ; 
     
    187187        CHECK(band); 
    188188        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_1BB); 
    189189        CHECK(!rt_band_is_offline(ctx, band)); 
     190        CHECK(rt_band_get_hasnodata_flag(ctx, band)); 
    190191        CHECK_EQUALS(rt_band_get_nodata(ctx, band), 0); 
    191192        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), 1); 
    192193    } 
     
    219220"0A000000"         /* SRID (int32 10) */ 
    220221"0300"             /* width (uint16 3) */ 
    221222"0200"             /* height (uint16 2) */ 
    222 "03"               /* First band type (8BSI, in memory) */ 
     223"43"               /* First band type (8BSI, in memory, hasnodata) */ 
    223224"FF"               /* nodata value (-1) */ 
    224225"FF"               /* pix(0,0) == -1 */ 
    225226"00"               /* pix(1,0) ==  0 */ 
     
    246247        CHECK(band); 
    247248        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_8BSI); 
    248249        CHECK(!rt_band_is_offline(ctx, band)); 
     250        CHECK(rt_band_get_hasnodata_flag(ctx,band)); 
    249251        CHECK_EQUALS(rt_band_get_nodata(ctx, band), -1); 
    250252        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), -1); 
    251253        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 0); 
     
    323325        CHECK(band); 
    324326        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_16BSI); 
    325327        CHECK(!rt_band_is_offline(ctx, band)); 
     328        CHECK(!rt_band_get_hasnodata_flag(ctx, band)); 
    326329        CHECK_EQUALS(rt_band_get_nodata(ctx, band), -1); 
    327330        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), -1); 
    328331        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 0); 
     
    387390        CHECK(band); 
    388391        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_16BSI); 
    389392        CHECK(!rt_band_is_offline(ctx, band)); 
     393        CHECK(!rt_band_get_hasnodata_flag(ctx,band)); 
    390394        CHECK_EQUALS(rt_band_get_nodata(ctx, band), -1); 
    391395        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), -1); 
    392396        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 0); 
     
    424428"0000000A"         /* SRID (int32 10) */ 
    425429"0003"             /* width (uint16 3) */ 
    426430"0002"             /* height (uint16 2) */ 
    427 "85"               /* First band type (16BSI, on disk) */ 
     431"C5"               /* First band type (16BSI, on disk, hasnodata) */ 
    428432"FFFF"             /* nodata value (-1) */ 
    429433"03"               /* ext band num == 3 */ 
    430434/* ext band path == /tmp/t.tif */ 
     
    448452        CHECK(band); 
    449453        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_16BSI); 
    450454        CHECK(rt_band_is_offline(ctx, band)); 
     455        CHECK(rt_band_get_hasnodata_flag(ctx,band)); 
    451456        CHECK_EQUALS(rt_band_get_nodata(ctx, band), -1); 
    452457        printf("ext band path: %s\n", rt_band_get_ext_path(ctx, band)); 
    453458        printf("ext band  num: %u\n", rt_band_get_ext_band_num(ctx, band)); 
     
    483488"FFFFFFFF"         /* SRID (int32 -1) */ 
    484489"0300"             /* width (uint16 3) */ 
    485490"0100"             /* height (uint16 1) */ 
    486 "05"               /* First band type (16BSI, in memory) */ 
     491"45"               /* First band type (16BSI, in memory, hasnodata) */ 
    487492"0100"             /* nodata value (1) */ 
    488493"0100"             /* pix(0,0) == 1 */ 
    489494"B401"             /* pix(1,0) == 436 */ 
     
    507512        CHECK(band); 
    508513        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_16BSI); 
    509514        CHECK(!rt_band_is_offline(ctx, band)); 
     515        CHECK(rt_band_get_hasnodata_flag(ctx,band)); 
    510516        CHECK_EQUALS(rt_band_get_nodata(ctx, band), 1); 
    511517        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), 1); 
    512518        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 436); 
     
    561567"FFFFFFFF"          /* srid (int32 -1) */ 
    562568"0500"              /* width (uint16 5) */ 
    563569"0500"              /* height (uint16 5) */ 
    564 "04"                /* 1st band pixel type (8BUI, in memory) */ 
     570"44"                /* 1st band pixel type (8BUI, in memory, hasnodata) */ 
    565571"00"                /* 1st band nodata 0 */ 
    566572"FDFEFDFEFEFDFEFEFDF9FAFEFEFCF9FBFDFEFEFDFCFAFEFEFE" /* 1st band pixels */ 
    567 "04"                /* 2nd band pixel type (8BUI, in memory) */ 
     573"44"                /* 2nd band pixel type (8BUI, in memory, hasnodata) */ 
    568574"00"                /* 2nd band nodata 0 */ 
    569575"4E627AADD16076B4F9FE6370A9F5FE59637AB0E54F58617087" /* 2nd band pixels */ 
    570 "04"                /* 3rd band pixel type (8BUI, in memory) */ 
     576"44"                /* 3rd band pixel type (8BUI, in memory, hasnodata) */ 
    571577"00"                /* 3rd band nodata 0 */ 
    572578"46566487A1506CA2E3FA5A6CAFFBFE4D566DA4CB3E454C5665" /* 3rd band pixels */ 
    573579; 
     
    590596        CHECK(band); 
    591597        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_8BUI); 
    592598        CHECK(!rt_band_is_offline(ctx, band)); 
     599        CHECK(rt_band_get_hasnodata_flag(ctx,band)); 
    593600        CHECK_EQUALS(rt_band_get_nodata(ctx, band), 0); 
    594601        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), 253); 
    595602        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 254); 
     
    604611        CHECK(band); 
    605612        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_8BUI); 
    606613        CHECK(!rt_band_is_offline(ctx, band)); 
     614        CHECK(rt_band_get_hasnodata_flag(ctx,band)); 
    607615        CHECK_EQUALS(rt_band_get_nodata(ctx, band), 0); 
    608616        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), 78); 
    609617        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 98); 
     
    618626        CHECK(band); 
    619627        CHECK_EQUALS(rt_band_get_pixtype(ctx, band), PT_8BUI); 
    620628        CHECK(!rt_band_is_offline(ctx, band)); 
     629        CHECK(rt_band_get_hasnodata_flag(ctx,band)); 
    621630        CHECK_EQUALS(rt_band_get_nodata(ctx, band), 0); 
    622631        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 0, 0), 70); 
    623632        CHECK_EQUALS(rt_band_get_pixel(ctx, band, 1, 0), 86); 
  • test/core/testapi.c

     
    2626    mem = malloc(datasize); 
    2727 
    2828    rt_band band = rt_band_new_inline(ctx, width, height, 
    29                                       pixtype, 0, mem); 
     29                                      pixtype, 1, 0, mem); 
    3030    assert(band); 
    3131    bandNum = rt_raster_add_band(ctx, raster, band); 
    3232    assert(bandNum>=0); 
     
    6060    size_t datasize = width * height; 
    6161    rt_raster raster = rt_raster_new(ctx, width, height); 
    6262    void * mem = calloc(datasize, sizeof(void)); 
    63     rt_band band = rt_band_new_inline(ctx, width, height, PT_32BSI, 0, mem); 
     63    rt_band band = rt_band_new_inline(ctx, width, height, PT_32BSI, 1, 0, mem); 
    6464     
    6565    /* Fill raster */ 
    6666    rt_band_set_pixel(ctx, band, 0, 0, 1); 
     
    864864    } 
    865865} 
    866866 
     867static void testBandHasNoData(rt_context ctx, rt_band band) 
     868{ 
     869    int flag; 
     870    int failure; 
     871 
     872    flag = rt_band_get_hasnodata_flag(ctx, band); 
     873    CHECK_EQUALS(flag, 1); 
     874 
     875    rt_band_set_hasnodata_flag(ctx, band, 0); 
     876    flag = rt_band_get_hasnodata_flag(ctx, band); 
     877    CHECK_EQUALS(flag, 0); 
     878 
     879    rt_band_set_hasnodata_flag(ctx, band, 10); 
     880    flag = rt_band_get_hasnodata_flag(ctx, band); 
     881    CHECK_EQUALS(flag, 1); 
     882 
     883    rt_band_set_hasnodata_flag(ctx, band, -10); 
     884    flag = rt_band_get_hasnodata_flag(ctx, band); 
     885    CHECK_EQUALS(flag, 1); 
     886} 
     887 
    867888int 
    868889main() 
    869890{ 
     
    11011122    band_64BF = addBand(ctx, raster, PT_64BF); 
    11021123    testBand64BF(ctx, band_64BF); 
    11031124 
     1125    printf("Testing band hasnodata flag\n"); 
     1126    testBandHasNoData(ctx, band_64BF); 
     1127 
    11041128    deepRelease(ctx, raster); 
    11051129    rt_context_destroy(ctx); 
    11061130 
  • rt_core/rt_api.c

     
    367367    int32_t offline; 
    368368    uint16_t width; 
    369369    uint16_t height; 
     370    int32_t hasnodata; /* a flag indicating if this band contains nodata values */ 
    370371    double nodataval; /* int will be converted ... */ 
    371372    int32_t ownsData; /* XXX mloskot: its behaviour needs to be documented */ 
    372373    union { 
     
    378379 
    379380rt_band 
    380381rt_band_new_inline(rt_context ctx, uint16_t width, uint16_t height, 
    381                    rt_pixtype pixtype, double nodataval, uint8_t* data) 
     382                   rt_pixtype pixtype, uint32_t hasnodata, double nodataval,  
     383                   uint8_t* data) 
    382384{ 
    383385    rt_band band = NULL; 
    384386 
     
    401403    band->offline = 0; 
    402404    band->width = width; 
    403405    band->height = height; 
     406    band->hasnodata = hasnodata; 
    404407    band->nodataval = nodataval; 
    405408    band->data.mem = data; 
    406409    band->ownsData = 0; 
     
    410413 
    411414rt_band 
    412415rt_band_new_offline(rt_context ctx, uint16_t width, uint16_t height, 
    413                     rt_pixtype pixtype, double nodataval, uint8_t bandNum, 
    414                     const char* path) 
     416                    rt_pixtype pixtype, uint32_t hasnodata, double nodataval,  
     417                    uint8_t bandNum, const char* path) 
    415418{ 
    416419    rt_band band = NULL; 
    417420 
     
    434437    band->offline = 1; 
    435438    band->width = width; 
    436439    band->height = height; 
     440    band->hasnodata = hasnodata; 
    437441    band->nodataval = nodataval; 
    438442    band->data.offline.bandNum = bandNum; 
    439443 
     
    469473 
    470474    /* band->data content is externally owned */ 
    471475    /* XXX jorgearevalo: not really... rt_band_from_wkb allocates memory for 
    472      * data.mem 
     476     * data.me 
    473477     */ 
    474478    ctx->dealloc(band); 
    475479} 
     
    611615#endif /* OPTIMIZE_SPACE */ 
    612616 
    613617int 
     618rt_band_get_hasnodata_flag(rt_context ctx, rt_band band) 
     619{ 
     620    assert(NULL != ctx); 
     621    assert(NULL != band); 
     622 
     623    return band->hasnodata;     
     624} 
     625 
     626void 
     627rt_band_set_hasnodata_flag(rt_context ctx, rt_band band, int flag) 
     628{ 
     629    assert(NULL != ctx); 
     630    assert(NULL != band); 
     631 
     632    band->hasnodata = (flag) ? 1 : 0; 
     633} 
     634 
     635int 
    614636rt_band_set_nodata(rt_context ctx, rt_band band, double val) 
    615637{ 
    616638    rt_pixtype pixtype = PT_END; 
     
    691713            break; 
    692714        default: 
    693715            ctx->err("Unknown pixeltype %d", pixtype); 
     716            band->hasnodata = 0; 
    694717            return -1; 
    695718    } 
    696719 
     720    // the NODATA value was just set, so this band has NODATA 
     721    rt_band_set_hasnodata_flag(ctx, band, 1); 
     722 
    697723    if ( fabs(band->nodataval - val) > 0.0001 ) 
    698724    { 
    699725#ifdef RT_WARN_ON_TRUNCATION 
     
    952978    assert(NULL != ctx); 
    953979    assert(NULL != band); 
    954980 
    955     return band->nodataval; 
     981    if (!band->hasnodata) 
     982        ctx->warn("Getting NODATA value for a band without NODATA values. Using %d", band->nodataval); 
     983 
     984    return band->nodataval;     
    956985} 
    957986 
    958987 
     
    20202049#define BANDTYPE_FLAGS_MASK 0xF0 
    20212050#define BANDTYPE_PIXTYPE_MASK 0x0F 
    20222051#define BANDTYPE_FLAG_OFFDB     (1<<7) 
    2023 #define BANDTYPE_FLAG_RESERVED1 (1<<6) 
     2052#define BANDTYPE_FLAG_HASNODATA (1<<6) 
    20242053#define BANDTYPE_FLAG_RESERVED2 (1<<5) 
    20252054#define BANDTYPE_FLAG_RESERVED3 (1<<4) 
    20262055 
    20272056#define BANDTYPE_PIXTYPE(x) ((x)&BANDTYPE_PIXTYPE_MASK) 
    20282057#define BANDTYPE_IS_OFFDB(x) ((x)&BANDTYPE_FLAG_OFFDB) 
     2058#define BANDTYPE_HAS_NODATA(x) ((x)&BANDTYPE_FLAG_HASNODATA) 
    20292059 
    20302060/* Read band from WKB as at start of band */ 
    20312061static rt_band 
     
    20672097 
    20682098    band->pixtype = type & BANDTYPE_PIXTYPE_MASK; 
    20692099    band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; 
     2100    band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1 : 0; 
    20702101    band->width = width; 
    20712102    band->height = height; 
    20722103 
    20732104#ifdef RT_API_DEBUG 
    2074     ctx->info(" Band pixtype:%s, offline:%d", 
     2105    ctx->info(" Band pixtype:%s, offline:%d, hasnodata:%d", 
    20752106                rt_pixtype_name(ctx, band->pixtype), 
    2076                 band->offline); 
     2107                band->offline, 
     2108                band->hasnodata); 
    20772109#endif 
    20782110 
    20792111    /* Check there's enough bytes to read nodata value */ 
     
    25912623        /* Add band type */ 
    25922624        *ptr = band->pixtype; 
    25932625        if ( band->offline ) *ptr |= BANDTYPE_FLAG_OFFDB; 
     2626        if ( band->hasnodata ) *ptr |= BANDTYPE_FLAG_HASNODATA; 
    25942627        ptr += 1; 
    25952628 
    25962629#if 0 // no padding required for WKB 
     
    27652798        int pixbytes = rt_pixtype_size(ctx, pixtype); 
    27662799 
    27672800        if ( pixbytes < 1 ) { 
    2768             ctx->err("Corrupted band: unkonwn pixtype"); 
     2801            ctx->err("Corrupted band: unknown pixtype"); 
    27692802            return 0; 
    27702803        } 
    27712804 
    2772         /* Add space for band type and data padding */ 
     2805        /* Add space for band type, hasnodata flag and data padding */ 
    27732806        size += pixbytes; 
    27742807 
    27752808        /* Add space for nodata value */ 
     
    28722905 
    28732906        /* Add band type */ 
    28742907        *ptr = band->pixtype; 
    2875         if ( band->offline ) 
    2876         { 
    2877             *ptr |= BANDTYPE_FLAG_OFFDB; 
    2878         } 
     2908        if ( band->offline ) { *ptr |= BANDTYPE_FLAG_OFFDB; } 
     2909        if ( band->hasnodata ) { *ptr |= BANDTYPE_FLAG_HASNODATA; } 
    28792910 
    28802911#ifdef RT_API_DEBUG 
    28812912        d_print_binary_hex(ctx, "PIXTYPE", dbg_ptr, size); 
     
    30683099#endif 
    30693100 
    30703101        band->offline = BANDTYPE_IS_OFFDB(type) ? 1 : 0; 
     3102        band->hasnodata = BANDTYPE_HAS_NODATA(type) ? 1: 0; 
    30713103        band->width = rast->width; 
    30723104        band->height = rast->height; 
    30733105        band->ownsData = 0; 
     
    31443176        } 
    31453177 
    31463178#ifdef RT_API_DEBUG 
     3179        ctx->info(" Has NODATA flag %d", band-hasnodata); 
    31473180        ctx->info(" NODATA value %d", band->nodataval); 
    31483181#endif 
    31493182        /* Consistency checking (ptr is pixbytes-aligned) */ 
  • rt_core/rt_api.h

     
    126126 */ 
    127127rt_band rt_band_new_inline(rt_context ctx, 
    128128                           uint16_t width, uint16_t height, 
    129                            rt_pixtype pixtype, double nodataval, 
    130                            uint8_t* data); 
     129                           rt_pixtype pixtype, uint32_t hasnodata, 
     130                           double nodataval, uint8_t* data); 
    131131 
    132132/** 
    133133 * Create an on-disk rt_band 
     
    150150 */ 
    151151rt_band rt_band_new_offline(rt_context ctx, 
    152152                            uint16_t width, uint16_t height, 
    153                             rt_pixtype pixtype, double nodataval, 
    154                             uint8_t bandNum, const char* path); 
     153                            rt_pixtype pixtype, uint32_t hasnodata, 
     154                            double nodataval, uint8_t bandNum, const char* path); 
    155155 
    156156/** 
    157157 * Return non-zero if the given band data is on 
     
    195195/* Destroy a raster band */ 
    196196void rt_band_destroy(rt_context ctx, rt_band band); 
    197197 
    198 /* Set nodata value 
     198/** 
     199 * Get hasnodata flag value 
    199200 * @param ctx : context, for thread safety 
     201 * @param band : the band on which to check the hasnodata flag 
     202 * @return the hasnodata flag. 
     203 */ 
     204int rt_band_get_hasnodata_flag(rt_context ctx, rt_band band); 
     205 
     206/** 
     207 * Set hasnodata flag value 
     208 * @param ctx : context, for thread safety 
     209 * @param band : the band on which to set the hasnodata flag 
     210 * @param flag : the new hasnodata flag value. Must be 1 or 0. 
     211 */ 
     212void rt_band_set_hasnodata_flag(rt_context ctx, rt_band band, int flag); 
     213 
     214/** 
     215 * Set nodata value 
     216 * @param ctx : context, for thread safety 
    200217 * @param band : the band to set nodata value to 
    201218 * @param val : the nodata value, must be in the range 
    202219 *              of values supported by this band's pixeltype 
     
    208225 */ 
    209226int rt_band_set_nodata(rt_context ctx, rt_band band, double val); 
    210227 
    211 /* Get nodata value 
     228/** 
     229 * Get nodata value 
    212230 * @param ctx : context, for thread safety 
    213231 * @param band : the band to set nodata value to 
    214232 * @return nodata value 
    215233 */ 
    216234double rt_band_get_nodata(rt_context ctx, rt_band band); 
    217235 
    218 /* Set pixel value 
     236/** 
     237 * Set pixel value 
    219238 * @param ctx : context, for thread safety 
    220239 * @param band : the band to set nodata value to 
    221240 * @param x : x ordinate 
     
    230249int rt_band_set_pixel(rt_context ctx, rt_band band, 
    231250                      uint16_t x, uint16_t y, double val); 
    232251 
    233 /* Get pixel value 
     252/** 
     253 * Get pixel value 
    234254 * 
    235255 * @param ctx : context, for thread safety 
    236256 * @param band : the band to set nodata value to 
  • doc/RFC1-SerializedFormat

     
    113113 
    114114 There are currently 12 supported pixel value types, so 4 
    115115 bits are enough to account for all. We'll reserve 
    116  the upper 4 bits for generic flags (might eventually add 
    117  hasnodatavalues or others) and define upmost as storage flag: 
     116 the upper 4 bits for generic flags and define upmost as 
     117 storage flag: 
    118118  
    119119 #define BANDTYPE_FLAGS_MASK 0xF0 
    120120 #define BANDTYPE_PIXTYPE_MASK 0x0F 
    121121 
    122122 #define BANDTYPE_FLAG_OFFDB     (1<<7) 
    123  #define BANDTYPE_FLAG_RESERVED1 (1<<6) 
     123 #define BANDTYPE_FLAG_HASNODATA (1<<6) 
    124124 #define BANDTYPE_FLAG_RESERVED2 (1<<5) 
    125125 #define BANDTYPE_FLAG_RESERVED3 (1<<4) 
    126126