From b7ef9f5e566163f0972907e63a5e985ef7c38fac Mon Sep 17 00:00:00 2001 From: Pedro Vicente Nunes Date: Tue, 17 Jun 2008 10:32:39 -0500 Subject: [svn-r15225] added a function that calls the jpeg library and writes a jgeg file for each HDF5 image tested: windows, linux --- tools/h52jpeg/h52jpeg.c | 192 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 180 insertions(+), 12 deletions(-) diff --git a/tools/h52jpeg/h52jpeg.c b/tools/h52jpeg/h52jpeg.c index 56a7498..eccf8f7 100644 --- a/tools/h52jpeg/h52jpeg.c +++ b/tools/h52jpeg/h52jpeg.c @@ -13,15 +13,21 @@ * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +/* From jpeg documentation + * + * Include file for users of JPEG library. + * You will need to have included system headers that define at least + * the typedefs FILE and size_t before you can include jpeglib.h. + * (stdio.h is sufficient on ANSI-conforming systems.) + * You may also wish to include "jerror.h". + */ + +#include #include #include - - -#if 0 #include "jpeglib.h" #include "jerror.h" -#endif #include "H5private.h" #include "h5tools.h" @@ -30,7 +36,6 @@ #include "H5IMpublic.h" - const char *progname = "h52jpeg"; int d_status = EXIT_SUCCESS; @@ -54,14 +59,13 @@ typedef struct const char *image_name; int image_type; int verbose; - - } h52jpeg_opt_t; /* prototypes */ static void usage(const char *prog); static int h52jpeg(h52jpeg_opt_t options); +static void write_JPEG_file(char *filename, JSAMPLE *image_buffer, int image_height, int image_width, int planes); /*------------------------------------------------------------------------- @@ -75,7 +79,7 @@ static int h52jpeg(h52jpeg_opt_t options); * *------------------------------------------------------------------------- */ -int main(int argc, char **argv) +int main(int argc, const char *argv[]) { h52jpeg_opt_t options; const char *image_type = NULL; @@ -151,11 +155,11 @@ static void usage(const char *prog) printf(" -v, --verbose Verbose mode, print object information\n"); printf(" -V, --version Print version number and exit\n"); printf(" -i, --image Image name (full path in HDF5 file)\n"); - printf(" -t T, --type=T Type of image (8bit or 24bit)\n"); + printf(" -t T, --type=T Type of image (graycolor or truecolor)\n"); printf("\n"); - printf(" T - is a string, either <8bit> or <24bit>\n"); + printf(" T - is a string, either or \n"); } @@ -196,6 +200,8 @@ static int h52jpeg(h52jpeg_opt_t opt) int j; int done; char jpeg_name[1024]; + int len; + /* open the HDF5 file */ if (( fid = h5tools_fopen(opt.file_name, H5F_ACC_RDONLY, H5P_DEFAULT, NULL, NULL, (size_t)0)) < 0) @@ -230,9 +236,23 @@ static int h52jpeg(h52jpeg_opt_t opt) case H5TRAV_TYPE_DATASET: name = travt->objs[i].name; - strcpy( jpeg_name, opt.template_name ); - strcat( jpeg_name, name ); + HDstrcpy( jpeg_name, opt.template_name ); + HDstrcat( jpeg_name, name ); + HDstrcat( jpeg_name, ".jpeg" ); + len = HDstrlen( jpeg_name); + + /* HDF5 path names might contain '/', replace with '_' */ + for (j = 0; j < len; j++) + { + if (jpeg_name[j] == '/') + { + jpeg_name[j] = '_'; + } + } + + + done = 0; if ( opt.verbose) @@ -255,8 +275,17 @@ static int h52jpeg(h52jpeg_opt_t opt) if ( H5IMread_image( fid, name, buf ) < 0 ) goto out; + write_JPEG_file (jpeg_name, + buf, + (int) height, + (int) width, + (int) planes); + + free( buf ); buf = NULL; + + done = 1; @@ -375,3 +404,142 @@ out: } + + +/* + * Sample routine for JPEG compression. We assume that the target file name + * and a compression quality factor are passed in. + * + * IMAGE DATA FORMATS: + * + * The standard input image format is a rectangular array of pixels, with + * each pixel having the same number of "component" values (color channels). + * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars). + * If you are working with color data, then the color values for each pixel + * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit + * RGB color. + * + * For this example, we'll assume that this data structure matches the way + * our application has stored the image in memory, so we can just pass a + * pointer to our image buffer. In particular, let's say that the image is + * RGB color and is described by: + */ + +static +void write_JPEG_file(char *filename, + JSAMPLE *image_buffer, /* Points to large array of R,G,B-order data */ + int image_height, /* Number of rows in image */ + int image_width, /* Number of columns in image */ + int planes) /* # of color components per pixel */ +{ + /* This struct contains the JPEG compression parameters and pointers to + * working space (which is allocated as needed by the JPEG library). + * It is possible to have several such structures, representing multiple + * compression/decompression processes, in existence at once. We refer + * to any one struct (and its associated working data) as a "JPEG object". + */ + struct jpeg_compress_struct cinfo; + /* This struct represents a JPEG error handler. It is declared separately + * because applications often want to supply a specialized error handler + * (see the second half of this file for an example). But here we just + * take the easy way out and use the standard error handler, which will + * print a message on stderr and call exit() if compression fails. + * Note that this struct must live as long as the main JPEG parameter + * struct, to avoid dangling-pointer problems. + */ + struct jpeg_error_mgr jerr; + /* More stuff */ + FILE * outfile; /* target file */ + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + int row_stride; /* physical row width in image buffer */ + + /* Step 1: allocate and initialize JPEG compression object */ + + /* We have to set up the error handler first, in case the initialization + * step fails. (Unlikely, but it could happen if you are out of memory.) + * This routine fills in the contents of struct jerr, and returns jerr's + * address which we place into the link field in cinfo. + */ + cinfo.err = jpeg_std_error(&jerr); + /* Now we can initialize the JPEG compression object. */ + jpeg_create_compress(&cinfo); + + /* Step 2: specify data destination (eg, a file) */ + /* Note: steps 2 and 3 can be done in either order. */ + + /* Here we use the library-supplied code to send compressed data to a + * stdio stream. You can also write your own code to do something else. + * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that + * requires it in order to write binary files. + */ + if ((outfile = fopen(filename, "wb")) == NULL) { + fprintf(stderr, "can't open %s\n", filename); + exit(1); + } + jpeg_stdio_dest(&cinfo, outfile); + + /* Step 3: set parameters for compression */ + + /* First we supply a description of the input image. + * Four fields of the cinfo struct must be filled in: + */ + cinfo.image_width = image_width; /* image width and height, in pixels */ + cinfo.image_height = image_height; + cinfo.input_components = planes; /* # of color components per pixel */ + + /* colorspace of input image */ + if (planes == 3) + cinfo.in_color_space = JCS_RGB; + else if (planes == 1) + cinfo.in_color_space = JCS_GRAYSCALE; + + /* Now use the library's routine to set default compression parameters. + * (You must set at least cinfo.in_color_space before calling this, + * since the defaults depend on the source color space.) + */ + jpeg_set_defaults(&cinfo); + /* Now you can set any non-default parameters you wish to. + * Here we just illustrate the use of quality (quantization table) scaling: + */ + jpeg_set_quality(&cinfo, 100, TRUE /* limit to baseline-JPEG values */); + + /* Step 4: Start compressor */ + + /* TRUE ensures that we will write a complete interchange-JPEG file. + * Pass TRUE unless you are very sure of what you're doing. + */ + jpeg_start_compress(&cinfo, TRUE); + + /* Step 5: while (scan lines remain to be written) */ + /* jpeg_write_scanlines(...); */ + + /* Here we use the library's state variable cinfo.next_scanline as the + * loop counter, so that we don't have to keep track ourselves. + * To keep things simple, we pass one scanline per call; you can pass + * more if you wish, though. + */ + row_stride = image_width * planes; /* JSAMPLEs per row in image_buffer */ + + while (cinfo.next_scanline < cinfo.image_height) { + /* jpeg_write_scanlines expects an array of pointers to scanlines. + * Here the array is only one element long, but you could pass + * more than one scanline at a time if that's more convenient. + */ + row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* Step 6: Finish compression */ + + jpeg_finish_compress(&cinfo); + /* After finish_compress, we can close the output file. */ + fclose(outfile); + + /* Step 7: release JPEG compression object */ + + /* This is an important step since it will release a good deal of memory. */ + jpeg_destroy_compress(&cinfo); + + /* And we're done! */ +} + -- cgit v0.12