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