diff --git a/.github/workflows/Linux_options.yml b/.github/workflows/Linux_options.yml index 8f132418..853f8032 100644 --- a/.github/workflows/Linux_options.yml +++ b/.github/workflows/Linux_options.yml @@ -18,17 +18,14 @@ concurrency: jobs: Linux_options: - runs-on: ubuntu-latest - env: - FC: gfortran - CC: gcc + runs-on: ubuntu-24.04 strategy: # fail-fast: true matrix: config: - { - options: "-DUSE_IPOLATES=ON" + options: "-DUSE_IPOLATES=ON -DBLA_VENDOR=OpenBLAS" } - { options: "-DUSE_AEC=ON" @@ -42,21 +39,30 @@ jobs: - { options: "-DUSE_OPENJPEG=ON" } + gcc-version: [12] + include: + - gcc-version: 14 steps: - name: install run: | sudo apt-get update - sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config - sudo apt-get install libpng-dev autotools-dev autoconf libaec-dev + sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config \ + libpng-dev autotools-dev autoconf libaec-dev libopenblas-serial-dev \ + libopenjp2-7 libopenjp2-7-dev + if [ -z $(type -P gcc-${{ matrix.gcc-version }}) ]; then + sudo apt-get install gcc-${{ matrix.gcc-version }} gfortran-${{ matrix.gcc-version }} + fi + echo "CC=gcc-${{ matrix.gcc-version }}" >> $GITHUB_ENV + echo "FC=gfortran-${{ matrix.gcc-version }}" >> $GITHUB_ENV - name: cache-jasper id: cache-jasper uses: actions/cache@v3 with: path: ~/jasper - key: jasper-${{ runner.os }}-1.900.1 + key: jasper-${{ runner.os }}-gcc${{ matrix.gcc-version }}-1.900.1 - name: checkout-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' @@ -70,7 +76,7 @@ jobs: if: steps.cache-jasper.outputs.cache-hit != 'true' run: | cd jasper - ./configure --prefix=$HOME/jasper + CFLAGS="-Wno-implicit-function-declaration -Wno-incompatible-pointer-types" ./configure --prefix=$HOME/jasper make make install @@ -79,7 +85,7 @@ jobs: uses: actions/cache@v3 with: path: ~/ip - key: ip-${{ runner.os }}-develop + key: ip-${{ runner.os }}-gcc${{ matrix.gcc-version }}-develop - name: checkout-ip if: steps.cache-ip.outputs.cache-hit != 'true' diff --git a/.github/workflows/developer.yml b/.github/workflows/developer.yml index 9f4defff..6755a5f8 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 -DMAKE_FTN_API=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..5180776b 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) @@ -35,10 +35,19 @@ option(FTP_EXTRA_TEST_FILES "Fetch even more large files from FTP and test them. option(MAKE_FTN_API "add ftn api?" off) option(DISABLE_STAT "disable posix feature" off) set(BUILD_COMMENTS "stock build") + option(BUILD_LIB "Build wgrib2 library?" on) -option(BUILD_SHARED_LIB "Build shared library?" off) +# if BUILD_LIB, then code is compiled as relocatable +option(BUILD_SHARED_LIB "Build shared library?" on) +# To create libwgrib2.so for python, you have to build with BUILD_SHARED_LIB off +# and manually create libwgrib2.so from the needed *.a files + 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 +87,10 @@ if(USE_G2CLIB) if(USE_PNG) message(FATAL_ERROR "If USE_G2CLIB is on, USE_PNG must be off") endif() +endif() - if(USE_JASPER) - message(FATAL_ERROR "If USE_G2CLIB is on, USE_JASPER must be off") - endif() +if (BUILD_SHARED_LIB AND NOT BUILD_LIB) + message(FATAL_ERROR "BUILD_SHARED_LIB is on but BUILD_LIB is off") endif() # If user wants to use NCEPLIBS-ip, find it and the sp library. @@ -103,28 +112,18 @@ 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...") if(USE_OPENMP) - find_package(OpenMP) - if(OpenMP_CXX_FOUND) - target_link_libraries(MyTarget PUBLIC OpenMP::OpenMP_CXX) - endif() -# if(OpenMP_Fortran_FOUND) -# target_link_libraries(MyTarget PUBLIC OpenMP::OpenMP_Fortran) -# endif() + find_package(OpenMP REQUIRED COMPONENTS C) endif() message(STATUS "Checking if the user wants to use PNG...") 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/CMakeLists.txt b/tests/CMakeLists.txt index d14fced4..e8a0ee3b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -166,6 +166,17 @@ if (USE_JASPER OR USE_OPENJPEG) copy_test_data(ref_jpeg2simple.txt) endif() +if (MAKE_FTN_API) + shell_test(test_ftn_api) +endif() +if (BUILD_LIB) + shell_test(test_lib) +endif() +if (BUILD_SHARED_LIB) + shell_test(test_shared_lib) +endif() + + if (FTP_TEST_FILES) copy_test_data(ref_WW3_Regional_US_West_Coast_20220718_0000.grib2.inv) copy_test_data(ref_merge_fcst.aqm.t12z.max_8hr_o3.227.grib2.txt) 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/tests/run_wgrib2_tests.sh b/tests/run_wgrib2_tests.sh index fbabce13..7dde2e92 100755 --- a/tests/run_wgrib2_tests.sh +++ b/tests/run_wgrib2_tests.sh @@ -112,5 +112,18 @@ echo "*** Testing write/read section" touch secs.txt diff -w secs.txt simple.txt + +echo "*** test pdt 48 ***" +n=`../wgrib2/wgrib2 ./data/gdas.t12z.pgrb2.1p00.anl.75r.grib2 -d 1 -set_pdt +48 -set_byte 4 12 00:12:0 | grep -c "aerosol_size"` +if [ "$n" -ne 1 ] ; then + exit 1 +fi +set -x +echo "*** test pdt 49 ***" +n=`../wgrib2/wgrib2 ./data/gdas.t12z.pgrb2.1p00.anl.75r.grib2 -d 1 -set_pdt +49 -set_byte 4 12 00:12:0 | grep -c "aerosol_size"` +if [ "$n" -ne 1 ] ; then + exit 1 +fi + echo "*** SUCCESS!" exit 0 diff --git a/tests/test_ftn_api.sh b/tests/test_ftn_api.sh new file mode 100755 index 00000000..fe8b079b --- /dev/null +++ b/tests/test_ftn_api.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# script to see if ftn_api compiled +# + +echo "see if ftn_api compiled" +set -xe + +if [ ! -f ../wgrib2/ftn_api/include/wgrib2api.mod ] ; then + echo "failed: did not find wgrib2api.mod" + exit 1 +fi + +echo "*** SUCCESS!" +exit 0 diff --git a/tests/test_lib.sh b/tests/test_lib.sh new file mode 100755 index 00000000..a7c46f1e --- /dev/null +++ b/tests/test_lib.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# script to see if shared lib was made +# + +echo "see if shared library made" +set -xe + +if [ ! -f ../wgrib2/libwgrib2.so -a ! -f ../wgrib2/libwgrib2.a ] ; then + echo "failed: did not find libwgrib2" + exit 1 +fi + +echo "*** SUCCESS!" +exit 0 diff --git a/tests/test_shared_lib.sh b/tests/test_shared_lib.sh new file mode 100755 index 00000000..fd96f986 --- /dev/null +++ b/tests/test_shared_lib.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# +# script to see if shared lib was made +# + +echo "see if shared library made" +set -xe + +if [ ! -f ../wgrib2/libwgrib2.so ] ; then + echo "failed: did not find libwgrib2.so" + exit 1 +fi + +echo "*** SUCCESS!" +exit 0 diff --git a/wgrib2/Aerosol.c b/wgrib2/Aerosol.c index 3ddf45be..9a458052 100644 --- a/wgrib2/Aerosol.c +++ b/wgrib2/Aerosol.c @@ -6,6 +6,7 @@ /* * 2/2012 Public Domain: Wesley Ebisuzaki + * 10/2024 fix to handle all pdts Wesley Ebisuzaki */ /* @@ -13,24 +14,19 @@ */ int f_aerosol_size(ARG0) { - int pdt, type; - unsigned char *sec4; + unsigned char *ptr; double size1, size2; - + if (mode >= 0) { - pdt = code_table_4_0(sec); - if (pdt < 44 || pdt > 48) return 0; - type = code_table_4_91(sec); - if (type == 255) return 0; - sec4 = sec[4]; - - size1 = scaled2dbl(INT1(sec4[14]), int4(sec4+15)); - size2 = scaled2dbl(INT1(sec4[19]), int4(sec4+20)); + ptr = code_table_4_91_location(sec); + if (ptr == NULL) return 0; + if (*ptr == 255) return 0; + size1 = scaled2dbl(INT1(ptr[1]), int4(ptr+2)); + size2 = scaled2dbl(INT1(ptr[6]), int4(ptr+7)); sprintf(inv_out,"aerosol_size "); inv_out += strlen(inv_out); - type = code_table_4_91(sec); - prt_code_table_4_91(type, size1, size2, inv_out); + prt_code_table_4_91(ptr[0], size1, size2, inv_out); } return 0; @@ -40,23 +36,19 @@ int f_aerosol_size(ARG0) { */ int f_aerosol_wavelength(ARG0) { - int pdt, type; - unsigned char *sec4; + unsigned char *ptr; double wave1, wave2; if (mode >= 0) { - pdt = code_table_4_0(sec); - if (pdt != 48) return 0; - type = code_table_4_91b(sec); - if (type == 255) return 0; - sec4 = sec[4]; - - wave1 = scaled2dbl(INT1(sec4[25]), int4(sec4+26)); - wave2 = scaled2dbl(INT1(sec4[30]), int4(sec4+31)); + ptr = code_table_4_91b_location(sec); + if (ptr == NULL) return 0; + if (*ptr == 255) return 0; + wave1 = scaled2dbl(INT1(ptr[1]), int4(ptr+2)); + wave2 = scaled2dbl(INT1(ptr[6]), int4(ptr+7)); sprintf(inv_out,"aerosol_wavelength "); inv_out += strlen(inv_out); - prt_code_table_4_91(type, wave1, wave2, inv_out); + prt_code_table_4_91(ptr[0], wave1, wave2, inv_out); } return 0; diff --git a/wgrib2/CMakeLists.txt b/wgrib2/CMakeLists.txt index 4a8033d3..ec750d72 100644 --- a/wgrib2/CMakeLists.txt +++ b/wgrib2/CMakeLists.txt @@ -2,6 +2,19 @@ # subdirectory. # # Kyle Gerheiser, Edward Hartnett, Wesley Ebisuzaki +# +# if BUILD_SHARED_LIB +# ftn_api -> shared library, interface to fortran +# wgrib2_lib -> shared (includes gctpc) +# +# if !BUILD_SHARED_LIB +# ftn_api -> static library, interface to fortran +# wgrib2_lib -> static library includeing gctpc +# +# note: in wgrib2 v3.1.3 or earlier, all the libraries +# incuding aec, jasper, etc were included with the wgrib2 library +# in github version, it is different. + # sets lib_src set(lib_src AAIG.c AAIGlong.c addtime.c aec_pk.c Aerosol.c Alarm.c @@ -10,7 +23,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 @@ -44,14 +57,16 @@ Type_reftime.c UDF.c Undefine.c units.c Unix_time.c Unmerge_fcst.c unpk_0.c unpk.c unpk_complex.c unpk_run_length.c update_sec3.c update_sec4.c v1_v2_if.c VerfTime.c Warn_old_g2lib.c Waves.c wgrib2_api.c wgrib2.c Wind_dir.c Wind_speed.c Wind_uv.c Write_sec.c -Wrt_grib.c wrtieee.c wxtext.c) +Wrt_grib.c wrtieee.c wxtext.c +) + +include_directories(gctpc/source/include) +add_subdirectory(gctpc) if(MAKE_FTN_API) add_subdirectory(ftn_api) endif() -add_subdirectory(gctpc) - # make this an object lib so we can re-use most of object files # The only files that differ are ${callable_src} which are compiled # with -DCALLABLE_WGRIB2 @@ -67,46 +82,40 @@ configure_file ( if(BUILD_LIB) - # with -DCALLABLE_WGRIB2 for the lib if(BUILD_SHARED_LIB) - add_library(wgrib2_lib SHARED ${lib_src} $ ${callable_src}) + add_library(wgrib2_lib SHARED ${lib_src} ) + set_property(TARGET wgrib2_lib PROPERTY POSITION_INDEPENDENT_CODE ON) else() - add_library(wgrib2_lib STATIC ${lib_src} $ ${callable_src}) + add_library(wgrib2_lib STATIC ${lib_src} $ ) +# add_library(wgrib2_lib STATIC ${lib_src} ) + set_property(TARGET wgrib2_lib PROPERTY POSITION_INDEPENDENT_CODE ON) endif() # library and executable have same name (wgrib2) but different target names set_target_properties(wgrib2_lib PROPERTIES OUTPUT_NAME wgrib2) - target_compile_definitions(wgrib2_lib PRIVATE CALLABLE_WGRIB2) + # target_compile_definitions(wgrib2_lib PRIVATE CALLABLE_WGRIB2) endif() -# without -DCALLABLE_WGRIB2 for the executable -add_executable(wgrib2_exe ${callable_src}) +add_executable(wgrib2_exe wgrib2_main.c) set_target_properties(wgrib2_exe PROPERTIES OUTPUT_NAME wgrib2) 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}) + target_link_libraries(wgrib2_exe PUBLIC NetCDF::NetCDF_C) endif() if(USE_PNG) target_link_libraries(obj_lib PUBLIC PNG::PNG) endif() -if(OpenMP_C_FOUND) +if(USE_OPENMP) 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) + target_link_libraries(wgrib2_exe PUBLIC ip::ip_d) # Link to the Fortran runtime library for each compiler if using ip2. # The wgrib2 exectuable is created using the C compiler and @@ -119,13 +128,18 @@ if(USE_IPOLATES) endif() -target_link_libraries(obj_lib PUBLIC gctpc -lm) +## target_link_libraries(obj_lib PUBLIC gctpc -lm) -# Link to gctpc directly because oobject libraries do not link transitively -target_link_libraries(wgrib2_exe PRIVATE gctpc) +# Link to gctpc directly because object libraries do not link transitively +target_link_libraries(wgrib2_exe PRIVATE gctpc -lm) if(USE_AEC) - target_link_libraries(wgrib2_exe PRIVATE aec) + target_link_libraries(wgrib2_exe PRIVATE ${LIBAEC_LIBRARIES}) +endif() + +if(USE_JASPER) + target_link_libraries(obj_lib PUBLIC g2c::g2c) + target_link_libraries(wgrib2_exe PRIVATE g2c::g2c) endif() if(USE_OPENJPEG) @@ -134,10 +148,11 @@ if(USE_OPENJPEG) endif() target_link_libraries(wgrib2_exe PRIVATE obj_lib) +# target_link_libraries(wgrib2_exe PRIVATE wgrib2_lib) if(BUILD_LIB) set(headers wgrib2_api.h wgrib2.h ${CMAKE_BINARY_DIR}/wgrib2/wgrib2_meta.h) - target_link_libraries(wgrib2_lib PUBLIC gctpc) +## target_link_libraries(wgrib2_lib PUBLIC gctpc) set_target_properties(wgrib2_lib PROPERTIES PUBLIC_HEADER "${headers}") target_compile_definitions(wgrib2_lib PUBLIC ${definitions_list}) @@ -160,6 +175,3 @@ install( ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) - - - 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/ExtName.c b/wgrib2/ExtName.c index 19850e88..af5b4390 100644 --- a/wgrib2/ExtName.c +++ b/wgrib2/ExtName.c @@ -188,9 +188,8 @@ int f_misc(ARG0) { strcat(inv_out,":"); inv_out += strlen(inv_out); } - if (pdt == 48) { + if (pdt == 48 || pdt == 49) { /* aerosol with optical properties */ f_aerosol_size(call_ARG0(inv_out,NULL)); - strcat(inv_out,":"); inv_out += strlen(inv_out); f_aerosol_wavelength(call_ARG0(inv_out,NULL)); strcat(inv_out,":"); 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/fatal_error.c b/wgrib2/fatal_error.c index 7b94a430..2c6d949c 100644 --- a/wgrib2/fatal_error.c +++ b/wgrib2/fatal_error.c @@ -1,9 +1,9 @@ #include #include #include -#ifdef CALLABLE_WGRIB2 + #include -#endif + #include "wgrib2.h" /* @@ -17,9 +17,9 @@ * fprintf(ARGS) * do_fatal_error_processing */ -#ifdef CALLABLE_WGRIB2 + extern jmp_buf fatal_err; -#endif + void fatal_error(const char *fmt, ...) @@ -32,9 +32,9 @@ void fatal_error(const char *fmt, ...) va_end(arg); err_bin(1); err_string(1); -#ifdef CALLABLE_WGRIB2 + longjmp(fatal_err,1); -#endif + exit(8); return; } diff --git a/wgrib2/ftn_api/CMakeLists.txt b/wgrib2/ftn_api/CMakeLists.txt index 7a8a8c3a..81a77dbc 100644 --- a/wgrib2/ftn_api/CMakeLists.txt +++ b/wgrib2/ftn_api/CMakeLists.txt @@ -13,21 +13,26 @@ set(c_src fort_wgrib2.c ) -add_library(wgrib2_api ${fortran_src} ${c_src}) +if (BUILD_SHARED_LIB) + add_library(wgrib2_ftn_api SHARED ${fortran_src} ${c_src}) +else() + add_library(wgrib2_ftn_api STATIC ${fortran_src} ${c_src}) + set_property(TARGET wgrib2_ftn_api PROPERTY POSITION_INDEPENDENT_CODE ON) +endif() set(module_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}") -set_target_properties(wgrib2_api PROPERTIES Fortran_MODULE_DIRECTORY ${module_dir}) +set_target_properties(wgrib2_ftn_api PROPERTIES Fortran_MODULE_DIRECTORY ${module_dir}) -target_include_directories(wgrib2_api +target_include_directories(wgrib2_ftn_api PUBLIC $ $) -target_link_libraries(wgrib2_api PUBLIC wgrib2_lib) +target_link_libraries(wgrib2_ftn_api PUBLIC wgrib2_lib) install(DIRECTORY ${module_dir} DESTINATION ${CMAKE_INSTALL_PREFIX}) install( - TARGETS wgrib2_api + TARGETS wgrib2_ftn_api EXPORT wgrib2_exports RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/wgrib2/gctpc/source/CMakeLists.txt b/wgrib2/gctpc/source/CMakeLists.txt index a077a587..8bf84a5b 100644 --- a/wgrib2/gctpc/source/CMakeLists.txt +++ b/wgrib2/gctpc/source/CMakeLists.txt @@ -1,3 +1,7 @@ +# note: this CMakelist.txt is for building the gctpc library +# wgrib2 now includes the library into the source compile +# so the wgrib2 library now include gctpc. This makes it +# easier for users who want to use the wgrib2 library. set(src alberfor.c @@ -76,7 +80,13 @@ set(src wviiinv.c ) +# if want shared library, had to make separate library +# otherwise include gctpc in libwgrib2.a + add_library(gctpc OBJECT ${src}) +if (BUILD_LIB) + set_property(TARGET gctpc PROPERTY POSITION_INDEPENDENT_CODE ON) +endif() target_include_directories(gctpc PUBLIC $ 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.c b/wgrib2/wgrib2.c index 806a5f26..b948ba35 100644 --- a/wgrib2/wgrib2.c +++ b/wgrib2/wgrib2.c @@ -1,4 +1,7 @@ -/* wgrib2 main module: public domain 2005 w. ebisuzaki +/* wgrib2: public domain 2005 w. ebisuzaki + * originally the main of the wgrib2 utility + * later became main or routine depending on CALLABLE_WGRIB2 + * finally wgrib2 utility became a wrapper that calls the wgrib2 routine * * CHECK code is now duplicated * if (decode) -- check before decoding @@ -17,10 +20,9 @@ #include #include -#ifdef CALLABLE_WGRIB2 + #include jmp_buf fatal_err; -#endif #include "grb2.h" #include "wgrib2.h" @@ -116,17 +118,9 @@ int version_if; /* 0-old stype 1-modern if */ * simple wgrib for GRIB2 files * */ -#ifndef CALLABLE_WGRIB2 - -int main(int argc, const char **argv) { - -#else int wgrib2(int argc, const char **argv) { -#endif - - //WNE FILE *in; struct seq_file in_file; unsigned char *msg, *sec[10]; /* sec[9] = last valid bitmap */ @@ -176,9 +170,9 @@ int wgrib2(int argc, const char **argv) { data = NULL; // ddata = NULL; -#ifdef CALLABLE_WGRIB2 + if (setjmp(fatal_err)) { - fprintf(stderr,"*** arg list to wgrib2:"); + fprintf(stderr,"*** arg list to wgrib2(..):"); for (i=0; i < argc; i++) { fprintf(stderr," %s", argv[i]); } @@ -186,9 +180,9 @@ int wgrib2(int argc, const char **argv) { if (ndata && data != NULL) free(data); ndata=0; if (in_file.file_type != NOT_OPEN) fclose_file(&in_file); - return 1; + return 8; } -#endif + /* no arguments .. help screen */ if (argc == 1) { @@ -565,7 +559,7 @@ int wgrib2(int argc, const char **argv) { if (GDS_max_size) free(old_gds); GDS_max_size = i + 100; /* add 100 just to avoid excessive memory allocations */ if ((old_gds = (unsigned char *) malloc(GDS_max_size) ) == NULL) { - fatal_error("memory allocation problem old_gds in wgrib2.main for %s",in_file.filename); + fatal_error("memory allocation problem old_gds in wgrib2(..) for %s",in_file.filename); } } #ifdef IS_OPENMP_4_0 @@ -692,7 +686,7 @@ int wgrib2(int argc, const char **argv) { data = (float *) malloc(sizeof(float) * (size_t) ndata); if (data == NULL) { ndata = 0; - fatal_error("main: memory allocation failed data",""); + fatal_error("wgrib2(..): memory allocation failed data",""); } } else { data = NULL; } 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, diff --git a/wgrib2/wgrib2_api.c b/wgrib2/wgrib2_api.c index d99e866d..3f081f00 100644 --- a/wgrib2/wgrib2_api.c +++ b/wgrib2/wgrib2_api.c @@ -3,7 +3,6 @@ #include #include "wgrib2.h" -#ifdef CALLABLE_WGRIB2 /* sort of like the command line version of wgrib2 @@ -43,4 +42,3 @@ int wgrib2a(char *arg1, ...) { return i; } -#endif diff --git a/wgrib2/wgrib2_main.c b/wgrib2/wgrib2_main.c new file mode 100644 index 00000000..449ce054 --- /dev/null +++ b/wgrib2/wgrib2_main.c @@ -0,0 +1,27 @@ +/* wgrib2 main module: public domain 2024 w. ebisuzaki + * + * ancient: wgrib2.c was the main for the wgrib2 utility. There was no wgrib2 library, and + * no call to the wgrib2(..). + * + * old: A user wanted to call wgrib2 from a C program. He converted wgrib2.c to be either a main(..) + * or a routine wgrib2(..) depending on a flag (CALLABLE_WGRIB2). There were two builds, + * one for the utility and a second for the library. + * + * new: move to github + * Reimplement the old idea to make the wgrib2 utility a call to wgrib2(..). + * This involves removing all references to CALLABLE_WGRIB2 + * This was tested in a pre-github version but never implemented because it provided no reward + * With github, the build system is being rebuilt from Kyle's version. Rather than the two + * builds, make it a single build with the wgrib2 utility calling wgrib2(..) + + * + * 8/2024 the main for the wgrib2 utility is moved from wgrib2.c to wgrib2_main.c + */ + +#include +#include "wgrib2_api.h" + + +int main(int argc, const char **argv) { + return wgrib2(argc, argv); +}