File: hdftor8.c

package info (click to toggle)
libhdf4 4.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 29,892 kB
  • sloc: ansic: 128,688; sh: 14,969; fortran: 12,444; java: 5,864; xml: 1,305; makefile: 900; yacc: 678; pascal: 418; perl: 360; javascript: 203; lex: 163; csh: 41
file content (363 lines) | stat: -rw-r--r-- 11,783 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF.  The full HDF 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/HDF/releases/.  *
 * If you do not have access to either file, you may request a copy from     *
 * help@hdfgroup.org.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*
 * hdftor8.c
 * Extract images from HDF file to raster files
 */

#include <stdlib.h>
#include <string.h>

#include "hdf.h"

#define PALETTE_SIZE 768 /* size of palette array */
#define COLOR_SIZE   256 /* size of palette color array */
                         /* COLOR_SIZE == PALETTE_SIZE / 3 */

#define INTERACTIVE  'i' /* interactive option */
#define RASTER_FILE  'r' /* raster filename template */
#define PALETTE_FILE 'p' /* palette filename template */
#define VERBOSE      'v' /* verbose option */

#define TEMPLATE_NUMBER '#' /* image or palette number positions */
#define TEMPLATE_XDIM   '@' /* image x dim positions */
#define TEMPLATE_YDIM   '%' /* image y dim positions */

const char D_RASTER_TEM[]  = "img#-@.%"; /* default raster file name template */
const char D_PALETTE_TEM[] = "pal#";     /*  default palette file name template */

int interactive; /* interactive option */
int verbose;     /* verbose option */

int         main(int argc, char *argv[]);
void        putRaster(const char *template, int32 xdim, int32 ydim, int imageNumber, uint8 *image);
void        putPalette(const char *template, int imageNumber, uint8 *palette);
void        convert(const char *template, int imageNumber, int32 xdim, int32 ydim, char *stringOut);
void        fillStr(const char **template, char **stringOut, char *string, char specialChar);
char       *newSpace(int32 size);
const char *getTemplate(const char *type, int imageNumber);

int
main(int argc, char *argv[])
{
    int         i, imageNumber, ispal, err_val;
    int32       xdim, ydim;
    char       *hdfFile;
    uint8      *image, palette[PALETTE_SIZE];
    const char *rasterTemplate = NULL, *paletteTemplate = NULL;

    if (argc < 2) {
        printf("%s,  version: 1.1   date: July 1, 1992\n", argv[0]);
        printf("\t This utility extracts all raster-8 images and/or\n");
        printf("\t palettes from an HDF file and stores them in two sets of\n");
        printf("\t files containing only images and palettes, respectively.\n");
        printf("Usage:\n");
        printf("hdftor8 hdf_file [-i] [-v] [-r image_file] [-p pal_file]\n");
        printf("\t -i: interactive (specify filenames interactively)\n");
        printf("\t -v: verbose (provide descriptive messages)\n");
        printf("\t Images and palettes are placed in the specified files\n");
        printf("\t The names of these files may contain special characters\n");
        printf("\t\t which will be replaced by numbers:\n");
        printf("\t  #    replace with image or palette number\n");
        printf("\t  @    replace with x dim of image\n");
        printf("\t  %%    replace with y dim of image\n");
        printf("\t If not specified, image filename defaults to img#-@.%%\n");
        printf("\t If not specified, palette filename defaults to pal.#\n\n");
        exit(1);
    }

    hdfFile = argv[1];

    for (i = 2; i < argc; i++) {
        if (*argv[i] == '-') {
            switch (argv[i][1]) {
                case INTERACTIVE:
                    interactive = TRUE;
                    break;
                case RASTER_FILE:
                    rasterTemplate = argv[++i];
                    break;
                case PALETTE_FILE:
                    paletteTemplate = argv[++i];
                    break;
                case VERBOSE:
                    verbose = TRUE;
                    break;
                default:
                    printf("Illegal option: %s, skipping...\n", argv[i]);
                    break;
            }
        }
        else
            printf("Illegal option: %s, skipping...\n", argv[i]);
    }

    if (!rasterTemplate && !interactive)
        rasterTemplate = D_RASTER_TEM;
    if (!paletteTemplate && !interactive)
        paletteTemplate = D_PALETTE_TEM;

    for (imageNumber = 1; !DFR8getdims(hdfFile, &xdim, &ydim, &ispal);) {
        image = (uint8 *)newSpace(xdim * ydim);
        if (verbose) {
            if (ispal)
                printf("Getting image and palette %d.\n", imageNumber);
            else
                printf("Getting image %d.\n", imageNumber);
            printf("Image dimensions : %d * %d\n", (int)xdim, (int)ydim);
        }
        if (!DFR8getimage(hdfFile, image, xdim, ydim, palette)) {
            putRaster(rasterTemplate, xdim, ydim, imageNumber, image);
            if (ispal)
                putPalette(paletteTemplate, imageNumber, palette);
            imageNumber++;
        }
        else
            break;
    }

    err_val = (int)HEvalue(1);
    if ((err_val != DFE_NOMATCH) && (err_val != DFE_NONE)) {
        if (verbose)
            HEprint(stderr, 0);
        exit(1);
    }
    return (0);
}

/*
 * putRaster
 *
 * Write the image to a raster image file.
 *
 * INPUT:
 *        template : pointer to template string
 *        xdim : x dimension of image
 *        ydim : y dimension of image
 *        imageNumber : (need I say more?)
 *        image : pointer to image array
 */
void
putRaster(const char *template, int32 xdim, int32 ydim, int imageNumber, uint8 *image)
{
    FILE *fd;
    char  fileName[DF_MAXFNLEN];

    if (!template) /* can assume interactive (see main) */
        template = getTemplate("image", imageNumber);

    convert(template, imageNumber, xdim, ydim, fileName);

    if (verbose)
        printf("Writing into image file : %s\n", fileName);

    if ((fd = fopen(fileName, "wb")) == NULL) {
        puts("Unable to open file. Exiting...");
        exit(1);
    }
    if (fwrite(image, (size_t)xdim, (size_t)ydim, fd) != (unsigned)ydim) {
        puts("Unable to write to file. Exiting...");
        exit(1);
    }
    if (fclose(fd)) {
        puts("Unable to close file. Exiting...");
        exit(1);
    }
}

/*
 * putPalette
 *
 * Write palette array out to palette file.
 *
 * INPUT:
 *        template : palette filename template
 *        imageNumber : Yes, the number of the image
 *        palette : pointer to the palette array
 */
void
putPalette(const char *template, int imageNumber, uint8 *palette)
{
    int   i;
    FILE *fd;
    char  fileName[DF_MAXFNLEN], reds[COLOR_SIZE];
    char  greens[COLOR_SIZE], blues[COLOR_SIZE];

    if (!template) /* can assume interactive (see main) */
        template = getTemplate("palette", imageNumber);

    convert(template, imageNumber, (int32)1, (int32)768, fileName);

    if (verbose)
        printf("Writing into palette file : %s\n", fileName);

    if ((fd = fopen(fileName, "wb")) == NULL) {
        puts("Unable to open file. Exiting...");
        exit(1);
    }

    for (i = 0; i < COLOR_SIZE; i++) {
        reds[i]   = *palette++;
        greens[i] = *palette++;
        blues[i]  = *palette++;
    }
    if (fwrite(reds, 1, COLOR_SIZE, fd) != COLOR_SIZE) {
        printf("Unable to write to file. Exiting...");
        exit(1);
    }
    if (fwrite(greens, 1, COLOR_SIZE, fd) != COLOR_SIZE) {
        printf("Unable to write to file. Exiting...");
        exit(1);
    }
    if (fwrite(blues, 1, COLOR_SIZE, fd) != COLOR_SIZE) {
        printf("Unable to write to file. Exiting...");
        exit(1);
    }
    if (fclose(fd)) {
        printf("Unable to close file. Exiting...");
        exit(1);
    }
}

/*
 * convert
 *
 * Determine the file name given the template, imageNumber, x dimension
 * and y dimension. Replaces template special characters with the
 * corresponding numbers.
 *
 * INPUT:
 *        template : file name template
 *        imageNumber :
 *        xdim : x dimension of image
 *        ydim : y dimension of image
 * OUTPUT:
 *        stringOut : the concocted file name
 */
void
convert(const char *template, int imageNumber, int32 xdim, int32 ydim, char *stringOut)
{
    char numStr[20], xStr[20], yStr[20];

    sprintf(numStr, "%03d", imageNumber);
    sprintf(xStr, "%03d", (int)xdim);
    sprintf(yStr, "%03d", (int)ydim);

    for (; (*template);) {
        switch (*template) {
            case TEMPLATE_NUMBER:
                fillStr(&template, &stringOut, numStr, TEMPLATE_NUMBER);
                break;
            case TEMPLATE_XDIM:
                fillStr(&template, &stringOut, xStr, TEMPLATE_XDIM);
                break;
            case TEMPLATE_YDIM:
                fillStr(&template, &stringOut, yStr, TEMPLATE_YDIM);
                break;
            default:
                *stringOut++ = *template ++;
        }
    }
    *stringOut = '\0';
}

/*
 * fillStr
 *
 * Fill a string of special characters with a number string.
 * If the number string is shorter than the number of special characters
 * then the string is padded with '0' on the left. Else the number of the
 * special characters is ignored.
 *
 * INPUT:
 *        template : pointer to pointer of string template
 *        string : pointer to the number string
 *        specialChar : the special character we are replacing
 * OUTPUT:
 *        stringOut : pointer to pointer of converted string (not really)
 * BUG: Both the pointer to the template string and the pointer to the
 *        converted string are moved to after the position of the conversion.
 */
void
fillStr(const char **template, char **stringOut, char *string, char specialChar)
{
    int templateLen, stringLen, i;

    for (templateLen = 1; *(++(*template)) == specialChar; templateLen++)
        ;
    stringLen = (int)strlen(string);

    for (i = templateLen - stringLen; i > 0; i--)
        *(*stringOut)++ = '0';

    for (; (*string);)
        *(*stringOut)++ = *string++;
}

/*
 * newSpace
 *
 * Allocate a space with little wastage
 *
 * INPUT:
 *        size : size of space request
 * RETURN:
 *        pointer to the space allocated
 *
 * BUG: This routine can only handle one request at any time,
 *        a second call cannot be made while the space is still
 *        in use (somewhere else).
 */
char *
newSpace(int32 size)
{
    static int32 oldSize  = 0;    /* must be static */
    static char *oldSpace = NULL; /* must be static */

    if (size >= oldSize) {
        free(oldSpace);
        if ((oldSpace = (char *)malloc((uint32)size)) == NULL) {
            puts("Out of memory. Abort.");
            exit(1);
        }
        oldSize = size;
    }

    return oldSpace;
}

/*
 * getTemplate
 *
 * Ask the user for a file name template string.
 *
 * INPUT:
 *        type : a description string of the type of file,
 *                i.e. image or palette.
 *        imageNumber :
 * RETURN:
 *        pointer to template string
 * BUG: This routine can only handle one request at any time,
 *        a second call cannot be made while the template is still
 *        in use (somewhere else).
 */
const char *
getTemplate(const char *type, int imageNumber)
{
    static char template[DF_MAXFNLEN];

    printf("This is %s %d.\nWhat template would you like?\n", type, imageNumber);
    scanf("%s", template);
    return template;
}