1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF.  The full HDF copyright notice, including       *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the COPYING file, which can be found at the root of the source code       *
9  * distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/.  *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /* $Id$ */
15 #include "hdf.h"
16 #ifndef I860
17 #include <stdlib.h>
18 #include <string.h>
19 #endif /* I860 */
20 
21 /* Exception checking macro */
22 #define EXCHECK(a,b)    if(a) goto b
23 
24 /* Static variables */
25 uint8       red_comp[256], green_comp[256], blue_comp[256];
26 
27 comp_info   cinfo;              /* compression structure */
28 
29 static intn
30 magnify(uint8 *from_buffer, uint8 *to_buffer, int32 from_x0,
31         int32 from_y0, int32 from_x1, int32 from_y1, int32 from_width,
32         int32 from_height, int32 to_width, int32 to_height);
33 
34 static intn
35 convert8to24(uint8 *img8_buf, uint8 *img24_buf, int32 img_xdim,
36              int32 img_ydim);
37 
38 static VOID usage(void);
39 
40 /**********************************************************************
41 *  Function :   magnify
42 *  Purpose  :   Magnify an image by independant X and Y magnification
43 *                   factors.  Note that the coordinates which specify
44 *                   the area in the "from" image are _inclusive_, i.e.
45 *                   if you would like to magnify the entire image, the
46 *                   "from" coordinates should be specified as:
47 *                   (0,0) and ((width-1),(height-1)), where "width"
48 *                   and "height" are the width and height of the image
49 *                   (respectively) in pixels.
50 *  Parameters   :
51 *           from_buffer - pointer to the buffer which contains the image
52 *                           to magnify
53 *           to_buffer - pointer to the buffer in which to place the
54 *                           magnified image
55 *           from_x0, from_y0 - Upper Left Corner (ULC) of the rectangular
56 *                           area in the image to magnify
57 *           from_x1, from_y1 - Lower Right Corner (LRC) of the rectangular
58 *                           area in the image to magnify
59 *           from_width, from_height - the width and height of the image
60 *                           to magnify (or "from" image)
61 *           to_width, to_height - the width and height of the magnified
62 *                           image (or "to" image)
63 *  Returns  :   (TRUE) for success, (FALSE) for error
64 *  Calls    :
65 *  Called by    :
66 **********************************************************************/
67 static intn
magnify(uint8 * from_buffer,uint8 * to_buffer,int32 from_x0,int32 from_y0,int32 from_x1,int32 from_y1,int32 from_width,int32 from_height,int32 to_width,int32 to_height)68 magnify(uint8 *from_buffer, uint8 *to_buffer, int32 from_x0,
69         int32 from_y0, int32 from_x1, int32 from_y1, int32 from_width,
70         int32 from_height, int32 to_width, int32 to_height)
71 {
72     uint8      *buf_off,        /* the current offset into the magnified data */
73                *last_buf,       /* pointer to the last useful magnified line */
74                *y_off,          /* the y offset into the data block */
75                *last_y_coor,    /* pointer to the last line copied */
76               **y_coor;         /* pointers to image data */
77     float64     temp_val,       /* temporary value for holding double results */
78                 wind_width,     /* the width of the window to magnify */
79                 wind_height;    /* the height of the window to magnify */
80     int32       u, v;           /* local unsigned counting variables */
81     int32      *x_coor,         /* the X coor. lookup table */
82                *x_coor_temp;    /* temporary pointer to the x lookup table */
83 
84     if (from_width == 0 || from_height == 0)    /* check for bad image dimensions */
85         return (FALSE);
86     if (to_width == 0 || to_height == 0)    /* check for bad image dimensions */
87         return (FALSE);
88     if (from_x0 > from_x1 || from_y0 > from_y1)     /* check for an invalid window */
89         return (FALSE);
90 
91 /* find width and height of the window to magnify */
92     wind_width = (float64)((from_x1 - from_x0) + 1);
93     wind_height = (float64)((from_y1 - from_y0) + 1);
94 
95 /* allocate room for the x coordinate lookup table */
96     x_coor = (int32 *) HDmalloc((int32) ((size_t)to_width * sizeof(int32)));
97     EXCHECK(x_coor == NULL, XCoorFailed);   /* check if malloc() failed */
98     temp_val = wind_width / (float64) to_width;
99     for (u = 0; u < to_width; u++)  /* calculate the x coordinate lookup table */
100         x_coor[u] = ((uint16) ((float64) u * temp_val) + from_x0);
101 
102 /* allocate room for the array of pointers */
103     y_coor = (uint8 **) HDmalloc((int32) ((size_t)to_height * sizeof(uint8 *)));
104     EXCHECK(y_coor == NULL, YCoorFailed);   /* check if malloc() failed */
105     temp_val = wind_height / (float64) to_height;
106     for (u = 0; u < to_height; u++)     /* calculate the y coordinates */
107         y_coor[u] = from_buffer + ((uint32) ((float64) u * temp_val) + (uint32)from_y0) * (uint32)from_width;
108 
109     last_buf = to_buffer;   /* set the previous line pointer */
110     buf_off = to_buffer;    /* set the pointer to the "to" image */
111     last_y_coor = NULL;     /* force to calculate the first line */
112 
113     for (u = 0; u < to_height; u++)
114       {     /* go through each magnified line */
115 /* if this line is not the same as the previous one, then make it again */
116           if (y_coor[u] != last_y_coor)
117             {
118                 last_y_coor = y_off = y_coor[u];
119                 x_coor_temp = x_coor;   /* assign the temporary pointer */
120                 last_buf = buf_off;     /* set the pointer to the previous line */
121                 for (v = 0; v < to_width; v++)  /* go through each line magnifying it */
122                     *buf_off++ = y_off[*x_coor_temp++];
123             }   /* end if */
124 /* this line is the same as the previous one, just copy it */
125           else
126             {
127                 HDmemcpy(buf_off, last_buf, to_width);  /* copy the previous line */
128                 buf_off += to_width;    /* advance the buffer offset pointer */
129             }   /* end else */
130       }     /* end for */
131     HDfree((char *) y_coor);
132     HDfree((char *) x_coor);
133     return (TRUE);
134 
135   YCoorFailed:      /* Failed to allocate memory for the Y coor. lookup table */
136     HDfree((VOIDP) x_coor);
137   XCoorFailed:      /* Failed to allocate memory for the X coor. lookup table */
138     return (FALSE);
139 }   /* end magnify() */
140 
141 /**********************************************************************
142 *  Function :   convert8to24
143 *  Purpose  :   Convert an 8-bit image to a 24-bit image, using the
144 *                   palette components already set up.
145 *  Parameters   :
146 *           img_8_buf - pointer to the buffer which contains the 8-bit image
147 *           img24_buf - pointer to the buffer in which to place the
148 *                           24-bit image
149 *           img_xdim, img_ydim - the width and height of the images
150 *  Returns  :   (TRUE) for success, (FALSE) for error
151 *  Calls    :
152 *  Called by    :
153 **********************************************************************/
154 static intn
convert8to24(uint8 * img8_buf,uint8 * img24_buf,int32 img_xdim,int32 img_ydim)155 convert8to24(uint8 *img8_buf, uint8 *img24_buf, int32 img_xdim,
156              int32 img_ydim)
157 {
158     uint32      pixels;         /* local counting variable */
159 
160     if (img_xdim <= 0 || img_ydim <= 0)     /* check for bad image dimensions */
161         return (FALSE);
162     if (img8_buf == NULL || img24_buf == NULL)  /* check for invalid images */
163         return (FALSE);
164 
165     pixels = (uint32)(img_xdim * img_ydim);   /* get the number of pixels to process */
166     while (pixels > 0)
167       {     /* do all the pixels */
168           *img24_buf++ = red_comp[*img8_buf];
169           *img24_buf++ = green_comp[*img8_buf];
170           *img24_buf++ = blue_comp[*img8_buf];
171           img8_buf++;
172           pixels--;
173       }     /* end while */
174     return (TRUE);
175 }   /* end convert8to24() */
176 
177 static VOID
usage(void)178 usage(void)
179 {
180     printf("USAGE: make24 [-s<scale>] [-j] <input HDF file> <output HDF file>\n");
181     printf("    -s<scale> : set scale for magnifying the 8-bit input file.\n");
182     printf("                scales between 0 and 1 shrink the image, scales\n");
183     printf("                greater than 1 expand the image.  Defaults to 1\n");
184     printf("    -j[quality] : use JPEG compression to store the 24-bit image\n");
185     printf("                Defaults to no compression, or quality level\n");
186     printf("                75, if no quality is specified\n");
187     printf("    <input HDF file>  : HDF file which contains an 8-bit image\n");
188     printf("    <output HDF file> : HDF file to store the 24-bit image\n");
189     exit(1);
190 }   /* end usage() */
191 
192 int
main(int argc,char * argv[])193 main(int argc, char *argv[])
194 {
195     intn        do_jpeg = FALSE;    /* flag to indicate JPEG compression */
196     intn        jpeg_qual = 75; /* JPEG quality factor */
197     intn        do_scale = FALSE;   /* flag to indicate whether to scale images */
198     float32     img_scale = (float32) 1.0;  /* scaling factor */
199     int32       xdim, ydim;     /* dimensions of the image to convert */
200     intn        ispal;          /* whether there's a palette with the image */
201     uint8      *img_buf;        /* buffer to store the image in */
202     uint8      *img24_buf;      /* buffer to store the 24-bit image in */
203     uint8      *pal_buf = NULL; /* buffer to store the palette in */
204     intn        file = 1;       /* the arguement the files start at */
205     intn        i;              /* local counting variable */
206 
207     if (argc < 3)
208         usage();
209 
210     if (argv[1][0] == '-' || argv[1][0] == '/')
211       {     /* check command line */
212           if ((argv[1][1] != 's' && argv[1][1] != 'j') || argc < 4)
213               usage();
214 
215           while (argv[file][0] == '-' || argv[file][0] == '/')
216             {
217                 switch (argv[file][1])
218                   {
219                       case 's':
220                           if ((img_scale = (float32) atof(&argv[file][2])) <= (float32)0.0)
221                             {   /* check for valid scale */
222                                 printf("Bad scale, must be greater than 0\n");
223                                 return (1);
224                             }   /* end if */
225                           do_scale = TRUE;
226                           break;
227 
228                       case 'j':
229                           if ((jpeg_qual = atoi(&argv[file][2])) <= 0 || jpeg_qual > 100)
230                             {
231                                 printf("Bad JPEG quality setting, should be between\n");
232                                 printf("1 and 100, using default value of 75\n");
233                                 jpeg_qual = 75;
234                             }   /* end if */
235                           do_jpeg = TRUE;
236                           break;
237 
238                       default:
239                           usage();
240 
241                   }     /* end switch */
242                 file++;
243             }   /* end while */
244       }     /* end if */
245 
246     /* get the image dimensions */
247     if (DFR8getdims(argv[file], &xdim, &ydim, &ispal) == FAIL)
248       {
249           printf("Error, bad dimensions in file: %s\n", argv[file]);
250           HEprint(stdout, 0);
251           return (1);
252       }     /* end if */
253 
254     if ((img_buf = (uint8 *) HDmalloc((size_t)(xdim * ydim))) == NULL)
255       {
256           printf("Error, cannot allocate space for %dx%d image\n", (int)xdim, (int)ydim);
257           return (1);
258       }     /* end if */
259 
260     if (ispal)
261       {
262           if ((pal_buf = (uint8 *) HDmalloc(768)) == NULL)
263             {
264                 printf("Error, cannot allocate space for image palette\n");
265                 return (1);
266             }   /* end if */
267       }     /* end if */
268     else
269         printf("No palette associated with image, using default grey scale converion\n");
270 
271     if (DFR8getimage(argv[file], img_buf, xdim, ydim, (ispal ? pal_buf : NULL)) == FAIL)
272       {
273           printf("Error reading image\n");
274           HEprint(stdout, 0);
275           return (1);
276       }     /* end if */
277 
278     if (do_scale)
279       {     /* check whether we should scale the image */
280           uint8      *scaled_image;     /* storage for the scaled image */
281           int32       new_xdim, new_ydim;   /* the new image's x and y dim. */
282 
283           new_xdim = (int32) (img_scale * (float32)xdim);    /* calc. new image's dimensions */
284           new_ydim = (int32) (img_scale * (float32)ydim);
285           if ((scaled_image = (uint8 *) HDmalloc((size_t)(new_xdim * new_ydim))) == NULL)
286             {
287                 printf("Error, cannot allocate space for %dx%d scaled image\n", (int)new_xdim, (int)new_ydim);
288                 return (1);
289             }   /* end if */
290           if (!magnify(img_buf, scaled_image, 0, 0, xdim - 1, ydim - 1, xdim, ydim, new_xdim, new_ydim))
291             {
292                 printf("Error scaling image, out of memory or bad dimensions\n");
293                 return (1);
294             }   /* end if */
295           HDfree((VOIDP) img_buf);     /* free the old image */
296 
297           img_buf = scaled_image;   /* use the new image for further processing */
298           xdim = new_xdim;
299           ydim = new_ydim;
300       }     /* end if */
301 
302     /* Generate the RGB components for the 8 -> 24 bit converter */
303     if (ispal)
304       {
305           uint8      *pal_ptr = pal_buf;    /* temporary pointer into the palette */
306 
307           for (i = 0; i < 256; i++)
308             {
309                 red_comp[i] = *pal_ptr++;
310                 green_comp[i] = *pal_ptr++;
311                 blue_comp[i] = *pal_ptr++;
312             }   /* end for */
313       }     /* end if */
314     else
315       {     /* no palette, use a greyscale palette */
316           for (i = 0; i < 256; i++)
317               red_comp[i] = green_comp[i] = blue_comp[i] = (uint8) i;
318       }     /* end else */
319 
320     /* allocate space for the 24-bit image */
321     if ((img24_buf = (uint8 *) HDmalloc((size_t)(xdim * ydim * 3))) == NULL)
322       {
323           printf("Error, cannot allocate space for %dx%d 24-bit image\n", (int)xdim, (int)ydim);
324           return (1);
325       }     /* end if */
326 
327     /* convert the image */
328     if (!convert8to24(img_buf, img24_buf, xdim, ydim))
329       {
330           printf("Error converting 8-bit image to 24-bit image\n");
331           return (1);
332       }     /* end if */
333 
334     if (do_jpeg)
335       {     /* set up JPEG compression if necessary */
336           cinfo.jpeg.quality = jpeg_qual;   /* set JPEG comp. parameters */
337           cinfo.jpeg.force_baseline = TRUE;
338           DF24setcompress(COMP_JPEG, &cinfo);   /* set compression parameters */
339       }     /* end if */
340 
341     /* store 24-bit image */
342     if (DF24putimage(argv[file + 1], (VOIDP) img24_buf, xdim, ydim) == FAIL)
343       {
344           printf("Error storing 24-bit image\n");
345           HEprint(stdout, 0);
346           return (1);
347       }     /* end if */
348 
349     return (0);
350 }   /* end make24 */
351