1 /****************************************************************
2  * uoutput.c
3  *
4  * Copyright (C) 1995-2002 Klaus Ehrenfried
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  *************************************************************************/
21 
22 #include <stdio.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 #include "upro.h"
28 #include <stdlib.h>
29 
30 #define MAX_LEN 512
31 
32 static char *command;
33 static int max_cmd_len = -1;
34 
35 /****************************************************************
36  * piper_open
37  ****************************************************************/
38 
xx_close(FILE * fp,char * filter)39 static void xx_close(FILE *fp, char *filter)
40 {
41   if (filter == NULL)
42     {
43       fclose(fp);
44     }
45   else
46     {
47       pclose(fp);
48     }
49 }
50 
51 /****************************************************************
52  * piper_open
53  ****************************************************************/
54 
xx_open(char * file_name,char * filter)55 static FILE *xx_open(char *file_name, char *filter)
56 {
57   FILE *fopen(), *fp;
58   int cmd_len;
59 
60   if (filter == NULL)
61     {
62       if ((fp=fopen(file_name, "wb")) == NULL)
63 	{
64 	  fprintf(stderr," Error opening file '%s'\n",file_name);
65 	  return(NULL);
66 	}
67       return(fp);
68     }
69 
70   cmd_len = strlen(filter);
71   if (cmd_len == 0)
72     {
73       fprintf(stderr,"No filter specified\n");
74       return(NULL);
75     }
76   cmd_len += strlen(file_name);
77   cmd_len += 10; /* for extra chars */
78 
79   if (cmd_len >= max_cmd_len)
80     {
81       cmd_len += 10;
82       if (max_cmd_len > 0) free(command);
83       if ((command = (char *) malloc(cmd_len)) == NULL)
84         {
85           fprintf(stderr,"Can't allocate %d bytes\n",cmd_len);
86           return(NULL);
87         }
88       max_cmd_len = cmd_len;
89     }
90 
91   sprintf(command,"%s > %s",filter,file_name);
92   fprintf(stdout," .... %s\n",command);
93 
94   if ((fp = popen(command, "w")) == NULL)
95     {
96       fprintf(stderr,"Can't open file via pipe '%s'\n",command);
97       return(NULL);
98     }
99 
100   return(fp);
101 }
102 
103 /****************************************************************
104  * out_image
105  ****************************************************************/
106 
out_image(unsigned char * image_buffer,unsigned char * color_table,int width,int height,int outtype,char * name_base,char * name_ext,int digits,int num,char * filter)107 int out_image
108 (
109  unsigned char *image_buffer,
110  unsigned char *color_table,
111  int width,
112  int height,
113  int outtype,
114  char *name_base,
115  char *name_ext,
116  int digits,
117  int num,
118  char *filter
119  )
120 {
121   FILE *fopen(), *fpout;
122   struct stat  statbuf;
123   char out_name[MAX_LEN];
124   char digiter[MAX_LEN];
125   unsigned char *red, *green, *blue, *pp, *zz, *wbuff;
126   int m,n,i,j,ic, len, zsize;
127   int fbm_planes, fbm_bits, fbm_physbits;
128   int fbm_rowlen, fbm_plnlen, fbm_clrlen;
129   double fbm_aspect;
130 
131   if (name_ext == NULL)
132     len=strlen(name_base)+digits+1;
133   else
134     len=strlen(name_base)+strlen(name_ext)+digits+1;
135 
136   if (len > MAX_LEN)
137     {
138       fprintf(stderr,"Image %d: File name too long!\n",num);
139       return(0);
140     }
141 
142   m=num;
143   for (i=(digits-1); i >= 0; i--)
144     {
145       n=m % 10;
146       switch (n)
147 	{
148 	case 0: digiter[i] = '0'; break;
149 	case 1: digiter[i] = '1'; break;
150 	case 2: digiter[i] = '2'; break;
151 	case 3: digiter[i] = '3'; break;
152 	case 4: digiter[i] = '4'; break;
153 	case 5: digiter[i] = '5'; break;
154 	case 6: digiter[i] = '6'; break;
155 	case 7: digiter[i] = '7'; break;
156 	case 8: digiter[i] = '8'; break;
157 	case 9: digiter[i] = '9'; break;
158 	default: break;
159 	}
160       m = (m - n) / 10;
161     }
162   digiter[digits] = '\0';
163 
164   if (name_ext == NULL)
165     sprintf(out_name,"%s.%s",name_base,digiter);
166   else
167     sprintf(out_name,"%s%s.%s",name_base,digiter,name_ext);
168 
169   if (stat(out_name, &statbuf) == 0)	/* exists already */
170     {
171       fprintf(stderr,
172 	      "Error: file '%s' already exists -- image %d not written\n",
173 	      out_name,num);
174       return(0);
175     }
176 
177   if ((fpout=xx_open(out_name, filter)) == NULL) return(0);
178 
179   fprintf(stdout,"Write '%s'\n",out_name);
180 
181   red=&color_table[0];
182   green=&color_table[MAXCOLORS];
183   blue=&color_table[2*MAXCOLORS];
184 
185   if (outtype == PPM_ASCII)
186     {
187       fprintf(fpout,"P3\n");
188       fprintf(fpout,"%d %d 255\n",width,height);
189 
190       pp = image_buffer;
191       for (i = 0; i < (width*height); i++)
192 	{
193 	  ic = *pp++;
194 	  fprintf(fpout,"%d %d %d\n",red[ic],green[ic],blue[ic]);
195  	}
196     }
197   else if (outtype == PPM_RAW)
198     {
199       zsize = 3 * width;
200       wbuff = malloc(zsize);
201       if (wbuff == NULL)
202 	{
203 	  fprintf(stderr,"Error allocating %d bytes\n",zsize);
204 	  xx_close(fpout,filter);
205 	  return(0);
206 	}
207 
208       fprintf(fpout,"P6\n");
209       fprintf(fpout,"%d %d 255\n",width,height);
210 
211       pp = image_buffer;
212       for (j = 0; j < height; j++)
213 	{
214 	  zz = wbuff;
215 	  for (i = 0; i < width; i++)
216 	    {
217 	      ic = *pp++;
218 	      *zz++ = red[ic];
219 	      *zz++ = green[ic];
220 	      *zz++ = blue[ic];
221 	    }
222 	  if (fwrite(wbuff, 1, zsize, fpout) != zsize)
223 	    {
224 	      fprintf(stderr,"Write error in row %d, '%s' is incomplete\n",
225 		      j, out_name);
226 	      xx_close(fpout,filter);
227 	      return(0);
228 	    }
229 	}
230       free(wbuff);
231     }
232   else if (outtype == FBM_MAPPED)
233     {
234       zsize = 256;
235       wbuff = calloc(1, zsize);
236       if (wbuff == NULL)
237 	{
238 	  fprintf(stderr,"Error allocating %d bytes\n", zsize);
239 	  xx_close(fpout,filter);
240 	  return(0);
241 	}
242       fbm_planes = 1;
243       fbm_bits = fbm_physbits = 8;
244       fbm_rowlen = width;
245       fbm_plnlen = width * height;
246       fbm_clrlen = 3 * MAXCOLORS;
247       fbm_aspect = 1.0;
248       strncpy (&wbuff[0],  "%bitmap", 8);
249       sprintf (&wbuff[8],  "%7d",  width);
250       sprintf (&wbuff[16], "%7d",  height);
251       sprintf (&wbuff[24], "%7d",  fbm_planes);
252       sprintf (&wbuff[32], "%7d",  fbm_bits);
253       sprintf (&wbuff[40], "%7d",  fbm_physbits);
254       sprintf (&wbuff[48], "%11d", fbm_rowlen);
255       sprintf (&wbuff[60], "%11d", fbm_plnlen);
256       sprintf (&wbuff[72], "%11d", fbm_clrlen);
257       sprintf (&wbuff[84], "%11.6f", fbm_aspect);
258       if (fwrite(wbuff, 1, zsize, fpout) != zsize)
259 	{
260 	  fprintf(stderr,"Error writing fbm header, '%s' is incomplete\n",
261 		  out_name);
262 	  xx_close(fpout,filter);
263 	  return(0);
264 	}
265       if (fwrite(color_table, 1, fbm_clrlen, fpout) != fbm_clrlen)
266 	{
267 	  fprintf(stderr,"Error writing fbm color table, '%s' is incomplete\n",
268 		  out_name);
269 	  xx_close(fpout,filter);
270 	  return(0);
271 	}
272       if (fwrite(image_buffer, 1, fbm_plnlen, fpout) != fbm_plnlen)
273 	{
274 	  fprintf(stderr,"Error writing fbm image, '%s' is incomplete\n",
275 		  out_name);
276 	  xx_close(fpout,filter);
277 	  return(0);
278 	}
279     }
280   else
281     {
282       fprintf(stderr,"Invalid output type\n");
283       xx_close(fpout,filter);
284       return(0);
285     }
286 
287   if (ferror(fpout))
288     {
289       fprintf(stderr,"Error writing ppm\n");
290       xx_close(fpout,filter);
291       return(0);
292     }
293 
294   xx_close(fpout,filter);
295 
296   return(1);
297 }
298