diff --git a/.github/workflows/developer.yml b/.github/workflows/developer.yml index c7b54f2..a82b9e2 100644 --- a/.github/workflows/developer.yml +++ b/.github/workflows/developer.yml @@ -62,7 +62,7 @@ jobs: export CFLAGS='-Wall -g -fprofile-abs-path -fprofile-arcs -ftest-coverage -O0 -I/home/runner/work/wgrib2/wgrib2/nceplibs/NCEPLIBS-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="$GITHUB_WORKSPACE/nceplibs/NCEPLIBS-ip;$GITHUB_WORKSPACE/nceplibs/jasper;$GITHUB_WORKSPACE/nceplibs/NCEPLIBS-g2c" -DTEST_FILE_DIR=/home/runner/data -DMAKE_FTN_API=ON -DUSE_NETCDF4=ON -DUSE_AEC=ON -DUSE_IPOLATES=ON -DUSE_JASPER=ON + cmake .. -DENABLE_DOCS=ON -DFTP_TEST_FILES=ON -DCMAKE_PREFIX_PATH="$GITHUB_WORKSPACE/nceplibs/NCEPLIBS-ip;$GITHUB_WORKSPACE/nceplibs/jasper;$GITHUB_WORKSPACE/nceplibs/NCEPLIBS-g2c" -DTEST_FILE_DIR=/home/runner/data -DMAKE_FTN_API=ON -DUSE_NETCDF4=ON -DUSE_AEC=ON -DUSE_IPOLATES=ON -DUSE_JASPER=ON -DUSE_PNG=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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 55dd0a6..c7426b0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,8 +131,7 @@ endif() message(STATUS "Checking if the user wants to use PNG...") if(USE_PNG) - find_package(ZLIB REQUIRED) - find_package(PNG REQUIRED) + find_package(g2c 1.9.0 CONFIG REQUIRED) endif() # Find required packages to use AEC diff --git a/spack/package.py b/spack/package.py index 225856a..b581594 100644 --- a/spack/package.py +++ b/spack/package.py @@ -175,11 +175,12 @@ def url_for_version(self, version): 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: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("g2c@develop +jasper", when="@develop +jasper") + depends_on("zlib-api", when="@3.2:3.4 +png") + depends_on("libpng", when="@3.2:3.4 +png") + depends_on("g2c@develop +png", when="@develop +png") depends_on("openjpeg", when="@3.2:3.4 +openjpeg") - depends_on("g2c +openjpeg", when="@develop +openjpeg") + depends_on("g2c@develop +openjpeg", when="@develop +openjpeg") @when("@:2 ^gmake@4.2:") diff --git a/wgrib2/CMakeLists.txt b/wgrib2/CMakeLists.txt index 9e1d006..8d351c7 100644 --- a/wgrib2/CMakeLists.txt +++ b/wgrib2/CMakeLists.txt @@ -22,10 +22,9 @@ Alias.c Ave_test.c Ave_var.c Bbox.c bitstream.c Box_ave.c 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 dec_png_clone.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 +CubeFace2global.c Cyclic.c Data.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 FlagTable.c flt2ieee.c flt2ieee_nan.c Flush.c fnlist.c For.c Ftime1.c Ftime2.c Ftime.c Ftn_api.c gaussian2ij.c Gctpc.c gctpc_ll2xy.c GDT.c @@ -108,10 +107,6 @@ if(USE_NETCDF) target_link_libraries(wgrib2_exe PUBLIC NetCDF::NetCDF_C) endif() -if(USE_PNG) - target_link_libraries(obj_lib PUBLIC PNG::PNG) -endif() - if(USE_OPENMP) target_link_libraries(obj_lib PUBLIC OpenMP::OpenMP_C) if(BUILD_SHARED_LIB) @@ -143,7 +138,7 @@ if(USE_AEC) target_link_libraries(wgrib2_exe PRIVATE ${LIBAEC_LIBRARIES}) endif() -if(USE_JASPER OR USE_OPENJPEG) +if(USE_JASPER OR USE_OPENJPEG OR USE_PNG) target_link_libraries(obj_lib PUBLIC g2c::g2c) target_link_libraries(wgrib2_exe PRIVATE g2c::g2c) endif() diff --git a/wgrib2/dec_png_clone.c b/wgrib2/dec_png_clone.c deleted file mode 100644 index 96ffbe0..0000000 --- a/wgrib2/dec_png_clone.c +++ /dev/null @@ -1,199 +0,0 @@ -#include "wgrib2.h" - -/* dec_png_clone() - * based on dec_png() from g2clib (public domain) by Steve Gilbert NCO/NCEP/NWS - * - * enc_png() from g2clib is limited to bit depth of 8, 16, 24, 32 - * and automnatically coverts bit_depth = ((int) (bit_depth + 7) / 8 ) * 8 - * dec_png() assumes a bit depth of 8, 16, 24, 32, and nbytes=bit_depth/8 - * - * the WMO grib2 specifications mention bit depth of 1, 2, 4, 8, 24, 32. - * so that is why dep_png() will fail for bit_depth of 1, 2 and 4 - * - * v1.0: copied dec_png() from g2clib, called it dep_png_clone() to avoid name - * conflict if also use g2clib - * - * 4/2021: v1.1 modification W. Ebisuzaki - * need to check if grib2 definition of bit_depth is the same as from - * decoding the png stream, otherwise silent bad decode - * if differs, then delayed error - * changed char *cout to unsigned char *cout to be consistent with wgrib2 - * Now handles bit_depth of 1, 2 and 4 as well as 8, 16, 24 and 32. - * - */ - -#ifdef USE_PNG - -#include -#include -#include -#include - -extern unsigned int last_message; - -struct png_stream { - unsigned char *stream_ptr; /* location to write PNG stream */ - int stream_len; /* number of bytes written */ -}; -typedef struct png_stream png_stream; - -void user_read_data_clone(png_structp , png_bytep , png_size_t ); - -void user_read_data_clone(png_structp png_ptr,png_bytep data, png_size_t length) -/* - Custom read function used so that libpng will read a PNG stream - from memory instead of a file on disk. -*/ -{ - char *ptr; - int offset; - png_stream *mem; - - mem=(png_stream *)png_get_io_ptr(png_ptr); - ptr=(void *)mem->stream_ptr; - offset=mem->stream_len; - memcpy(data,ptr+offset,length); - mem->stream_len += length; -} - - - -int dec_png_clone(unsigned char *pngbuf,int *width,int *height, unsigned char *cout, int *grib2_bit_depth, unsigned int ndata) -{ - int interlace,color,compres,filter,bit_depth; - int j,k, rowlen, tmp; - long int rowlen_bits; - png_structp png_ptr; - png_infop info_ptr,end_info; - png_bytepp row_pointers; - png_stream read_io_ptr; - png_uint_32 h32, w32; - -/* check if stream is a valid PNG format */ - - if ( png_sig_cmp(pngbuf,0,8) != 0) - return (-3); - -/* create and initialize png_structs */ - - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, - NULL, NULL); - if (!png_ptr) - return (-1); - - info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - { - png_destroy_read_struct(&png_ptr,(png_infopp)NULL,(png_infopp)NULL); - return (-2); - } - - end_info = png_create_info_struct(png_ptr); - if (!end_info) - { - png_destroy_read_struct(&png_ptr,(png_infopp)info_ptr,(png_infopp)NULL); - return (-2); - } - -/* Set Error callback */ - - if (setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_read_struct(&png_ptr, &info_ptr,&end_info); - return (-3); - } - -/* Initialize info for reading PNG stream from memory */ - - read_io_ptr.stream_ptr=(png_voidp)pngbuf; - read_io_ptr.stream_len=0; - -/* Set new custom read function */ - - png_set_read_fn(png_ptr,(png_voidp)&read_io_ptr,(png_rw_ptr)user_read_data_clone); -/* png_init_io(png_ptr, fptr); */ - -/* support for larger grids */ - png_set_user_limits(png_ptr, PNG_WIDTH_MAX, PNG_HEIGHT_MAX); - -/* Read and decode PNG stream */ - png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - -/* Get pointer to each row of image data */ - - row_pointers = png_get_rows(png_ptr, info_ptr); - -/* Get image info, such as size, depth, colortype, etc... */ - - /*printf("SAGT:png %d %d %d\n",info_ptr->width,info_ptr->height,info_ptr->bit_depth);*/ - // (void)png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *)width, (png_uint_32 *)height, - (void)png_get_IHDR(png_ptr, info_ptr, &w32, &h32, - &bit_depth, &color, &interlace, &compres, &filter); - - *height = h32; - *width = w32; - if ((unsigned int) h32 * (unsigned int) w32 > ndata) fatal_error("png decode: size of png grid too large",""); - -/* Check if image was grayscale */ - -/* - if (color != PNG_COLOR_TYPE_GRAY ) { - fprintf(stderr,"dec_png: Grayscale image was expected. \n"); - } -*/ - if ( color == PNG_COLOR_TYPE_RGB ) { - bit_depth=24; - } - else if ( color == PNG_COLOR_TYPE_RGB_ALPHA ) { - bit_depth=32; - } - - if (bit_depth != *grib2_bit_depth) { - fprintf(stderr, "** DELAYED ERROR: png bit depth error: Sec 5 octet 20 is %d, png lib value (%d) is used **\n", - *grib2_bit_depth, bit_depth); - fprintf(stderr, "** file will be read incorrectly by some grib libraries such as NCEPlib\n"); - fprintf(stderr, "** add -reset_delayed_error option to continue processing\n"); - *grib2_bit_depth = bit_depth; - last_message |= DELAYED_MISC; - } - -/* Copy image data to output string */ - - /* get number of bytes per row used to store packed numbers */ - rowlen = png_get_rowbytes(png_ptr, info_ptr); - - rowlen_bits = w32 * bit_depth; - - // to test bitstream code: if (bit_depth == 32) { - // if (rowlen_bits % 8 == 0) { - // if (bit_depth == 32) { - if (rowlen_bits % 8 == 0) { -#pragma omp parallel for private(j,k) schedule(static) - for (j = 0; j < h32; j++) { - for (k = 0; k < rowlen; k++) { - cout[j*rowlen+k]=*(row_pointers[j]+k); - } - } - } - else { - /* bitstream is set to *cout */ - init_bitstream(cout); - for (j = 0; j < h32; j++) { - rowlen_bits = w32 * bit_depth; - k = 0; - while (rowlen_bits > 0) { - tmp = (int) *(row_pointers[j] + k++); - add_bitstream(tmp, rowlen_bits > 8 ? 8: rowlen_bits); - rowlen_bits -= 8; - } - } - finish_bitstream(); - } - -/* Clean up */ - - png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); - return 0; - -} -#endif /* USE_PNG */ diff --git a/wgrib2/unpk.c b/wgrib2/unpk.c index 936a62a..39326cf 100644 --- a/wgrib2/unpk.c +++ b/wgrib2/unpk.c @@ -17,8 +17,7 @@ #endif #ifdef USE_PNG - #include - int i; + #include "grib2.h" #endif #ifdef USE_AEC @@ -47,7 +46,7 @@ int unpk_grib(unsigned char **sec, float *data) { double bin_scale, dec_scale, b; #ifdef USE_PNG - int width, height; + int i, width, height; #endif #if (defined USE_JASPER || defined USE_OPENJPEG) @@ -251,7 +250,7 @@ int unpk_grib(unsigned char **sec, float *data) { if ((c = (unsigned char *) malloc(4*sizeof(char) * (size_t) ndata)) == NULL) fatal_error("unpk: png decode allocation error", ""); - i = (int) dec_png_clone(sec[7]+5, &width, &height, (unsigned char *) c, &nbits, ndata); + i = g2c_dec_png(sec[7]+5, &width, &height, (unsigned char *) c); if (i) fatal_error_i("unpk: png decode error %d",i); mask_pointer = (bitmap_flag == 255) ? NULL : sec[6] + 6; diff --git a/wgrib2/wgrib2.h b/wgrib2/wgrib2.h index 7deb9d0..f17fe14 100644 --- a/wgrib2/wgrib2.h +++ b/wgrib2/wgrib2.h @@ -502,7 +502,7 @@ int wrt_sec(unsigned const char *sec0, unsigned const char *sec1, unsigned const int scaling(unsigned char **sec, double *base, int *decimal, int *binary, int *nbits); 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 g2c_dec_png(unsigned char *pngbuf, int *width, int *height, unsigned char *cout); int ieee_grib_out(unsigned char **sec, float *data, unsigned int ndata, struct seq_file *out); int jpeg_grib_out(unsigned char **sec, float *data, unsigned int ndata, int nx, int ny, int use_scale, int dec_scale, int bin_scale, FILE *out);