diff --git a/.github/workflows/developer.yml b/.github/workflows/developer.yml index 9f4defff..fa9dd0d5 100644 --- a/.github/workflows/developer.yml +++ b/.github/workflows/developer.yml @@ -21,6 +21,7 @@ jobs: env: FC: gfortran CC: gcc + LD_LIBRARY_PATH: "/home/runner/jasper/lib/" permissions: id-token: write @@ -31,7 +32,7 @@ jobs: - name: install run: | sudo apt-get update - sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config + sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config libopenblas-dev sudo apt-get install libpng-dev autotools-dev libaec-dev autoconf gcovr doxygen - name: cache-jasper @@ -39,7 +40,7 @@ jobs: uses: actions/cache@v4 with: path: ~/jasper - key: jasper-${{ runner.os }}-1.900.1 + key: jasper-${{ runner.os }}-4.0.0 - name: checkout-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' @@ -47,15 +48,15 @@ jobs: with: repository: jasper-software/jasper path: jasper - ref: version-1.900.1 + ref: version-4.0.0 - name: build-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' run: | cd jasper - ./configure --prefix=$HOME/jasper - make - make install + cmake -B build_dir -DCMAKE_INSTALL_PREFIX=~/jasper + cmake --build build_dir + cmake --install build_dir - name: checkout-ip uses: actions/checkout@v4 @@ -71,7 +72,23 @@ jobs: cd build cmake .. -DCMAKE_INSTALL_PREFIX=~/ip -DCMAKE_PREFIX_PATH=~ make -j2 - make install + make install + + - name: checkout-g2c + uses: actions/checkout@v4 + with: + repository: NOAA-EMC/NCEPLIBS-g2c + path: g2c + ref: develop + + - name: build-g2c + run: | + cd g2c + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/g2c -DCMAKE_PREFIX_PATH="~/jasper" + make -j2 + make install - name: checkout uses: actions/checkout@v4 @@ -90,10 +107,10 @@ jobs: cd wgrib2 mkdir build cd build - export CFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0' - export FCFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0' - export FFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0' - cmake .. -DENABLE_DOCS=ON -DFTP_TEST_FILES=ON -DCMAKE_PREFIX_PATH="~/ip;~/jasper" -DTEST_FILE_DIR=/home/runner/data -DUSE_NETCDF4=ON -DUSE_AEC=ON -DUSE_IPOLATES=ON -DUSE_JASPER=ON + export CFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0 -I/home/runner/g2c/include' + export FCFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0' + export FFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0' + cmake .. -DENABLE_DOCS=ON -DFTP_TEST_FILES=ON -DCMAKE_PREFIX_PATH="~/ip;~/jasper;~/g2c" -DTEST_FILE_DIR=/home/runner/data -DUSE_NETCDF4=ON -DUSE_AEC=ON -DUSE_IPOLATES=ON -DUSE_JASPER=ON make VERBOSE=1 ctest --verbose --output-on-failure --rerun-failed gcovr --root .. -v --html-details --exclude ../tests --exclude CMakeFiles --print-summary -o test-coverage.html &> /dev/null @@ -115,4 +132,4 @@ jobs: - name: Upload built documentation uses: actions/upload-pages-artifact@v1 with: - path: wgrib2/build/docs/html # Path to the built site files + path: wgrib2/build/docs/html # Path to the built site files \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 07168a58..da99120f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ cmake_minimum_required(VERSION 3.15) file(STRINGS "VERSION" pVersion) # Set up project with version number from VERSION file. -project(wgrib2 VERSION ${pVersion} LANGUAGES Fortran C) +project(wgrib2 VERSION ${pVersion} LANGUAGES C) # Handle user build options. option(ENABLE_DOCS "Enable generation of doxygen-based documentation." OFF) @@ -39,6 +39,10 @@ option(BUILD_LIB "Build wgrib2 library?" on) option(BUILD_SHARED_LIB "Build shared library?" off) option(BUILD_WGRIB "Build wgrib code?" off) +if (MAKE_FTN_API OR USE_IPOLATES) + enable_language(Fortran) +endif() + # Developers can use this option to specify a local directory which # holds the test files. They will be copied instead of fetching the # files via FTP. @@ -78,10 +82,6 @@ if(USE_G2CLIB) if(USE_PNG) message(FATAL_ERROR "If USE_G2CLIB is on, USE_PNG must be off") endif() - - if(USE_JASPER) - message(FATAL_ERROR "If USE_G2CLIB is on, USE_JASPER must be off") - endif() endif() # If user wants to use NCEPLIBS-ip, find it and the sp library. @@ -103,17 +103,13 @@ endif() message(STATUS "Checking if the user wants to use Jasper...") if(USE_JASPER) - list(APPEND definitions_list -DUSE_JASPER) - find_package(Jasper REQUIRED) - if(JASPER_VERSION_STRING VERSION_GREATER_EQUAL "1.900.25") - list(APPEND definitions_list -DJAS_VERSION_MAJOR=2) - endif() + find_package(g2c 1.9.0 CONFIG REQUIRED) endif() # Find required packages to use OpenJPEG message(STATUS "Checking if the user wants to use OpenJPEG...") if(USE_OPENJPEG) - find_package(OpenJPEG REQUIRED) +find_package(OpenJPEG REQUIRED) endif() message(STATUS "Checking if the user want to use OpenMP...") diff --git a/spack/package.py b/spack/package.py index 26a199d1..7ddd52a3 100644 --- a/spack/package.py +++ b/spack/package.py @@ -170,12 +170,15 @@ def url_for_version(self, version): conflicts("+openmp", when="%apple-clang") depends_on("ip@5.1:", when="@develop +ipolates") + depends_on("lapack", when="@develop +ipolates") depends_on("libaec@1.0.6:", when="@3.2: +aec") depends_on("netcdf-c", when="@3.2: +netcdf4") - depends_on("jasper@:2", when="@3.2: +jasper") + depends_on("jasper@:2", when="@3.2:3.4 +jasper") + depends_on("g2c", when="@develop +jasper") depends_on("zlib-api", when="@3.2: +png") depends_on("libpng", when="@3.2: +png") depends_on("openjpeg", when="@3.2: +openjpeg") + @when("@:2 ^gmake@4.2:") diff --git a/tests/run_jpeg_tests.sh b/tests/run_jpeg_tests.sh index a2035400..69c1c7a8 100644 --- a/tests/run_jpeg_tests.sh +++ b/tests/run_jpeg_tests.sh @@ -9,10 +9,10 @@ echo "" echo "*** Running wgrib2 jpeg tests" echo "*** Converting from jpeg to simple packing" -../wgrib2/wgrib2 data/gdaswave.t00z.wcoast.0p16.f000.grib2 -set_grib_type simple -grib_out jpeg2simple.grb -../wgrib2/wgrib2 jpeg2simple.grb -v2 -s > jpeg2simple.txt -touch jpeg2simple.txt -diff -w jpeg2simple.txt data/ref_jpeg2simple.txt +../wgrib2/wgrib2 data/gdaswave.t00z.wcoast.0p16.f000.grib2 -set_grib_type simple -grib_out junk_jpeg2simple.grb +../wgrib2/wgrib2 junk_jpeg2simple.grb -v2 -s > junk_jpeg2simple.txt +touch junk_jpeg2simple.txt +diff -w junk_jpeg2simple.txt data/ref_jpeg2simple.txt echo "*** SUCCESS!" -exit 0 \ No newline at end of file +exit 0 diff --git a/wgrib2/CMakeLists.txt b/wgrib2/CMakeLists.txt index 4a8033d3..6308b6c2 100644 --- a/wgrib2/CMakeLists.txt +++ b/wgrib2/CMakeLists.txt @@ -10,7 +10,7 @@ Check_pdt_size.c Checksum.c Cluster.c cname.c codetable_4_230.c CodeTable.c Code_Values.c Code_Values_JMA.c complex_pk.c Config.c copy.c crc32.c Cress_lola.c Csv.c Csv_long.c cubed_sphere2ll.c CubeFace2global.c Cyclic.c Data.c decenc_openjpeg.c dec_png_clone.c -Dump.c Earth.c Else.c enc_jpeg2000_clone.c End.c Endif.c Ensemble.c +Dump.c Earth.c Else.c End.c Endif.c Ensemble.c Ens_processing.c Ens_qc.c EOF.c Export_lonlat.c ExtName.c fatal_error.c Fcst_ave.c ffopen.c Fi.c File.c Fix_CFSv2_fcst.c Fix_ncep_2.c Fix_ncep_3.c Fix_ncep_4.c Fix_ncep.c Fix_undef.c @@ -88,12 +88,6 @@ if(USE_NETCDF) target_link_libraries(obj_lib PUBLIC NetCDF::NetCDF_C) endif() -if(USE_JASPER) - include_directories(${JASPER_INCLUDE_DIR}) - target_include_directories(obj_lib PUBLIC ${JASPER_INCLUDE_DIR}) - target_link_libraries(obj_lib PUBLIC ${JASPER_LIBRARIES}) -endif() - if(USE_PNG) target_link_libraries(obj_lib PUBLIC PNG::PNG) endif() @@ -102,9 +96,6 @@ if(OpenMP_C_FOUND) target_link_libraries(obj_lib PUBLIC OpenMP::OpenMP_C) endif() -if(USE_G2CLIB) -endif() - if(USE_IPOLATES) target_link_libraries(obj_lib PUBLIC ip::ip_d) @@ -128,6 +119,11 @@ if(USE_AEC) target_link_libraries(wgrib2_exe PRIVATE aec) endif() +if(USE_JASPER) + target_link_libraries(obj_lib PUBLIC g2c::g2c) + target_link_libraries(wgrib2_exe PRIVATE g2c::g2c) +endif() + if(USE_OPENJPEG) include_directories(${OPENJPEG_INCLUDE_DIRS}) target_link_libraries(wgrib2_exe PRIVATE ${OPENJPEG_LIBRARIES}) diff --git a/wgrib2/Config.c b/wgrib2/Config.c index 76f84fd1..d1d2e688 100644 --- a/wgrib2/Config.c +++ b/wgrib2/Config.c @@ -4,9 +4,6 @@ #include #include #include "wgrib2.h" -#ifdef USE_JASPER -#include -#endif #include "grb2.h" #include "fnlist.h" @@ -50,11 +47,8 @@ int f_config(ARG0) { strcat(inv_out, USE_AEC " is installed\n" ); #endif #ifdef USE_JASPER - strcat(inv_out, "Jasper "); - strcat(inv_out, jas_getversion()); - strcat(inv_out, " is installed\n"); + strcat(inv_out,USE_JASPER " is installed\n"); inv_out += strlen(inv_out); -// sprintf(inv_out,"JAS_VERSION_MAJOR=%d\n", JAS_VERSION_MAJOR); #endif #ifdef USE_OPENJPEG strcat(inv_out,USE_OPENJPEG " is installed\n"); diff --git a/wgrib2/enc_jpeg2000_clone.c b/wgrib2/enc_jpeg2000_clone.c deleted file mode 100644 index f19ddfa2..00000000 --- a/wgrib2/enc_jpeg2000_clone.c +++ /dev/null @@ -1,194 +0,0 @@ -#include -#include -#include "wgrib2.h" - -#ifdef USE_JASPER -#include -#define JAS_1_700_2 - -/* 2004-12-16 Public Domain Steve Gilbert */ - - -int enc_jpeg2000_clone(unsigned char *cin,int width,int height,int nbits, - int ltype, int ratio, int retry, char *outjpc, - int jpclen) -/*$$$ SUBPROGRAM DOCUMENTATION BLOCK -* . . . . -* SUBPROGRAM: enc_jpeg2000 Encodes JPEG2000 code stream -* PRGMMR: Gilbert ORG: W/NP11 DATE: 2002-12-02 -* -* ABSTRACT: This Function encodes a grayscale image into a JPEG2000 code stream -* specified in the JPEG2000 Part-1 standard (i.e., ISO/IEC 15444-1) -* using JasPer Software version 1.500.4 (or 1.700.2 ) written by the -* University of British Columbia, Image Power Inc, and others. -* JasPer is available at http://www.ece.uvic.ca/~mdadams/jasper/. -* -* PROGRAM HISTORY LOG: -* 2002-12-02 Gilbert -* 2004-12-16 Gilbert - Added retry argument/option to allow option of -* increasing the maximum number of guard bits to the -* JPEG2000 algorithm. -* -* USAGE: int enc_jpeg2000(unsigned char *cin,g2int width,g2int height, -* g2int nbits, g2int ltype, g2int ratio, -* g2int retry, char *outjpc, g2int jpclen) -* -* INPUT ARGUMENTS: -* cin - Packed matrix of Grayscale image values to encode. -* width - width of image -* height - height of image -* nbits - depth (in bits) of image. i.e number of bits -* used to hold each data value -* ltype - indicator of lossless or lossy compression -* = 1, for lossy compression -* != 1, for lossless compression -* ratio - target compression ratio. (ratio:1) -* Used only when ltype == 1. -* retry - Pointer to option type. -* 1 = try increasing number of guard bits -* otherwise, no additional options -* jpclen - Number of bytes allocated for new JPEG2000 code stream in -* outjpc. -* -* INPUT ARGUMENTS: -* outjpc - Output encoded JPEG2000 code stream -* -* RETURN VALUES : -* > 0 = Length in bytes of encoded JPEG2000 code stream -* -3 = Error decode jpeg2000 code stream. -* -5 = decoded image had multiple color components. -* Only grayscale is expected. -* -* REMARKS: -* -* Requires JasPer Software version 1.500.4 or 1.700.2 -* -* ATTRIBUTES: -* LANGUAGE: C -* MACHINE: IBM SP -* -*$$$*/ -{ - int ier,rwcnt; - jas_image_t image; - jas_stream_t *jpcstream,*istream; - jas_image_cmpt_t cmpt,*pcmpt; -#define MAXOPTSSIZE 1024 - char opts[MAXOPTSSIZE]; - -/* - printf(" enc_jpeg2000:width %ld\n",width); - printf(" enc_jpeg2000:height %ld\n",height); - printf(" enc_jpeg2000:nbits %ld\n",nbits); - printf(" enc_jpeg2000:jpclen %ld\n",jpclen); -*/ -// jas_init(); - -// -// Set lossy compression options, if requested. -// - if ( ltype != 1 ) { - opts[0]=(char)0; - } - else { - snprintf(opts,MAXOPTSSIZE,"mode=real\nrate=%f",1.0/(float)ratio); - } - if ( retry == 1 ) { // option to increase number of guard bits - strcat(opts,"\nnumgbits=4"); - } - //printf("SAGopts: %s\n",opts); - -// -// Initialize the JasPer image structure describing the grayscale -// image to encode into the JPEG2000 code stream. -// - image.tlx_=0; - image.tly_=0; -#ifdef JAS_1_500_4 - image.brx_=(uint_fast32_t)width; - image.bry_=(uint_fast32_t)height; -#endif -#ifdef JAS_1_700_2 - image.brx_=(jas_image_coord_t)width; - image.bry_=(jas_image_coord_t)height; -#endif - image.numcmpts_=1; - image.maxcmpts_=1; -#ifdef JAS_1_500_4 - image.colormodel_=JAS_IMAGE_CM_GRAY; /* grayscale Image */ -#endif -#ifdef JAS_1_700_2 - image.clrspc_=JAS_CLRSPC_SGRAY; /* grayscale Image */ - image.cmprof_=0; -#endif - - -/* - image.inmem_=1; - is only used for japser version 1.x up to 1.9.24 - for newer code the above line is removed - */ -#if JAS_VERSION_MAJOR == 1 - image.inmem_=1; -#endif -#ifndef JAS_VERSION_MAJOR - image.inmem_=1; -#endif - - - - - cmpt.tlx_=0; - cmpt.tly_=0; - cmpt.hstep_=1; - cmpt.vstep_=1; -#ifdef JAS_1_500_4 - cmpt.width_=(uint_fast32_t)width; - cmpt.height_=(uint_fast32_t)height; -#endif -#ifdef JAS_1_700_2 - cmpt.width_=(jas_image_coord_t)width; - cmpt.height_=(jas_image_coord_t)height; - cmpt.type_=JAS_IMAGE_CT_COLOR(JAS_CLRSPC_CHANIND_GRAY_Y); -#endif - cmpt.prec_=nbits; - cmpt.sgnd_=0; - cmpt.cps_=(nbits+7)/8; - - pcmpt=&cmpt; - image.cmpts_=&pcmpt; - -// -// Open a JasPer stream containing the input grayscale values -// - istream=jas_stream_memopen((char *)cin,height*width*cmpt.cps_); - cmpt.stream_=istream; - -// -// Open an output stream that will contain the encoded jpeg2000 -// code stream. -// - jpcstream=jas_stream_memopen(outjpc,(int)jpclen); - -// -// Encode image. -// - ier=jpc_encode(&image,jpcstream,opts); - if ( ier != 0 ) { - printf(" jpc_encode return = %d \n",ier); - return -3; - } -// -// Clean up JasPer work structures. -// - rwcnt=jpcstream->rwcnt_; - ier=jas_stream_close(istream); - ier=jas_stream_close(jpcstream); -// -// Return size of jpeg2000 code stream -// - return (rwcnt); - -} - -#endif diff --git a/wgrib2/jpeg_pk.c b/wgrib2/jpeg_pk.c index 495d49ca..cc4661cf 100644 --- a/wgrib2/jpeg_pk.c +++ b/wgrib2/jpeg_pk.c @@ -7,6 +7,10 @@ #include "wgrib2.h" #include "fnlist.h" +#ifdef USE_JASPER + #include "grib2.h" +#endif + /* 10/2024 Public Domain Wesley Ebisuzaki */ #if defined USE_JASPER || defined USE_OPENJPEG @@ -163,11 +167,11 @@ int jpeg2000_grib_out(unsigned char **sec, float *data, unsigned int ndata, outjpc = (char *) malloc(jpclen); #ifdef USE_JASPER - i = enc_jpeg2000_clone(cdata,ix,iy,nbits,ltype,ratio,retry,outjpc,jpclen); + i = g2c_enc_jpeg2000(cdata,ix,iy,nbits,ltype,ratio,retry,outjpc,jpclen); // we try to catch following error: "error: too few guard bits (need at least x)" if (i == -3) { retry = 1; - i = enc_jpeg2000_clone(cdata,ix,iy,nbits,ltype,ratio,retry,outjpc,jpclen); + i = g2c_enc_jpeg2000(cdata,ix,iy,nbits,ltype,ratio,retry,outjpc,jpclen); } free(cdata); #endif diff --git a/wgrib2/unpk.c b/wgrib2/unpk.c index 42b3e854..eae07106 100644 --- a/wgrib2/unpk.c +++ b/wgrib2/unpk.c @@ -12,13 +12,14 @@ #include "wgrib2.h" #include "grb2.h" +#ifdef USE_JASPER + #include "grib2.h" +#endif + #ifdef USE_PNG #include int i; #endif -#ifdef USE_JASPER - #include -#endif #ifdef USE_AEC #include @@ -49,15 +50,7 @@ int unpk_grib(unsigned char **sec, float *data) { int width, height; #endif -#ifdef USE_JASPER - jas_image_t *image; - char *opts; - jas_stream_t *jpcstream; - jas_image_cmpt_t *pcmpt; - jas_matrix_t *jas_data; - int j, k; -#endif -#ifdef USE_OPENJPEG +#if (defined USE_JASPER || defined USE_OPENJPEG) int *ifld, err; unsigned int kk; #endif @@ -201,47 +194,25 @@ int unpk_grib(unsigned char **sec, float *data) { // decode jpeg2000 #ifdef USE_JASPER + ifld = (int *) malloc(ndata * sizeof(int)); + if (ifld == 0) fatal_error("unpk: memory allocation error",""); + err = g2c_dec_jpeg2000((char *) sec[7]+5, (size_t) GB2_Sec7_size(sec)-5, ifld); + if (err != 0) fatal_error_i("dec_jpeg2000, error %d",err); - image = NULL; - opts = NULL; - jpcstream=jas_stream_memopen((char *) sec[7]+5, (int) GB2_Sec7_size(sec)-5); - image = jpc_decode(jpcstream, opts); - if (image == NULL) fatal_error("jpeg2000 decoding", ""); - pcmpt = image->cmpts_[0]; - if (image->numcmpts_ != 1 ) - fatal_error("unpk: Found color image. Grayscale expected",""); - - jas_data=jas_matrix_create(jas_image_height(image), jas_image_width(image)); - jas_image_readcmpt(image,0,0,0,jas_image_width(image), jas_image_height(image),jas_data); - - // transfer data - - k = ndata - pcmpt->height_ * pcmpt->width_; - -// #pragma omp parallel for private(ii,j) - for (ii=0;iiheight_;ii++) { - for (j=0;jwidth_;j++) { -// data[k++] = (((jas_data->rows_[ii][j])*bin_scale)+reference)*dec_scale; - data[k+j+ii*pcmpt->width_] = (((jas_data->rows_[ii][j])*bin_scale)+reference)*dec_scale; - } - } - - if (bitmap_flag == 0 || bitmap_flag == 254) { - k = ndata - pcmpt->height_ * pcmpt->width_; - mask_pointer = sec[6] + 6; - mask = 0; + if (bitmap_flag == 0 || bitmap_flag == 254) { + mask_pointer = sec[6] + 6; + mask = 0; + kk = 0; for (ii = 0; ii < ndata; ii++) { - if ((ii & 7) == 0) mask = *mask_pointer++; - data[ii] = (mask & 128) ? data[k++] : UNDEFINED; - mask <<= 1; + if ((ii & 7) == 0) mask = *mask_pointer++; + data[ii] = (mask & 128) ? ((ifld[kk++]*bin_scale)+reference)*dec_scale : UNDEFINED; + mask <<= 1; } - } + } else if (bitmap_flag != 255) { fatal_error_i("unknown bitmap: %d", bitmap_flag); } - jas_matrix_destroy(jas_data); - jas_stream_close(jpcstream); - jas_image_destroy(image); + free(ifld); return 0; #endif #ifdef USE_OPENJPEG diff --git a/wgrib2/wgrib2.h b/wgrib2/wgrib2.h index 6339601c..95005b15 100644 --- a/wgrib2/wgrib2.h +++ b/wgrib2/wgrib2.h @@ -503,8 +503,6 @@ int scaling(unsigned char **sec, double *base, int *decimal, int *binary, int *n unsigned char *mk_bms(float *data, unsigned int *ndata); int dec_png_clone(unsigned char *pngbuf,int *width,int *height, unsigned char *cout, int *grib2_bit_depth, unsigned int ndata); -int enc_jpeg2000_clone(unsigned char *cin,int width,int height,int nbits, int ltype, - int ratio, int retry, char *outjpc, int jpclen); #ifdef USE_OPENJPEG int dec_jpeg2000_clone(char *injpc, int bufsize, int *outfld); int enc_jpeg2000_clone_float(float *data, int width, int height, int nbits,