/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include "h5hltest.h" #include "H5srcdir.h" #include "H5LTpublic.h" #include "H5IMpublic.h" #include "pal_rgb.h" #define FILE_NAME "test_image1.h5" #define FILE2 "test_image2.h5" #define FILE3 "test_image3.h5" #define DATA_FILE1 "image8.txt" #define DATA_FILE2 "image24pixel.txt" #define DATA_FILE3 "image24plane.txt" #define DATA_FILE4 "usa.wri" #define PAL2_FILE "sepia.pal" #define PAL3_FILE "earth.pal" #define IMAGE1_NAME "image8bit" #define IMAGE2_NAME "image24bitpixel" #define IMAGE3_NAME "image24bitplane" #define PAL_NAME "palette" #define PAL1_NAME "rainbow" #define PAL2_NAME "sepia" #define PAL3_NAME "earth" #define PAL4_NAME "blue-red" #define WIDTH 400 #define HEIGHT 200 #define PAL_ENTRIES 256 /* struct to store RGB values read from a .pal file */ typedef struct rgb_t { unsigned char r; unsigned char g; unsigned char b; } rgb_t; /* prototypes */ static int test_simple(void); static int test_data(void); static int test_generate(void); static int read_data(const char* file_name, hsize_t *width, hsize_t *height ); static int read_palette(const char* file_name, rgb_t *palette, size_t palette_size); /* globals */ unsigned char *image_data = NULL; /*------------------------------------------------------------------------- * the main program *------------------------------------------------------------------------- */ int main(void) { int nerrors=0; nerrors += test_simple()<0 ?1:0; nerrors += test_data()<0 ?1:0; nerrors += test_generate()<0 ?1:0; if (nerrors) goto error; printf("All image tests passed.\n"); return 0; error: printf("***** %d IMAGE TEST%s FAILED! *****\n",nerrors, 1 == nerrors ? "" : "S"); return 1; } /*------------------------------------------------------------------------- * a simple test that generates images and palettes *------------------------------------------------------------------------- */ static int test_simple(void) { hsize_t width = WIDTH; hsize_t height = HEIGHT; hsize_t planes; hid_t fid; int i, j, n, space; hsize_t u; char interlace[20]; hssize_t npals; /* 8-bit image */ unsigned char *buf1 = NULL; unsigned char pal[ PAL_ENTRIES * 3 ]; /* palette array */ hsize_t pal_dims[2] = {PAL_ENTRIES,3}; /* palette dimensions */ /* 24-bit image */ unsigned char *buf2 = NULL; /* read data */ unsigned char *buf1_out = NULL; unsigned char *buf2_out = NULL; unsigned char pal_out[ PAL_ENTRIES * 3 ]; /* palette array */ hsize_t pal_dims_out[2]; /* palette dimensions */ /* Allocate image buffers */ buf1 = (unsigned char *)HDmalloc(WIDTH * HEIGHT); HDassert(buf1); buf2 = (unsigned char *)HDmalloc(WIDTH * HEIGHT * 3); HDassert(buf2); buf1_out = (unsigned char *)HDmalloc(WIDTH * HEIGHT); HDassert(buf1_out); buf2_out = (unsigned char *)HDmalloc(WIDTH * HEIGHT * 3); HDassert(buf2_out); /* create an image */ space = WIDTH*HEIGHT / PAL_ENTRIES; for (i=0, j=0, n=0; i < WIDTH*HEIGHT; i++, j++ ) { buf1[i] = (unsigned char)n; if ( j > space ) { n++; j=0; } } /* create an image */ space = WIDTH*HEIGHT / 256; for (i=0, j=0, n=0; i < WIDTH*HEIGHT*3; i+=3, j++ ) { buf2[i] = (unsigned char)n; buf2[i+1] = 0; buf2[i+2] = (unsigned char)(255 - n); if ( j > space ) { n++; j=0; } } /*------------------------------------------------------------------------- * define a palette, blue to red tones *------------------------------------------------------------------------- */ for ( i=0, n=0; i e ! k | / |__________________________|/ / ! | / (imax,1,1) / ! |----------> s ! i ! */ if(fscanf( f, "%d %d %d", &imax, &jmax, &kmax ) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ if(fscanf( f, "%f %f %f", &valex, &xmin, &xmax ) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ /* Sanity check on scanned-in values */ if(imax < 1 || jmax < 1 || kmax < 1) goto out; /* Test product for integer overflow */ if(imax > INT_MAX / jmax) goto out; if(imax * jmax > INT_MAX / kmax) goto out; n_elements = imax * jmax * kmax; /* Test buffer sizes for overflow */ if(n_elements > INT_MAX / (int)sizeof(unsigned char)) goto out; if(n_elements > INT_MAX / (int)sizeof(float)) goto out; data = (float *)HDmalloc((size_t)n_elements * sizeof(float)); if(NULL == data) goto out; image_data = (unsigned char *)HDmalloc((size_t)n_elements * sizeof(unsigned char)); if(NULL == image_data) goto out; for ( i = 0; i < n_elements; i++ ) { if(fscanf( f, "%f ", &value ) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ data[i] = value; } HDfclose(f); f = NULL; /*------------------------------------------------------------------------- * transform the data from floating point to unsigned char * we are processing all the data here *------------------------------------------------------------------------- */ HL_TESTING2("make indexed image from all the data"); for ( i = 0; i < n_elements; i++ ) image_data[i] = (unsigned char)(( 255 * (data[i] - xmin ) ) / (xmax - xmin )); /* Make the image */ if ((H5IMmake_image_8bit(fid,"All data",(hsize_t)imax,(hsize_t)jmax,image_data))<0) goto out; PASSED(); /*------------------------------------------------------------------------- * transform the data from floating point to unsigned char * here we just process the land data *------------------------------------------------------------------------- */ HL_TESTING2("make indexed image from land data"); for ( i = 0; i < n_elements; i++ ) { if ( data[i] < 0 ) image_data[i] = 0; else image_data[i] = (unsigned char)(( 255 * (data[i] ) ) / xmax ); } /* make the image */ if ((H5IMmake_image_8bit(fid,"Land data",(hsize_t)imax,(hsize_t)jmax,image_data))<0) goto out; PASSED(); /*------------------------------------------------------------------------- * transform the data from floating point to unsigned char * here we just process the sea data *------------------------------------------------------------------------- */ HL_TESTING2("make indexed image from sea data"); for ( i = 0; i < n_elements; i++ ) { if ( data[i] > 0 ) image_data[i] = 0; else image_data[i] = (unsigned char)(( 255 * (data[i] - xmin ) ) / xmin ); } /* make the image */ if ((H5IMmake_image_8bit(fid,"Sea data",(hsize_t)imax,(hsize_t)jmax,image_data))<0) goto out; PASSED(); /*------------------------------------------------------------------------- * make a palette and attach it to the datasets *------------------------------------------------------------------------- */ HL_TESTING2("attaching palettes"); /* make a palette */ if ((H5IMmake_palette(fid,PAL1_NAME,pal_dims,pal_rgb))<0) goto out; /* attach the palette to the image datasets */ if ((H5IMlink_palette(fid,"All data",PAL1_NAME))<0) goto out; if ((H5IMlink_palette(fid,"Land data",PAL1_NAME))<0) goto out; if ((H5IMlink_palette(fid,"Sea data",PAL1_NAME))<0) goto out; PASSED(); /*------------------------------------------------------------------------- * close *------------------------------------------------------------------------- */ if (H5Fclose(fid)<0) goto out; /* Release memory buffers */ HDfree(data); HDfree(image_data); /* Indicate success */ return 0; /* error zone, gracefully close */ out: /* Release memory buffers */ if(data) HDfree(data); if(image_data) HDfree(image_data); H5E_BEGIN_TRY { H5Fclose(fid); } H5E_END_TRY; if(f) HDfclose(f); H5_FAILED(); return retval; } /*------------------------------------------------------------------------- * read_data * utility function to read ASCII image data * the files have a header of the type * * components * n * height * n * width * n * * followed by the image data * *------------------------------------------------------------------------- */ static int read_data(const char* fname, /*IN*/ hsize_t *width, /*OUT*/ hsize_t *height /*OUT*/) { int i, n; int color_planes; char str[20]; FILE *f = NULL; int w, h; int n_elements; const char *data_file = H5_get_srcdir_filename(fname); int ret_val = -1; /*------------------------------------------------------------------------- * read *------------------------------------------------------------------------- */ if(NULL == (f = HDfopen(data_file, "r"))) { printf( "Could not open file %s. Try set $srcdir \n", data_file ); goto out; } if(fscanf(f, "%s", str) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ if(fscanf(f, "%d", &color_planes) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ if(fscanf(f, "%s", str) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ if(fscanf(f, "%d", &h) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ if(fscanf(f, "%s", str) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ if(fscanf(f, "%d", &w) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ /* Check product for overflow */ if(w < 1 || h < 1 || color_planes < 1) goto out; if(w > INT_MAX / h) goto out; if(w * h > INT_MAX / color_planes) goto out; /* Compute buffer size */ n_elements = w * h * color_planes; /* Check buffer size for overflow */ if(n_elements > INT_MAX / (int)sizeof(unsigned char)) goto out; /* Release the buffer, if it was previously allocated */ if(image_data) HDfree(image_data); /* Allocate the image data buffer */ image_data = (unsigned char *)HDmalloc((size_t)n_elements * sizeof(unsigned char)); if(NULL == image_data) goto out; *width = (hsize_t)w; *height = (hsize_t)h; /* Read data elements */ for(i = 0; i < n_elements; i++) { if(fscanf(f, "%d", &n) < 0 && HDferror(f)) { printf( "fscanf error in file %s.\n", data_file ); goto out; } /* end if */ image_data[i] = (unsigned char)n; } /* end for */ /* Indicate success */ ret_val = 1; out: if(f) HDfclose(f); return ret_val; } /* end read_data() */ /*------------------------------------------------------------------------- * read_palette * Read an ASCII palette file .PAL into an array * the files have a header of the type * * Parameters: * fname - name of file to read. * palette - array of rgb_t to store the read palette. * palette_size - number of elements in 'palette' array * *------------------------------------------------------------------------- */ #define STRING_JASC "JASC-PAL" #define VERSION_JASC "0100" #define STRING_CWPAL "CWPAL" #define VERSION_CWPAL "100" static int read_palette(const char* fname, rgb_t *palette, size_t palette_size) { FILE *file; char buffer[80]; unsigned u; unsigned int red; unsigned int green; unsigned int blue; unsigned nentries; const char *data_file = H5_get_srcdir_filename(fname); /* ensure the given palette is valid */ if (!palette) return -1; /* open the input file */ if (!(file = HDfopen(data_file, "r"))) { printf( "Could not open file %s. Try set $srcdir \n", data_file ); return -1; } /* read the file ident string */ if (HDfgets(buffer, sizeof(buffer), file) == NULL) { HDfclose(file); return -1; } /* ensure it matches the palette file ident string */ if ( HDstrncmp(buffer, STRING_JASC, sizeof(STRING_JASC) - 1) != 0 && HDstrncmp(buffer, STRING_CWPAL, sizeof(STRING_CWPAL) - 1) != 0 ) { HDfclose(file); return -1; } /* read the version string */ if (HDfgets(buffer, sizeof(buffer), file) == NULL) { HDfclose(file); return -1; } /* ensure it matches the palette file version string */ if ( HDstrncmp(buffer, VERSION_JASC, sizeof(VERSION_JASC) - 1) != 0 && HDstrncmp(buffer, VERSION_CWPAL, sizeof(VERSION_CWPAL) - 1) != 0 ) { HDfclose(file); return -1; } /* read the number of colors */ if (HDfgets(buffer, sizeof(buffer), file) == NULL) { HDfclose(file); return -1; } /* extract the number of colors. check for missing version or number of colors in this case it reads the first entry */ if ( HDstrlen( buffer ) > 4 ) { HDfclose(file); return -1; } if (sscanf(buffer, "%u", &nentries) != 1) { HDfclose(file); return -1; } /* ensure there are a sensible number of colors in the palette */ if ((nentries > 256) || (nentries > palette_size)) { HDfclose(file); return(-1); } /* read the palette entries */ for (u = 0; u < nentries; u++) { /* extract the red, green and blue color components. */ if (fscanf(file, "%u %u %u", &red, &green, &blue) != 3) { HDfclose(file); return -1; } /* store this palette entry */ palette[u].r = (unsigned char)red; palette[u].g = (unsigned char)green; palette[u].b = (unsigned char)blue; } /* close file */ HDfclose(file); return (int)nentries; }