diff --git a/include/interfaces/reader/eas3.h b/include/interfaces/reader/eas3.h index 00686f9..266d91c 100644 --- a/include/interfaces/reader/eas3.h +++ b/include/interfaces/reader/eas3.h @@ -347,6 +347,21 @@ || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || || || \************************************************************************************************************/ + /*----------------------------------------------------------------------------------------------------------*\ + ! ! + ! DESCRIPTION: ! + ! ------------ ! + ! This function deallocates the data structure used to store an numerical dataset ! + ! and can be called if an error occurs or once the data is no longer needed is to be closed. ! + ! The deallocation will be carried out down to the structure levels that have been allocated. ! + ! ! + \*----------------------------------------------------------------------------------------------------------*/ + void + eas3_free_data(eas3_data* data); + + uchar + bwc_to_eas3(bwc_stream *const stream, eas3_data *const data); + /*----------------------------------------------------------------------------------------------------------*\ ! FUNCTION NAME: bwc_data* read_eas3(const char* const filename) ! ! -------------- ! diff --git a/include/library/private/codestream.h b/include/library/private/codestream.h index 0445b59..2e022aa 100755 --- a/include/library/private/codestream.h +++ b/include/library/private/codestream.h @@ -100,6 +100,10 @@ size_t assemble_codestream (bwc_codec *const codec, bwc_stream *const stream); //==========|==========================|======================|======|======|===================== + bwc_codec* parse_main_header (bwc_codec *const codec, + bwc_stream *const data, + bitstream *const stream); + //==========|==========================|======================|======|======|===================== bwc_codec* parse_codestream (bwc_codec *const codec, bwc_stream *const stream, uint8 const layer); diff --git a/include/library/private/libbwc.h b/include/library/private/libbwc.h index 5d67736..1afab38 100755 --- a/include/library/private/libbwc.h +++ b/include/library/private/libbwc.h @@ -142,6 +142,10 @@ uint64 const tilesTS, bwc_tile_instr const instr); //==========|==========================|======================|======|=======|==================== + bwc_header* bwc_open_header (void *const inpbuf); + //==========|==========================|======================|======|=======|==================== + void bwc_close_header (bwc_header *const header); + //==========|==========================|======================|======|=======|==================== uchar bwc_create_compression (bwc_codec *const codec, bwc_stream *const data, char *const rate_control); diff --git a/include/library/private/types.h b/include/library/private/types.h index 0320a8e..06b49b6 100755 --- a/include/library/private/types.h +++ b/include/library/private/types.h @@ -659,18 +659,25 @@ bwc_prog_ord progression; // Packet progression order. } bwc_gl_ctrl; - /*----------------------------------------------------------------------------------------------*\ - ! ! - ! DESCRIPTION: ! - ! ------------ ! - ! ! - ! This structure holds all the necessary parameters defining and controling a bwc ! - ! (de-)compression run. ! - ! ! - ! The meter structure is used to store measurements, including important time ! - ! measurements, for a particular compression run. ! - ! ! - \*----------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Structure that is used to probe header information from a compressed data set. + */ +/*================================================================================================*/ + typedef struct + { + bwc_gl_inf info; // Global info structure + bwc_gl_ctrl control; // Global control structure + bwc_span aux; // Auxiliary info. codestream block. + bwc_span com; // Comment codestream block. + } bwc_header; + +/*================================================================================================*/ +/** + * @details Structure holding all the necessary parameters defining and controlling a bwc + * (de-)compression run. + */ +/*================================================================================================*/ typedef struct { bwc_gl_inf info; // Global info structure diff --git a/include/tools/bwccmdl.h b/include/tools/bwccmdl.h deleted file mode 100644 index be53e0b..0000000 --- a/include/tools/bwccmdl.h +++ /dev/null @@ -1,350 +0,0 @@ -/*====================================================================================================================*\ -|| || -|| /$$$$$$$ /$$ /$$ /$$ /$$ || -|| | $$__ $$|__/ | $$ /$ | $$| $$ || -|| | $$ \ $$ /$$ /$$$$$$ | $$ /$$$| $$| $$$$$$$ /$$$$$$ /$$$$$$ /$$$$$$ || -|| | $$$$$$$ | $$ /$$__ $$ | $$/$$ $$ $$| $$__ $$ /$$__ $$ /$$__ $$ /$$__ $$ || -|| | $$__ $$| $$| $$ \ $$ | $$$$_ $$$$| $$ \ $$| $$ \ $$| $$ \ $$| $$ \ $$ || -|| | $$ \ $$| $$| $$ | $$ | $$$/ \ $$$| $$ | $$| $$ | $$| $$ | $$| $$ | $$ || -|| | $$$$$$$/| $$| $$$$$$$ | $$/ \ $$| $$ | $$| $$$$$$/| $$$$$$/| $$$$$$$/ || -|| |_______/ |__/ \____ $$ |__/ \__/|__/ |__/ \______/ \______/ | $$____/ || -|| /$$ \ $$ | $$ || -|| | $$$$$$/ | $$ || -|| \______/ |__/ || -|| || -|| DESCRIPTION: || -|| ------------ || -|| This is a simple command line tool that uses the Big Whoop library to (de)com- || -|| press a 2- to 4-dimensional IEEE 754 floating point array. For further infor- || -|| mation use the --help (-h) argument in the command-line or consult the appro- || -|| priate README file. || -|| || -|| STRUCTS: || -|| -------- || -|| DESCRIPTION NEEDED. || -|| || -|| DEVELOPMENT HISTORY: || -|| -------------------- || -|| || -|| Date Author Change Id Release Description || -|| ---- ------ --------- ------- ----------- || -|| 13.10.2017 Patrick Vogler B87D120 V 0.1.0 source file created || -|| 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 Command line tool refac- || -|| tored. || -|| || -|| || -|| ------------------------------------------------------------------------------------------------------ || -|| || -|| Copyright (c) 2023, High Performance Computing Center - University of Stuttgart || -|| || -|| Redistribution and use in source and binary forms, with or without modification, are permitted || -|| provided that the following conditions are met: || -|| || -|| (1) Redistributions of source code must retain the above copyright notice, this list of || -|| conditions and the following disclaimer. || -|| || -|| (2) Redistributions in binary form must reproduce the above copyright notice, this list || -|| of conditions and the following disclaimer in the documentation and/or other materials || -|| provided with the distribution. || -|| || -|| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED || -|| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A || -|| PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR || -|| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT || -|| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS || -|| INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR || -|| TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF || -|| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. || -|| || -\*====================================================================================================================*/ -#ifndef BWC_CMDL_H -#define BWC_CMDL_H - - /********************************************************************************************************************\ - || _ _ _ ____ _ _ _ ___ ____ || - || | |\ | | | | | | \ |___ || - || | | \| |___ |___ |__| |__/ |___ || - || || - \********************************************************************************************************************/ - #include - - /********************************************************************************************************************\ - || _ _ ____ ____ ____ ____ ____ || - || |\/| |__| | |__/ | | [__ || - || | | | | |___ | \ |__| ___] || - || || - \********************************************************************************************************************/ - /*------------------------------------------------------------------------------------------------------------------*\ - ! DESCRIPTION: ! - ! ------------ ! - ! ! - ! These macros define minimum and maximum operators as well as an operator used ! - ! to evaluate the size of an array. ! - ! ! - ! MACROS: ! - ! ------- ! - ! Name Description ! - ! ---- ----------- ! - ! MAX(x, y) - Returns the maximum value of ! - ! two values. ! - ! ! - ! MIN(x, y) - Returns the minimum value of ! - ! two values. ! - ! ! - ! GET_LEN(x) - Returns the size of an array. ! - ! ! - ! DEVELOPMENT HISTORY: ! - ! -------------------- ! - ! ! - ! Date Author Change Id Release Description ! - ! ---- ------ --------- ------- ----------- ! - ! 21.03.2018 Patrick Vogler B87D120 V 0.1.0 macros created ! - ! 16.09.2019 Patrick Vogler B87E7E4 V 0.1.0 Added GET_LEN(X) macro. ! - ! ! - \*------------------------------------------------------------------------------------------------------------------*/ - #define MAX(x, y) (((x) < (y))?(y):(x)) - #define MIN(x, y) (((x) > (y))?(y):(x)) - - /*------------------------------------------------------------------------------------------------------------------*\ - ! DESCRIPTION: ! - ! ------------ ! - ! ! - ! These Constants define codestream markers used to create the embedded code- ! - ! stream. ! - ! ! - ! MACROS: ! - ! ------- ! - ! Name Description ! - ! ---- ----------- ! - ! SOC - Start of code-stream ! - ! SGI - Global data-set information ! - ! SGC - Global control parameters ! - ! SGR - Global register containing tile ! - ! bitstream size information ! - ! SAX - Auxiliary data-set information ! - ! TLM - Packet lengths: main header ! - ! PLM - Packet lengths: tile-part ! - ! PPM - Quantization default ! - ! COM - Comment ! - ! EOH - End of header ! - ! PLT - Packed packet headers: main header ! - ! PPT - Packed packet headers: tile-part ! - ! SOT - Start of tile ! - ! SOP - Start of packet ! - ! EPH - End of packet header ! - ! SOD - Start of data ! - ! EOC - End of code-stream ! - ! ! - ! DEVELOPMENT HISTORY: ! - ! -------------------- ! - ! ! - ! Date Author Change Id Release Description ! - ! ---- ------ --------- ------- ----------- ! - ! 01.12.2017 Patrick Vogler B87D120 V 0.1.0 macros created ! - ! ! - \*------------------------------------------------------------------------------------------------------------------*/ - #define SOC 0xFF50 - #define SGI 0xFF51 - #define SGC 0xFF52 - #define SAX 0xFF53 - #define TLM 0xFF54 - #define PLM 0xFF55 - #define PPM 0xFF56 - #define COM 0xFF57 - #define EOH 0xFF58 - #define PLT 0xFF60 - #define PPT 0xFF61 - #define SOT 0xFF90 - #define SOP 0xFF91 - #define EPH 0xFF92 - #define SOD 0xFF93 - #define EOC 0xFFFF - - /*------------------------------------------------------------------------------------------------------------------*\ - ! DESCRIPTION: ! - ! ------------ ! - ! ! - ! These macros define flags used for codestream parsing. ! - ! ! - ! MACROS: ! - ! ------- ! - ! Name Description ! - ! ---- ----------- ! - ! CODESTREAM_OK - No errors detected in Codestream ! - ! ! - ! CODESTREAM_READ - Codestream has been fully read. ! - ! ! - ! DEVELOPMENT HISTORY: ! - ! -------------------- ! - ! ! - ! Date Author Change Id Release Description ! - ! ---- ------ --------- ------- ----------- ! - ! 01.08.2019 Patrick Vogler B87D120 V 0.1.0 macros created ! - ! ! - \*------------------------------------------------------------------------------------------------------------------*/ - #define CODESTREAM_OK 0x00 - #define CODESTREAM_READ 0x80 - - /*------------------------------------------------------------------------------------------------------------------*\ - ! DESCRIPTION: ! - ! ------------ ! - ! ! - ! These Constants define common error messages used throughout the bwc library. ! - ! ! - ! MACROS: ! - ! ------- ! - ! Name Description ! - ! ---- ----------- ! - ! CSTERROR - Codestream parser has encoun- ! - ! tered invalid marker. ! - ! ! - ! MEMERROR - Allocation has returned a NULL ! - ! pointer due to limited memory. ! - ! ! - ! RDERROR - Invalid number of bytes read ! - ! from file. ! - ! ! - ! WRTERROR - Invalid number of bytes writ- ! - ! ten to file. ! - ! ! - ! DEVELOPMENT HISTORY: ! - ! -------------------- ! - ! ! - ! Date Author Change Id Release Description ! - ! ---- ------ --------- ------- ----------- ! - ! 01.12.2017 Patrick Vogler B87D120 V 0.1.0 macros created ! - ! ! - \*------------------------------------------------------------------------------------------------------------------*/ - #define CSTERROR "o##########################################################o\n"\ - "| ERROR: Invalid Codestream |\n"\ - "o##########################################################o\n" - - #define MEMERROR "o##########################################################o\n"\ - "| ERROR: Out of Memory |\n"\ - "o##########################################################o\n" - - #define RDERROR "o##########################################################o\n"\ - "| ERROR: Invalid Number of Bytes Read from File. |\n"\ - "o##########################################################o\n" - - #define WRTERROR "o##########################################################o\n"\ - "| ERROR: Invalid Number of Bytes Written to File. |\n"\ - "o##########################################################o\n" - - #define GET_DIM(x) (sizeof(x)/sizeof(*(x))) - /********************************************************************************************************************\ - || ___ ____ ____ ____ _ _ _ ____ ___ ___ _ _ ___ ____ ____ || - || | \ |___ |__/ |__/ | | | |___ | \ | \_/ |__] |___ [__ || - || |__/ |___ | \ | \ | \/ |___ |__/ | | | |___ ___] || - || || - \********************************************************************************************************************/ - /*------------------------------------------------------------------------------------------------------------------*\ - ! DESCRIPTION: ! - ! ------------ ! - ! ! - ! This structure defines the attributes of a single argument supported by the bwc ! - ! command line tool. ! - ! ! - ! PARAMETERS: ! - ! ----------- ! - ! Name Type Description ! - ! ---- ---- ----------- ! - ! active char - Flag indicating if the argu- ! - ! ment is active. ! - ! ! - ! arg_long char - Long form of the argument name. ! - ! ! - ! arg_short char - Short form of the argument ! - ! name. ! - ! ! - ! arg_type char - Flag signaling if the argument ! - ! is optional. ! - ! ! - ! type char - Flag signaling the argument ! - ! type. ! - ! ! - ! usage char - A string of 24 characters de- ! - ! scribing the argument usage. ! - ! ! - ! definition char - A string of 1024 characters ! - ! containing the argument de- ! - ! scription. ! - ! ! - ! DEVELOPMENT HISTORY: ! - ! -------------------- ! - ! ! - ! Date Author Change Id Release Description ! - ! ---- ------ --------- ------- ----------- ! - ! 14.02.2019 Patrick Vogler B87D120 V 0.1.0 struct created ! - ! 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 clean up ! - ! ! - \*------------------------------------------------------------------------------------------------------------------*/ - typedef struct - { - char active; - char arg_long[25]; - char arg_short[3]; - char arg_type[4]; - char type[5]; - char usage[25]; - char definition[1024]; - } bwc_cmdl_args; - - /*------------------------------------------------------------------------------------------------------------------*\ - ! DESCRIPTION: ! - ! ------------ ! - ! This structure describes a linked list which stores all the arguments and their ! - ! attributes supplied to the command line tool by the user. ! - ! ! - ! PARAMETERS: ! - ! ----------- ! - ! Name Type Description ! - ! ---- ---- ----------- ! - ! hash unsigned int(64 bit) - Uniquely identifiable hash that ! - ! corresponds to the arg/opt name. ! - ! ! - ! count unsigned int(8 bit) - Counter that signifies the num- ! - ! ber of modifier values stored ! - ! in the linked list node. ! - ! ! - ! dim unsigned int(8 bit) - Dimension(s) for which the mod- ! - ! ifiers have been defined ! - ! ! - ! active char - Flag indicating if the arg/opt ! - ! is active. ! - ! ! - ! num_opt double* - Array of numerical modifier ! - ! values. ! - ! ! - ! lit_opt char** - Character array of literal mod- ! - ! ifier values. ! - ! ! - ! DEPENDENCIES: ! - ! ------------- ! - ! Name TYPE ! - ! ---- ---- ! - ! next opt* ! - ! ! - ! root opt* ! - ! ! - ! DEVELOPMENT HISTORY: ! - ! -------------------- ! - ! ! - ! Date Author Change Id Release Description ! - ! ---- ------ --------- ------- ----------- ! - ! 26.04.2019 Patrick Vogler B87D120 V 0.1.0 struct created ! - ! 26.11.2020 Patrick Vogler B87E7E4 V 0.1.0 clean up ! - ! ! - \*------------------------------------------------------------------------------------------------------------------*/ - typedef struct arg - { - uint64_t hash; - uint8_t count; - uint8_t dim; - char active; - double *num_opt; - char **lit_opt; - struct arg *next; - struct arg *root; - } bwc_cmdl_arg_node; -#endif \ No newline at end of file diff --git a/src/interfaces/reader/eas3.c b/src/interfaces/reader/eas3.c index baacce0..4ab8203 100644 --- a/src/interfaces/reader/eas3.c +++ b/src/interfaces/reader/eas3.c @@ -76,7 +76,25 @@ #include #include "eas3.h" -#include "bwccmdl.h" + + +/************************************************************************************************************\ +|| _ _ ____ ____ ____ ____ ____ || +|| |\/| |__| | |__/ | | [__ || +|| | | | | |___ | \ |__| ___] || +|| || +\************************************************************************************************************/ +#define MEMERROR "o##########################################################o\n"\ + "| ERROR: Out of memory |\n"\ + "o##########################################################o\n" + +#define RDERROR "o##########################################################o\n"\ + "| ERROR: Invalid Number of Bytes Read from File. |\n"\ + "o##########################################################o\n" + +#define WRTERROR "o##########################################################o\n"\ + "| ERROR: Invalid Number of Bytes Written to File. |\n"\ + "o##########################################################o\n" /************************************************************************************************************\ || ___ ____ _ _ _ ____ ___ ____ ____ _ _ _ _ ____ ___ _ ____ _ _ ____ || @@ -84,15 +102,11 @@ || | | \ | \/ | | | |___ | |__| | \| |___ | | |__| | \| ___] || || || \************************************************************************************************************/ - -/*----------------------------------------------------------------------------------------------------------*\ -! ! -! DESCRIPTION: ! -! ------------ ! -! This macro is used to write an additional chunck of size length to the auxilliary ! -! information. ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Enqueues a chunck of size length to the auxilliary information. + */ +/*================================================================================================*/ #define aux_enqueue(aux, chunck, chunck_len) \ { \ if (aux.pos + chunck_len > aux.len) \ @@ -107,6 +121,11 @@ aux.pos += chunck_len; \ } +/*================================================================================================*/ +/** + * @details Dequeues a chunck of size length from the auxilliary information. + */ +/*================================================================================================*/ #define aux_dequeue(aux, chunck, chunck_len) \ { \ if(aux.pos + chunck_len <= aux.len) { \ @@ -117,37 +136,14 @@ } \ } -/*----------------------------------------------------------------------------------------------------------*\ -! ! -! DESCRIPTION: ! -! ------------ ! -! This function converts the endianess of half, single or double precision values. ! -! ! -! PARAMETERS: ! -! ----------- ! -! Variable Type Description ! -! -------- ---- ----------- ! -! value void* - Memory address of the parame- ! -! ter to be converted. ! -! ! -! RETURN VALUE: ! -! ------------- ! -! Type Description ! -! ---- ----------- ! -! - - ! -! ! -! DEVELOPMENT HISTORY: ! -! -------------------- ! -! ! -! Date Author Change Id Release Description ! -! ---- ------ --------- ------- ----------- ! -! 30.04.2019 Patrick Vogler B87D120 V 0.1.0 function created ! -! 21.11.2019 Patrick Vogler B87E7E4 V 0.1.0 functionality expanded ! -! to 32 bit integers ! -! 21.11.2019 Patrick Vogler B87E7E4 V 0.1.0 functionality expanded ! -! to 16 bit integers ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Converts the endianess of half, single, or double precision values. + * + * @param[inout] value Pointer to the parameter to be converted. + * @param[in] accuracy Precision/accuracy of the pointed parameter. + */ +/*================================================================================================*/ static void endian_conversion(void *value, uint8_t const accuracy) @@ -201,34 +197,56 @@ endian_conversion(void *value, } } -/*----------------------------------------------------------------------------------------------------------*\ -! ! -! DESCRIPTION: ! -! ------------ ! -! This function deallocates the data structure used to store an numerical dataset ! -! and can be called if an error occurs or once the data is no longer needed is to be closed. ! -! The deallocation will be carried out down to the structure levels that have been allocated. ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Deallocates the provided eas3_data structure including all contained data. + * + * @param[in] data Pointer to eas3_data structure to be filled. + */ +/*================================================================================================*/ void eas3_free_data(eas3_data* data) { - if(data) - { - //if(data->aux) - //{ - //free(data->aux->memory); - //data->aux->access = NULL; - //data->aux->position = 0; - //data->aux->size = 0; - // TODO: remove - //data->aux->L = 0; - //} - //free(data->aux); - free(data); - } + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + eas3_param_names *param, *temp; + + if(data != NULL) + { + if (data->param_names != NULL) + { + param = data->param_names->root; + + while(param != NULL) + { + temp = param; + param = param -> next; + free(temp); + } + } + + if (data->field.d != NULL) + free(data->field.d); + + if (data->field.f != NULL) + free(data->field.f); + + if(data->aux.ptr != NULL) + free(data->aux.ptr); + + free(data); + } } +/*================================================================================================*/ +/** + * @details Adds a parameter name to the linked list inside the eas3_data structure. + * + * @param[in] data Pointer to eas3_data structure to be filled. + * @param[in] name Name to be added to the linked list. + */ +/*================================================================================================*/ void eas3_add_param_name(eas3_data *const data, char *name) { @@ -283,49 +301,137 @@ eas3_add_param_name(eas3_data *const data, char *name) strcpy(data->param_names->name, name ? name : "undefined"); } -/*----------------------------------------------------------------------------------------------------------*\ -! FUNCTION NAME: uchar read_eas3_header(bwc_data *const data) ! -! -------------- ! -! ! -! DESCRIPTION: ! -! ------------ ! -! This function opens an eas3 file and checks it for its validity. Once the specified file ! -! has been verified, its header and flow field data is read and stored in the bwc_data ! -! structure. ! -! ! -! ! -! PARAMETERS: ! -! ----------- ! -! Variable Type Description ! -! -------- ---- ----------- ! -! filename char* - Defines the filename of the eas3 file ! -! that is to be opened and read. ! -! ! -! RETURN VALUE: ! -! ------------- ! -! Type Description ! -! ---- ----------- ! -! file - Defines a structure used to store all ! -! the relevant parameters and the data ! -! field of an eas3 file. ! -! ! -! DEVELOPMENT HISTORY: ! -! -------------------- ! -! ! -! Date Author Change Id Release Description Of Change ! -! ---- ------ --------- ------- --------------------- ! -! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ -static uchar -read_eas3_header(FILE *const fp, eas3_data *const data) +/*================================================================================================*/ +/** + * @details Parses the uncompressed output from bwc_stream into the eas3_data. + * + * @param[in] stream Pointer to uncompressed data set. + * @param[inout] data Pointer to eas3_data structure to be filled. + * + * @retval uchar + */ +/*================================================================================================*/ +uchar +bwc_to_eas3(bwc_stream *const stream, eas3_data *const data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64 Lread; + uint64 size; + uint64 i; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + uchar *buffer_char; + char param_name[ATTRLEN + 1] = {}; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + eas3_std_params *params; + + params = &data->params; + + data->aux.ptr = calloc(stream->codestream.aux->size, sizeof(uchar)); + data->aux.pos = 0; + data->aux.len = stream->codestream.aux->size; + if(!data->aux.ptr) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(data->aux.ptr); + return 1; + } + memcpy(data->aux.ptr, stream->codestream.aux->memory, + stream->codestream.aux->size); + + aux_dequeue(data->aux, (uchar*)params, 176); + + endian_conversion(¶ms->nts, 8); + endian_conversion(¶ms->npar, 8); + endian_conversion(¶ms->ndim1, 8); + endian_conversion(¶ms->ndim2, 8); + endian_conversion(¶ms->ndim3, 8); + endian_conversion(¶ms->accuracy, 8); + if(params->accuracy != 1 && params->accuracy != 2) + { + fprintf(stderr, "o##########################################################o\n"\ + "| ERROR: The accuracy of the specified dataset is not sup- |\n"\ + "| ported by the compression algorithm. |\n"\ + "o##########################################################o\n"); + return 1; + } + + buffer_char = calloc(params->nts, sizeof(uint64)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + aux_dequeue(data->aux, buffer_char, params->nts * sizeof(uint64)); + + if(params->attribute_mode == EAS3_ALL_ATTR) + { + buffer_char = realloc(buffer_char, params->nts * ATTRLEN * sizeof(char)); + if(!buffer_char) + { + // memory allocation error + fprintf(stderr, MEMERROR); + free(buffer_char); + return 1; + } + aux_dequeue(data->aux, buffer_char, params->nts * ATTRLEN * sizeof(char)); + + for(i = 0; i < params->npar; ++i) + { + aux_dequeue(data->aux, param_name, ATTRLEN * sizeof(char)); + eas3_add_param_name(data, param_name); + memset(param_name, 0, ATTRLEN + 1); + } + } + + size = params->ndim1 * params->ndim2 * params->ndim3 * + params->nts * params->npar; + + if(params->accuracy == 1) + { + data->field.d = NULL; + data->field.f = calloc(size, sizeof(float)); + memcpy(data->field.f, stream->out, size*sizeof(float)); + } + else if(params->accuracy == 2) + { + data->field.f = NULL; + data->field.d = calloc(size, sizeof(double)); + memcpy(data->field.d, stream->out, size*sizeof(double)); + } + + return 0; +} + +/*================================================================================================*/ +/** + * @details Reads the header from an open eas3 file pointer parsing the header information into + * the eas3_data structure argument. + * + * @param[in] fp Readily opened file pointer. + * @param[inout] data Structure to store eas3 data. + * + * @retval uchar + */ +/*================================================================================================*/ +static uchar +read_eas3_header(FILE *const fp, eas3_data *const data) { /*-----------------------*\ ! DEFINE INT VARIABLES: ! \*-----------------------*/ uint64 Lread; uint64 i; - uint8 precision; /*-----------------------*\ ! DEFINE CHAR VARIABLES: ! @@ -336,7 +442,6 @@ read_eas3_header(FILE *const fp, eas3_data *const data) /*-----------------------*\ ! DEFINE STRUCTS: ! \*-----------------------*/ - bwc_gl_inf *info; eas3_std_params *params; /*-----------------------*\ @@ -550,13 +655,9 @@ read_eas3_header(FILE *const fp, eas3_data *const data) return 1; } + aux_enqueue(data->aux, param_name, ATTRLEN * sizeof(char)); eas3_add_param_name(data, param_name); - /*--------------------------------------------------------*\ - ! Read the parameter name from the file stream and add all ! - ! the necessary parameter information to the paramter ! - ! linked list. | - \*--------------------------------------------------------*/ memset(param_name, 0, ATTRLEN + 1); } } @@ -632,40 +733,17 @@ read_eas3_header(FILE *const fp, eas3_data *const data) return 0; } -/*----------------------------------------------------------------------------------------------------------*\ -! FUNCTION NAME: uchar read_eas3_header(bwc_data *const data) ! -! -------------- ! -! ! -! DESCRIPTION: ! -! ------------ ! -! This function opens an eas3 file and checks it for its validity. Once the specified file ! -! has been verified, its header and flow field data is read and stored in the bwc_data ! -! structure. ! -! ! -! ! -! PARAMETERS: ! -! ----------- ! -! Variable Type Description ! -! -------- ---- ----------- ! -! filename char* - Defines the filename of the eas3 file ! -! that is to be opened and read. ! -! ! -! RETURN VALUE: ! -! ------------- ! -! Type Description ! -! ---- ----------- ! -! file - Defines a structure used to store all ! -! the relevant parameters and the data ! -! field of an eas3 file. ! -! ! -! DEVELOPMENT HISTORY: ! -! -------------------- ! -! ! -! Date Author Change Id Release Description Of Change ! -! ---- ------ --------- ------- --------------------- ! -! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Writes the header information from the eas3_data structure into the open eas3 + * file pointer. + * + * @param[in] fp Readily opened file pointer. + * @param[inout] data Structure to store eas3 data. + * + * @retval uchar + */ +/*================================================================================================*/ static uchar write_eas3_header(FILE *const fp, eas3_data *const data) { @@ -682,7 +760,6 @@ write_eas3_header(FILE *const fp, eas3_data *const data) /*-----------------------*\ ! DEFINE STRUCTS: ! \*-----------------------*/ - bwc_gl_inf *info; eas3_std_params *params; eas3_param_names *param_names; @@ -729,7 +806,13 @@ write_eas3_header(FILE *const fp, eas3_data *const data) ! Convert the size parameters, used to write the rest of ! ! the header, to little endian. ! \*--------------------------------------------------------*/ + endian_conversion(¶ms->file_type, 8); endian_conversion(¶ms->accuracy, 8); + endian_conversion(¶ms->nts, 8); + endian_conversion(¶ms->npar, 8); + endian_conversion(¶ms->ndim1, 8); + endian_conversion(¶ms->ndim2, 8); + endian_conversion(¶ms->ndim3, 8); endian_conversion(¶ms->size_time, 8); endian_conversion(¶ms->size_parameter, 8); endian_conversion(¶ms->size_dim1, 8); @@ -739,6 +822,8 @@ write_eas3_header(FILE *const fp, eas3_data *const data) endian_conversion(¶ms->udef_int_size, 8); endian_conversion(¶ms->udef_real_size, 8); + data->params = *params; + /*--------------------------------------------------------*\ ! Allocate the buffer character array. If successful, get ! ! the timestep array from the auxiliary information block ! @@ -872,40 +957,16 @@ write_eas3_header(FILE *const fp, eas3_data *const data) || | |__| |__] |___ | |___ | |__| | \| |___ | | |__| | \| ___] || || || \************************************************************************************************************/ -/*----------------------------------------------------------------------------------------------------------*\ -! FUNCTION NAME: bwc_data* read_eas3(const char* const filename) ! -! -------------- ! -! ! -! DESCRIPTION: ! -! ------------ ! -! This function opens an eas3 file and checks it for its validity. Once the specified file ! -! has been verified, its header and flow field data is read and stored in the bwc_data ! -! structure. ! -! ! -! ! -! PARAMETERS: ! -! ----------- ! -! Variable Type Description ! -! -------- ---- ----------- ! -! filename char* - Defines the filename of the eas3 file ! -! that is to be opened and read. ! -! ! -! RETURN VALUE: ! -! ------------- ! -! Type Description ! -! ---- ----------- ! -! file - Defines a structure used to store all ! -! the relevant parameters and the data ! -! field of an eas3 file. ! -! ! -! DEVELOPMENT HISTORY: ! -! -------------------- ! -! ! -! Date Author Change Id Release Description Of Change ! -! ---- ------ --------- ------- --------------------- ! -! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Opens an eas3 file and checks it for its validity. Then, it reads header and flow + * field data and returns a filled instance of the eas3_data structure. + * + * @param[in] filename Name of the eas3 file. + * + * @retval eas3_data* + */ +/*================================================================================================*/ eas3_data* read_eas3(char *const filename) { @@ -1068,40 +1129,16 @@ read_eas3(char *const filename) return data; } -/*----------------------------------------------------------------------------------------------------------*\ -! FUNCTION NAME: uchar write_eas3(bwc_data *const file, char *const filename) ! -! -------------- ! -! ! -! DESCRIPTION: ! -! ------------ ! -! This function creates a valid eas3 file from the information stored in the bwc_data ! -! structure. ! -! ! -! PARAMETERS: ! -! ----------- ! -! Variable Type Description ! -! -------- ---- ----------- ! -! filename char* - Defines the filename of the eas3 file ! -! that is to be opened and read. ! -! ! -! file bwc_data* - Defines a structure used to store all ! -! the relevant parameters and the data ! -! field of an eas3 file. ! -! ! -! RETURN VALUE: ! -! ------------- ! -! Type Description ! -! ---- ----------- ! -! uchar - Returns an unsigned char for error handling. ! -! ! -! DEVELOPMENT HISTORY: ! -! -------------------- ! -! ! -! Date Author Change Id Release Description Of Change ! -! ---- ------ --------- ------- --------------------- ! -! 20.06.2018 Patrick Vogler B87D120 V 0.1.0 function created ! -! ! -\*----------------------------------------------------------------------------------------------------------*/ +/*================================================================================================*/ +/** + * @details Opens an eas3 file and writes the content from the provided eas3_data structure. + * + * @param[in] data Data to be written into the eas3 file. + * @param[in] filename Name of the eas3 file. + * + * @retval uchar + */ +/*================================================================================================*/ uchar write_eas3(eas3_data *const data, char *const filename) { diff --git a/src/library/codestream.c b/src/library/codestream.c index 3c0d8d3..aec991c 100755 --- a/src/library/codestream.c +++ b/src/library/codestream.c @@ -912,7 +912,7 @@ parse_main_header(bwc_codec *const codec, bwc_stream *const data, bitstream *con data->codestream.com->memory = get_chunck(stream, Lcom - 2); data->codestream.com->size = Lcom -2; - status |= CODESTREAM_ERROR; + status |= CODESTREAM_COM_READ; break; } diff --git a/src/library/libbwc.c b/src/library/libbwc.c index bf01f88..b886f64 100755 --- a/src/library/libbwc.c +++ b/src/library/libbwc.c @@ -1498,8 +1498,9 @@ bwc_set_com(bwc_stream *const data, char const *const com, uint16 size) ! Save the global info structure to a temporary variable ! ! to make the code more readable. ! \*--------------------------------------------------------*/ + data->codestream.com = calloc(1, sizeof(bwc_span)); data->codestream.com->memory = calloc(size, sizeof(char)); - if(!data->codestream.com->memory) + if(!data->codestream.com->memory) { // memory allocation error fprintf(stderr, MEMERROR); @@ -1536,18 +1537,19 @@ bwc_set_aux(bwc_stream *const data, char const *const aux, uint32 size) ! Save the global info structure to a temporary variable ! ! to make the code more readable. ! \*--------------------------------------------------------*/ - data->codestream.com->memory = calloc(size, sizeof(char)); - if(!data->codestream.com->memory) + data->codestream.aux = calloc(1, sizeof(bwc_span)); + data->codestream.aux->memory = calloc(size, sizeof(char)); + if(!data->codestream.aux->memory) { // memory allocation error fprintf(stderr, MEMERROR); return 1; } - memcpy(data->codestream.com->memory, aux, size * sizeof(char)); - data->codestream.com->access = data->codestream.com->memory; - data->codestream.com->size = size; - data->codestream.com->position = 0; + memcpy(data->codestream.aux->memory, aux, size * sizeof(char)); + data->codestream.aux->access = data->codestream.aux->memory; + data->codestream.aux->size = size; + data->codestream.aux->position = 0; return 0; } @@ -2490,15 +2492,14 @@ set_quant_step_size(bwc_codec *const codec, double delta) \*--------------------------------------------------------*/ if((delta <= 0) || (delta >= 2)) { - fprintf(stderr, "o==========================================================o\n"\ - "| WARNING: Invalid quantization step size |\n"\ - "| |\n"\ - "| The quantization step size does not lie within |\n"\ - "| the acceptable range of: |\n"\ - "| |\n"\ - "| 0 < step size < 2 |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid quantization step size \n"\ + " \n"\ + " The quantization step size does not lie within \n"\ + " the acceptable range of: \n"\ + " \n"\ + " 0 < step size < 2 \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); return; } @@ -2782,14 +2783,13 @@ bwc_set_decomp(bwc_codec *const codec, uint8 decompX, uint8 decompY, uint8 decom if((control->decompX > 63) || (control->decompY > 63) || (control->decompZ > 63) || (control->decompTS > 31)) { - fprintf(stderr, "o==========================================================o\n"\ - "| WARNING: Invalid decomposition level value |\n"\ - "| |\n"\ - "| The maximum acceptable decomposition level is |\n"\ - "| 63 for all spatial and 31 for the temporal |\n"\ - "| dimensions. |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid decomposition level value \n"\ + " \n"\ + " The maximum acceptable decomposition level is \n"\ + " 63 for all spatial and 31 for the temporal \n"\ + " dimensions. \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); /*--------------------------------------------------------*\ ! Reset the decomposition levels to their standard values. ! @@ -2924,13 +2924,12 @@ bwc_set_precincts(bwc_codec *const codec, uint8 pX, uint8 pY, uint8 pZ, uint8 pT ((control->precSizeTS < 1) && (info->nTS >> 1)) || (control->precSizeX > 15) || (control->precSizeY > 15) || (control->precSizeZ > 15) || (control->precSizeTS > 15)) { - fprintf(stderr, "o==========================================================o\n"\ - "| WARNING: Invalid precinct size |\n"\ - "| |\n"\ - "| The maximum acceptable precinct size is 2^15, |\n"\ - "| the smallest valid precinct size is 2^1. |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid precinct size \n"\ + " \n"\ + " The maximum acceptable precinct size is 2^15, \n"\ + " the smallest valid precinct size is 2^1. \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); /*--------------------------------------------------------*\ ! Reset the codeblock sizes to their standard values. ! @@ -3023,15 +3022,14 @@ bwc_set_codeblocks(bwc_codec *const codec, uint8 cbX, uint8 cbY, uint8 cbZ, uint ((control->cbX + control->cbY + control->cbZ + control->cbTS) < 4) || ((control->cbX + control->cbY + control->cbZ + control->cbTS) > 20)) { - fprintf(stderr, "o==========================================================o\n"\ - "| WARNING: Invalid codeblock size |\n"\ - "| |\n"\ - "| The maximum acceptable codeblock size is 2^20 |\n"\ - "| with a maximum allowable number of datapoints |\n"\ - "| in each dimension of 2^10. The smallest valid |\n"\ - "| codeblock size is 2^4. |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid codeblock size \n"\ + " \n"\ + " The maximum acceptable codeblock size is 2^20 \n"\ + " with a maximum allowable number of datapoints \n"\ + " in each dimension of 2^10. The smallest valid \n"\ + " codeblock size is 2^4. \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); /*--------------------------------------------------------*\ ! Reset the codeblock sizes to their standard values. ! @@ -3106,19 +3104,18 @@ bwc_set_qm(bwc_codec *const codec, uint8 Qm) ! Check if the Q number formate range is valid and amend ! ! the bwc_codec structure accordingly. ! \*--------------------------------------------------------*/ - if((int8)(PREC_BIT - Qm) < 2) + if((int8)(PREC_BIT - Qm) < 1) { - fprintf(stderr, "o==========================================================o\n"\ - "| WARNING: Invalid Q number formate range |\n"\ - "| |\n"\ - "| The specified Q number formate range is larger |\n"); + fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid Q number formate range \n"\ + " \n"\ + " The specified Q number formate range is larger \n"); #ifdef BWC_SINGLE_PRECISION - fprintf(stderr, "| than the permitted 30 bits. |\n"); + fprintf(stderr, " than the permitted 30 bits. \n"); #else - fprintf(stderr, "| than the permitted 62 bits. |\n"); + fprintf(stderr, " than the permitted 62 bits. \n"); #endif - fprintf(stderr, "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); } else { @@ -3213,17 +3210,16 @@ bwc_set_tiles(bwc_codec *const codec, uint64 tilesX, uint64 tilesY, uint64 tiles (control->tileSizeZ < 16 && control->tileSizeZ > info->nZ)|| (control->tileSizeTS < 16 && control->tileSizeTS > info->nTS)) { - fprintf(stderr,"o==========================================================o\n"\ - "| WARNING: Invalid Tile Dimensions |\n"\ - "| |\n"\ - "| One or more of the specified tile dimensions |\n"\ - "| has a value that falls outside of its valid |\n"\ - "| range. Please verify that all tile dimension |\n"\ - "| are within the range of: |\n"\ - "| |\n"\ - "| 16 ≤ Tile_Size_Xi ≤ Grid_Points_Xi |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid Tile Dimensions \n"\ + " \n"\ + " One or more of the specified tile dimensions \n"\ + " has a value that falls outside of its valid \n"\ + " range. Please verify that all tile dimension \n"\ + " are within the range of: \n"\ + " \n"\ + " 16 ≤ Tile_Size_Xi ≤ Grid_Points_Xi \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); return; } @@ -3255,16 +3251,15 @@ bwc_set_tiles(bwc_codec *const codec, uint64 tilesX, uint64 tilesY, uint64 tiles \*--------------------------------------------------------*/ if(((double)num_tiles_X * num_tiles_Y * num_tiles_Z * num_tiles_TS) > 0xFFFFFFFFFFFFFFFF) { - fprintf(stderr,"o==========================================================o\n"\ - "| WARNING: Invalid Tile Dimensions |\n"\ - "| |\n"\ - "| The number of tiles exceeds its maxmum allowa- |\n"\ - "| ble value. Please adjust all tile dimension so |\n"\ - "| that the number of tiles falls within the range |\n"\ - "| of: |\n"\ - "| Number_of_Tiles < 2^64 |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid Tile Dimensions \n"\ + " \n"\ + " The number of tiles exceeds its maxmum allowa- \n"\ + " ble value. Please adjust all tile dimension so \n"\ + " that the number of tiles falls within the range \n"\ + " of: \n"\ + " Number_of_Tiles < 2^64 \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); /*--------------------------------------------------------*\ ! Reset the tile sizes to their standard values. ! @@ -3285,15 +3280,14 @@ bwc_set_tiles(bwc_codec *const codec, uint64 tilesX, uint64 tilesY, uint64 tiles \*--------------------------------------------------------*/ if(((double)tilesX * tilesY * tilesZ * tilesTS) > 0xFFFFFFFFFFFFFFFF) { - fprintf(stderr,"o==========================================================o\n"\ - "| WARNING: Invalid Number Of Tiles |\n"\ - "| |\n"\ - "| The number of tiles exceeds its maxmum allowa- |\n"\ - "| ble value of: |\n"\ - "| |\n"\ - "| Number_of_Tiles < 2^64 |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid Number Of Tiles \n"\ + " \n"\ + " The number of tiles exceeds its maxmum allowa- \n"\ + " ble value of: \n"\ + " \n"\ + " Number_of_Tiles < 2^64 \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); return; } @@ -3318,18 +3312,17 @@ bwc_set_tiles(bwc_codec *const codec, uint64 tilesX, uint64 tilesY, uint64 tiles (control->tileSizeZ < 16 && control->tileSizeZ > info->nZ)|| (control->tileSizeTS < 16 && control->tileSizeTS > info->nTS)) { - fprintf(stderr,"o==========================================================o\n"\ - "| WARNING: Invalid Number Of Tiles |\n"\ - "| |\n"\ - "| One or more of the tile dimensions has a value |\n"\ - "| that falls outside of its valid range. Please |\n"\ - "| verify that the number of tiles for all dimen- |\n"\ - "| sions are set so that the corresponding tile |\n"\ - "| sizes fall within the range of: |\n"\ - "| |\n"\ - "| 16 ≤ Tile_Size_Xi ≤ Grid_Points_Xi |\n"\ - "| |\n"\ - "o==========================================================o\n"); + fprintf(stderr,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"\ + " WARNING: Invalid Number Of Tiles \n"\ + " \n"\ + " One or more of the tile dimensions has a value \n"\ + " that falls outside of its valid range. Please \n"\ + " verify that the number of tiles for all dimen- \n"\ + " sions are set so that the corresponding tile \n"\ + " sizes fall within the range of: \n"\ + " \n"\ + " 16 ≤ Tile_Size_Xi ≤ Grid_Points_Xi \n"\ + ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); /*--------------------------------------------------------*\ ! Reset the tile sizes to their standard values. ! @@ -3359,6 +3352,98 @@ bwc_set_tiles(bwc_codec *const codec, uint64 tilesX, uint64 tilesY, uint64 tiles control->CSsgc |= (0x01 << 9); } +/*================================================================================================*/ +/** + * @details This function opens the header of a compressed data set and parses it into an + * instance of type bwc_header. + * + * @param[in] inpbuf Pointer to compressed data set. + * + * @retval bwc_header* + */ +/*================================================================================================*/ +bwc_header* bwc_open_header(void *const inpbuf) +{ + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + bwc_codec* codec; + bwc_stream* data; + bitstream* stream; + bwc_header* header; + + /*--------------------------------------------------------*\ + ! Initialize a codec, stream, and bitstream for parsing. ! + \*--------------------------------------------------------*/ + data = bwc_init_stream(inpbuf, NULL, decomp); + codec = bwc_alloc_decoder(); + stream = init_bitstream(data->inp, 10, 'd'); + + /*--------------------------------------------------------*\ + ! Parse the main header into the codec structure. ! + \*--------------------------------------------------------*/ + parse_main_header(codec, data, stream); + if(!codec) + { + return NULL; + } + + /*--------------------------------------------------------*\ + ! Allocate header and copy info and control structures. ! + \*--------------------------------------------------------*/ + header = calloc(1, sizeof(bwc_header)); + header->info = codec->info; + header->control = codec->control; + + /*--------------------------------------------------------*\ + ! Shallow copy aux data to span. ! + \*--------------------------------------------------------*/ + if (data->codestream.aux) + { + header->aux.memory = data->codestream.aux->memory; + header->aux.size = data->codestream.aux->size; + } + + /*--------------------------------------------------------*\ + ! Shallow copy com data to span. ! + \*--------------------------------------------------------*/ + if (data->codestream.com) + { + header->com.memory = data->codestream.com->memory; + header->com.size = data->codestream.com->size; + } + + free(stream); + free(data); + free(codec); + + return header; +} + +/*================================================================================================*/ +/** + * @details This function closes the header information in the bwc_header pointer. + * + * @param[in] header Instance of type bwc_header. + */ +/*================================================================================================*/ +void bwc_close_header(bwc_header *const header) +{ + if (header) + { + if (header->aux.memory) + { + free(header->aux.memory); + } + if (header->com.memory) + { + free(header->com.memory); + } + free(header); + } +} + + /*----------------------------------------------------------------------------------------------------------*\ ! FUNCTION NAME: void bwc_create_compression(bwc_codec *codec, char *rate_control) ! ! -------------- ! diff --git a/src/tools/bwccmdl.c b/src/tools/bwccmdl.c index 8b29197..b6a8d2b 100644 --- a/src/tools/bwccmdl.c +++ b/src/tools/bwccmdl.c @@ -14,7 +14,7 @@ || || \* -------------------------------------------------------------------------------------------- */ /** - * @file test.c + * @file bwccmdl.c * * This file defines a simple command line tool that uses the Big Whoop library to * (de) compress a 2- to 4-dimensional IEEE 754 floating point array. For further @@ -48,13 +48,15 @@ #include #include #include +#include +#include +#include #include #include #include #include "eas3.h" #include "bwc.h" -#include "bwccmdl.h" /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*\ || _ _ ____ ____ ____ ____ ____ || @@ -63,6 +65,64 @@ || || \*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ /// @cond DO_NOT_DOCUMENT +/*================================================================================================*/ +/** + * @details These macros define common error messages used throughout the BigWhoop cli. + */ +/*================================================================================================*/ +#define MEMERROR "o##########################################################o\n"\ + "| ERROR: Out of memory |\n"\ + "o##########################################################o\n" + +#define TYPERROR "o##########################################################o\n"\ + "| ERROR: Invalid file type. |\n"\ + "o##########################################################o\n" + +#define FINERROR "o##########################################################o\n"\ + "| ERROR: Could not open specified input file. |\n"\ + "o##########################################################o\n" + +#define FOUERROR "o##########################################################o\n"\ + "| ERROR: Could not open specified output file. |\n"\ + "o##########################################################o\n" + +#define RDERROR "o##########################################################o\n"\ + "| ERROR: Invalid number of bytes read from file. |\n"\ + "o##########################################################o\n" + +#define WRTERROR "o##########################################################o\n"\ + "| ERROR: Invalid number of bytes written to file. |\n"\ + "o##########################################################o\n" + +/*================================================================================================*/ +/** + * @details These macros are used to set and probe the cli_arguments optSet variable + */ +/*================================================================================================*/ +#define BITRT 0x8000 +#define CBLKS 0x4000 +#define CMPRT 0x2000 +#define DCLVL 0x1000 +#define DWTKL 0x0800 +#define FLOUT 0x0400 +#define FLREF 0x0200 +#define OMPTH 0x0100 +#define PRORD 0x0080 +#define PRECS 0x0040 +#define QFRMT 0x0020 +#define QTSIZ 0x0010 +#define QTSTL 0x0008 +#define TILES 0x0004 +#define USQLY 0x0002 + +/*================================================================================================*/ +/** + * @details Macros to determine the minimum or maximum of two values. + */ +/*===========================================================================|====================*/ +#define MAX(x, y) (((x) < (y))?(y):(x)) // Returns maximum between two values +#define MIN(x, y) (((x) > (y))?(y):(x)) // Returns minimum between two values + /*================================================================================================*/ /** * @details This macro defines a simple operation to remove a supplied deliminator from a string. @@ -81,13 +141,31 @@ || |___ |__| | \| ___] | | | | \| | ___] || || || \*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ +/*================================================================================================*/ +/** + * @details String containing the header used for the cli output. + */ +/*================================================================================================*/ +static char bwc_header_art[] = "==============================================================\n"\ + " \n"\ + " .:-------------: .:-------------: \n"\ + " .+++++++++++++++= :+++++++++++++++- \n"\ + " :+++. -++= -++= \n"\ + " :+++. -++= -++= \n"\ + " -++++++++++++++= -++= -++= \n"\ + " .=++---------=++= -++= -++= \n"\ + " :+++ :++= -++= -++= \n"\ + " .+++=--------=+++---=+++---=+++------------: \n"\ + " -=++++++++++++++++++++++++++++++++++++++++- \n"\ + " \n"; + /*================================================================================================*/ /** * @details Character strings containing the cli version and bug report e-mail address. */ /*================================================================================================*/ const char *argp_program_version = "bwc 0.1.0"; -const char *argp_program_bug_address = "hpcpvogl@hlrs.de"; +const char *argp_program_bug_address = "patrick.vogler@hlrs.de"; /*================================================================================================*/ /** @@ -101,10 +179,10 @@ static char doc[] = "\n"\ "\n"\ "Available use cases:\n"\ "\n"\ - " Compression: bwc -c [INPUT] [OPTIONS]\n"\ - " Decompression: bwc -d [INPUT] [OPTIONS]\n"\ - " Analysis: bwc -a [INPUT] -r [REFERENCE]\n"\ - " Information: bwc -h [INPUT]\n"\ + " Compression: bwc -C [INPUT] [OPTIONS]\n"\ + " Decompression: bwc -D [INPUT] [OPTIONS]\n"\ + " Analysis: bwc -A [INPUT] -R [REFERENCE]\n"\ + " Information: bwc -H [INPUT]\n"\ "\n"\ "Valid Option Values:\n"\ "\n" @@ -117,13 +195,13 @@ static char doc[] = "\n"\ "\n" " Numerical values that can be specified globally or for\n" " all spacial and temporal directions individually:\n" - " ndir = * or ndir = x/y/z/ts.\n"; + " ndir = * or ndir = x,y,z,ts.\n"; /*"\n" " Single string.\n" " One or more strings seperated by commas: sarr = *,*,...\n" " Strings that can be specified globally or for all\n" " spacial and temporal directions individually:\n" - " sdir = * or sdir = x/y/z/ts.\n"*/ + " sdir = * or sdir = x,y,z,ts.\n"*/ //=================================================================================================| /** @@ -138,21 +216,21 @@ static struct argp_option options[] = { //====================|=====|============|====================|================================|===| {0, 0, 0, 0, " [FILE OPTIONS]\n", 1}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"analysis", 'a', "", 0, "Analyze Peak Signal to Noise" +{"analysis", 'A', "", 0, "Analyze Peak Signal to Noise" " Ratio (PSNR) and Mean Square" " Error (MSE) between input and" " reference file.\n", 1}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"comp", 'c', "", 0, "Compress a numerical dataset.", 1}, +{"comp", 'C', "", 0, "Compress a numerical dataset.", 1}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"decomp", 'd', "", 0, "Decompress a BigWhoop file.", 1}, +{"decomp", 'D', "", 0, "Decompress a BigWhoop file.", 1}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"header", 'h', "", 0, "Display the header information" +{"header", 'H', "", 0, "Display the header information" " of a BigWhoop file.\n", 1}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"output", 'o', "", 0, "Defines output file.", 1}, +{"output", 'O', "", 0, "Defines output file.", 1}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"reference", 'r', "", 0, "Reference file used for PSNR" +{"reference", 'R', "", 0, "Reference file used for PSNR" " and MSE calculation.", 1}, //====================|=====|============|====================|================================|===| //--------------------|-----|------------|--------------------|--------------------------------|---| @@ -165,9 +243,6 @@ static struct argp_option options[] = { "for error resilient decoding of" " compressed dataset.\n", 2}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"stream", 's', 0, OPTION_HIDDEN, "Stream data to and from " - "/.", 2}, -//--------------------|-----|------------|--------------------|--------------------------------|---| {"verbose", 'v', 0, 0, "Display compression statistics " "and applied compression " "parameters.", 2}, @@ -184,13 +259,13 @@ static struct argp_option options[] = { "point. Accepts real numbers in " "the range of 0 < * < 64.\n", 3}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"codeblock", 'B', "", 0, "Codeblock size in log2 format. " +{"codeblock", 'c', "", 0, "Codeblock size in log2 format. " "Accepts natural numbers in the " "range of 1 <= * <= 10 with the " "sum having to lie in the range " "of 4 < sum* < 20.\n", 3}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"decomplvl", 'D', "", 0, "Number of wavelet decomposi" +{"decomplvl", 'd', "", 0, "Number of wavelet decomposi" "tions applied to the data " "arrays. Accepts natural numbers" " in the range of 1 <= * <= 63." @@ -217,13 +292,13 @@ static struct argp_option options[] = { "Accepts real numbers in the " "range of 0 < * < 2.\n", 3}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"qformat", 'Q', "", 0, "Fractional bits of the Q number" +{"qformat", 'm', "", 0, "Fractional bits of the Q number" " format used in the floating-to" "-fixed point transfomration. " "Accepts natural numbers in the " "range of 1 <= * <= 62.\n", 3}, //--------------------|-----|------------|--------------------|--------------------------------|---| -{"compratio", 'R', "", 0, "Target ratio between the uncom" +{"compratio", 'r', "", 0, "Target ratio between the uncom" "presssed and compressed file " "size. Accepts positive real " "numbers.\n", 3}, @@ -254,11 +329,11 @@ static struct argp_option options[] = { /*=====================================================|==========================================*/ typedef enum { - cli_err, //!< Command-line interface error + cli_ini, //!< Undefined command line mode cli_cmp, //!< Compression run cli_dcp, //!< Decompression run cli_anl, //!< Analyse distortion of reconstr. file - cli_hdr, //!< Display header information + cli_inf, //!< Display BWC Header Information } cli_mode; /*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*\ @@ -274,15 +349,33 @@ typedef enum /*===========================|=========================|==========================================*/ typedef struct { + char *args[2]; cli_mode mode; //!< Current state of the cli tool + uint16_t optSet; //!< Flag signaling witch opt has been set - FILE *fpIn, *fpOut; //!< Pointer to input/output file - char* *in, *out; //!< Name of the input/output files + char *in, *out, *ref; //!< Name of the in/out/ref file - float bitrate[10]; //!< Quality layers defined by bitrate. + bool erresilience; //!< Flag signalling error resilience + bool verbose; //!< Flag signalling verbose output - bwc_stream *stream; //!< Structure defining the BigWhoop I/O - bwc_codec *codec; //!< Structure defining the BigWhoop codec + uint64_t tileSize[4]; //!< Spatial/Temporal tile size + uint8_t precSize[4]; //!< Spatial/Temporal precinct size + uint8_t cblkSize[4]; //!< Spatial/Temporal codeblock size + + bwc_dwt_filter dwtKernel[4]; //!< Spatial/Temporal wavelet kernels + + double rate[10]; //!< Quality layers defining rate ctrl. + uint8_t decompLevel[4]; //!< N.o. Spatial/temporal dwt decompo. + + double qt_step_size; //!< Global qunatization step size + uint8_t Qm; //!< Q number format range (m) + + uint8_t useLayer; //!< Quality layer used for decompression + + uint64_t nThreads; //!< Number of OpenMP threads + + //bwc_quant_st quantization_style; //!< Quantization style + //bwc_prog_ord progression; //!< Packet progression order } cli_arguments; @@ -294,8 +387,48 @@ typedef struct \*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/ /*================================================================================================*/ /** - * @details This function analyzes one option at a time and sets the corresponding value and - * passes arguments in the bwc_codec struct. + * @details This function takes the argument string, removes the supplied deliminators and + * verifies that the values are valid. If decimal is set to true the decimal point + * in a floating point value will be ignored. + * + * @param[in] arg Argument corresponding to the option key. + * @param[in] delim Character used to deliminate between values. + * @param[in] dec Bool signaling if string contains floating point values. + * + * @retval -1 Error + * @retval 0 OK + */ +/*================================================================================================*/ +static error_t +verify_opt(char *arg, char deliminator, bool decimal) +{ + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char *parse; + + remove_deliminator(arg, parse, deliminator); + + for(parse = arg; *parse; parse++) + { + if (decimal == true) + { + if (!isdigit(*parse) && *parse != ' ' && *parse != '.') + return EXIT_FAILURE; + } + else + { + if (!isdigit(*parse) && *parse != ' ') + return EXIT_FAILURE; + } + } + return EXIT_SUCCESS; +} + +/*================================================================================================*/ +/** + * @details This function analyzes one option at a time and sets the corresponding value in + * the cli arguments struct. * * @param[in] key Option's key corresponding to the field value in the arg_option struct. * @param[in] arg Argument corresponding to the option key. @@ -303,338 +436,857 @@ typedef struct * * @retval -1 Error * @retval 0 OK + */ +/*================================================================================================*/ static error_t parse_opt(int key, char *arg, struct argp_state *state) { - */ /*-----------------------*\ ! DEFINE INT VARIABLES: ! \*-----------------------*/ - //uint64_t buff_LL; - //uint64_t multiplier; - - //uint16_t buffI; -/* + int64_t buff; uint8_t i; - //uint8_t length, shift; - */ - /*-----------------------*\ ! DEFINE REAL VARIABLES: ! \*-----------------------*/ - /* + double compRatio; + double qt_step_size; float bitrate; - */ /*-----------------------*\ - ! DEFINE REAL VARIABLES: ! + ! DEFINE CHAR VARIABLES: ! \*-----------------------*/ - /* char *end; - */ + char *token, *ptr; /*-----------------------*\ ! DEFINE STRUCTS: ! \*-----------------------*/ - /* cli_arguments *arguments; - bwc_codec *codec; - bwc_stream *stream; - */ /*-----------------------*\ ! DEFINE ASSERTIONS: ! \*-----------------------*/ - /* assert(state); - */ - /*--------------------------------------------------------*\ - ! Save frequently used variables/structures to temporary ! - ! variables to make the code more readable. ! - \*--------------------------------------------------------*/ - /* + /* Save frequently used variables/structures to * + * temporary variables. */ arguments = state->input; - codec = arguments->codec; - stream = arguments->stream; - */ - /*--------------------------------------------------------*\ - ! Parse the cli arguments according to the supplied opt. ! - \*--------------------------------------------------------*/ - /* + /* Parse the cli arguments. */ switch(key) { - case 'c': + /* Ingest compression argument. */ + case 'C': { - arguments->mode = bwc_cmp; - printf("Compress\n"); - if(arg[0] == '-') + if (arguments->mode != cli_ini) { - argp_error(state, "No input specified\n"); + argp_error(state, "Arguments define multiple use cases.\n"); + } + else if ((arg == NULL) || (arg[0] == '-')) + { + argp_error(state, "file names that start with an '-'" + " are not supported.\n"); } else { - arguments->input = ; + arguments->mode = cli_cmp; + arguments->in = arg; } break; } - case 'd': + + /* Ingest decompression argument. */ + case 'D': { - arguments->mode = bwc_dcp; - printf("Decompress\n"); + if (arguments->mode != cli_ini) + { + argp_error(state, "Arguments define multiple use cases.\n"); + } + else if ((arg == NULL) || (arg[0] == '-')) + { + argp_error(state, "file names that start with an '-'" + " are not supported.\n"); + } + else + { + arguments->mode = cli_dcp; + arguments->in = arg; + } break; } - case 'a': + + /* Ingest analysis argument. */ + case 'A': { - //arguments->analysis = arg; + if (arguments->mode != cli_ini) + { + argp_error(state, "Arguments define multiple use cases.\n"); + } + else if ((arg == NULL) || (arg[0] == '-')) + { + argp_error(state, "file names that start with an '-'" + " are not supported.\n"); + } + else + { + arguments->mode = cli_anl; + arguments->in = arg; + } + break; } - case 'h': + + /* Ingest header info argument. */ + case 'H': { - //arguments->header = arg; + if (arguments->mode != cli_ini) + { + argp_error(state, "Arguments define multiple use cases.\n"); + } + else if ((arg == NULL) || (arg[0] == '-')) + { + argp_error(state, "file names that start with an '-'" + " are not supported.\n"); + } + else + { + arguments->mode = cli_inf; + arguments->in = arg; + } + break; } - case 'o': + + /* Ingest output argument. */ + case 'O': { - //arguments->output = arg; + if (arguments->optSet & FLOUT) + { + argp_error(state, "The output file can only be defined once.\n"); + } + + if ((arg == NULL) || (arg[0] == '-')) + { + argp_error(state, "file names that start with an '-'" + " are not supported.\n"); + } + else + { + arguments->out = arg; + arguments->optSet |= FLOUT; + } break; } - case 'r': + + /* Ingest reference argument. */ + case 'R': { - //arguments->reference = arg; - break; - } - case 's': - { - //arguments->stream = 1; + if (arguments->optSet & FLREF) + { + argp_error(state, "The reference file can only be defined once.\n"); + } + + if ((arg == NULL) || (arg[0] == '-')) + { + argp_error(state, "file names that start with an '-'" + " are not supported.\n"); + } + else + { + arguments->ref = arg; + arguments->optSet |= FLREF; + } break; } + + /* Ingest verbose argument. */ case 'v': { - //arguments->stream = 1; + arguments->verbose = true; break; } + + /* Ingest bit rates. */ case 'b': { - remove_deliminator(arg, end, ','); + if (arguments->optSet & BITRT) + { + argp_error(state, "The bitrate can only be defined once.\n"); + } + else if (arguments->optSet & CMPRT) + { + argp_error(state, "The size reduction requires to be specified " + "either by a bit rate or a compression ratio, " + "never both.\n"); + } + + if (verify_opt(arg, ',', true) == EXIT_FAILURE) + { + argp_error(state, "Invalid deliminator in the bitrate option\n"); + } for(bitrate = strtod(arg, &end), i = 0; arg != end && i < 10; bitrate = strtod(arg, &end), i++) { arg = end; - if(bitrate > 0 && bitrate < 64 && errno != ERANGE) + if (bitrate > 0 && bitrate <= 64 && errno != ERANGE) { - arguments->bitrate[i] = (float) bitrate; + arguments->rate[i] = (double) bitrate; } else { + errno = 0; argp_error(state, "The specified bitrate (%f) is " "out of the supported range.\n", bitrate); - - arguments->mode = cli_err; + } + } + + arguments->optSet |= BITRT; + break; + } + + /* Ingest codeblock size. */ + case 'c': + { + if (arguments->optSet & CBLKS) + { + argp_error(state, "The codeblock size can only be defined once.\n"); + } + + if (verify_opt(arg, ',', false) == EXIT_FAILURE) + { + argp_error(state, "Invalid deliminator in the codeblock" + " size option.\n"); + } + + for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; + buff = strtoll(arg, &end, 10), i++) + { + arg = end; + + if (buff >= 0 && buff <= 10 && errno != ERANGE) + { + arguments->cblkSize[i] = (uint8_t) buff; + } + else + { errno = 0; + argp_error(state, "The specified codeblock size (%ld) " + "is out of the supported range.\n", buff); break; } } - break; - } - case 'B': - { - // remove_deliminator(arg, end, '/'); - // for(buff_LL = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; - // buff_LL = strtoll(arg, &end, 10), i++) - // { - // arg = end; - // if (errno == ERANGE) - // { - // printf("range error, got "); - // errno = 0; - // } - - // if(buff_LL > 1 && buff_LL < 10) - // { - // arguments->codeblock[i] = (uint8_t) buff_LL; - // } - // else - // { - // argp_error(state, "The specified codeblock size (%ld) " - // "is out of the supported range.\n", buff_LL); - // } - // } - - // if(i == 1) - // { - // arguments->codeblock[1] = - // arguments->codeblock[2] = - // arguments->codeblock[3] = arguments->codeblock[0]; - // } - // else if(i != 4) - // { - // argp_error(state, "The codeblock argument expects either a " - // "single global or 4 dirctional values\n"); - // } - - // if(((arguments->codeblock[0] + arguments->codeblock[1] + - // arguments->codeblock[2] + arguments->codeblock[3]) < 4) || - // ((arguments->codeblock[0] + arguments->codeblock[1] + - // arguments->codeblock[2] + arguments->codeblock[3]) > 20)) - // { - // argp_error(state, "The sum of the specified codeblock sizes " - // "is outside of the supported range\n"); - // } - break; - } - case 'R': - { - // arguments->compratio = (uint8_t)strtoll(arg, &end, 10); - // printf("%d\n", arguments->compratio); - break; - } - case 'D': - { - */ -/* remove_deliminator(arg, end, '/'); - - for(buff_LL = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; - buff_LL = strtoll(arg, &end, 10), i++) + if (i == 1) { - arg = end; - if (errno == ERANGE) - { - printf("range error, got "); - errno = 0; - } - - if(buff_LL >= 1 && buff_LL <= 63) - { - arguments->codeblock[i] = (uint8_t) buff_LL; - } - else - { - argp_error(state, "The specified codeblock size (%ld) " - "is out of the supported range.\n", buff_LL); - } + arguments->cblkSize[1] = + arguments->cblkSize[2] = + arguments->cblkSize[3] = arguments->cblkSize[0]; } - - if(i == 1) - { - arguments->codeblock[1] = - arguments->codeblock[2] = - arguments->codeblock[3] = arguments->codeblock[0]; - } - else if(i != 4) + else if (i != 4) { argp_error(state, "The codeblock argument expects either a " "single global or 4 directional values\n"); - }*/ - /* + } + + arguments->optSet |= CBLKS; break; } + + /* Ingest compression ratio. */ + case 'r': + { + if (arguments->optSet & CMPRT) + { + argp_error(state, "The compression ratio can only be defined once.\n"); + } + else if (arguments->optSet & BITRT) + { + argp_error(state, "The size reduction requires to be specified " + "either by a bit rate or a compression ratio, " + "never both.\n"); + } + + if (verify_opt(arg, ',', true) == EXIT_FAILURE) + { + argp_error(state, "Invalid deliminator in the compression" + " ratio option \n"); + } + + for(compRatio = strtod(arg, &end), i = 0; arg != end && i < 10; + compRatio = strtod(arg, &end), i++) + { + arg = end; + + if (compRatio > 0 && compRatio < 65536 && errno != ERANGE) + { + arguments->rate[i] = (double) compRatio; + } + else + { + errno = 0; + argp_error(state, "The specified compression ratio (%f) is " + "out of the supported range.\n", compRatio); + } + } + + arguments->optSet |= CMPRT; + break; + } + + /* Ingest decomposition level. */ + case 'd': + { + if (arguments->optSet & DCLVL) + { + argp_error(state, "The compression ratio can only be defined once.\n"); + } + + if (verify_opt(arg, ',', false) == EXIT_FAILURE) + { + argp_error(state, "Invalid deliminator in the decomposition" + " level option.\n"); + } + + for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; + buff = strtoll(arg, &end, 10), i++) + { + arg = end; + + if (buff > 0 && buff <= 63 && errno != ERANGE) + { + arguments->decompLevel[i] = (uint8_t) buff; + } + else + { + errno = 0; + argp_error(state, "The specified decomposition level (%ld) " + "is out of the supported range.\n", buff); + break; + } + } + + if (i == 1) + { + arguments->decompLevel[1] = + arguments->decompLevel[2] = + arguments->decompLevel[3] = arguments->decompLevel[0]; + } + else if (i != 4) + { + argp_error(state, "The decomposition level argument expects either a " + "single global or 4 directional values\n"); + } + + arguments->optSet |= DCLVL; + break; + } + + /* Ingest number of OpenMP threads. */ case 'n': { - // buff_LL = strtoll(arg, &end, 10); - // if((buff_LL < 1) || (buff_LL > 255)) - // { - // argp_error(state, "The number of OpenMP threads specified" - // "is out of the supported range.\n"); - // } - // else - // { - // arguments->nthreads = (uint8_t)buff_LL; - // } + if (arguments->optSet & OMPTH) + { + argp_error(state, "The number of OpenMP threads can only be " + "defined once.\n"); + } + + buff = strtoll(arg, &end, 10); + + if (errno == ERANGE) + { + errno = 0; + argp_error(state, "The specified number of OpenMP threads (%ld) " + "is out of the supported range.\n", buff); + } + else + { + arguments->nThreads = (uint64_t) buff; + } + + arguments->optSet |= OMPTH; break; } + + /* Ingest quality layer to be used for decompression. */ case 'l': { - printf("l\n"); + if (arguments->optSet & USQLY) + { + argp_error(state, "The quality layer used for decompression" + " can only be defined once.\n"); + } + + buff = strtoll(arg, &end, 10); + + if (buff > 0 && buff <= 255 && errno != ERANGE) + { + errno = 0; + argp_error(state, "The specified quality layer (%ld) " + "is out of the supported range.\n", buff); + } + else + { + arguments->useLayer = (uint8_t) buff; + } + + arguments->optSet |= USQLY; break; } + + /* Ingest wavelet kernels. */ case 'k': { - printf("k\n"); + if (arguments->optSet & DWTKL) + { + argp_error(state, "The wavelet kernels can only be defined once.\n"); + } + + for(token = strtok_r(arg, ",", &ptr), i = 0; + token != NULL && i < 4; + token = strtok_r(NULL, ",", &ptr), i++) + { + if (strcasecmp(token, "leGall") == 0) + arguments->dwtKernel[i] = bwc_dwt_5_3; + else if (strcasecmp(token, "CDF") == 0) + arguments->dwtKernel[i] = bwc_dwt_9_7; + else if (strcasecmp(token, "Haar") == 0) + arguments->dwtKernel[i] = bwc_dwt_haar; + else + argp_error(state, "Waveket kernel %s is unknown " + "to the library.\n", token); + } + + if (i == 1) + { + arguments->dwtKernel[1] = + arguments->dwtKernel[2] = + arguments->dwtKernel[3] = arguments->dwtKernel[0]; + } + else if (i != 4) + { + argp_error(state, "The wavelet kernel argument expects either a " + "single global or 4 directional values\n"); + } + + arguments->optSet |= DWTKL; break; } + + /* Ingest quantization step size. */ case 'q': { - printf("q\n"); + if (arguments->optSet & QTSIZ) + { + argp_error(state, "The quantization step size can only be " + "defined once.\n"); + } + + qt_step_size = strtod(arg, &end); + + if (qt_step_size > 0 && qt_step_size < 2 && errno != ERANGE) + { + arguments->qt_step_size = (double) qt_step_size; + } + else + { + errno = 0; + argp_error(state, "The specified quantization step size (%f) is " + "out of the supported range.\n", qt_step_size); + } + + arguments->optSet |= QTSIZ; break; } - case 'Q': + + /* Ingest Q number format range. */ + case 'm': { - printf("Q\n"); + if (arguments->optSet & QFRMT) + { + argp_error(state, "The Q format range can only be defined once.\n"); + } + + buff = strtoll(arg, &end, 10); + if (buff > 0 && buff < 63 && errno != ERANGE) + { + arguments->Qm = (uint8_t) buff; + } + else + { + errno = 0; + argp_error(state, "The specified Q number format range (%ld) " + "is out of the supported range.\n", buff); + } + + arguments->optSet |= QFRMT; break; } + + /* Ingest error resilience setting. */ case 'e': { - printf("e\n"); + arguments->erresilience = true; break; } + + /* Ingest tile size. */ case 't': { - printf("t\n"); + if (arguments->optSet & TILES) + { + argp_error(state, "The tile size can only be defined once.\n"); + } + + if (verify_opt(arg, ',', false) == EXIT_FAILURE) + { + argp_error(state, "Invalid deliminator in the tile" + " size option.\n"); + } + + for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; + buff = strtoll(arg, &end, 10), i++) + { + arg = end; + + if (buff >= 16 && errno != ERANGE) + { + arguments->tileSize[i] = (uint64_t) buff; + } + else + { + errno = 0; + argp_error(state, "The specified tile size (%ld) " + "is out of the supported range.\n", buff); + break; + } + } + + if (i == 1) + { + arguments->tileSize[1] = + arguments->tileSize[2] = + arguments->tileSize[3] = arguments->tileSize[0]; + } + else if (i != 4) + { + argp_error(state, "The tile argument expects either a " + "single global or 4 directional values\n"); + } + + arguments->optSet |= TILES; break; } + + /* Ingest precinct size. */ case 'p': { - printf("p\n"); + if (arguments->optSet & PRECS) + { + argp_error(state, "The precinct size can only be defined once.\n"); + } + + if (verify_opt(arg, ',', false) == EXIT_FAILURE) + { + argp_error(state, "Invalid deliminator in the precinct" + " size option.\n"); + } + + for(buff = strtoll(arg, &end, 10), i = 0; arg != end && i < 4; + buff = strtoll(arg, &end, 10), i++) + { + arg = end; + + if (buff >= 0 && buff <= 15 && errno != ERANGE) + { + arguments->precSize[i] = (uint8_t) buff; + } + else + { + errno = 0; + argp_error(state, "The specified precinct size (%ld) " + "is out of the supported range.\n", buff); + break; + } + } + + if (i == 1) + { + arguments->precSize[1] = + arguments->precSize[2] = + arguments->precSize[3] = arguments->precSize[0]; + } + else if (i != 4) + { + argp_error(state, "The precinct argument expects either a " + "single global or 4 directional values\n"); + } + + arguments->optSet |= PRECS; break; } - case ARGP_KEY_NO_ARGS: - { - argp_usage (state); - break; - } - - case ARGP_KEY_ARG: - - // Too many arguments. - if(state->arg_num > 1) - argp_usage(state); - break; - + /* Check if the user supplied options fit the supported * + * use case. */ case ARGP_KEY_END: - */ - /*if(!((arguments->analysis != NULL) && (arguments->comp == NULL) - && (arguments->decomp == NULL) - && (arguments->header == NULL) - && (arguments->output == NULL) - && (arguments->reference != NULL)) && - !((arguments->comp != NULL) && (arguments->analysis == NULL) - && (arguments->decomp == NULL) - && (arguments->header == NULL) - && (arguments->reference == NULL)) && - !((arguments->decomp != NULL) && (arguments->analysis == NULL) - && (arguments->comp == NULL) - && (arguments->header == NULL) - && (arguments->reference == NULL)) && - !((arguments->header != NULL) && (arguments->analysis == NULL) - && (arguments->comp == NULL) - && (arguments->decomp == NULL) - && (arguments->output == NULL) - && (arguments->reference == NULL))) + { + if (((arguments->mode == cli_cmp || + arguments->mode == cli_dcp) && (arguments->in == NULL || arguments->ref != NULL)) || + (arguments->mode == cli_inf && (arguments->in == NULL || arguments->ref != NULL + || arguments->out != NULL)) || + (arguments->mode == cli_anl && (arguments->in == NULL || arguments->ref == NULL + || arguments->out != NULL))) { argp_error(state, "The User supplied options do not fit the " "supported use cases.\n"); - }*/ - /* + } + else if (arguments->mode == cli_ini) + { + argp_usage(state); + } break; + } + /* Output standard usage message if no arg is defined. */ + case ARGP_KEY_NO_ARGS: + { + if (arguments->mode == cli_ini) + argp_usage (state); + break; + } + + /* Return error if key is unknown. */ default: - return ARGP_ERR_UNKNOWN; + return ARGP_ERR_UNKNOWN; } return EXIT_SUCCESS; } -*/ -// initialize the argp struct. Which will be used to parse and use the args. -//static struct argp argp = {options, parse_opt, 0, doc}; +void +printheaderIO(char const *input, char const *output, char const *reference) +{ + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char cli_buffer[1024] = {0}; + char cli_verbose[4096] = {0}; + + strcat(cli_verbose, bwc_header_art); + strcat(cli_verbose, "--------------------------- I/O --------------------------\n\n"); + + sprintf(cli_buffer," Input: %s \n", input); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + sprintf(cli_buffer," Output: %s \n", output); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + sprintf(cli_buffer," Reference: %s \n", reference); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + printf("%s", cli_verbose); +} + +void +printctrl(bwc_gl_ctrl *const control) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint8_t i; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char cli_buffer[1024] = {0}; + char cli_verbose[4096] = {0}; + + strcat(cli_verbose, "\n"); + strcat(cli_verbose, "----------------- Compression Parameters -----------------\n"); + strcat(cli_verbose, "\n"); + + strcat(cli_verbose," Tile Size: \n"); + sprintf(cli_buffer," - Samples in 1.D: %27ld\n"\ + " - Samples in 2.D: %27ld\n"\ + " - Samples in 3.D: %27ld\n"\ + " - Samples in 4.D: %27ld\n", control->tileSizeX, + control->tileSizeY, + control->tileSizeZ, + control->tileSizeTS); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + strcat(cli_verbose, " __________________________________________________________\n"); + strcat(cli_verbose, "\n"); + strcat(cli_verbose, " 1.D | 2.D | 3.D | 4.D\n"); + sprintf(cli_buffer, " Decomposition Levels: %18d |%4d |%4d |%4d\n", + control->decompX, + control->decompY, + control->decompZ, + control->decompTS); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + sprintf(cli_buffer, " Precincts [log2]: %18d |%4d |%4d |%4d\n", + control->precSizeX, + control->precSizeY, + control->precSizeZ, + control->precSizeTS); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + sprintf(cli_buffer, " Codeblocks [log2]: %18d |%4d |%4d |%4d\n", + control->cbX, + control->cbY, + control->cbZ, + control->cbTS); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + strcat(cli_verbose, " __________________________________________________________\n"); + strcat(cli_verbose, "\n"); + + sprintf(cli_buffer, " Q Number Format: %27d\n", control->Qm); + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + if (control->error_resilience) + { + sprintf(cli_buffer, " Error Resilience: %27s\n", "true"); + } + else + { + sprintf(cli_buffer, " Error Resilience: %27s\n", "false"); + } + strcat(cli_verbose, cli_buffer); + memset(cli_buffer, '0', sizeof(char) * 1024); + + strcat(cli_verbose, " __________________________________________________________\n"); + strcat(cli_verbose, "\n"); + + for(i = 0; i < control->nLayers; ++i) + { + sprintf(cli_buffer, " Quality Layer Nr. %d: %33.2f bpd\n", i, + control->bitrate[i]); + strcat(cli_verbose, cli_buffer); + } + + memset(cli_buffer, '0', sizeof(char) * 1024); + strcat(cli_verbose, "\n==============================================================\n"); + printf("%s", cli_verbose); +} + +static unsigned char +output_analysis(eas3_data *const ref_data, eas3_data *const org_data) +{ + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t size; + uint64_t i; + + uint8_t p; + + /*-----------------------*\ + ! DEFINE FLOAT VARIABLES: ! + \*-----------------------*/ + double MSE, PSNR; + double peakVal; + double sum; + + double *dOrig, *dRef; + float *fOrig, *fRef; + + bwc_float minVal, maxVal; + + /*-----------------------*\ + ! DEFINE STRUCTS: ! + \*-----------------------*/ + eas3_param_names *param_name; + + dOrig = org_data->field.d; + dRef = ref_data->field.d; + + fOrig = org_data->field.f; + fRef = ref_data->field.f; + + if(org_data->params.ndim1 == ref_data->params.ndim1 && + org_data->params.ndim2 == ref_data->params.ndim2 && + org_data->params.ndim3 == ref_data->params.ndim3 && + org_data->params.nts == ref_data->params.nts && + org_data->params.npar == ref_data->params.npar) + { + size = (uint64_t)ref_data->params.ndim1 * ref_data->params.ndim2 * + ref_data->params.ndim3 * ref_data->params.nts; + + peakVal = -1.7976931348623157e+308; + PSNR = + MSE = 0; + + if(ref_data->param_names) + { + param_name = ref_data->param_names->root; + p = 0; + while(param_name != NULL) + { + minVal = 1.7976931348623157e+308; + maxVal = -1.7976931348623157e+308; + + if(ref_data->params.accuracy == 2) + { + for(i = 0; i < size; ++i) + { + minVal = MIN(minVal, (double)dRef[i + p * size]); + maxVal = MAX(maxVal, (double)dRef[i + p * size]); + + sum = ((double)dRef[i + p * size] - (double)dOrig[i + p * size]); + + MSE += sum * sum; + } + } + else if(ref_data->params.accuracy == 1) + { + for(i = 0; i < size; ++i) + { + minVal = MIN(minVal, (double)fRef[i + p * size]); + maxVal = MAX(maxVal, (double)fRef[i + p * size]); + + sum = ((double)fRef[i + p * size] - (double)fOrig[i + p * size]); + + MSE += sum * sum; + } + } + peakVal = MAX(peakVal, maxVal - minVal); + param_name = param_name->next; + p++; + } + } + + MSE /= (double)size * ref_data->params.npar; + PSNR = 20 * log10(peakVal/(2 * sqrt(MSE))); + + printf("==============================================================\n"); + printf(" Mean Square Error: %*.2e\n", 22, MSE); + printf(" Peak Signal-to-Noise Ratio: %*.2f\n", 22, PSNR); + printf("==============================================================\n"); + + } + + return EXIT_SUCCESS; +} + +/*================================================================================================*/ +/** + * @details Initialize the argp struct. used to parse the command line arguments + */ +/*================================================================================================*/ +static struct argp argp = {options, parse_opt, 0, doc, 0, 0, 0}; /*================================================================================================*/ /** @@ -650,97 +1302,463 @@ parse_opt(int key, /*================================================================================================*/ int main(int argc, char *argv[]) { - int i = 0; - int size = 0; + /*-----------------------*\ + ! DEFINE BOOL VARIABLES: ! + \*-----------------------*/ + bool delim = false; + + /*-----------------------*\ + ! DEFINE INT VARIABLES: ! + \*-----------------------*/ + uint64_t size = 0; + uint64_t root, Lfield; + uint8_t i; + uint8_t error_handle = EXIT_SUCCESS; + + /*-----------------------*\ + ! DEFINE REAL VARIABLES: ! + \*-----------------------*/ + double rtype, exp; + + /*-----------------------*\ + ! DEFINE CHAR VARIABLES: ! + \*-----------------------*/ + char rate[200] = {0}; + + char *cli_output = NULL; + char *buffer = NULL; + + unsigned char *input = NULL; + unsigned char *output = NULL; + + /*-----------------------*\ + ! DEFINE FILE POINTER: ! + \*-----------------------*/ + FILE *fp = NULL; + + /*-----------------------*\ + ! DEFINE DER. VARIABLES: ! + \*-----------------------*/ + bwc_precision precision; + bwc_header *header; + bwc_stream *stream = NULL; + bwc_codec *coder = NULL; + /*-----------------------*\ ! DEFINE STRUCTS: ! \*-----------------------*/ - cli_arguments arguments = {0}; + eas3_data *data = NULL; + eas3_data *ref_data = NULL; + cli_arguments arguments = {0}; - eas3_data *data; - uchar *input; - uchar *output; + /* Parse the command line arguments and invoke the appro- * + * priate bwccmdl mode. */ + if (argp_parse(&argp, argc, argv, 0, 0, &arguments) == EXIT_FAILURE) + { + error_handle = EXIT_FAILURE; + goto OUT; + } - data = read_eas3("TGV_125.eas"); + /* Set the number of OpenMP threads. */ + #if defined (_OPENMP) + if (arguments.optSet & OMPTH) + omp_set_num_threads((int)arguments.nThreads); + #endif - printf("I read eas3. No guarantees. Check validity. Compression will start now ...\n"); + /* Compress the user supplied data set. */ + if (arguments.mode == cli_cmp) + { + /* Evaluate the appropriate output file. */ + if ((arguments.optSet & FLOUT) == 0) + arguments.out = arguments.in; + if ((buffer = strrchr(arguments.out, '.')) == NULL) + { + error_handle = EXIT_FAILURE; + printf(TYPERROR); + goto OUT; + } + cli_output = calloc(strlen(arguments.out) - strlen(buffer) + 5, sizeof(char)); + if (cli_output == NULL) + { + error_handle = EXIT_FAILURE; + printf(MEMERROR); + goto OUT; + } + sprintf(cli_output, "%.*s.bwc", (int)(strlen(arguments.out) - strlen(buffer)), arguments.out); - size = data->params.ndim1 * data->params.ndim2 * - data->params.ndim3 * data->params.nts * - data->params.npar; + if (arguments.verbose == true) + { + printheaderIO(arguments.in, cli_output, arguments.ref); + } + + // TODO: Define a universal data structure and implement a reader + // that ingests different file formats + if ((data = read_eas3(arguments.in)) == NULL) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + /* Evaluate the input and output buffer size and initial- * + * size the BigWhoop data and coder structs. */ + size = data->params.ndim1 * data->params.ndim2 * + data->params.ndim3 * data->params.nts * + data->params.npar; - bwc_precision precision; - if (data->params.accuracy == 1) - { - precision = bwc_precision_single; - input = (uchar*)data->field.f; - output = calloc(size, sizeof(float)); - } - else if (data->params.accuracy == 2) - { - precision = bwc_precision_double; - input = (uchar*)data->field.d; - output = calloc(size, sizeof(double)); - } + if (data->params.accuracy == 1) + { + precision = bwc_precision_single; + input = (unsigned char*)data->field.f; + output = calloc(size, sizeof(float)); + } + else if (data->params.accuracy == 2) + { + precision = bwc_precision_double; + input = (unsigned char*)data->field.d; + output = calloc(size, sizeof(double)); + } - bwc_mode mode = comp; - bwc_stream* stream = bwc_init_stream(input, output, comp); - bwc_codec* coder = bwc_alloc_coder(data->params.ndim1, - data->params.ndim2, - data->params.ndim3, - data->params.nts, - data->params.npar, - precision); - // TODO: implement setters for codeblocks, decomposition etc. - //bwc_set_qm(coder, 32); - char rate[10]; // TODO: replace with cmdl argument - sprintf(rate, "%05.3f", 4.0); - rate[strlen(rate)-1] = '0'; - printf("rate %s \n", rate); + stream = bwc_init_stream(input, output, comp); + coder = bwc_alloc_coder(data->params.ndim1, + data->params.ndim2, + data->params.ndim3, + data->params.nts, + data->params.npar, + precision); + bwc_set_aux(stream, (char*)data->aux.ptr, data->aux.len); - bwc_create_compression(coder, stream, rate); - bwc_compress(coder, stream); - bwc_free_codec(coder); + if ((arguments.optSet & TILES) != 0) + { + bwc_set_tiles(coder, arguments.tileSize[0], + arguments.tileSize[1], + arguments.tileSize[2], + arguments.tileSize[3], bwc_tile_sizeof); - // TODO: implement I/O of bwc file - // TODO: bwc_header_info + } - write_eas3(data, "output.eas"); - data = read_eas3("output.eas"); - write_eas3(data, "output2.eas"); + // TODO: Implement the kernel setter as a global function + // and define the proper verbose output layout. + /*if ((arguments.optSet & DWTKL) != 0) + { + bwc_set_kernels(coder, arguments.dwtKernel[0], + arguments.dwtKernel[1], + arguments.dwtKernel[2], + arguments.dwtKernel[3]); + }*/ - eas3_free_data(data); - free(output); - - /*--------------------------------------------------------*\ - ! Initialize the arguments structure. ! - \*--------------------------------------------------------*/ - //arguments.stream = calloc(1, sizeof(bwc_stream)); - //arguments.codec = calloc(1, sizeof(bwc_codec)); - //if((arguments.stream == NULL) || - //(arguments.codec == NULL)) - //{ - // memory allocation error - //fprintf(stderr, MEMERROR); - //return EXIT_FAILURE; - //} + if ((arguments.optSet & DCLVL) != 0) + { + bwc_set_decomp(coder, arguments.decompLevel[0], + arguments.decompLevel[1], + arguments.decompLevel[2], + arguments.decompLevel[3]); + } - /*--------------------------------------------------------*\ - ! Parse the cli arguments. ! - \*--------------------------------------------------------*/ - //argp_parse(&argp, argc, argv, 0, 0, &arguments); - //if(arguments.mode == cli_err) - //{ - //return EXIT_FAILURE; - //} + if ((arguments.optSet & PRECS) != 0) + { + bwc_set_precincts(coder, arguments.precSize[0], + arguments.precSize[1], + arguments.precSize[2], + arguments.precSize[3]); + } - //for(i = 0; i < 10; ++i) - //printf("bitrate %d:\t%f\n",i,arguments.bitrate[i]); + if ((arguments.optSet & CBLKS) != 0) + { + bwc_set_codeblocks(coder, arguments.cblkSize[0], + arguments.cblkSize[1], + arguments.cblkSize[2], + arguments.cblkSize[3]); + } + if ((arguments.optSet & QFRMT) != 0) + { + bwc_set_qm(coder, arguments.Qm); + } + if (arguments.erresilience == true) + { + bwc_set_error_resilience(coder); - //printf("ARG1: %s", arguments.args[0]); - //printf("\nVERBOSE: %s", arguments.verbose? "yes" : "no"); - //printf("\nOption1: %s", arguments.option1); - //printf("\n"); + } + + /* Initialize the rate control string according to the * + * specified bit rate/compression ratio. */ + if ((arguments.optSet & BITRT) != 0) + { + rtype = 1.0; + exp = 1.0; + } + else if ((arguments.optSet & CMPRT) != 0) + { + rtype = 64.0; + exp = -1.0; + } + else + { + rtype = 1.0; + exp = 1.0; + arguments.rate[0] = 64; + } + + for(i = 0; i < 10 && strlen(rate) < 192; ++i) + { + if (arguments.rate[i] > 0) + { + sprintf(rate + strlen(rate), "%05.3f,", pow(arguments.rate[i]/rtype, exp)); + } + } + rate[strlen(rate) - 1] = '0'; + + if (bwc_create_compression(coder, stream, rate) == EXIT_FAILURE) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + if(arguments.verbose == true) + { + printctrl(&coder->control); + } + + size = bwc_compress(coder, stream); + + /* Write the codestream to the speicifed file. */ + fp = fopen(cli_output, "wb"); + if (fp == NULL) + { + error_handle = EXIT_FAILURE; + printf(FOUERROR); + goto OUT; + } + + if (fwrite(stream->out, sizeof(unsigned char), size, fp) != size) + { + error_handle = EXIT_FAILURE; + printf(WRTERROR); + goto OUT; + } + } + else if (arguments.mode == cli_dcp) + { + /* Evaluate the appropriate output file. */ + if ((arguments.optSet & FLOUT) == 0) + arguments.out = arguments.in; + if ((buffer = strrchr(arguments.out, '.')) == NULL) + { + error_handle = EXIT_FAILURE; + printf(TYPERROR); + goto OUT; + } + cli_output = calloc(strlen(arguments.out) - strlen(buffer) + 5, sizeof(char)); + if (cli_output == NULL) + { + error_handle = EXIT_FAILURE; + printf(MEMERROR); + goto OUT; + } + sprintf(cli_output, "%.*s.eas", (int)(strlen(arguments.out) - strlen(buffer)), arguments.out); + + if (arguments.verbose == true) + { + printheaderIO(arguments.in, cli_output, arguments.ref); + } + + if ((fp = fopen(arguments.in, "r")) == NULL) + { + error_handle = EXIT_FAILURE; + printf(FINERROR); + goto OUT; + } + + root = ftell(fp); + fseek(fp, 0L, SEEK_END); + Lfield = ftell(fp) - root; + fseek(fp, root, SEEK_SET); + + /* Read the compressed data from the input file. */ + input = calloc(Lfield, sizeof(unsigned char)); + if (fread(input, sizeof(unsigned char), Lfield, fp) != Lfield) + { + error_handle = EXIT_FAILURE; + printf(RDERROR); + goto OUT; + } + + /* Retrieve header information and allocate output buffer. */ + header = bwc_open_header(input); + size = header->info.nX * header->info.nY * header->info.nZ * + header->info.nTS * header->info.nPar; + if(header->info.data_prec == bwc_precision_double) + { + output = calloc(size, sizeof(double)); + } + else if(header->info.data_prec == bwc_precision_single) + { + output = calloc(size, sizeof(float)); + } + bwc_close_header(header); + + printctrl(&header->control); + + /* Initialize and run the decompression. */ + stream = bwc_init_stream(input, output, comp); + coder = bwc_alloc_decoder(); + if (bwc_create_decompression(coder, stream, 0) == EXIT_FAILURE) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + bwc_decompress(coder, stream); + + /* Parse decompressed data into eas3 data structure * + * and write to the output file. */ + data = calloc(1, sizeof(eas3_data)); + bwc_to_eas3(stream, data); + write_eas3(data, cli_output); + + goto OUT; + } + else if (arguments.mode == cli_anl) + { + if (arguments.verbose == true) + { + printheaderIO(arguments.in, cli_output, arguments.ref); + } + + /* Ingest the reference data input. */ + if ((ref_data = read_eas3(arguments.ref)) == NULL) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + + /* Ingest the compressed data input. */ + if ((fp = fopen(arguments.in, "r")) == NULL) + { + error_handle = EXIT_FAILURE; + printf(FINERROR); + goto OUT; + } + + root = ftell(fp); + fseek(fp, 0L, SEEK_END); + Lfield = ftell(fp) - root; + fseek(fp, root, SEEK_SET); + + /* Read the compressed data from the input file. */ + input = calloc(Lfield, sizeof(unsigned char)); + if (fread(input, sizeof(unsigned char), Lfield, fp) != Lfield) + { + error_handle = EXIT_FAILURE; + printf(RDERROR); + goto OUT; + } + + /* Retrieve header information and allocate output buffer. */ + header = bwc_open_header(input); + size = header->info.nX * header->info.nY * header->info.nZ * + header->info.nTS * header->info.nPar; + if(header->info.data_prec == bwc_precision_double) + { + output = calloc(size, sizeof(double)); + } + else if(header->info.data_prec == bwc_precision_single) + { + output = calloc(size, sizeof(float)); + } + bwc_close_header(header); + + if(arguments.verbose == true) + { + printctrl(&header->control); + } + + /* Initialize and run the decompression. */ + stream = bwc_init_stream(input, output, comp); + coder = bwc_alloc_decoder(); + if (bwc_create_decompression(coder, stream, 0) == EXIT_FAILURE) + { + error_handle = EXIT_FAILURE; + goto OUT; + } + bwc_decompress(coder, stream); + + /* Parse decompressed data into eas3 data structure * + * and write to the output file. */ + data = calloc(1, sizeof(eas3_data)); + bwc_to_eas3(stream, data); + + output_analysis(ref_data, data); + + goto OUT; + } + else if (arguments.mode == cli_inf) + { + printheaderIO(arguments.in, cli_output, arguments.ref); + + if ((fp = fopen(arguments.in, "r")) == NULL) + { + error_handle = EXIT_FAILURE; + printf(FINERROR); + goto OUT; + } + + root = ftell(fp); + fseek(fp, 0L, SEEK_END); + Lfield = ftell(fp) - root; + fseek(fp, root, SEEK_SET); + + /* Read the compressed data from the input file. */ + input = calloc(Lfield, sizeof(unsigned char)); + if (fread(input, sizeof(unsigned char), Lfield, fp) != Lfield) + { + error_handle = EXIT_FAILURE; + printf(RDERROR); + goto OUT; + } + + /* Retrieve header information. */ + header = bwc_open_header(input); + size = header->info.nX * header->info.nY * header->info.nZ * + header->info.nTS * header->info.nPar; + if(header->info.data_prec == bwc_precision_double) + { + output = calloc(size, sizeof(double)); + } + else if(header->info.data_prec == bwc_precision_single) + { + output = calloc(size, sizeof(float)); + } + bwc_close_header(header); + + printctrl(&header->control); + } + else + { + return EXIT_FAILURE; + } + +OUT: + if (coder != NULL) + bwc_free_codec(coder); + + if (data != NULL) + eas3_free_data(data); + + if (ref_data != NULL) + eas3_free_data(ref_data); + + if (stream !=NULL) + free(stream); + + if (output != NULL) + free(output); + + if (cli_output != NULL) + free(cli_output); + + if (fp != NULL) + fclose(fp); + + return error_handle; }