Statistics
| Revision:

gvsig-raster / libjni-potrace / trunk / libjni-potrace / src / main / native / jpotrace / mkbitmap.c @ 1780

History | View | Annotate | Download (18.8 KB)

1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

    
5
/* mkbitmap.c: a standalone program for converting greymaps to bitmaps
6
   while optionally applying the following enhancements: highpass
7
   filter, interpolated scaling, inversion. */
8

    
9
#include <stdio.h>
10
#include <errno.h>
11
#include <string.h>
12
#include <stdlib.h>
13
#include <math.h>
14
#include <getopt.h>
15

    
16
#include "greymap.h"
17
#include "bitmap_io.h"
18
#include "platform.h"
19

    
20
#ifdef HAVE_CONFIG_H
21
#include "config.h"
22
#endif
23

    
24
#define SAFE_MALLOC(var, n, typ) \
25
  if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error 
26

    
27
/* structure to hold command line options */
28
struct info_s {
29
  char *outfile;     /* output file */
30
  char **infiles;    /* input files */
31
  int infilecount;   /* how many input files? */
32
  int invert;        /* invert input? */
33
  int highpass;      /* use highpass filter? */
34
  double lambda;     /* highpass filter radius */
35
  int scale;         /* scaling factor */
36
  int linear;        /* linear scaling? */
37
  int bilevel;       /* convert to bilevel? */
38
  double level;      /* cutoff grey level */
39
  char *outext;      /* default output file extension */
40
};
41
typedef struct info_s info_t;
42

    
43
static info_t info;
44

    
45
/* apply highpass filter to greymap. Return 0 on success, 1 on error
46
   with errno set. */
47
static int highpass(greymap_t *gm, double lambda) {
48
  greymap_t *gm1;
49
  double f, g;
50
  double c, d;
51
  double B;
52
  int x, y;
53

    
54
  /* we obtain a highpass filter by subtracting a lowpass filter from
55
     the identity */
56
  /* create scrap greymap */
57
  gm1 = gm_new(gm->w, gm->h);
58
  if (!gm1) {
59
    return 1;
60
  }
61

    
62
  /* calculate filter coefficients from given lambda */
63
  B =  1+2/(lambda*lambda);
64
  c = B-sqrt(B*B-1);
65
  d = 1-c;
66

    
67
  for (y=0; y<gm->h; y++) {
68
    /* apply low-pass filter to row y */
69
    /* left-to-right */
70
    f = g = 0;
71
    for (x=0; x<gm->w; x++) {
72
      f = f*c + GM_GET(gm, x, y)*d;
73
      g = g*c + f*d;
74
      GM_UPUT(gm1, x, y, g);
75
    }
76

    
77
    /* right-to-left */
78
    for (x=gm->w-1; x>=0; x--) {
79
      f = f*c + GM_GET(gm1, x, y)*d;
80
      g = g*c + f*d;
81
      GM_UPUT(gm1, x, y, g);
82
    }
83

    
84
    /* left-to-right mop-up */
85
    for (x=0; x<gm->w; x++) {
86
      f = f*c;
87
      g = g*c + f*d;
88
      if (f+g < 1/255.0) {
89
        break;
90
      }
91
      GM_UPUT(gm1, x, y, GM_GET(gm1, x, y)+g);
92
    }
93
  }
94

    
95
  for (x=0; x<gm->w; x++) {
96
    /* apply low-pass filter to column x */
97
    /* bottom-to-top */
98
    f = g = 0;
99
    for (y=0; y<gm->h; y++) {
100
      f = f*c + GM_GET(gm1, x, y)*d;
101
      g = g*c + f*d;
102
      GM_UPUT(gm1, x, y, g);
103
    }
104

    
105
    /* top-to-bottom */
106
    for (y=gm->h-1; y>=0; y--) {
107
      f = f*c + GM_GET(gm1, x, y)*d;
108
      g = g*c + f*d;
109
      GM_UPUT(gm1, x, y, g);
110
    }
111

    
112
    /* bottom-to-top mop-up */
113
    for (y=0; y<gm->h; y++) {
114
      f = f*c;
115
      g = g*c + f*d;
116
      if (f+g < 1/255.0) {
117
        break;
118
      }
119
      GM_UPUT(gm1, x, y, GM_GET(gm1, x, y)+g);
120
    }
121
  }
122

    
123
  /* original - lo-pass = hi-pass */
124
  for (y=0; y<gm->h; y++) {
125
    for (x=0; x<gm->w; x++) {
126
      f = GM_GET(gm, x, y);
127
      f -= GM_GET(gm1, x, y);
128
      f += 128;    /* normalize! */
129
      GM_PUT(gm, x, y, f);
130
    }
131
  }
132
  gm_free(gm1);
133
  return 0;
134
}
135

    
136
/* scale greymap by factor s, using linear interpolation. If
137
   bilevel=0, return a pointer to a greymap_t. If bilevel=1, return a
138
   pointer to a potrace_bitmap_t and use cutoff threshold c (0=black,
139
   1=white).  On error, return NULL with errno set. */
140

    
141
static void *interpolate_linear(greymap_t *gm, int s, int bilevel, double c) {
142
  int p00, p01, p10, p11;
143
  int i, j, x, y;
144
  double xx, yy, av;
145
  int c1 = 0;
146
  int w, h;
147
  double p0, p1;
148
  greymap_t *gm_out = NULL;
149
  potrace_bitmap_t *bm_out = NULL;
150

    
151
  w = gm->w;
152
  h = gm->h;
153

    
154
  /* allocate output bitmap/greymap */
155
  if (bilevel) {
156
    bm_out = bm_new(w*s, h*s);
157
    if (!bm_out) {
158
      return NULL;
159
    }
160
    bm_clear(bm_out, 0);
161
    c1 = (int)(c*255);
162
  } else {
163
    gm_out = gm_new(w*s, h*s);
164
    if (!gm_out) {
165
      return NULL;
166
    }
167
  }
168

    
169
  /* interpolate */
170
  for (i=0; i<w; i++) {
171
    for (j=0; j<h; j++) {
172
      p00 = GM_GET(gm, i, j);
173
      p01 = GM_GET(gm, i, j+1);
174
      p10 = GM_GET(gm, i+1, j);
175
      p11 = GM_GET(gm, i+1, j+1);
176
      
177
      if (bilevel) {
178
        /* treat two special cases which are very common */
179
        if (p00 < c1 && p01 < c1 && p10 < c1 && p11 < c1) {
180
          for (x=0; x<s; x++) {
181
            for (y=0; y<s; y++) {
182
              BM_PUT(bm_out, i*s+x, j*s+y, 1);
183
            }
184
          }
185
          continue;
186
        }
187
        if (p00 >= c1 && p01 >= c1 && p10 >= c1 && p11 >= c1) {
188
          continue;
189
        }
190
      }
191
      
192
      /* the general case */
193
      for (x=0; x<s; x++) {
194
        xx = x/(double)s;
195
        p0 = p00*(1-xx) + p10*xx;
196
        p1 = p01*(1-xx) + p11*xx;
197
        for (y=0; y<s; y++) {
198
          yy = y/(double)s;
199
          av = p0*(1-yy) + p1*yy;
200
          if (bilevel) {
201
            BM_PUT(bm_out, i*s+x, j*s+y, av < c1);
202
          } else {
203
            GM_PUT(gm_out, i*s+x, j*s+y, av);
204
          }
205
        }
206
      }
207
    }
208
  }
209
  if (bilevel) {
210
    return (void *)bm_out;
211
  } else {
212
    return (void *)gm_out;
213
  }
214
}
215

    
216
/* same as interpolate_linear, except use cubic interpolation (slower
217
   and better). */
218

    
219
/* we need this typedef so that the SAFE_MALLOC macro will work */
220
typedef double double4[4];
221

    
222
static void *interpolate_cubic(greymap_t *gm, int s, int bilevel, double c) {
223
  int w, h;
224
  double4 *poly = NULL; /* poly[s][4]: fixed interpolation polynomials */
225
  double p[4];              /* four current points */
226
  double4 *window = NULL; /* window[s][4]: current state */
227
  double t, v;
228
  int k, l, i, j, x, y;
229
  double c1 = 0;
230
  greymap_t *gm_out = NULL;
231
  potrace_bitmap_t *bm_out = NULL;
232

    
233
  SAFE_MALLOC(poly, s, double4);
234
  SAFE_MALLOC(window, s, double4);
235

    
236
  w = gm->w;
237
  h = gm->h;
238

    
239
  /* allocate output bitmap/greymap */
240
  if (bilevel) {
241
    bm_out = bm_new(w*s, h*s);
242
    if (!bm_out) {
243
      goto malloc_error;
244
    }
245
    bm_clear(bm_out, 0);
246
    c1 = c * 255;
247
  } else {
248
    gm_out = gm_new(w*s, h*s);
249
    if (!gm_out) {
250
      goto malloc_error;
251
    }
252
  }
253

    
254
  /* pre-calculate interpolation polynomials */
255
  for (k=0; k<s; k++) {
256
    t = k/(double)s;
257
    poly[k][0] = 0.5 * t * (t-1) * (1-t);
258
    poly[k][1] = -(t+1) * (t-1) * (1-t) + 0.5 * (t-1) * (t-2) * t;
259
    poly[k][2] = 0.5 * (t+1) * t * (1-t) - t * (t-2) * t;
260
    poly[k][3] = 0.5 * t * (t-1) * t;
261
  }
262

    
263
  /* interpolate */
264
  for (y=0; y<h; y++) {
265
    x=0;
266
    for (i=0; i<4; i++) {
267
      for (j=0; j<4; j++) {
268
        p[j] = GM_BGET(gm, x+i-1, y+j-1);
269
      }
270
      for (k=0; k<s; k++) {
271
        window[k][i] = 0.0;
272
        for (j=0; j<4; j++) {
273
          window[k][i] += poly[k][j] * p[j];
274
        }
275
      }
276
    }
277
    while (1) {
278
      for (l=0; l<s; l++) {
279
        for (k=0; k<s; k++) {
280
          v = 0.0;
281
          for (i=0; i<4; i++) {
282
            v += window[k][i] * poly[l][i];
283
          }
284
          if (bilevel) {
285
            BM_PUT(bm_out, x*s+l, y*s+k, v < c1);
286
          } else {
287
            GM_PUT(gm_out, x*s+l, y*s+k, v);
288
          }            
289
        }
290
      }
291
      x++;
292
      if (x>=w) {
293
        break;
294
      }
295
      for (i=0; i<3; i++) {
296
        for (k=0; k<s; k++) {
297
          window[k][i] = window[k][i+1];
298
        }
299
      }
300
      i=3;
301
      for (j=0; j<4; j++) {
302
        p[j] = GM_BGET(gm, x+i-1, y+j-1);
303
      }
304
      for (k=0; k<s; k++) {
305
        window[k][i] = 0.0;
306
        for (j=0; j<4; j++) {
307
          window[k][i] += poly[k][j] * p[j];
308
        }
309
      }
310
    }
311
  }
312

    
313
  free(poly);
314
  free(window);
315

    
316
  if (bilevel) {
317
    return (void *)bm_out;
318
  } else {
319
    return (void *)gm_out;
320
  }
321

    
322
 malloc_error:
323
  free(poly);
324
  free(window);
325
  return NULL;
326
}
327

    
328
/* ---------------------------------------------------------------------- */
329

    
330
/* process a single file, containing one or more images. On error,
331
   print error message to stderr and exit with code 2. On warning,
332
   print warning message to stderr. */
333

    
334
static void process_file(FILE *fin, FILE *fout, char *infile, char *outfile) {
335
  int r;
336
  greymap_t *gm;
337
  potrace_bitmap_t *bm;
338
  void *sm;
339
  int x, y;
340
  int count;
341

    
342
  for (count=0; ; count++) {
343
    r = gm_read(fin, &gm);
344
    switch (r) {
345
    case -1:  /* system error */
346
      fprintf(stderr, ""MKBITMAP": %s: %s\n", infile, strerror(errno));
347
      exit(2);
348
    case -2:  /* corrupt file format */
349
      fprintf(stderr, ""MKBITMAP": %s: file format error: %s\n", infile, gm_read_error);
350
      exit(2);
351
    case -3:  /* empty file */
352
      if (count>0) {  /* end of file */
353
        return;
354
      }
355
      fprintf(stderr, ""MKBITMAP": %s: empty file\n", infile);
356
      exit(2);
357
    case -4:  /* wrong magic */
358
      if (count>0) {
359
        fprintf(stderr, ""MKBITMAP": %s: warning: junk at end of file\n", infile);
360
        return;
361
      }
362
      fprintf(stderr, ""MKBITMAP": %s: file format not recognized\n", infile);
363
      fprintf(stderr, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
364
      exit(2);
365
    case 1:  /* unexpected end of file */
366
      fprintf(stderr, ""MKBITMAP": %s: warning: premature end of file\n", infile);
367
      break;
368
    }
369
    
370
    if (info.invert) {
371
      for (y=0; y<gm->h; y++) {
372
        for (x=0; x<gm->w; x++) {
373
          GM_UPUT(gm, x, y, 255-GM_UGET(gm, x, y));
374
        }
375
      }
376
    }
377
    
378
    if (info.highpass) {
379
      r = highpass(gm, info.lambda);
380
      if (r) {
381
        fprintf(stderr, ""MKBITMAP": %s: %s\n", infile, strerror(errno));
382
        exit(2);
383
      }
384
    }
385
    
386
    if (info.linear) {
387
      sm = interpolate_linear(gm, info.scale, info.bilevel, info.level);
388
    } else {
389
      sm = interpolate_cubic(gm, info.scale, info.bilevel, info.level);
390
    }      
391
    if (!sm) {
392
      fprintf(stderr, ""MKBITMAP": %s: %s\n", infile, strerror(errno));
393
      exit(2);
394
    }
395
    gm_free(gm);
396
    
397
    if (info.bilevel) {
398
      bm = (potrace_bitmap_t *)sm;
399
      bm_writepbm(fout, bm);
400
      bm_free(bm);
401
    } else {
402
      gm = (greymap_t *)sm;
403
      gm_writepgm(fout, gm, NULL, 1, GM_MODE_POSITIVE, 1.0);
404
      gm_free(gm);
405
    }    
406
  }
407
}
408

    
409
/* ---------------------------------------------------------------------- */
410
/* some info functions and option processing */
411

    
412
static int license(FILE *f) {
413
  fprintf(f, 
414
  "This program is free software; you can redistribute it and/or modify\n"
415
  "it under the terms of the GNU General Public License as published by\n"
416
  "the Free Software Foundation; either version 2 of the License, or\n"
417
  "(at your option) any later version.\n"
418
  "\n"
419
  "This program is distributed in the hope that it will be useful,\n"
420
  "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
421
  "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
422
  "GNU General Public License for more details.\n"
423
  "\n"
424
  "You should have received a copy of the GNU General Public License\n"
425
  "along with this program; if not, write to the Free Software\n"
426
  "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.\n"
427
          );
428
  return 0;
429
}
430

    
431
static int usage(FILE *f) {
432
  fprintf(f, "Usage: "MKBITMAP" [options] [file...]\n");
433
  fprintf(f, "Options:\n");
434
  fprintf(f, " -h, --help           - print this help message and exit\n");
435
  fprintf(f, " -v, --version        - print version info and exit\n");
436
  fprintf(f, " -l, --license        - print license info and exit\n");
437
  fprintf(f, " -o, --output <file>  - output to file\n");
438
  fprintf(f, " -x, --nodefaults     - turn off default options\n");
439
  fprintf(f, "Inversion:\n");
440
  fprintf(f, " -i, --invert         - invert the input (undo 'blackboard' effect)\n");
441
  fprintf(f, "Highpass filtering:\n");
442
  fprintf(f, " -f, --filter <n>     - apply highpass filter with radius n (default 4)\n");
443
  fprintf(f, " -n, --nofilter       - no highpass filtering\n");
444
  fprintf(f, "Scaling:\n");
445
  fprintf(f, " -s, --scale <n>      - scale by integer factor n (default 2)\n");
446
  fprintf(f, " -1, --linear         - use linear interpolation\n");
447
  fprintf(f, " -3, --cubic          - use cubic interpolation (default)\n");
448
  fprintf(f, "Thresholding:\n");
449
  fprintf(f, " -t, --threshold <n>  - set threshold for bilevel conversion (default 0.45)\n");
450
  fprintf(f, " -g, --grey           - no bilevel conversion, output a greymap\n");
451

    
452
  fprintf(f, "\n");
453
  fprintf(f, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
454
  fprintf(f, "The default options are: -f 4 -s 2 -3 -t 0.45\n");
455
  
456
  return 0;
457
}
458

    
459
static struct option longopts[] = {
460
  {"help",          0, 0, 'h'},
461
  {"version",       0, 0, 'v'},
462
  {"license",       0, 0, 'l'},
463
  {"output",        1, 0, 'o'},
464
  {"reset",         0, 0, 'x'},
465
  {"invert",        0, 0, 'i'},
466
  {"filter",        1, 0, 'f'},
467
  {"nofilter",      0, 0, 'n'},
468
  {"scale",         1, 0, 's'},
469
  {"linear",        0, 0, '1'},
470
  {"cubic",         0, 0, '3'},
471
  {"grey",          0, 0, 'g'},
472
  {"threshold",     1, 0, 't'},
473
  {0, 0, 0, 0}
474
};
475

    
476
static char *shortopts = "hvlo:xif:ns:13gt:";
477

    
478
/* process options. On error, print error message to stderr and exit
479
   with code 1 */
480
static void dopts(int ac, char *av[]) {
481
  int c;
482
  char *p;
483
  
484
  /* set defaults for command line parameters */
485
  info.outfile = NULL;    /* output file */
486
  info.infiles = NULL;    /* input files */
487
  info.infilecount = 0;   /* how many input files? */
488
  info.invert = 0;        /* invert input? */
489
  info.highpass = 1;      /* use highpass filter? */
490
  info.lambda = 4;        /* highpass filter radius */
491
  info.scale = 2;         /* scaling factor */
492
  info.linear = 0;        /* linear scaling? */
493
  info.bilevel = 1;       /* convert to bilevel? */
494
  info.level = 0.45;      /* cutoff grey level */
495
  info.outext = ".pbm";   /* output file extension */
496

    
497
  while ((c = getopt_long(ac, av, shortopts, longopts, NULL)) != -1) {
498
    switch (c) {
499
    case 'h':
500
      fprintf(stdout, ""MKBITMAP" "VERSION". Transforms images into bitmaps with scaling and filtering.\n\n");
501
      usage(stdout);
502
      exit(0);
503
      break;
504
    case 'v':
505
      fprintf(stdout, ""MKBITMAP" "VERSION". Copyright (C) 2001-2007 Peter Selinger.\n");
506
      exit(0);
507
      break;
508
    case 'l':
509
      fprintf(stdout, ""MKBITMAP" "VERSION". Copyright (C) 2001-2007 Peter Selinger.\n\n");
510
      license(stdout);
511
      exit(0);
512
      break;
513
    case 'o':
514
      free(info.outfile);
515
      info.outfile = strdup(optarg);
516
      break;
517
    case 'x':
518
      info.invert = 0;
519
      info.highpass = 0;
520
      info.scale = 1;
521
      info.bilevel = 0;
522
      info.outext = ".pgm";
523
      break;
524
    case 'i':
525
      info.invert = 1;
526
      break;
527
    case 'f':
528
      info.highpass = 1;
529
      info.lambda = strtod(optarg, &p);
530
      if (*p || info.lambda<0) {
531
        fprintf(stderr, ""MKBITMAP": invalid filter radius -- %s\n", optarg);
532
        exit(1);
533
      }
534
      break;
535
    case 'n':
536
      info.highpass = 0;
537
      break;
538
    case 's':
539
      info.scale = strtol(optarg, &p, 0);
540
      if (*p || info.scale<=0) {
541
        fprintf(stderr, ""MKBITMAP": invalid scaling factor -- %s\n", optarg);
542
        exit(1);
543
      }
544
      break;
545
    case '1':
546
      info.linear = 1;
547
      break;
548
    case '3':
549
      info.linear = 0;
550
      break;
551
    case 'g':
552
      info.bilevel = 0;
553
      info.outext = ".pgm";
554
      break;
555
    case 't':
556
      info.bilevel = 1;
557
      info.outext = ".pbm";
558
      info.level = strtod(optarg, &p);
559
      if (*p || info.level<0) {
560
        fprintf(stderr, ""MKBITMAP": invalid threshold -- %s\n", optarg);
561
        exit(1);
562
      }
563
      break;
564
    case '?':
565
      fprintf(stderr, "Try --help for more info\n");
566
      exit(1);
567
      break;
568
    default:
569
      fprintf(stderr, ""MKBITMAP": Unimplemented option -- %c\n", c);
570
      exit(1);
571
    }
572
  }
573
  info.infiles = &av[optind];
574
  info.infilecount = ac-optind;
575
  return;
576
}
577

    
578
/* ---------------------------------------------------------------------- */
579
/* auxiliary functions for file handling */
580

    
581
/* open a file for reading. Return stdin if filename is NULL or "-" */ 
582
static FILE *my_fopen_read(char *filename) {
583
  if (filename == NULL || strcmp(filename, "-") == 0) {
584
    return stdin;
585
  }
586
  return fopen(filename, "rb");
587
}
588

    
589
/* open a file for writing. Return stdout if filename is NULL or "-" */ 
590
static FILE *my_fopen_write(char *filename) {
591
  if (filename == NULL || strcmp(filename, "-") == 0) {
592
    return stdout;
593
  }
594
  return fopen(filename, "wb");
595
}
596

    
597
/* close a file, but do nothing is filename is NULL or "-" */
598
static void my_fclose(FILE *f, char *filename) {
599
  if (filename == NULL || strcmp(filename, "-") == 0) {
600
    return;
601
  }
602
  fclose(f);
603
}
604

    
605
/* make output filename from input filename. Return an allocated value. */
606
static char *make_outfilename(char *infile, char *ext) {
607
  char *outfile;
608
  char *p;
609

    
610
  if (strcmp(infile, "-") == 0) {
611
    return strdup("-");
612
  }
613

    
614
  outfile = (char *) malloc(strlen(infile)+strlen(ext)+5);
615
  if (!outfile) {
616
    return NULL;
617
  }
618
  strcpy(outfile, infile);
619
  p = strrchr(outfile, '.');
620
  if (p) {
621
    *p = 0;
622
  }
623
  strcat(outfile, ext);
624

    
625
  /* check that input and output filenames are different */
626
  if (strcmp(infile, outfile) == 0) {
627
    strcpy(outfile, infile);
628
    strcat(outfile, "-out");
629
  }
630

    
631
  return outfile;
632
}
633

    
634
/* ---------------------------------------------------------------------- */
635
/* Main function */
636

    
637
int main(int ac, char *av[]) {
638
  FILE *fin, *fout;
639
  int i;
640
  char *outfile;
641

    
642
  /* platform-specific initializations, e.g., set file i/o to binary */
643
  platform_init();
644

    
645
  /* process options */
646
  dopts(ac, av);
647

    
648
  /* there are several ways to call us:
649
     mkbitmap                    -- stdin to stdout
650
     mkbitmap -o outfile         -- stdin to outfile
651
     mkbitmap file...            -- encode each file and generate outfile names
652
     mkbitmap file... -o outfile -- concatenate files and write to outfile
653
  */
654

    
655
  if (info.infilecount == 0 && info.outfile == NULL) {  /* stdin to stdout */
656

    
657
    process_file(stdin, stdout, "stdin", "stdout");
658
    return 0;
659

    
660
  } else if (info.infilecount == 0) {                  /* stdin to outfile */
661

    
662
    fout = my_fopen_write(info.outfile);
663
    if (!fout) {
664
      fprintf(stderr, ""MKBITMAP": %s: %s\n", info.outfile, strerror(errno));
665
      exit(2);
666
    }
667
    process_file(stdin, fout, "stdin", info.outfile);
668
    my_fclose(fout, info.outfile);
669
    return 0;
670

    
671
  } else if (info.outfile == NULL) {       /* infiles -> multiple outfiles */
672

    
673
    for (i=0; i<info.infilecount; i++) {
674
      outfile = make_outfilename(info.infiles[i], info.outext);
675
      if (!outfile) {
676
        fprintf(stderr, ""MKBITMAP": %s\n", strerror(errno));
677
        exit(2);
678
      }
679
      fin = my_fopen_read(info.infiles[i]);
680
      if (!fin) {
681
        fprintf(stderr, ""MKBITMAP": %s: %s\n", info.infiles[i], strerror(errno));
682
        exit(2);
683
      }
684
      fout = my_fopen_write(outfile);
685
      if (!fout) {
686
        fprintf(stderr, ""MKBITMAP": %s: %s\n", outfile, strerror(errno));
687
        exit(2);
688
      }
689
      process_file(fin, fout, info.infiles[i], outfile);
690
      my_fclose(fin, info.infiles[i]);
691
      my_fclose(fout, outfile);
692
      free(outfile);
693
    }
694
    return 0;
695

    
696
  } else {                                    /* infiles to single outfile */
697

    
698
    fout = my_fopen_write(info.outfile);
699
    if (!fout) {
700
      fprintf(stderr, ""MKBITMAP": %s: %s\n", info.outfile, strerror(errno));
701
      exit(2);
702
    }
703
    for (i=0; i<info.infilecount; i++) {
704
      fin = my_fopen_read(info.infiles[i]);
705
      if (!fin) {
706
        fprintf(stderr, ""MKBITMAP": %s: %s\n", info.infiles[i], strerror(errno));
707
        exit(2);
708
      }
709
      process_file(fin, fout, info.infiles[i], info.outfile);
710
      my_fclose(fin, info.infiles[i]);
711
    }
712
    my_fclose(fout, info.outfile);
713
    return 0;
714

    
715
  }      
716

    
717
  /* not reached */
718
}
719

    
720