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