r56: Improved option processing
[ctsim.git] / src / sdf2img.c
1 /*****************************************************************************
2 **  This is part of the CTSim program
3 **  Copyright (C) 1983-2000 Kevin Rosenberg
4 **
5 **  $Id: sdf2img.c,v 1.3 2000/05/16 04:33:59 kevin Exp $
6 **  $Log: sdf2img.c,v $
7 **  Revision 1.3  2000/05/16 04:33:59  kevin
8 **  Improved option processing
9 **
10 **  Revision 1.2  2000/05/08 20:02:32  kevin
11 **  ANSI C changes
12 **
13 **  Revision 1.1.1.1  2000/04/28 13:02:44  kevin
14 **  Initial CVS import for first public release
15 **
16 **
17 **
18 **  This program is free software; you can redistribute it and/or modify
19 **  it under the terms of the GNU General Public License (version 2) as
20 **  published by the Free Software Foundation.
21 **
22 **  This program is distributed in the hope that it will be useful,
23 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
24 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 **  GNU General Public License for more details.
26 **
27 **  You should have received a copy of the GNU General Public License
28 **  along with this program; if not, write to the Free Software
29 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30 ******************************************************************************/
31
32 /* FILE
33  *   sdf2img.c          Convert an SDF file to a viewable format image
34  */
35
36 #include "ct.h"
37
38 #if HAVE_PNG
39 void sdf2d_to_png (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax);
40 #endif
41 #if HAVE_GIF
42 void sdf2d_to_gif (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax);
43 #endif
44 void sdf2d_to_pgm (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax);
45 void sdf2d_to_pgmasc (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax);
46
47 enum { O_SCALE, O_MIN, O_MAX, O_AUTO, O_CENTER, O_STATS, O_FORMAT, O_LABELS, 
48        O_HELP, O_VERBOSE, O_VERSION, O_DEBUG };
49
50 static struct option my_options[] =
51 {
52   {"scale", 1, 0, O_SCALE},
53   {"min", 1, 0, O_MIN},
54   {"max", 1, 0, O_MAX},
55   {"auto", 1, 0, O_AUTO},
56   {"center", 1, 0, O_CENTER},
57   {"format", 1, 0, O_FORMAT},
58   {"labels", 0, 0, O_LABELS},
59   {"stats", 0, 0, O_STATS},
60   {"verbose", 0, 0, O_VERBOSE},
61   {"debug", 0, 0, O_DEBUG},
62   {"help", 0, 0, O_HELP},
63   {"version", 0, 0, O_VERSION},
64   {0, 0, 0, 0}
65 };
66
67 #define O_AUTO_FULL   1
68 #define O_AUTO_STD0_1 2
69 #define O_AUTO_STD0_5 3
70 #define O_AUTO_STD1   4
71 #define O_AUTO_STD2   5
72 #define O_AUTO_STD3   6
73
74 #define O_AUTO_FULL_STR  "full"
75 #define O_AUTO_STD0_1_STR  "std0.1"
76 #define O_AUTO_STD0_5_STR  "std0.5"
77 #define O_AUTO_STD1_STR  "std1"
78 #define O_AUTO_STD2_STR  "std2"
79 #define O_AUTO_STD3_STR  "std3"
80
81 #define O_CENTER_MEAN      1
82 #define O_CENTER_MODE      2
83 #define O_CENTER_MEAN_STR  "mean"
84 #define O_CENTER_MODE_STR  "mode"
85
86 #define O_FORMAT_GIF       1
87 #define O_FORMAT_PNG       2
88 #define O_FORMAT_PGM       3
89 #define O_FORMAT_PGMASC    4
90 #define O_FORMAT_GIF_STR   "gif"
91 #define O_FORMAT_PNG_STR   "png" 
92 #define O_FORMAT_PGM_STR   "pgm"
93 #define O_FORMAT_PGMASC_STR "pgmasc"
94
95 void 
96 sdf2img_usage (const char *program)
97 {
98   fprintf(stdout, "sdf2img_usage: %s sdfname outfile [OPTIONS]\n", kbasename(program));
99   fprintf(stdout, "Convert SDF2D file to an image file\n");
100   fprintf(stdout, "\n");
101   fprintf(stdout, "     sdfname    Name of input SDF file\n");
102   fprintf(stdout, "     outfile    Name of output file\n");
103   fprintf(stdout, "     --format   Output format\n");
104   fprintf(stdout, "         pgm    PGM (portable graymap) format (default)\n");
105   fprintf(stdout, "         pgmasc PGM (portable graymap) ASCII format\n");
106 #ifdef HAVE_PNG
107   fprintf(stdout, "         png    PNG format\n");
108 #endif
109 #ifdef HAVE_GIF
110   fprintf(stdout, "         gif    GIF format\n");
111 #endif
112   fprintf(stdout, "     --center   Center of window\n");
113   fprintf(stdout, "         mode   Mode is center of window (default)\n");
114   fprintf(stdout, "         mean   Mean is center of window\n");
115   fprintf(stdout, "     --auto     Set auto window\n");
116   fprintf(stdout, "         full   Use full window (default)\n");
117   fprintf(stdout, "         std0.1 Use 0.1 standard deviation about center\n");
118   fprintf(stdout, "         std0.5 Use 0.5 standard deviation about center\n");
119   fprintf(stdout, "         std1   Use one standard deviation about center\n");
120   fprintf(stdout, "         std2   Use two standard deviations about center\n");
121   fprintf(stdout, "         std3   Use three standard deviations about center\n");
122   fprintf(stdout, "     --scale    Scaling factor for output size\n");
123   fprintf(stdout, "     --min      Set minimum intensity\n");
124   fprintf(stdout, "     --max      Set maximum intensity\n");
125   fprintf(stdout, "     --stats    Print image statistics\n");
126   fprintf(stdout, "     --labels   Print image labels\n");
127   fprintf(stdout, "     --debug    Set debug mode\n");
128   fprintf(stdout, "     --verbose  Set verbose mode\n");
129   fprintf(stdout, "     --version  Print version\n");
130   fprintf(stdout, "     --help     Print this help message\n");
131 }
132
133
134 int 
135 sdf2img_main (int argc, char *const argv[])
136 {
137   IMAGE *im;
138   double densmin = HUGE_VAL, densmax = -HUGE_VAL;
139   char *in_file, *out_file;
140   int opt_verbose = 0;
141   int opt_scale = 1;
142   int opt_auto = O_AUTO_FULL;
143   int opt_set_max = 0;
144   int opt_set_min = 0;
145   int opt_stats = 0;
146   int opt_debug = 0;
147   int opt_center = O_CENTER_MODE;
148   int opt_format = O_FORMAT_PGM;
149   int opt_labels = 0;
150
151   while (1)
152     {
153       int c = getopt_long (argc, argv, "", my_options, NULL);
154       char *endptr = NULL;
155       char *endstr;
156       
157       if (c == -1)
158         break;
159       
160       switch (c)
161         {
162         case O_MIN:
163           opt_set_min = 1;
164           densmin = strtod(optarg, &endptr);
165           endstr = optarg + strlen(optarg);
166           if (endptr != endstr)
167             {
168               fprintf(stderr, "Error setting --min to %s\n", optarg);
169               sdf2img_usage(argv[0]);
170               return (1);
171             }
172           break;
173         case O_MAX:
174           opt_set_max = 1;
175           densmax = strtod(optarg, &endptr);
176           endstr = optarg + strlen(optarg);
177           if (endptr != endstr)
178             {
179               fprintf(stderr, "Error setting --max to %s\n", optarg);
180               sdf2img_usage(argv[0]);
181               return (1);
182             }
183           break;
184         case O_SCALE:
185           opt_scale = strtol(optarg, &endptr, 10);
186           endstr = optarg + strlen(optarg);
187           if (endptr != endstr)
188             {
189               fprintf(stderr,"Error setting --scale to %s\n", optarg);
190               sdf2img_usage(argv[0]);
191               return (1);
192             }
193           break;
194         case O_AUTO:
195           if (strcmp(optarg, O_AUTO_FULL_STR) == 0)
196             opt_auto = O_AUTO_FULL;
197           else if (strcmp(optarg, O_AUTO_STD1_STR) == 0)
198             opt_auto = O_AUTO_STD1;
199           else if (strcmp(optarg, O_AUTO_STD0_5_STR) == 0)
200             opt_auto = O_AUTO_STD0_5;
201           else if (strcmp(optarg, O_AUTO_STD0_1_STR) == 0)
202             opt_auto = O_AUTO_STD0_1;
203           else if (strcmp(optarg, O_AUTO_STD2_STR) == 0)
204             opt_auto = O_AUTO_STD2;
205           else if (strcmp(optarg, O_AUTO_STD3_STR) == 0)
206             opt_auto = O_AUTO_STD3;
207           else
208             {
209               fprintf(stderr, "Invalid auto mode %s\n", optarg);
210               sdf2img_usage(argv[0]);
211               return (1);
212             }
213                 break;
214         case O_CENTER:
215           if (strcmp(optarg, O_CENTER_MEAN_STR) == 0)
216             opt_center = O_CENTER_MEAN;
217           else if (strcmp(optarg, O_CENTER_MODE_STR) == 0)
218             opt_center = O_CENTER_MODE;
219           else
220             {
221               fprintf(stderr, "Invalid center mode %s\n", optarg);
222               sdf2img_usage(argv[0]);
223               return (1);
224             }
225                 break;
226         case O_FORMAT:
227           if (strcmp(optarg, O_FORMAT_PGM_STR) == 0)
228             opt_format = O_FORMAT_PGM;
229           else if (strcmp(optarg, O_FORMAT_PGMASC_STR) == 0)
230             opt_format = O_FORMAT_PGMASC;
231 #if HAVE_PNG
232           else if (strcmp(optarg, O_FORMAT_PNG_STR) == 0)
233             opt_format = O_FORMAT_PNG;
234 #endif
235 #if HAVE_GIF
236           else if (strcmp(optarg, O_FORMAT_GIF_STR) == 0)
237             opt_format = O_FORMAT_GIF;
238 #endif
239           else {
240               fprintf(stderr, "Invalid format mode %s\n", optarg);
241               sdf2img_usage(argv[0]);
242               return (1);
243             }
244           break;
245         case O_LABELS:
246           opt_labels = 1;
247           break;
248         case O_VERBOSE:
249           opt_verbose = 1;
250           break;
251         case O_DEBUG:
252           opt_debug = 1;
253           break;
254         case O_STATS:
255           opt_stats = 1;
256           break;
257         case O_VERSION:
258 #ifdef VERSION
259           fprintf(stdout, "Version %s\n", VERSION);
260 #else
261           fprintf(stderr, "Unknown version number");
262 #endif
263           exit(0);
264         case O_HELP:
265         case '?':
266           sdf2img_usage(argv[0]);
267           return (0);
268         default:
269           sdf2img_usage(argv[0]);
270           return (1);
271         }
272     }
273
274   if (optind + 2 != argc)
275     {
276       sdf2img_usage(argv[0]);
277       return (1);
278     }
279   
280   in_file = argv[optind];
281   out_file = argv[optind+1];
282
283   if ((im = image_load (in_file)) == NULL)
284     {
285       fprintf(stderr, "File %s does not exist\n", in_file);
286       return (1);
287     }
288
289   if (opt_labels) 
290     {
291       int nlabels = im->dfp_2d->dfp->num_label;
292       int i;
293
294       for (i = 0; i < nlabels; i++)
295         {
296           SDF_BLK blk;
297           if (sdf_read_label(&blk.lab, i, im->dfp_2d->dfp) != SDF_OK)
298             break;
299           if (blk.lab.label_type == LT_HISTORY) {
300             fprintf(stdout, "History: %s\n", blk.lab.label_str);
301             fprintf(stdout, "  calc time = %.2f secs\n", blk.lab.calc_time);
302             fprintf(stdout, "  Timestamp = %s\n", td_str_tmdt(&blk.lab.timedate));
303           } else if (blk.lab.label_type == LT_TITLE) {
304             fprintf(stdout, "Title: %s\n", blk.lab.label_str);
305             fprintf(stdout, "  Timestamp = %s\n", td_str_tmdt(&blk.lab.timedate));
306           } else if (blk.lab.label_type == LT_NOTE) {
307             fprintf(stdout, "Note: %s\n", blk.lab.label_str);
308             fprintf(stdout, "  Timestamp = %s\n", td_str_tmdt(&blk.lab.timedate));
309           }
310         }
311     }
312
313   if (opt_stats || (! (opt_set_max && opt_set_min)))
314     {
315       double minfound = HUGE_VAL, maxfound = -HUGE_VAL;
316       double mode = 0, mean = 0, stddev = 0, window = 0;
317       double spread;
318       int hist[256];
319       int ibin, nbin = 256;
320       int max_bin, max_binindex; 
321       double maxbin;
322       int ix, iy;
323
324       maxbin = nbin - 1;
325       for (ix = 0; ix < im->nx; ix++)
326         {
327           for (iy = 0; iy < im->ny; iy++)
328             {
329               if (im->v[ix][iy] > maxfound)
330                 maxfound = im->v[ix][iy];
331               if (im->v[ix][iy] < minfound)
332                 minfound = im->v[ix][iy];
333               mean += im->v[ix][iy];
334             }
335         }
336       spread = maxfound - minfound;
337       if (spread == 0)
338         mode = minfound;
339       else
340         {
341           for (ibin = 0; ibin < nbin; ibin++)
342             hist[ibin] = 0;
343           for (ix = 0; ix < im->nx; ix++)
344             {
345               for (iy = 0; iy < im->ny; iy++)
346                 {
347                   int b = (int) ((((im->v[ix][iy] - minfound) / spread) * (double) maxbin) + 0.5);
348                   hist[b]++;
349                 }
350             }
351           max_binindex = 0;
352           max_bin = -1;
353           for (ibin = 0; ibin < nbin; ibin++)
354             {
355               if (hist[ibin] > max_bin)
356                 {
357                   max_bin = hist[ibin];
358                   max_binindex = ibin;
359                 }
360             }
361           mode = (((double) max_binindex) * spread / ((double) maxbin)) + minfound;
362         }
363
364       if (opt_auto == O_AUTO_FULL)
365         {
366           if (! opt_set_max)
367             densmax = maxfound;
368           if (! opt_set_min)
369             densmin = minfound;
370         }
371       if (opt_stats || opt_auto != O_AUTO_FULL)
372         {
373           mean /= im->nx * im->ny;
374           for (ix = 0; ix < im->nx; ix++)
375             {
376               for (iy = 0; iy < im->ny; iy++)
377                 {
378                   double diff = (im->v[ix][iy] - mean);
379                   stddev += diff * diff;
380                 }
381             }
382           stddev = sqrt(stddev / (im->nx * im->ny));
383           if (opt_auto == O_AUTO_FULL)
384             ;
385           else if (opt_auto == O_AUTO_STD1)
386             window = stddev;
387           else if (opt_auto == O_AUTO_STD0_1)
388             window = stddev * 0.1;
389           else if (opt_auto == O_AUTO_STD0_5)
390             window = stddev * 0.5;
391           else if (opt_auto == O_AUTO_STD2)
392             window = stddev * 2;
393           else if (opt_auto == O_AUTO_STD3)
394             window = stddev * 3;
395           else
396             {
397               fprintf(stderr, "Internal Error: Invalid auto mode %d\n", opt_auto);
398               return (1);
399             }
400         }
401       if (opt_stats)
402         {
403           fprintf(stdout,"nx=%d\n", im->nx);
404           fprintf(stdout,"ny=%d\n", im->ny);
405           fprintf(stdout,"min=%f\n", minfound);
406           fprintf(stdout,"max=%f\n", maxfound);
407           fprintf(stdout,"mean=%f\n", mean);
408           fprintf(stdout,"mode=%f\n", mode);
409           fprintf(stdout,"stddev=%f\n", stddev);
410         }
411       if (opt_auto != O_AUTO_FULL)
412         {
413           double center;
414
415           if (opt_center == O_CENTER_MODE)
416             center = mode;
417           else if (opt_center == O_CENTER_MEAN)
418             center = mean;
419           else
420             {
421               fprintf(stderr, "Internal Error: Invalid center mode %d\n", opt_center);
422               return (1);
423             }
424           if (! opt_set_max)
425             densmax = center + window;
426           if (! opt_set_min)
427             densmin = center - window;
428         }
429     }
430
431   if (opt_stats)
432     {
433       fprintf(stdout,"min_disp=%f\n", densmin);
434       fprintf(stdout,"max_disp=%f\n", densmax);
435     }
436   
437   if (opt_format == O_FORMAT_PGM)
438     sdf2d_to_pgm (im, out_file, opt_scale, opt_scale, densmin, densmax);
439   else if (opt_format == O_FORMAT_PGMASC)
440     sdf2d_to_pgmasc (im, out_file, opt_scale, opt_scale, densmin, densmax);
441 #if HAVE_PNG
442   else if (opt_format == O_FORMAT_PNG)
443     sdf2d_to_png (im, out_file, opt_scale, opt_scale, densmin, densmax);
444 #endif
445 #if HAVE_GIF
446   else if (opt_format == O_FORMAT_GIF) 
447     sdf2d_to_gif (im, out_file, opt_scale, opt_scale, densmin, densmax);
448 #endif
449   else
450     {
451       fprintf(stderr, "Internal Error: Invalid format mode %d\n", opt_format);
452       return (1);
453     }
454   return (0);
455 }
456
457
458 void 
459 sdf2d_to_pgm (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax)
460 {
461   FILE *fp;
462   int irow;
463   unsigned char *rowp;
464
465   rowp = (unsigned char *) sys_alloc(im->nx * nxcell,"sdf2d_to_img");
466   if (rowp == NULL)
467     return;
468
469   if ((fp = fopen (outfile, "wb")) == NULL)
470      return;
471
472   fprintf(fp, "P5\n");
473   fprintf(fp, "%d %d\n", im->nx, im->ny);
474   fprintf(fp, "255\n");
475
476   for (irow = im->ny - 1; irow >= 0; irow--)
477     {
478       int icol, ir;
479
480       for (icol = 0; icol < im->nx; icol++)
481         {
482           double dens;
483           int p;
484           int pos = icol * nxcell;
485           dens = (im->v[icol][irow] - densmin) / (densmax - densmin);
486           if (dens < 0)
487             dens = 0;
488           else if (dens > 1)
489             dens = 1;
490           for (p = pos; p < pos + nxcell; p++)
491             {
492               rowp[p] = (unsigned int) (dens * 255.);
493             }
494         }
495       for (ir = 0; ir < nycell; ir++)
496         {
497           int ic;
498           for (ic = 0; ic < im->nx * nxcell; ic++) 
499             fprintf(fp, "%c ", rowp[ic]);
500         }
501     }
502   sys_free(rowp, "sdf2img");
503
504   fclose(fp);
505 }
506
507 void 
508 sdf2d_to_pgmasc (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax)
509 {
510   FILE *fp;
511   int irow;
512   unsigned char *rowp;
513
514   rowp = (unsigned char *) sys_alloc(im->nx * nxcell,"sdf2d_to_img");
515   if (rowp == NULL)
516     return;
517
518   if ((fp = fopen (outfile, "wb")) == NULL)
519      return;
520
521   fprintf(fp, "P2\n");
522   fprintf(fp, "%d %d\n", im->nx, im->ny);
523   fprintf(fp, "255\n");
524
525   for (irow = im->ny - 1; irow >= 0; irow--)
526     {
527       int icol, ir;
528
529       for (icol = 0; icol < im->nx; icol++)
530         {
531           double dens;
532           int p;
533           int pos = icol * nxcell;
534           dens = (im->v[icol][irow] - densmin) / (densmax - densmin);
535           if (dens < 0)
536             dens = 0;
537           else if (dens > 1)
538             dens = 1;
539           for (p = pos; p < pos + nxcell; p++)
540             {
541               rowp[p] = (unsigned int) (dens * 255.);
542             }
543         }
544       for (ir = 0; ir < nycell; ir++)
545         {
546           int ic;
547           for (ic = 0; ic < im->nx * nxcell; ic++) 
548             fprintf(fp, "%d ", rowp[ic]);
549           fprintf(fp, "\n");
550         }
551     }
552   sys_free(rowp, "sdf2img");
553
554   fclose(fp);
555 }
556
557
558 #ifdef HAVE_PNG
559 void 
560 sdf2d_to_png (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax)
561 {
562   FILE *fp;
563   png_structp png_ptr;
564   png_infop info_ptr;
565   int irow;
566   unsigned char *rowp;
567
568   rowp = (unsigned char *) sys_alloc(im->nx * nxcell,"sdf2d_to_img");
569   if (rowp == NULL)
570     return;
571
572   if ((fp = fopen (outfile, "wb")) == NULL)
573      return;
574
575   png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
576   if (! png_ptr)
577     return;
578
579   info_ptr = png_create_info_struct(png_ptr);
580   if (! info_ptr)
581     {
582       png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
583       fclose(fp);
584       return;
585     }
586
587   if (setjmp(png_ptr->jmpbuf))
588     {
589       png_destroy_write_struct(&png_ptr, &info_ptr);
590       fclose(fp);
591       return;
592     }
593
594   png_init_io(png_ptr, fp);
595
596   png_set_IHDR(png_ptr, info_ptr, im->nx * nxcell, im->ny * nycell, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_DEFAULT);
597
598   png_write_info(png_ptr, info_ptr);
599   for (irow = im->ny - 1; irow >= 0; irow--)
600     {
601       png_bytep row_pointer;
602       int icol, ir;
603
604       for (icol = 0; icol < im->nx; icol++)
605         {
606           double dens;
607           int p;
608           int pos = icol * nxcell;
609           dens = (im->v[icol][irow] - densmin) / (densmax - densmin);
610           if (dens < 0)
611             dens = 0;
612           else if (dens > 1)
613             dens = 1;
614           for (p = pos; p < pos + nxcell; p++)
615             {
616               rowp[p] = (unsigned int) (dens * 255.);
617             }
618         }
619       row_pointer = rowp;
620       for (ir = 0; ir < nycell; ir++)
621         {
622           png_write_rows (png_ptr, &row_pointer, 1);
623         }
624     }
625   sys_free(rowp, "sdf2img");
626
627   png_write_end(png_ptr, info_ptr);
628   png_destroy_write_struct(&png_ptr, &info_ptr);
629
630   fclose(fp);
631 }
632 #endif
633
634 #ifdef HAVE_GD
635 #include "gd.h"
636 #define N_GRAYSCALE 256
637 #endif
638
639 void
640 sdf2d_to_gif (IMAGE *im, char *outfile, int nxcell, int nycell, double densmin, double densmax)
641 {
642 #ifdef HAVE_GD
643   gdImagePtr gif;
644   FILE *out;
645   int gs_indices[N_GRAYSCALE];
646   int i;
647   int irow;
648   int lastrow;
649   unsigned char *rowp;
650
651   rowp = (unsigned char *) sys_alloc(im->nx * nxcell,"sdf2d_to_img");
652   if (rowp == NULL)
653     return;
654
655   gif = gdImageCreate(im->nx * nxcell, im->ny * nycell);
656   for (i = 0; i < N_GRAYSCALE; i++)
657     gs_indices[i] = gdImageColorAllocate(gif, i, i, i);
658
659   lastrow = im->ny * nycell - 1;
660   for (irow = 0; irow < im->ny; irow++)
661     {
662       int icol, ir;
663       int rpos = irow * nycell;
664       for (ir = rpos; ir < rpos + nycell; ir++)
665         {
666           for (icol = 0; icol < im->nx; icol++)
667             {
668               double dens;
669               int ic;
670               int cpos = icol * nxcell;
671               dens = (im->v[icol][irow] - densmin) / (densmax - densmin);
672               if (dens < 0)
673                 dens = 0;
674               else if (dens > 1)
675                 dens = 1;
676               for (ic = cpos; ic < cpos + nxcell; ic++)
677                 {
678                   rowp[ic] = (unsigned int) (dens * (double) (N_GRAYSCALE - 1));
679                   gdImageSetPixel(gif, ic, lastrow - ir, gs_indices[rowp[ic]]);
680                 }
681             }
682         }
683     }
684   sys_free(rowp, "sdf2img");
685
686   if ((out = fopen(outfile,"w")) == NULL)
687     {
688       fprintf(stderr,"Error opening output file %s for writing\n", outfile);
689       exit(1);
690     }
691   gdImageGif(gif,out);
692   fclose(out);
693   gdImageDestroy(gif);
694 #else
695   fprintf(stderr, "This version does not support GIF");
696 #endif
697 }
698
699 #ifndef NO_MAIN
700 int 
701 main (int argc, char *const argv[])
702 {
703   return (sdf2img_main(argc, argv));
704 }
705 #endif