1 /*
2  * xvpi.c - load routine for `Pi' format pictures.
3  *
4  * The `Pi' format is made by Yanagisawa.
5  * It is common among many Japanese personal computer users.
6  *
7  */
8 
9 #include "xv.h"
10 #include <setjmp.h>
11 
12 #ifdef HAVE_PI
13 
14 typedef unsigned short data16;
15 typedef unsigned int data32;
16 
17 struct pi_info {
18     jmp_buf jmp;
19     FILE *fp;
20     struct {
21 	int rest;
22 	byte cur;
23     }bs;
24     long fsize;
25     byte mode;
26     int width, height;
27     float aspect;
28     int cbits;
29     int numcols;
30     byte *cmap;
31     struct ct_t{
32 	struct elt_t *top;
33 	struct elt_t{
34 	    struct elt_t *old, *recent;
35 	    byte val;
36 	} *elt;
37     }*ct;
38     int defcmap;
39     int writing_grey;
40 };
41 
42 static void pi_open_file         PARM((struct pi_info*, char*));
43 static void pi_read_header       PARM((struct pi_info*, char**));
44 static void pi_check_id          PARM((struct pi_info*));
45 static void pi_read_comment      PARM((struct pi_info*, char**));
46 static void pi_read_palette      PARM((struct pi_info*));
47 static void pi_expand            PARM((struct pi_info*, byte**));
48 static byte pi_read_color        PARM((struct pi_info*, int));
49 static int pi_read_position      PARM((struct pi_info*));
50 static data32 pi_read_length     PARM((struct pi_info*));
51 static int pi_copy_pixels        PARM((struct pi_info*,
52 				     byte*, int, int, data32));
53 
54 static void pi_write_header      PARM((struct pi_info*,
55 				       char*, byte*, byte*, byte*));
56 static void pi_write_id          PARM((struct pi_info*));
57 static void pi_write_comment     PARM((struct pi_info*, char*));
58 static void pi_write_palette     PARM((struct pi_info*, byte*, byte*, byte*));
59 static void pi_compress          PARM((struct pi_info*, byte*));
60 static void pi_write_gabage      PARM((struct pi_info*));
61 static void pi_write_color       PARM((struct pi_info*, int, int));
62 static int pi_test_matching      PARM((struct pi_info*,
63 				       byte*, int, int, data32*));
64 static void pi_write_position    PARM((struct pi_info*, int));
65 static void pi_write_length      PARM((struct pi_info*, data32));
66 
67 static void pi_table_create      PARM((struct pi_info*));
68 static byte pi_table_get_value   PARM((struct pi_info*, int, int));
69 static int pi_table_lookup_value PARM((struct pi_info*, int, int));
70 static data32 pi_read_bits       PARM((struct pi_info*, int));
71 static void pi_write_bits        PARM((struct pi_info*, data32, int));
72 static void pi_init_pi_info      PARM((struct pi_info*));
73 static void pi_cleanup_pi_info   PARM((struct pi_info*, int));
74 static void pi_cleanup_pinfo     PARM((PICINFO*));
75 static void pi_memory_error      PARM((char*, char*));
76 static void pi_error             PARM((struct pi_info*, int));
77 static void pi_file_error        PARM((struct pi_info*, int));
78 static void pi_file_warning      PARM((struct pi_info*, int));
79 static void pi_show_pi_info      PARM((struct pi_info*));
80 static void *pi_malloc           PARM((size_t, char*));
81 static void *pi_realloc          PARM((void*, size_t, char*));
82 
83 
84 static char *pi_id = "Pi";
85 static char *pi_msgs[] = {
86     NULL,
87 #define PI_OPEN 1
88     "couldn't open.",
89 #define PI_CORRUPT 2
90     "file corrupted.",
91 #define PI_FORMAT 3
92     "not PI format.",
93 #define PI_PLANES 4
94     "bad number of planes.",
95 #define PI_WRITE 5
96     "write failed.",
97 };
98 
99 
100 /* The main routine of `Pi' loader. */
LoadPi(fname,pinfo)101 int LoadPi(fname, pinfo)
102     char *fname;
103     PICINFO *pinfo;
104 {
105     struct pi_info pi;
106     int e;
107     int i;
108     if(DEBUG) fputs("LoadPi:\n", stderr);
109 
110     pinfo->comment = NULL;
111     pi_init_pi_info(&pi);
112     if((e = setjmp(pi.jmp)) != 0){
113 	/* When an error occurs, comes here. */
114 	pi_cleanup_pi_info(&pi, 0);
115 	pi_cleanup_pinfo(pinfo);
116 	if(DEBUG) fputs("\n", stderr);
117 	return 0;
118     }
119 
120     pi_open_file(&pi, fname);
121     pi_read_header(&pi, &pinfo->comment);
122     pi_expand(&pi, &pinfo->pic);
123 
124     pinfo->normw = pinfo->w = pi.width;
125     pinfo->normh = pinfo->h = pi.height;
126     pinfo->type = PIC8;
127     if(pi.numcols > 256)	/* shouldn't happen. */
128 	pi.numcols = 256;
129     for(i = 0; i < pi.numcols; i++){
130 	pinfo->r[i] = pi.cmap[i * 3    ];
131 	pinfo->g[i] = pi.cmap[i * 3 + 1];
132 	pinfo->b[i] = pi.cmap[i * 3 + 2];
133     }
134     pinfo->frmType = F_PI;
135     pinfo->colType = F_FULLCOLOR;
136     sprintf(pinfo->fullInfo, "Pi, %d colors (%ld bytes)",
137 	    pi.numcols, pi.fsize);
138     sprintf(pinfo->shrtInfo, "%dx%d Pi.", pi.width, pi.height);
139     normaspect = pi.aspect;
140 
141     pi_cleanup_pi_info(&pi, 0);
142     if(DEBUG) fputs("\n", stderr);
143     return 1;
144 }
145 
pi_open_file(pi,fname)146 static void pi_open_file(pi, fname)
147     struct pi_info *pi;
148     char *fname;
149 {
150     if((pi->fp = fopen(fname, "rb")) == NULL)
151 	pi_file_error(pi, PI_OPEN);
152     fseek(pi->fp, (size_t) 0, SEEK_END);
153     pi->fsize = ftell(pi->fp);
154     fseek(pi->fp, (size_t) 0, SEEK_SET);
155 }
156 
pi_read_header(pi,comm)157 static void pi_read_header(pi, comm)
158     struct pi_info *pi;
159     char **comm;
160 {
161     byte buf[10];
162     int mda;
163     int i;
164 
165     pi_check_id(pi);
166     pi_read_comment(pi, comm);
167 
168     if(fread(buf, (size_t) 10, (size_t) 1, pi->fp) != 1)
169 	pi_file_error(pi, PI_CORRUPT);
170 
171     pi->mode = buf[0];
172     pi->defcmap = pi->mode & 0x80;
173     if(buf[1] != 0 && buf[2] != 0)
174 	pi->aspect = (float) buf[2] / (int) buf[1];
175     pi->cbits = buf[3];
176     pi->numcols = 1 << pi->cbits;
177 
178     if(pi->cbits != 4 && pi->cbits != 8)
179 	pi_error(pi, PI_PLANES);
180 
181     mda = (int) buf[8] << 8 | (int) buf[9];
182     for(i = 0; i < mda; i++){
183 	if(fgetc(pi->fp) == EOF)
184 	    pi_file_error(pi, PI_CORRUPT);
185     }
186 
187     if(fread(buf, (size_t) 4, (size_t) 1, pi->fp) != 1)
188 	pi_file_error(pi, PI_CORRUPT);
189     pi->width  = (int) buf[0] << 8 | (int) buf[1];
190     pi->height = (int) buf[2] << 8 | (int) buf[3];
191 
192     pi_read_palette(pi);
193 
194     if(DEBUG) pi_show_pi_info(pi);
195 }
196 
pi_check_id(pi)197 static void pi_check_id(pi)
198     struct pi_info *pi;
199 {
200     char buf[2];
201 
202     if(fread(buf, (size_t) 2, (size_t) 1, pi->fp) != 1)
203 	pi_file_error(pi, PI_CORRUPT);
204     if(strncmp(buf, pi_id, (size_t) 2) != 0)
205 	pi_error(pi, PI_FORMAT);
206 }
207 
pi_read_comment(pi,comm)208 static void pi_read_comment(pi, comm)
209     struct pi_info *pi;
210     char **comm;
211 {
212 /*
213  * The comment format is like:
214  *   comment string `^Z' dummy string `\0'
215  */
216     int max = -1, i = 0;
217     int c;
218 
219     while(1){
220 	if((c = fgetc(pi->fp)) == EOF)
221 	    pi_file_error(pi, PI_CORRUPT);
222 	if(c == '\032')		/* 0x1a, '^Z' */
223 	    break;
224 	if(max < i){
225 	    max += 32;
226 	    *comm = pi_realloc(*comm, (size_t) max + 1, "pi_read_comment(1)");
227 	}
228 	(*comm)[i++] = c;
229     }
230     if(max < i){
231 	max++;
232 	*comm = pi_realloc(*comm, (size_t) max + 1, "pi_read_comment(2)");
233     }
234     (*comm)[i] = '\0';
235 
236     while((c = fgetc(pi->fp)) != '\0'){		/* skip the dummy area */
237 	if(c == EOF)
238 	    pi_file_error(pi, PI_CORRUPT);
239     }
240 }
241 
pi_read_palette(pi)242 static void pi_read_palette(pi)
243     struct pi_info *pi;
244 {
245     pi->cmap = pi_malloc((size_t) pi->numcols * 3, "pi_read_palette");
246     if(pi->mode & 0x80){
247 	if(pi->numcols == 16){
248 	    int i;
249 	    byte on;
250 
251 	    on = 0x77;
252 	    for(i = 0; i < 8; i++){
253 		pi->cmap[i * 3    ] = i & 2 ? on : 0;
254 		pi->cmap[i * 3 + 1] = i & 4 ? on : 0;
255 		pi->cmap[i * 3 + 2] = i & 1 ? on : 0;
256 	    }
257 	    on = 0xff;
258 	    for(; i < 16; i++){
259 		pi->cmap[i * 3    ] = i & 2 ? on : 0;
260 		pi->cmap[i * 3 + 1] = i & 4 ? on : 0;
261 		pi->cmap[i * 3 + 2] = i & 1 ? on : 0;
262 	    }
263 	}else{	/* pi->numcols == 256 */
264 	    int i;
265 	    byte r, g, b;
266 	    r = g = b = 0;
267 	    for(i = 0; i < 256; i++){
268 		pi->cmap[i * 3    ] = r;
269 		pi->cmap[i * 3 + 1] = g;
270 		pi->cmap[i * 3 + 2] = b;
271 		if((b += 0x40) == 0){
272 		    if((r += 0x20) == 0)
273 			g += 0x20;
274 		}
275 	    }
276 	}
277     }else{
278 	if(fread(pi->cmap, (size_t) pi->numcols * 3, (size_t) 1, pi->fp) != 1)
279 	    pi_file_error(pi, PI_CORRUPT);
280     }
281 }
282 
283 /* The main routine to expand `Pi' file. */
pi_expand(pi,pic)284 static void pi_expand(pi, pic)
285     struct pi_info *pi;
286     byte **pic;
287 {
288     byte prev_col = 0;
289     int prev_pos = -1;
290     int cnt = 0, max_cnt = pi->width * pi->height;
291 
292     *pic = pi_malloc((size_t) max_cnt, "pi_expand");   // GRR POSSIBLE OVERFLOW / FIXME
293 
294     pi_table_create(pi);
295 
296     if(pi->width > 2){
297 	(*pic)[0] = pi_read_color(pi, 0);
298 	(*pic)[1] = pi_read_color(pi, (*pic)[0]);
299 
300 	while(cnt < max_cnt){
301 	    int pos = pi_read_position(pi);
302 	    if(pos != prev_pos){
303 		data32 len = pi_read_length(pi);
304 		cnt = pi_copy_pixels(pi, *pic, cnt, pos, len);
305 		prev_col = (*pic)[cnt - 1];
306 		prev_pos = pos;
307 	    }else{
308 		do{
309 		    prev_col = pi_read_color(pi, (int) prev_col);
310 		    (*pic)[cnt++] = prev_col;
311 		    prev_col = pi_read_color(pi, (int) prev_col);
312 		    (*pic)[cnt++] = prev_col;
313 		}while(pi_read_bits(pi, 1) == 1);
314 
315 		prev_pos = -1;
316 	    }
317 	}
318     }else{
319 	while(cnt < max_cnt){
320 	    prev_col = pi_read_color(pi, (int) prev_col);
321 	    (*pic)[cnt++] = prev_col;
322 	}
323     }
324 }
325 
pi_read_color(pi,prev)326 static byte pi_read_color(pi, prev)
327     struct pi_info *pi;
328     int prev;
329 {
330     byte n;
331     if(pi->cbits == 4){
332 	if(pi_read_bits(pi, 1) == 1)
333 	    n = pi_read_bits(pi, 1);			/* 1x */
334 	else{
335 	    if(pi_read_bits(pi, 1) == 0)
336 		n = pi_read_bits(pi, 1) + 2;		/* 00x */
337 	    else{
338 		if(pi_read_bits(pi, 1) == 0)
339 		    n = pi_read_bits(pi, 2) + 4;	/* 010xx */
340 		else
341 		    n = pi_read_bits(pi, 3) + 8;	/* 011xxx */
342 	    }
343 	}
344     }else{	/* cbits == 8 */
345 	if(pi_read_bits(pi, 1) == 1)
346 	    n = pi_read_bits(pi, 1);
347 	else{
348 	    int bits = 0;
349 	    byte base = 2;
350 	    while(bits < 6){
351 		if(pi_read_bits(pi, 1) == 0)
352 		    break;
353 		bits++;
354 		base <<= 1;
355 	    }
356 	    n = pi_read_bits(pi, bits + 1) + base;
357 	}
358     }
359 
360     return pi_table_get_value(pi, prev, (int) n);
361 }
362 
pi_read_position(pi)363 static int pi_read_position(pi)
364     struct pi_info *pi;
365 {
366     byte r;
367     if((r = pi_read_bits(pi, 2)) != 3)
368 	return (int) r;
369     else
370 	return (int) pi_read_bits(pi, 1) + 3;
371 }
372 
pi_read_length(pi)373 static data32 pi_read_length(pi)
374     struct pi_info *pi;
375 {
376     data32 r = 1;
377     int bits = 0;
378     while(pi_read_bits(pi, 1) == 1){
379 	r <<= 1;
380 	bits++;
381     }
382     if(bits > 0)
383 	return r + pi_read_bits(pi, bits);
384     return 1;
385 }
386 
pi_copy_pixels(pi,pic,cnt,pos,len)387 static int pi_copy_pixels(pi, pic, cnt, pos, len)
388     struct pi_info *pi;
389     byte *pic;
390     int cnt, pos;
391     data32 len;
392 {
393     int s = 0, d = cnt;
394     int max = pi->width * pi->height;
395     switch(pos){
396     case 0:
397 	if(cnt < 2){
398 	    if(pic[0] == pic[1])
399 		s = cnt - 2;
400 	    else
401 		s = cnt - 4;
402 	}else{
403 	    if(pic[cnt - 2] == pic[cnt - 1])
404 		s = cnt - 2;
405 	    else
406 		s = cnt - 4;
407 	}
408 	break;
409     case 1:
410 	s = cnt - pi->width;
411 	break;
412     case 2:
413 	s = cnt - pi->width * 2;
414 	break;
415     case 3:
416 	s = cnt - pi->width + 1;
417 	break;
418     case 4:
419 	s = cnt - pi->width - 1;
420     }
421 
422     len *= 2;
423     while(s < 0 && len != 0 && d < max){
424 	pic[d++] = pic[-(s++) % 2];
425 	len--;
426     }
427     while(len != 0 && d < max){
428 	pic[d++] = pic[s++];
429 	len--;
430     }
431     return d;
432 }
433 
434 /* The main routine of `Pi' saver. */
WritePi(fp,pic,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,comment)435 int WritePi(fp, pic, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
436 	    comment)
437     FILE *fp;
438     byte *pic;
439     int ptype, w, h;
440     byte *rmap, *gmap, *bmap;
441     int numcols, colorstyle;
442     char *comment;
443 {
444     byte rtemp[256], gtemp[256], btemp[256];
445     struct pi_info pi;
446     int e;
447 
448     if(DEBUG) fputs("WritePi\n", stderr);
449     pi_init_pi_info(&pi);
450     pi.fp = fp;
451     pi.width  = w;
452     pi.height = h;
453     pi.writing_grey = (colorstyle == F_GREYSCALE);
454     if(ptype == PIC24){
455 	if(!(pic = Conv24to8(pic, w, h, 256, rtemp, gtemp, btemp)))
456 	    pi_memory_error("Conv24to8", "WritePi");
457 	rmap = rtemp;
458 	gmap = gtemp;
459 	bmap = btemp;
460 	numcols = 256;
461     }
462 
463     if((e = setjmp(pi.jmp)) != 0){
464 	/* When an error occurs, comes here. */
465 	pi_cleanup_pi_info(&pi, 1);
466 	if(DEBUG) fputs("\n", stderr);
467 	return -1;
468     }
469 
470     pi.numcols = numcols;
471     pi_write_header(&pi, comment,  rmap, gmap, bmap);
472     pi_compress(&pi, pic);
473     pi_write_gabage(&pi);
474 
475     pi_cleanup_pi_info(&pi, 1);
476     if(DEBUG) fputs("\n", stderr);
477     return 0;
478 }
479 
pi_write_header(pi,comm,r,g,b)480 static void pi_write_header(pi, comm, r, g, b)
481     struct pi_info *pi;
482     char *comm;
483     byte *r, *g, *b;
484 {
485     byte buf[14];
486 
487     if(DEBUG) pi_show_pi_info(pi);
488 
489     pi_write_id(pi);
490     pi_write_comment(pi, comm);
491 
492     buf[0] = buf[1] = buf[2] = 0;
493     buf[3] = pi->cbits = pi->numcols > 16 ? 8 : 4;
494     buf[4] = 'X';
495     buf[5] = 'V';
496     buf[6] = ' ';
497     buf[7] = ' ';
498     buf[8] = buf[9] = 0;
499     buf[10] = pi->width >> 8;
500     buf[11] = pi->width;
501     buf[12] = pi->height >> 8;
502     buf[13] = pi->height;
503     if(fwrite(buf, (size_t) 14, (size_t) 1, pi->fp) != 1)
504 	pi_file_error(pi, PI_WRITE);
505 
506     pi_write_palette(pi, r, g, b);
507 }
508 
pi_write_id(pi)509 static void pi_write_id(pi)
510     struct pi_info *pi;
511 {
512     if(fwrite(pi_id, (size_t) 2, (size_t) 1, pi->fp) != 1)
513 	pi_file_error(pi, PI_WRITE);
514 }
515 
pi_write_comment(pi,comm)516 static void pi_write_comment(pi, comm)
517     struct pi_info *pi;
518     char *comm;
519 {
520     if(comm){
521 	int i;
522 	for(i = 0; comm[i]; i++){
523 	    if(comm[i] == '\032')	/* 0x1a, '^Z' */
524 		comm[i] = ' ';
525 	}
526 	if(i > 0){
527 	    if(fwrite(comm, (size_t) i, (size_t) 1, pi->fp) != 1)
528 		pi_file_error(pi, PI_WRITE);
529 	}
530     }
531 
532     if(fwrite("\032\0", (size_t) 2, (size_t) 1, pi->fp) != 1)
533 	pi_file_error(pi, PI_WRITE);
534 }
535 
pi_write_palette(pi,r,g,b)536 static void pi_write_palette(pi, r, g, b)
537     struct pi_info *pi;
538     byte *r, *g, *b;
539 {
540     int i;
541     int pinum = 1 << pi->cbits;
542     char buf[3];
543 
544     for(i = 0; i < pi->numcols; i++){
545 	buf[0] = *r++;
546 	buf[1] = *g++;
547 	buf[2] = *b++;
548 	if(pi->writing_grey)
549 	    buf[0] = buf[1] = buf[2] = MONO(buf[0], buf[1], buf[2]);
550 	if(fwrite(buf, (size_t) 3, (size_t) 1, pi->fp) != 1)
551 	    pi_file_error(pi, PI_WRITE);
552     }
553     for( ; i < pinum; i++){
554 	if(fwrite(buf, (size_t) 3, (size_t) 1, pi->fp) != 1)
555 	    pi_file_error(pi, PI_WRITE);
556     }
557     pi->numcols = pinum;
558 }
559 
560 /* The main routine to compress `Pi' format. */
pi_compress(pi,pic)561 static void pi_compress(pi, pic)
562     struct pi_info *pi;
563     byte *pic;
564 {
565     byte prev_col = 0;
566     int prev_pos = -1;
567     int cnt = 0, max_cnt = pi->width * pi->height;
568     pi_table_create(pi);
569 
570     if(pi->width > 2){
571 	int pos;
572 	data32 len;
573 
574 	pi_write_color(pi, 0,      pic[0]);
575 	pi_write_color(pi, pic[0], pic[1]);
576 	pos = pi_test_matching(pi, pic, prev_pos, cnt, &len);
577 	while(cnt < max_cnt){
578 	    if(pos >= 0){
579 		pi_write_position(pi, pos);
580 		pi_write_length(pi, len);
581 		if((cnt += len * 2) >= max_cnt)
582 		    break;
583 		prev_col = pic[cnt - 1];
584 		prev_pos = pos;
585 		pos = pi_test_matching(pi, pic, prev_pos, cnt, &len);
586 	    }else{
587 		pi_write_position(pi, prev_pos);
588 		prev_pos = -1;
589 		while(pos < 0){
590 		    pi_write_color(pi, (int) prev_col, pic[cnt]);
591 		    prev_col = pic[cnt];
592 		    if(++cnt >= max_cnt)
593 			break;
594 		    pi_write_color(pi, (int) prev_col, pic[cnt]);
595 		    prev_col = pic[cnt];
596 		    if(++cnt >= max_cnt)
597 			break;
598 		    pos = pi_test_matching(pi, pic, -1, cnt, &len);
599 		    if(pos < 0)
600 			pi_write_bits(pi, 1, 1);
601 		    else
602 			pi_write_bits(pi, 0, 1);
603 		}
604 	    }
605 	}
606     }else{
607 	while(cnt < max_cnt){
608 	    pi_write_color(pi, (int) prev_col, pic[cnt]);
609 	    prev_col = pic[cnt++];
610 	}
611     }
612 }
613 
pi_write_gabage(pi)614 static void pi_write_gabage(pi)
615     struct pi_info *pi;
616 {
617     pi_write_bits(pi, 0, 32);
618 }
619 
pi_write_color(pi,prev,col)620 static void pi_write_color(pi, prev, col)
621     struct pi_info *pi;
622     int prev, col;
623 {
624     int n = pi_table_lookup_value(pi, prev, col);
625 
626     if(pi->cbits == 4){
627 	if(n < 2)
628 	    pi_write_bits(pi, (data32) n | 2, 2);
629 	else if(n < 4)
630 	    pi_write_bits(pi, (data32) n - 2, 3);
631 	else if(n < 8)
632 	    pi_write_bits(pi, (data32) (n - 4) | 8, 5);
633 	else
634 	    pi_write_bits(pi, (data32) (n - 8) | 24, 6);
635     }else{	/* cbits == 8 */
636 	if(n < 2){
637 	    pi_write_bits(pi, (data32) n | 2, 2);
638 	}else{
639 	    int bits = 0;
640 	    byte base = 2;
641 	    while(bits < 6){
642 		if(n < (int) base * 2)
643 		    break;
644 		bits++;
645 		base <<= 1;
646 	    }
647 	    pi_write_bits(pi, 0, 1);
648 	    if(bits > 0)
649 		pi_write_bits(pi, 0xffffffff, bits);
650 	    if(bits < 6)
651 		pi_write_bits(pi, 0, 1);
652 	    pi_write_bits(pi, (data32) n - base, bits + 1);
653 	}
654     }
655 }
656 
pi_test_matching(pi,pic,prev,cnt,len)657 static int pi_test_matching(pi, pic, prev, cnt, len)
658     struct pi_info *pi;
659     byte *pic;
660     int prev, cnt;
661     data32 *len;
662 {
663     data32 lens[5];
664     int pos, p;
665     int s, d = 0;
666     int max = pi->width * pi->height;
667 
668     for(pos = 0; pos < 5; pos++){
669 	switch(pos){
670 	case 0:
671 	    if(cnt < 2){
672 		if(pic[0] == pic[1])
673 		    d = cnt - 2;
674 		else
675 		    d = cnt - 4;
676 	    }else{
677 		if(pic[cnt - 2] == pic[cnt - 1])
678 		    d = cnt - 2;
679 		else
680 		    d = cnt - 4;
681 	    }
682 	    break;
683 	case 1:
684 	    d = cnt - pi->width;
685 	    break;
686 	case 2:
687 	    d = cnt - pi->width * 2;
688 	    break;
689 	case 3:
690 	    d = cnt - pi->width + 1;
691 	    break;
692 	case 4:
693 	    d = cnt - pi->width - 1;
694 	}
695 	s = cnt;
696 	lens[pos] = 0;
697 
698 	if(prev == 0 && pos == 0)
699 	    continue;
700 
701 	while(d < max){
702 	    if(pic[(d < 0) ? (-d) % 2 : d] != pic[s])
703 		break;
704 	    lens[pos]++;
705 	    d++;
706 	    s++;
707 	}
708 
709     }
710 
711     for(pos = 0, p = 1; p < 5; p++){
712 	if(lens[p] >= lens[pos])
713 	    pos = p;
714     }
715 
716     if(lens[pos] / 2 == 0)
717 	return -1;
718     *len = lens[pos] / 2;
719     return pos;
720 }
721 
pi_write_position(pi,pos)722 static void pi_write_position(pi, pos)
723     struct pi_info *pi;
724     int pos;
725 {
726     switch(pos){
727     case 0:
728 	pi_write_bits(pi, 0, 2);
729 	break;
730     case 1:
731 	pi_write_bits(pi, 1, 2);
732 	break;
733     case 2:
734 	pi_write_bits(pi, 2, 2);
735 	break;
736     case 3:
737 	pi_write_bits(pi, 6, 3);
738 	break;
739     case 4:
740 	pi_write_bits(pi, 7, 3);
741 	break;
742     }
743 }
744 
pi_write_length(pi,len)745 static void pi_write_length(pi, len)
746     struct pi_info *pi;
747     data32 len;
748 {
749     int bits = 0;
750     data32 base = 1;
751 
752     while(len >= base * 2){
753 	bits++;
754 	base <<= 1;
755     }
756     if(bits > 0){
757 	pi_write_bits(pi, 0xffffffff, bits);
758 	pi_write_bits(pi, 0, 1);
759 	pi_write_bits(pi, len - base, bits);
760     }else
761 	pi_write_bits(pi, 0, 1);
762 }
763 
764 /*
765  * These pi_table_* functions manipulate the color table.
766  * pi_table_create:
767  *	allocates and initializes a color table.
768  * pi_table_get_value:
769  *	get the specified value, and move it to the top of the list.
770  * pi_table_lookup_value:
771  *	look up the specified value, and move it to the top of the list.
772  */
pi_table_create(pi)773 static void pi_table_create(pi)
774     struct pi_info *pi;
775 {
776     struct ct_t *t;
777     int i;
778     byte mask = pi->numcols - 1;
779     pi->ct = pi_malloc(sizeof *pi->ct * pi->numcols, "pi_table_create(1)");
780     for(i = 0, t = pi->ct; i < pi->numcols; i++, t++){
781 	int j;
782 	byte v = i;
783 	t->elt = pi_malloc(sizeof *t->elt * pi->numcols, "pi_table_create(2)");
784 	t->top = &t->elt[pi->numcols - 1];
785 	for(j = 0; j < pi->numcols; j++){
786 	    v = (v + 1) & mask;
787 	    if(j > 0)
788 		t->elt[j].old    = &t->elt[j - 1];
789 	    else
790 		t->elt[0].old    = t->top;
791 	    if(j < pi->numcols - 1)
792 		t->elt[j].recent = &t->elt[j + 1];
793 	    else
794 		t->elt[j].recent = &t->elt[0];
795 	    t->elt[j].val    = v;
796 	}
797 	t->elt[0].old = t->top;
798 	t->top->recent = &t->elt[0];
799     }
800 }
801 
pi_table_get_value(pi,left,num)802 static byte pi_table_get_value(pi, left, num)
803     struct pi_info *pi;
804     int left, num;
805 {
806     struct ct_t *t = &pi->ct[left];
807     struct elt_t *e = t->top;
808     if(left >= pi->numcols || num >= pi->numcols)
809 	abort();
810     if(num != 0){
811 	do {
812 	    e = e->old;
813 	}while(--num != 0);
814 
815 	e->old->recent = e->recent;
816 	e->recent->old = e->old;
817 
818 	e->recent = t->top->recent;
819 	e->recent->old = e;
820 	e->old = t->top;
821 	t->top->recent = e;
822 
823 	t->top = e;
824     }
825     return e->val;
826 }
827 
pi_table_lookup_value(pi,left,v)828 static int pi_table_lookup_value(pi, left, v)
829     struct pi_info *pi;
830     int left, v;
831 {
832     struct ct_t *t = &pi->ct[left];
833     struct elt_t *e = t->top;
834     int num = 0;
835 
836     if(left >= pi->numcols || v >= pi->numcols)
837 	abort();
838 
839     while(e->val != v){
840 	e = e->old;
841 	num++;
842     }
843 
844     if(num != 0){
845 	e->old->recent = e->recent;
846 	e->recent->old = e->old;
847 
848 	e->recent = t->top->recent;
849 	e->recent->old = e;
850 	e->old = t->top;
851 	t->top->recent = e;
852 
853 	t->top = e;
854     }
855 
856     return num;
857 }
858 
859 /*
860  * These 2 functions read or write to a bit stream.
861  * pi_read_bits:
862  *	reads a specified-bit data from the bit stream.
863  * pi_write_bits:
864  *	writes a specified-bit data to the bit stream.
865  */
pi_read_bits(pi,numbits)866 static data32 pi_read_bits(pi, numbits)
867     struct pi_info *pi;
868     int numbits;
869 {
870     data32 r = 0;
871 
872     while(numbits > 0){
873 	while(pi->bs.rest > 0 && numbits > 0){
874 	    r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0);
875 	    pi->bs.cur <<= 1;
876 	    pi->bs.rest--;
877 	    numbits--;
878 	}
879 	if(numbits > 0){
880 	    int c;
881 	    if((c = fgetc(pi->fp)) == EOF)
882 		pi_file_warning(pi, PI_CORRUPT);
883 	    pi->bs.cur  = c;
884 	    pi->bs.rest = 8;
885 	}
886     }
887 
888     return r;
889 }
890 
pi_write_bits(pi,dat,bits)891 static void pi_write_bits(pi, dat, bits)
892     struct pi_info *pi;
893     data32 dat;
894     int bits;
895 {
896     data32 dat_mask = 1 << (bits - 1);
897     while(bits > 0){
898 	while(pi->bs.rest < 8 && bits > 0){
899 	    pi->bs.cur <<= 1;
900 	    if(dat & dat_mask)
901 		pi->bs.cur |= 1;
902 	    pi->bs.rest++;
903 	    bits--;
904 	    dat_mask >>= 1;
905 	}
906 	if(pi->bs.rest >= 8){
907 	    if(fputc((int)pi->bs.cur, pi->fp) == EOF)
908 		pi_file_error(pi, PI_WRITE);
909 	    pi->bs.cur  = 0;
910 	    pi->bs.rest = 0;
911 	}
912     }
913 }
914 
915 /*
916  * The routines to initialize or clean up.
917  * pi_inif_pi_info:
918  *	initializes a pi_info structure.
919  * pi_cleanup_pi_info:
920  *	cleanup pi_info structure. It frees allocated memories.
921  * pi_cleanup_pinfo:
922  *	cleanup PICINFO structure when an error occurs.
923  */
pi_init_pi_info(pi)924 static void pi_init_pi_info(pi)
925     struct pi_info *pi;
926 {
927     pi->fp = NULL;
928     pi->bs.rest = 0;
929     pi->bs.cur = 0;
930     pi->fsize = 0;
931     pi->mode = 0;
932     pi->width = pi->mode = 0;
933     pi->aspect = 1.0;
934     pi->cbits = 0;
935     pi->numcols = 0;
936     pi->cmap = NULL;
937     pi->ct = NULL;
938     pi->defcmap = 0;
939     pi->writing_grey = 0;
940 }
941 
pi_cleanup_pi_info(pi,writing)942 static void pi_cleanup_pi_info(pi, writing)
943     struct pi_info *pi;
944     int writing;
945 {
946     if(pi->fp && !writing){
947 	fclose(pi->fp);
948 	pi->fp = NULL;
949     }
950     if(pi->cmap){
951 	free(pi->cmap);
952 	pi->cmap = NULL;
953     }
954     if(pi->ct){
955 	int i;
956 	for(i = 0; i < pi->numcols; i++)
957 	    free(pi->ct[i].elt);
958 	free(pi->ct);
959 	pi->ct = NULL;
960     }
961 }
962 
pi_cleanup_pinfo(pinfo)963 static void pi_cleanup_pinfo(pinfo)
964     PICINFO *pinfo;
965 {
966     if(pinfo->pic){
967 	free(pinfo->pic);
968 	pinfo->pic = NULL;
969     }
970     if(pinfo->comment){
971 	free(pinfo->comment);
972 	pinfo->comment = NULL;
973     }
974 }
975 
976 /*
977  * Error handling routins.
978  * pi_memory_error:
979  *	shows a error message, and terminates.
980  * pi_error:
981  *	shows a non-file error message.
982  * pi_file_error:
983  *	shows a file error message.
984  */
pi_memory_error(scm,fn)985 static void pi_memory_error(scm, fn)
986     char *scm, *fn;
987 {
988     char buf[128];
989     sprintf(buf, "%s: couldn't allocate memory. (%s)", scm ,fn);
990     FatalError(buf);
991 }
992 
pi_error(pi,mn)993 static void pi_error(pi, mn)
994     struct pi_info *pi;
995     int mn;
996 {
997     SetISTR(ISTR_WARNING, "%s", pi_msgs[mn]);
998     longjmp(pi->jmp, 1);
999 }
1000 
pi_file_error(pi,mn)1001 static void pi_file_error(pi, mn)
1002     struct pi_info *pi;
1003     int mn;
1004 {
1005     if(feof(pi->fp))
1006 	SetISTR(ISTR_WARNING, "%s (end of file)", pi_msgs[mn]);
1007     else
1008 	SetISTR(ISTR_WARNING, "%s (%s)", pi_msgs[mn], ERRSTR(errno));
1009     longjmp(pi->jmp, 1);
1010 }
1011 
pi_file_warning(pi,mn)1012 static void pi_file_warning(pi, mn)
1013     struct pi_info *pi;
1014     int mn;
1015 {
1016     if(feof(pi->fp))
1017 	SetISTR(ISTR_WARNING, "%s (end of file)", pi_msgs[mn]);
1018     else
1019 	SetISTR(ISTR_WARNING, "%s (%s)", pi_msgs[mn], ERRSTR(errno));
1020 }
1021 
pi_show_pi_info(pi)1022 static void pi_show_pi_info(pi)
1023     struct pi_info *pi;
1024 {
1025     fprintf(stderr, "  file size: %ld.\n", pi->fsize);
1026     fprintf(stderr, "  mode: 0x%02x.\n", pi->mode);
1027     fprintf(stderr, "  image size: %dx%d.\n", pi->width, pi->height);
1028     fprintf(stderr, "  aspect: %f.\n", pi->aspect);
1029     fprintf(stderr, "  number of color bits: %d.\n", pi->cbits);
1030     fprintf(stderr, "  number of colors: %d.\n", pi->numcols);
1031     fprintf(stderr, "  using default colormap: %s.\n",
1032 	    pi->defcmap ? "true" : "false");
1033     fprintf(stderr, "  writing greyscale image: %s.\n",
1034 	    pi->writing_grey ? "true" : "false");
1035 }
1036 
1037 /*
1038  * Memory related routines.  If failed, they calls pi_memory_error.
1039  */
pi_malloc(n,fn)1040 static void *pi_malloc(n, fn)
1041     size_t n;
1042     char *fn;
1043 {
1044     void *r = (void *) malloc(n);
1045     if(r == NULL)
1046 	pi_memory_error("malloc", fn);
1047     return r;
1048 }
1049 
pi_realloc(p,n,fn)1050 static void *pi_realloc(p, n, fn)
1051     void *p;
1052     size_t n;
1053     char *fn;
1054 {
1055     void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
1056     if(r == NULL)
1057 	pi_memory_error("realloc", fn);
1058     return r;
1059 }
1060 #endif /* HAVE_PI */
1061