1 /*
2  * xvhips.c - load routine for 'HIPS' format pictures
3  *
4  * LoadHIPS(fname, numcols)
5  */
6 
7 /*
8  * Copyright 1989, 1990 by the University of Pennsylvania
9  *
10  * Permission to use, copy, and distribute for non-commercial purposes,
11  * is hereby granted without fee, providing that the above copyright
12  * notice appear in all copies and that both the copyright notice and this
13  * permission notice appear in supporting documentation.
14  *
15  * The software may be modified for your own purposes, but modified versions
16  * may not be distributed.
17  *
18  * This software is provided "as is" without any express or implied warranty.
19  */
20 
21 #include "xv.h"
22 
23 #ifdef HAVE_HIPS
24 
25 #define Boolean FREDDIE
26 #include "xvhips.h"
27 #undef Boolean
28 
29 #include <alloca.h>
30 
31 #define LINES 100
32 #define LINELENGTH 132
33 
34 static int   fread_header(int fd, struct header *hd);
35 static char  *getline(int fd, char **s, int *l);
36 static int   dfscanf(int fd);
37 static void  make_grayscale(char *r, char *g, char *b);
38 static float hls_value (float n1, float n2, float hue);
39 static void  hls_to_rgb(float h, float l, float s,
40                         float *r, float *g, float *b);
41 static void  make_huescale(char *r, char *g, char *b);
42 static void  make_heatscale(char *r, char *g, char *b);
43 static int   load_colourmap(char *filestem, int max_colours,
44                             char *r, char *g, char *b);
45 
46 /************************************************************************
47  *
48  * Read Header routines
49  *
50  ************************************************************************/
51 
52 static char *ssave[LINES];
53 static int slmax[LINES];
54 static int lalloc = 0;
55 //extern char *calloc();
56 
57 
58 
fread_header(fd,hd)59 static int fread_header(fd, hd)
60   int fd;
61   struct header *hd;
62 {
63   int lineno, len, i;
64   char *s;
65 
66 /*fprintf(stderr,"fread_header: entered\n");*/
67   if(lalloc<1) {
68     ssave[0] = calloc(LINELENGTH, sizeof (char));
69     slmax[0] = LINELENGTH;
70     lalloc = 1;
71   }
72 /*fprintf(stderr,"fread_header: ssave allocated\n");*/
73   getline(fd,&ssave[0],&slmax[0]);
74   hd->orig_name = calloc(strlen(ssave[0])+1, sizeof (char));
75   strcpy(hd->orig_name,ssave[0]);
76   getline(fd,&ssave[0],&slmax[0]);
77   hd->seq_name = calloc(strlen(ssave[0])+1, sizeof (char));
78   strcpy(hd->seq_name,ssave[0]);
79   hd->num_frame = dfscanf(fd);
80   getline(fd,&ssave[0],&slmax[0]);
81   hd->orig_date = calloc(strlen(ssave[0])+1, sizeof (char));
82   strcpy(hd->orig_date,ssave[0]);
83   hd->rows = dfscanf(fd);
84   hd->cols = dfscanf(fd);
85   hd->bits_per_pixel = dfscanf(fd);
86   hd->bit_packing = dfscanf(fd);
87   hd->pixel_format = dfscanf(fd);
88   lineno = 0;
89   len = 1;
90   getline(fd,&ssave[0],&slmax[0]);
91   s = ssave[0];
92   while(*(s += strlen(s)-3) == '|') {
93     len += strlen(ssave[lineno]);
94     lineno++;
95     if (lineno >= LINES)
96       fprintf(stderr, "Too many lines in header history");
97     if(lineno >= lalloc) {
98       ssave[lineno] = calloc(LINELENGTH, sizeof (char));
99       slmax[lineno] = LINELENGTH;
100       lalloc++;
101     }
102     getline(fd,&ssave[lineno],&slmax[lineno]);
103     s = ssave[lineno];
104   }
105   len += strlen(ssave[lineno]);
106   hd->seq_history = calloc(len, sizeof (char));
107   hd->seq_history[0] = '\0';
108   for (i=0;i<=lineno;i++)
109     strcat(hd->seq_history,ssave[i]);
110   lineno = 0;
111   len = 1;
112   while(strcmp(getline(fd,&ssave[lineno],&slmax[lineno]),".\n")) {
113     len += strlen(ssave[lineno]);
114     lineno++;
115     if (lineno >= LINES)
116       fprintf(stderr, "Too many lines in header desc.");
117     if(lineno >= lalloc) {
118       ssave[lineno] = calloc(LINELENGTH, sizeof (char));
119       slmax[lineno] = LINELENGTH;
120       lalloc++;
121     }
122   }
123   hd->seq_desc = calloc(len, sizeof (char));
124   *hd->seq_desc = '\0';
125   for (i=0;i<lineno;i++)
126     strcat(hd->seq_desc,ssave[i]);
127 /*fprintf(stderr,"fread_header: exiting\n");*/
128   return 0;
129 }
130 
131 
132 
getline(fd,s,l)133 static char *getline(fd,s,l)
134   int fd;
135   char **s;
136   int *l;
137 {
138   int i,m;
139   char c,*s1,*s2;
140 
141   i = 0;
142   s1 = *s;
143   m = *l;
144   while(read(fd,&c,1) == 1 && c != '\n') {
145     if (m-- <= 2) {
146       s2 = calloc(LINELENGTH+*l,sizeof (char));
147       strcpy(s2,*s);
148       *s = s2;
149       *l += LINELENGTH;
150       m = LINELENGTH;
151       s1 = s2 + strlen(s2);
152     }
153     *s1++ = c;
154   }
155   if (c == '\n') {
156     *s1++ = '\n';
157     *s1 = '\0';
158     return *s;
159   }
160   fprintf(stderr, "Unexpected EOF while reading header.");
161   return NULL;
162 }
163 
164 
165 
dfscanf(fd)166 static int dfscanf(fd)
167   int fd;
168 {
169   int i;
170 
171   getline(fd,&ssave[0],&slmax[0]);
172   sscanf(ssave[0],"%d",&i);
173   return(i);
174 }
175 
176 
177 
178 /*******************************************/
LoadHIPS(fname,pinfo)179 int LoadHIPS(fname,pinfo)
180      char *fname;
181      PICINFO * pinfo;
182 /*******************************************/
183 {
184   FILE  *fp;
185   struct header h;
186   char * pic;
187 
188   /* open the stream, if necesary */
189   fp=fopen(fname,"r");
190   if (!fp) return 0;
191 
192   if (!fread_header(fileno(fp), &h)) {
193     SetISTR(ISTR_WARNING,"Can't read HIPS header");
194     return 0;
195   }
196 
197   pinfo->w = h.cols;
198   pinfo->h = h.rows;
199   pic = pinfo->pic = (byte *) malloc(h.rows * h.cols);   // GRR POSSIBLE OVERFLOW / FIXME
200   if (!pic) FatalError("couldn't malloc HIPS file");
201 
202   if (!fread(pic, 1, h.cols*h.rows, fp)) {
203     SetISTR(ISTR_WARNING,"Error reading HIPS data.\n");
204     return 0;
205   }
206   fclose (fp);
207 
208   pinfo->frmType = F_SUNRAS;
209   pinfo->colType = F_FULLCOLOR;
210   sprintf(pinfo->fullInfo, "HIPS file (%d bytes)", h.cols*h.rows);
211   sprintf(pinfo->shrtInfo, "HIPS file.");
212   pinfo->comment = (char *) NULL;
213 
214   {
215     char cmapname[256];
216     /* Check header for colormap spec */
217     char * s = h.seq_desc - 1;
218     char * cmaptag = "+COLORMAP";
219     int sl = strlen(cmaptag);
220     cmapname[0] = 0;
221     while (*++s)
222       if (*s == '+')
223 	if (strncmp(s, cmaptag, sl) == 0) {
224 	  char * p = s + sl;
225 	  while (*p && (*p == ' ' || *p == '\n' || *p == '\t')) p++;
226 	  sscanf(p, "%s", cmapname);
227 	  SetISTR(ISTR_INFO, cmapname);
228 	  fprintf(stderr, "Colormap = [%s]\n", cmapname);
229 	}
230 
231     if (strcmp(cmapname, "gray") == 0 || strcmp(cmapname, "grey") == 0)
232       make_grayscale(pinfo->r, pinfo->g, pinfo->b);
233     else if (strcmp(cmapname, "heat") == 0)
234       make_heatscale(pinfo->r, pinfo->g, pinfo->b);
235     else if (strcmp(cmapname, "hues") == 0)
236       make_huescale(pinfo->r, pinfo->g, pinfo->b);
237     else if (!cmapname[0] || !load_colourmap(cmapname, 256, pinfo->r, pinfo->g, pinfo->b))
238       make_grayscale(pinfo->r, pinfo->g, pinfo->b);
239     sprintf(pinfo->fullInfo, "HIPS file (%d x %d), Colormap = [%s]", h.cols, h.rows, cmapname);
240   }
241 
242   return 1;
243 }
244 
245 
246 
make_grayscale(char * r,char * g,char * b)247 static void make_grayscale(char * r, char * g, char * b)
248 {
249   int i;
250   /* default grayscale colors */
251   r[0] = 40; g[0] = 150; b[0] = 100; /* "green4" background */
252   for(i = 1; i < 256; i++)
253     r[i] = g[i] = b[i] = i;
254 }
255 
256 
257 
hls_value(n1,n2,hue)258 static float hls_value (n1, n2, hue)
259   float n1,n2,hue;
260 {
261 	if (hue>360.0)
262 	  hue-=360.0 ;
263 	else if (hue<0.0)
264 	  hue+=360.0 ;
265 
266 	if (hue<60.0)
267 	  return( n1+(n2-n1)*hue/60.0 ) ;
268 	else if (hue<180.0)
269 	  return ( n2 ) ;
270 	else if (hue<240.0)
271 	  return ( n1+(n2-n1)*(240.0-hue)/60.0 ) ;
272 	else
273 	  return (n1) ;
274 }
275 
276 
277 
hls_to_rgb(h,l,s,r,g,b)278 static void hls_to_rgb(h,l,s,  r,g,b)
279   float h, l, s;
280   float *r, *g, *b;
281 {
282 	static float m1, m2 ;
283 
284 	if (l<=0.5)
285 		m2=l*(1+s) ;
286 	else
287 		m2=l+s-l*s ;
288 	m1=2.0*l-m2 ;
289 	if (s==0.0) *r=*g=*b=l ;
290 	else {
291 		*r=hls_value(m1,m2,h+120.0) ;
292 		*g=hls_value(m1,m2,h) ;
293 		*b=hls_value(m1,m2,h-120.0) ;
294 	}
295 
296 }
297 
298 
299 
make_huescale(char * r,char * g,char * b)300 static void make_huescale(char * r, char * g, char * b)
301 {
302   int j;
303   r[0] = g[0] = b[0] = 0;
304   for (j = 1; j<256; j++)
305     {
306       float fr, fg, fb;
307       hls_to_rgb((double)(256.0-j)*360.0/256.0, 0.5, 1.0, &fr, &fg, &fb);
308       r[j] = rint(255*fr);
309       g[j] = rint(255*fg);
310       b[j] = rint(255*fb);
311     }
312 }
313 
314 
315 
make_heatscale(char * r,char * g,char * b)316 static void make_heatscale(char * r, char * g, char * b)
317 {
318   int j;
319   r[0] = g[0] = b[0] = 0;
320   for (j = 1; j<256; j++)
321     {
322       if(j<255/2)
323 	r[j] = j*255/(255/2-1);
324       else
325 	r[j]=255;
326       if (j>=255/2+255/3)
327 	g[j] = 255;
328       else if (j>255/3)
329 	g[j] = (j-255/3)*255/(255/2-1);
330       else
331 	g[j] = 0;
332       if (j>255/2)
333 	b[j] = (j-255/2)*255/(255-255/2-1);
334       else
335 	b[j] = 0;
336     }
337 }
338 
339 
340 
load_colourmap(char * filestem,int max_colours,char * r,char * g,char * b)341 static int load_colourmap(char *filestem, int max_colours,
342                           char *r, char *g, char *b)
343 {
344   FILE * fp;
345   int numread=0;
346   char * filename;
347   char str[200];
348   int num_colors;
349   /*
350    * Look for palette file in local directory
351    */
352 
353   filename = (char*)alloca(strlen(filestem) + 5);
354   strcpy(filename, filestem);
355   strcat(filename, ".PAL"); /* Add the PAL suffix to the name specified */
356   fp = fopen(filename,"r");
357   if (!fp) {
358     /*
359      * If not found, try in $IM2HOME/etc/palettes
360      */
361     char * im2home = (char*)getenv("IM2HOME");
362     char * palette_subdirectory = "etc/palettes";
363     char * fullfilename;
364     if (!im2home)
365       {
366 	im2home = "/home/jewel/imagine2";
367 	fprintf(stderr,"IM2HOME environment variable not set -- using [%s]\n",im2home);
368       }
369     fullfilename = alloca(strlen(im2home)+strlen(palette_subdirectory)+strlen(filename)+5);
370     sprintf(fullfilename, "%s/%s/%s",im2home,palette_subdirectory,filename);
371     fp = fopen(fullfilename,"r");
372     if (!fp)
373       {
374 	fprintf(stderr,"Couldn't find any palette file -- looked for [%s] and [%s].\n",
375 		filename,fullfilename);
376 	perror("Last system error message was");
377 	return 0;
378       }
379   }
380 
381   strcpy(str,"(null)");
382   if (!fscanf(fp,"%s\n",str) || strncmp(str,"Palette",7) != 0) {
383     fprintf(stderr,"error: First line of palette file should be `Palette', not [%s]\n", str);
384     return 0;
385   }
386 
387   fscanf(fp,"%[^\n]",str) ; /* Scan to end of line */
388   fscanf (fp,"%d",&num_colors);/* Read the number of colours in the file */
389   fgets(str,120,fp) ; /* Skip the text description, and general info lines */
390   fgets(str,120,fp) ;
391 
392   while ((numread<max_colours)&&(numread<num_colors)) {
393     int rc, gc, bc;
394     fscanf (fp,"%d %d %d -", &rc, &gc, &bc) ; /* Get the (r,g,b) tuples */
395     r[numread] = rc;
396     g[numread] = gc;
397     b[numread] = bc;
398     numread++;
399     fgets(str,120,fp) ; /* Skip the description, if present */
400   }
401 
402   SetISTR(ISTR_INFO,"Read %d colors from palette file [%s]", numread, filename);
403   return (numread) ; /* Return the number of colours ACTUALLY READ */
404 }
405 
406 #endif /* HAVE_HIPS */
407