1 /*
2  * xvpic.c - load routine for `PIC' format pictures.
3  *
4  * The `PIC' format is used by many Japanese personal computer users.
5  */
6 
7 #include "xv.h"
8 #include <setjmp.h>
9 
10 #ifdef HAVE_PIC
11 
12 typedef unsigned short data16;
13 typedef unsigned int data32;
14 
15 struct pic_info {
16     jmp_buf jmp;
17     FILE *fp;
18     struct {
19 	int rest;
20 	byte cur;
21     }bs;
22     long fsize;
23     int type, mode;
24     int width, height;
25     float aspect;
26     int cbits;
27     int cmapped;
28     byte *cmap;
29     int cached;
30     struct cache_t {
31 	int newest;
32 	struct cachenode_t {
33 	    data32 dat;
34 	    int newer, older;
35 	} *node;
36     } cache;
37     int g_bits, r_bits, b_bits, i_bits;
38     int inv_gr;
39     int tiled256;
40     int numcols;
41     int writing_grey;
42     data32 *data;
43 };
44 
45 static void pic_open_file              PARM((struct pic_info*,char*));
46 static void pic_check_id               PARM((struct pic_info*));
47 static void pic_read_comment           PARM((struct pic_info*, char**));
48 static void pic_read_header            PARM((struct pic_info*));
49 static void pic_expand_data            PARM((struct pic_info*));
50 static int pic_expanding_read_len      PARM((struct pic_info*));
51 static data32 pic_expanding_read_color PARM((struct pic_info*));
52 static void pic_expanding_read_chain
53 			PARM((struct pic_info*, int, int, data32));
54 static void pic_make_xvpic
55 			PARM((struct pic_info*, byte**, byte*, byte*, byte*));
56 
57 static void pic_write_id               PARM((struct pic_info*));
58 static void pic_write_comment          PARM((struct pic_info*, char*));
59 static void pic_write_header           PARM((struct pic_info*));
60 static void pic_write_palette
61 			PARM((struct pic_info*, byte*, byte*, byte*));
62 static void pic_make_sparse_data       PARM((struct pic_info*, byte*));
63 static void pic_write_data             PARM((struct pic_info*));
64 static void pic_write_length           PARM((struct pic_info*, data32));
65 static void pic_write_color            PARM((struct pic_info*, data32));
66 static void pic_write_chain
67 			PARM((struct pic_info*, int, int, data32));
68 
69 static data32 pic_read_rgb             PARM((struct pic_info*));
70 static data32 pic_read_color_code      PARM((struct pic_info*));
71 static void pic_write_rgb              PARM((struct pic_info*, data32));
72 static void pic_write_color_code       PARM((struct pic_info*, data32));
73 
74 static void pic_cache_init             PARM((struct pic_info*));
75 static data32 pic_cache_get_value      PARM((struct pic_info*, int));
76 static void pic_cache_add_value        PARM((struct pic_info*, data32));
77 static int pic_cache_lookup            PARM((struct pic_info*, data32));
78 
79 static data32 pic_read_bits            PARM((struct pic_info*, int));
80 static void pic_write_bits             PARM((struct pic_info*, data32, int));
81 static byte pic_pad_bit                PARM((int, data32));
82 
83 static void pic_init_info              PARM((struct pic_info*));
84 static void pic_cleanup_pic_info       PARM((struct pic_info*, int));
85 static void pic_cleanup_pinfo          PARM((PICINFO*));
86 static void pic_memory_error           PARM((char*, char*));
87 static void pic_error                  PARM((struct pic_info*, int));
88 static void pic_file_error             PARM((struct pic_info*, int));
89 static void pic_file_warning           PARM((struct pic_info*, int));
90 static void pic_show_pic_info          PARM((struct pic_info*));
91 static void *pic_malloc                PARM((size_t, char*));
92 static void *pic_realloc               PARM((void*, size_t, char*));
93 
94 
95 static char *pic_id = "PIC";
96 
97 /* Error Messages */
98 static char *pic_msgs[] = {
99     NULL,
100 #define PIC_OPEN 1
101     "can't open file.",
102 #define PIC_CORRUPT 2
103     "file corrupted.",
104 #define PIC_FORMAT 3
105     "not PIC format.",
106 #define PIC_SUPPORT 4
107     "unsupported type.",
108 #define PIC_COMMENT 5
109     "can't read comment.",
110 #define PIC_TYPE 6
111     "bad machine type.",
112 #define PIC_MODE 7
113     "bad machine-dependent mode.",
114 #define PIC_NUM_COLORS 8
115     "bad number of colors.",
116 #define PIC_SIZE 9
117     "bad size.",
118 #define PIC_ASPECT 10
119     "bad aspect.",
120 #define PIC_WRITE 11
121     "write failed.",
122 };
123 
124 #define H4(b) (((b) >> 4) & 0x0f)
125 #define L4(b) ( (b)       & 0x0f)
126 
127 
128 /* The main routine to load a PIC file. */
LoadPIC(fname,pinfo)129 int LoadPIC(fname, pinfo)
130     char *fname;
131     PICINFO *pinfo;
132 {
133     int e;
134     struct pic_info pic;
135     char buf[128];
136 
137     if(DEBUG) fputs("LoadPIC:\n", stderr);
138 
139     pic_init_info(&pic);
140 
141     pinfo->comment = NULL;
142     if((e = setjmp(pic.jmp)) != 0){
143 	/* When an error occurs, comes here. */
144 	pic_cleanup_pic_info(&pic, 0);
145 	pic_cleanup_pinfo(pinfo);
146 	if(DEBUG) fputs("\n", stderr);
147 	return 0;
148     }
149 
150     pic_open_file(&pic, fname);
151     pic_check_id(&pic);
152     pic_read_comment(&pic, &pinfo->comment);
153     pic_read_header(&pic);
154     pic_expand_data(&pic);
155     pic_make_xvpic(&pic, &pinfo->pic, pinfo->r, pinfo->g, pinfo->b);
156 
157     pinfo->w = pic.width;
158     if(pic.tiled256)
159 	pinfo->h = pic.height * 2;
160     else
161 	pinfo->h = pic.height;
162     pinfo->normw = pinfo->w;
163     pinfo->normh = pinfo->h;
164     pinfo->type = pic.cmapped ? PIC8 : PIC24;
165     pinfo->frmType = F_PIC;
166     pinfo->colType = F_FULLCOLOR;
167     strcpy(pinfo->fullInfo, "PIC");
168     switch(pic.type){
169     case 0x0:
170 	strcat(pinfo->fullInfo, ", X68k");
171 	break;
172     case 0x1:
173 	strcat(pinfo->fullInfo, ", PC-88VA");
174 	if(pic.mode & 1)
175 	    strcat(pinfo->fullInfo, ", HR");
176 	if(pic.mode & 2)
177 	    strcat(pinfo->fullInfo, ", tiled 256");
178 	break;
179     case 0x2:
180 	strcat(pinfo->fullInfo, ", FM-TOWNS");
181 	if(pic.mode == 0x5){
182 	    strcat(pinfo->fullInfo, ", low-resolution");
183 	}else{
184 	    strcat(pinfo->fullInfo, ", high-resolution");
185 	}
186 	break;
187     case 0x3:
188 	strcat(pinfo->fullInfo, ", Macintosh");
189 	break;
190     case 0xf:
191 	;
192     }
193     sprintf(buf, " (%ld bytes)", pic.fsize);
194     strcat(pinfo->fullInfo, buf);
195     sprintf(pinfo->shrtInfo, "%dx%d(aspect %4.2f) PIC.",
196 	    pinfo->w, pinfo->h, pic.aspect);
197     if (!nopicadjust)
198 	normaspect = pic.aspect;
199 
200     pic_cleanup_pic_info(&pic, 0);
201     if(DEBUG) fputs("\n", stderr);
202     return 1;
203 }
204 
pic_open_file(pi,fname)205 static void pic_open_file(pi, fname)
206     struct pic_info *pi;
207     char *fname;
208 {
209     if((pi->fp = fopen(fname, "rb")) == NULL)
210 	pic_file_error(pi, PIC_OPEN);
211     fseek(pi->fp, (size_t) 0, SEEK_END);
212     pi->fsize = ftell(pi->fp);
213     fseek(pi->fp, (size_t) 0, SEEK_SET);
214 }
215 
pic_check_id(pi)216 static void pic_check_id(pi)
217     struct pic_info *pi;
218 {
219     char buf[3];
220     if(fread(buf, (size_t) 3, (size_t) 1, pi->fp) != 1)
221 	pic_file_error(pi, PIC_CORRUPT);
222     if(strncmp(buf, pic_id, (size_t) 3) != 0)
223 	pic_error(pi, PIC_FORMAT);
224 }
225 
pic_read_comment(pi,comm)226 static void pic_read_comment(pi, comm)
227     struct pic_info *pi;
228     char **comm;
229 {
230     /* The comment field is like:
231      * comment-string ^Z dummy \0 \0
232      */
233     int max = -1, i = 0;
234     int c;
235 
236     while(1){
237 	if((c = fgetc(pi->fp)) == EOF)
238 	    pic_file_error(pi, PIC_CORRUPT);
239 	if(c == '\032')			/* 0x1a, '^Z' */
240 	    break;
241 	if(max < i){
242 	    max += 32;
243 	    *comm = pic_realloc(*comm, (size_t) max + 1, "pic_read_comment#1");
244 	}
245 	(*comm)[i++] = c;
246     }
247 
248     if(max < i){
249 	max++;
250 	*comm = pic_realloc(*comm, (size_t) max + 1, "pic_read_comment#2");
251     }
252     (*comm)[i] = '\0';
253 
254     while((c = fgetc(pi->fp)) != '\0'){	/* skip the dummy area */
255 	if(c == EOF)
256 	    pic_file_error(pi, PIC_CORRUPT);
257     }
258 
259     if(fgetc(pi->fp) != '\0')		/* check the reserved byte */
260 	pic_error(pi, PIC_SUPPORT);
261 }
262 
pic_read_header(pi)263 static void pic_read_header(pi)
264     struct pic_info *pi;
265 {
266     pi->mode   = pic_read_bits(pi, 4);
267     pi->type   = pic_read_bits(pi, 4);
268     pi->cbits  = pic_read_bits(pi, 16);
269     pi->width  = pic_read_bits(pi, 16);
270     pi->height = pic_read_bits(pi, 16);
271 
272     /* machine-dependent setup. */
273     switch(pi->type){
274     case 0x0:				/* X68K */
275 	if(pi->mode != 0)
276 	    pic_error(pi, PIC_MODE);
277 	switch(pi->cbits){
278 	case 4:
279 	    pi->aspect = 1.0;
280 	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
281 	    pi->i_bits = 1;
282 	    pi->cmapped = 1;
283 	    break;
284 
285 	case 8:
286 	    pi->aspect = 4.0 / 3.0;
287 	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
288 	    pi->i_bits = 1;
289 	    pi->cmapped = 1;
290 	    break;
291 
292 	case 15:
293 	    pi->aspect = 4.0 / 3.0;
294 	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
295 	    pi->cached = 1;
296 	    break;
297 
298 	case 16:
299 	    pi->aspect = 4.0 / 3.0;
300 	    pi->g_bits = pi->r_bits = pi->b_bits = 5;
301 	    pi->i_bits = 1;
302 	    pi->cached = 1;
303 	    break;
304 
305 	default:
306 	    pic_error(pi, PIC_NUM_COLORS);
307 	}
308 	break;
309 
310     case 0x1:				/* PC-88VA */
311 	if(pi->height > 1000)
312 	    pic_error(pi, PIC_SIZE);
313 	switch(pi->width * 1000 + pi->height){
314 	case 640400:
315 	case 640204:
316 	case 640200:
317 	case 320408:
318 	case 320400:
319 	case 320200:
320 	    break;
321 	default:
322 	    pic_error(pi, PIC_SIZE);
323 	}
324 	pi->aspect = 400.0 / pi->height;
325 	pi->aspect *= pi->width / 640.0;
326 	if(pi->mode & 0x1)		/* HR mode */
327 	    pi->aspect *= 2.0;
328 	if(pi->mode & 0x2){		/* tiled 256 format */
329 	    if(pi->cbits != 16)
330 		pic_error(pi, PIC_NUM_COLORS);
331 	    pi->tiled256 = 1;
332 	}
333 	switch(pi->cbits){
334 	case 8:
335 	    pi->g_bits = pi->r_bits = 3;
336 	    pi->b_bits = 2;
337 	    break;
338 
339 	case 12:
340 	    pi->g_bits = pi->r_bits = pi->b_bits = 4;
341 	    pi->cached = 1;
342 	    break;
343 
344 	case 16:
345 	    pi->g_bits = 6;
346 	    pi->r_bits = pi->b_bits = 5;
347 	    pi->cached = 1;
348 	    break;
349 
350 	default:
351 	    pic_error(pi, PIC_NUM_COLORS);
352 	}
353 	break;
354 
355     case 0x2:				/* FM-TOWNS */
356 	if(pi->cbits != 15)
357 	    pic_error(pi, PIC_NUM_COLORS);
358 	switch(pi->mode){
359 	case 0x5:
360 	case 0xc:
361 	    break;
362 	default:
363 	    pic_error(pi, PIC_MODE);
364 	}
365 	pi->g_bits = pi->r_bits = pi->b_bits = 5;
366 	pi->cached = 1;
367 	break;
368 
369     case 0x3:				/* MAC */
370 	if(pi->cbits != 15)
371 	    pic_error(pi, PIC_NUM_COLORS);
372 	pi->r_bits = pi->g_bits = pi->b_bits = 5;
373 	pi->inv_gr = 1;
374 	break;
375 
376     case 0xf:				/* misc */
377 	{
378 	    byte ah, al;
379 
380 	    switch(pi->mode){
381 	    case 0x0:
382 		break;
383 	    case 0x1:
384 		pi->aspect = 4.0 / 3.0;
385 		break;
386 	    case 0xf:
387 		break;
388 	    default:
389 		pic_error(pi, PIC_MODE);
390 	    }
391 	    pic_read_bits(pi, 16);	/* x */
392 	    pic_read_bits(pi, 16);	/* y */
393 	    ah = pic_read_bits(pi, 8);
394 	    al = pic_read_bits(pi, 8);
395 	    if(ah > 0 && al > 0)
396 		pi->aspect = (float) al / (int) ah;
397 	    else if(pi->mode == 0xf)
398 		pic_error(pi, PIC_ASPECT);
399 	    switch(pi->cbits){
400 	    case 4:
401 	    case 8:
402 		pi->g_bits = pi->r_bits = pi->b_bits = pic_read_bits(pi, 8);
403 		pi->cmapped = 1;
404 		break;
405 
406 	    case 12:
407 		pi->g_bits = pi->r_bits = pi->b_bits = 4;
408 		pi->cached = 1;
409 		break;
410 
411 	    case 15:
412 		pi->g_bits = pi->r_bits = pi->b_bits = 5;
413 		pi->cached = 1;
414 		break;
415 
416 	    case 16:
417 		pi->g_bits = pi->r_bits = pi->b_bits = 5;
418 		pi->i_bits = 1;
419 		pi->cached = 1;
420 		break;
421 
422 	    case 24:
423 		pi->g_bits = pi->r_bits = pi->b_bits = 8;
424 		pi->cached = 1;
425 		break;
426 
427 	    case 32:
428 		pic_error(pi, PIC_SUPPORT);
429 		break;
430 
431 	    default:
432 		pic_error(pi, PIC_NUM_COLORS);
433 	    }
434 	}
435 	break;
436 
437     default:
438 	pic_error(pi, PIC_TYPE);
439     }
440 
441     pi->numcols = 1 << pi->cbits;
442 
443     /* read palette data */
444     if(pi->cmapped){
445 	int i;
446 	pi->cmap = pic_malloc((size_t) 3 * pi->numcols, "pic_read_header#1");
447 	for(i = 0; i < pi->numcols; i++){
448 	    data32 c = pic_read_rgb(pi);
449 	    pi->cmap[i * 3    ] = c >> 16 & 0xff;
450 	    pi->cmap[i * 3 + 1] = c >>  8 & 0xff;
451 	    pi->cmap[i * 3 + 2] = c       & 0xff;
452 	}
453     }
454 
455     /* setup color code cache */
456     if(pi->cached)
457 	pic_cache_init(pi);
458 
459 
460     pi->data = pic_malloc(sizeof(data32) * pi->width * pi->height,   // GRR POSSIBLE OVERFLOW / FIXME
461 			  "pic_read_header#2");
462     {
463 	int i;
464 	for(i = 0; i < pi->width * pi->height; i++)
465 	    pi->data[i] = 0xffffffff;
466     }
467 
468     if(DEBUG)
469 	pic_show_pic_info(pi);
470 }
471 
472 /* The main routine to expand a PIC file. */
pic_expand_data(pi)473 static void pic_expand_data(pi)
474     struct pic_info *pi;
475 {
476     int cnt;
477     data32 c;
478     pi->data[0] = c = 0;
479     for(cnt = -1; cnt < pi->width * pi->height; ){
480 	int len = pic_expanding_read_len(pi);
481 	cnt += len;
482 	if(cnt < pi->width * pi->height){
483 	    int x = cnt % pi->width;
484 	    int y = cnt / pi->width;
485 	    data32 c = pic_expanding_read_color(pi);
486 	    pic_expanding_read_chain(pi, x, y, c);
487 	}
488     }
489 }
490 
pic_expanding_read_len(pi)491 static int pic_expanding_read_len(pi)
492     struct pic_info *pi;
493 {
494     int len;
495     byte bits;
496     for(len = 2, bits = 1; pic_read_bits(pi, 1) == 1; bits++)
497 	len <<= 1;
498     return len - 1 + pic_read_bits(pi, bits);
499 }
500 
pic_expanding_read_color(pi)501 static data32 pic_expanding_read_color(pi)
502     struct pic_info *pi;
503 {
504     if(pi->cached){
505 	byte b = pic_read_bits(pi, 1);
506 	if(b){
507 	    return pic_cache_get_value(pi, (int) pic_read_bits(pi, 7));
508 	}else{
509 	    data32 c = pic_read_color_code(pi);
510 	    pic_cache_add_value(pi, c);
511 	    return c;
512 	}
513     }
514     return pic_read_color_code(pi);
515 }
516 
pic_expanding_read_chain(pi,x,y,c)517 static void pic_expanding_read_chain(pi, x, y, c)
518     struct pic_info *pi;
519     int x, y;
520     data32 c;
521 {
522     pi->data[y * pi->width + x] = c;
523     if(pic_read_bits(pi, 1) == 1){
524 	int fin = 0;
525 	while(!fin){
526 	    switch(pic_read_bits(pi, 2)){
527 	    case 1:	/* left */
528 		pi->data[(++y) * pi->width + (--x)] = c;
529 		break;
530 	    case 2:	/* middle */
531 		pi->data[(++y) * pi->width +    x ] = c;
532 		break;
533 	    case 3:	/* right */
534 		pi->data[(++y) * pi->width + (++x)] = c;
535 		break;
536 	    case 0:	/* far or nothing */
537 		if(pic_read_bits(pi, 1) == 0)
538 		    fin = 1;
539 		else{
540 		    if(pic_read_bits(pi, 1) == 0)
541 			pi->data[(++y) * pi->width + (x -= 2)] = c;
542 		    else
543 			pi->data[(++y) * pi->width + (x += 2)] = c;
544 		}
545 	    }
546 	}
547     }
548 }
549 
550 /*
551  * Make a picture from the expanded data.
552  */
pic_make_xvpic(pi,xp,rp,gp,bp)553 static void pic_make_xvpic(pi, xp, rp, gp, bp)
554     struct pic_info *pi;
555     byte **xp, *rp, *gp, *bp;
556 {
557     if(pi->cmapped){
558 	if(pi->tiled256)
559 	    *xp = pic_malloc((size_t) pi->width * pi->height * 2,   // GRR POSSIBLE OVERFLOW / FIXME
560 			     "pic_make_xvpic#1");
561 	else
562 	    *xp = pic_malloc((size_t) pi->width * pi->height,   // GRR POSSIBLE OVERFLOW / FIXME
563 			     "pic_make_xvpic#2");
564     }else
565 	*xp = pic_malloc((size_t) pi->width * pi->height * 3,   // GRR POSSIBLE OVERFLOW / FIXME
566 			 "pic_make_xvpic#3");
567 
568     if(pi->cmapped){
569 	int i;
570 
571 	for(i = 0; i < pi->numcols; i++){
572 	    rp[i] = pi->cmap[i * 3    ];
573 	    gp[i] = pi->cmap[i * 3 + 1];
574 	    bp[i] = pi->cmap[i * 3 + 2];
575 	}
576 
577 	if(pi->tiled256){
578 	    int pic_idx = 0, dat_idx;
579 	    data16 col = 0;
580 	    for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){
581 		if(pi->data[dat_idx] != 0xffffffff)
582 		    col = pi->data[dat_idx];
583 		(*xp)[pic_idx++] = col      & 0xff;
584 		(*xp)[pic_idx++] = col >> 8 & 0xff;
585 		dat_idx++;
586 	    }
587 	}else{
588 	    int pic_idx = 0, dat_idx;
589 	    byte col = 0;
590 	    for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){
591 		if(pi->data[dat_idx] != 0xffffffff)
592 		    col = pi->data[dat_idx];
593 		(*xp)[pic_idx++] = col;
594 	    }
595 	}
596     }else{
597 	int pic_idx = 0, dat_idx;
598 	byte r = 0, g = 0, b = 0;
599 	for(dat_idx = 0; dat_idx < pi->width * pi->height; dat_idx++){
600 	    if(pi->data[dat_idx] != 0xffffffff){
601 		data32 col = pi->data[dat_idx];
602 		r = col >> 16 & 0xff;
603 		g = col >>  8 & 0xff;
604 		b = col       & 0xff;
605 	    }
606 	    (*xp)[pic_idx++] = r;
607 	    (*xp)[pic_idx++] = g;
608 	    (*xp)[pic_idx++] = b;
609 	}
610     }
611 }
612 
613 
614 /* The main routine to write PIC file. */
WritePIC(fp,pic0,ptype,w,h,rmap,gmap,bmap,numcols,colorstyle,comment)615 int WritePIC(fp, pic0, ptype, w, h, rmap, gmap, bmap, numcols, colorstyle,
616 	     comment)
617     FILE *fp;
618     byte *pic0;
619     int ptype, w, h;
620     byte *rmap, *gmap, *bmap;
621     int numcols, colorstyle;
622     char *comment;
623 {
624     struct pic_info pic;
625     int e;
626 
627     if(DEBUG) fputs("WritePIC:\n", stderr);
628 
629     pic_init_info(&pic);
630     pic.fp = fp;
631     pic.width  = w;
632     pic.height = h;
633     pic.writing_grey = (colorstyle == F_GREYSCALE);
634     if(ptype != PIC24){		/* PIC8  */
635 	pic.cmapped = 1;
636 	pic.cached  = 0;
637 	pic.cbits   = 8;
638 	pic.g_bits  =
639 	pic.r_bits  =
640 	pic.b_bits  = 8;
641 	pic.i_bits  = 0;
642 	pic.numcols = numcols;
643     }else{			/* PIC24 */
644 	pic.cmapped = 0;
645 	pic.cached  = 1;
646 	pic.cbits   = 24;
647 	pic.g_bits  =
648 	pic.r_bits  =
649 	pic.b_bits  = 8;
650 	pic.i_bits  = 0;
651 	pic.numcols = 1 << 24;
652 	pic_cache_init(&pic);
653     }
654 
655     if((e = setjmp(pic.jmp)) != 0){
656 	/* When an error occurs while writing, comes here. */
657 	pic_cleanup_pic_info(&pic, 1);
658 	if(DEBUG) fputs("\n", stderr);
659 	return -1;
660     }
661 
662     pic_write_id(&pic);
663     pic_write_comment(&pic, comment);
664     pic_write_header(&pic);
665     if(pic.cmapped)
666 	pic_write_palette(&pic, rmap, gmap, bmap);
667     pic_make_sparse_data(&pic, pic0);
668     pic_write_data(&pic);
669     pic_write_bits(&pic, 0, 8);
670 
671     pic_cleanup_pic_info(&pic, 1);
672     if(DEBUG) fputs("\n", stderr);
673     return 0;
674 }
675 
pic_write_id(pi)676 static void pic_write_id(pi)
677     struct pic_info *pi;
678 {
679     if(fwrite("PIC", (size_t) 3, (size_t) 1, pi->fp) != 1)
680 	pic_file_error(pi, PIC_WRITE);
681 }
682 
pic_write_comment(pi,comm)683 static void pic_write_comment(pi, comm)
684     struct pic_info *pi;
685     char *comm;
686 {
687     if(comm){
688 	while(*comm){
689 	    int c = *comm;
690 	    if(c == '\032')
691 		c = ' ';
692 	    if(fputc(*comm, pi->fp) == EOF)
693 		pic_file_error(pi, PIC_WRITE);
694 	    comm++;
695 	}
696     }
697     /* write ^Z, 0, and reserved. */
698     if(fwrite("\032\0\0", (size_t)3, (size_t) 1, pi->fp) != 1)
699 	pic_file_error(pi, PIC_WRITE);
700 }
701 
pic_write_header(pi)702 static void pic_write_header(pi)
703     struct pic_info *pi;
704 {
705     if(DEBUG) pic_show_pic_info(pi);
706     pic_write_bits(pi, (data32) 0, 4);			/* mode:  1:1 */
707     pic_write_bits(pi, (data32) 0xf, 4);		/* type: misc */
708     pic_write_bits(pi, (data32) pi->cbits, 16);		/* bits */
709     pic_write_bits(pi, (data32) pi->width, 16);		/* width */
710     pic_write_bits(pi, (data32) pi->height, 16);	/* height */
711     pic_write_bits(pi, (data32) 0xffff, 16);		/* x: unused */
712     pic_write_bits(pi, (data32) 0xffff, 16);		/* y: unused */
713     pic_write_bits(pi, (data32) 0x0101, 16);		/* real aspect */
714 }
715 
pic_write_palette(pi,r,g,b)716 static void pic_write_palette(pi, r, g, b)
717     struct pic_info *pi;
718     byte *r, *g, *b;
719 {
720     int i;
721     data32 rgb = 0;
722     pic_write_bits(pi, (data32) pi->g_bits, 8);
723     for(i = 0; i < pi->numcols; i++){
724 	rgb = (data32) *r++ << 16 | (data32) *g++ << 8 | (data32) *b++;
725 	pic_write_rgb(pi, rgb);
726     }
727     for( ; i < 256; i++)
728 	pic_write_rgb(pi, rgb);
729 }
730 
pic_make_sparse_data(pi,dat)731 static void pic_make_sparse_data(pi, dat)
732     struct pic_info *pi;
733     byte *dat;
734 {
735     int i;
736     data32 c;
737 
738     pi->data = pic_malloc(sizeof(data32) * pi->width * pi->height,   // GRR POSSIBLE OVERFLOW / FIXME
739 			  "pic_make_sparse_data");
740 
741     if(pi->cmapped){
742 	c = 0;
743 	for(i = 0; i < pi->width * pi->height; i++){
744 	    if(c != dat[i])
745 		c = pi->data[i] = dat[i];
746 	    else
747 		pi->data[i] = 0xffffffff;
748 	}
749     }else{
750 	int j = 0;
751 	c = 0;
752 	for(i = 0; i < pi->width * pi->height; i++){
753 	    data32 r, g, b, t;
754 	    r = dat[j++];
755 	    g = dat[j++];
756 	    b = dat[j++];
757 	    t = r << 16 | g << 8 | b;
758 	    if(c != t)
759 		c = pi->data[i] = t;
760 	    else
761 		pi->data[i] = 0xffffffff;
762 	}
763     }
764 }
765 
pic_write_data(pi)766 static void pic_write_data(pi)
767     struct pic_info *pi;
768 {
769     int i;
770     int max = pi->width * pi->height;
771     data32 c = 0;
772 
773     i = -1;
774     while(i < max){
775 	int j;
776 	for(j = i + 1; j < max; j++){
777 	    if(pi->data[j] != 0xffffffff)
778 		break;
779 	}
780 	pic_write_length(pi, (data32) j - i);
781 	i = j;
782 	if(i < max){
783 	    pic_write_color(pi, c = pi->data[i]);
784 	    pic_write_chain(pi, i % pi->width, i / pi->width, c);
785 	}
786     }
787 }
788 
pic_write_length(pi,len)789 static void pic_write_length(pi, len)
790     struct pic_info *pi;
791     data32 len;
792 {
793     int bits = 0;	/* leading 1's */
794     int max = 2;
795 
796     while(len > max){
797 	max = (max + 1) * 2;
798 	bits++;
799     }
800     pic_write_bits(pi, 0xffffffff, bits);
801     pic_write_bits(pi, 0, 1);
802     pic_write_bits(pi, len - max / 2, bits + 1);
803 }
804 
pic_write_color(pi,c)805 static void pic_write_color(pi, c)
806     struct pic_info *pi;
807     data32 c;
808 {
809     if(pi->cached){
810 	int idx = pic_cache_lookup(pi, c);
811 	if(idx < 0){	/* not found */
812 	    pic_write_bits(pi, 0, 1);
813 	    pic_write_color_code(pi, c);
814 	    pic_cache_add_value(pi, c);
815 	}else{		/* found */
816 	    pic_write_bits(pi, (data32) 0xffffffff, 1);
817 	    pic_write_bits(pi, (data32) idx, 7);
818 	}
819     }else
820 	pic_write_color_code(pi, c);
821 }
822 
pic_write_chain(pi,x,y,c)823 static void pic_write_chain(pi, x, y, c)
824     struct pic_info *pi;
825     int x, y;
826     data32 c;
827 {
828     int ctr = (y + 1) * pi->width + x;
829 
830     if(y < pi->height - 1 &&
831        (                      pi->data[ctr    ] == c  ||
832 	(x > 0             && pi->data[ctr - 1] == c) ||
833 	(x < pi->width - 1 && pi->data[ctr + 1] == c) ||
834 	(x > 1             && pi->data[ctr - 2] == c) ||
835 	(x < pi->width - 2 && pi->data[ctr + 2] == c))){
836 	pic_write_bits(pi, 1, 1);
837 	while(++y < pi->height){
838 	    if(pi->data[ctr] == c){				  /* center */
839 		pic_write_bits(pi, 2, 2);
840 		pi->data[ctr] = 0xffffffff;
841 		ctr += pi->width;
842 	    }else if(x > 0 && pi->data[ctr - 1] == c){		  /* left */
843 		pic_write_bits(pi, 1, 2);
844 		pi->data[ctr - 1] = 0xffffffff;
845 		ctr += pi->width - 1;
846 	    }else if(x < pi->width - 1 && pi->data[ctr + 1] == c){/* right */
847 		pic_write_bits(pi, 3, 2);
848 		pi->data[ctr + 1] = 0xffffffff;
849 		ctr += pi->width + 1;
850 	    }else if(x > 1 && pi->data[ctr - 2] == c){		  /* 2-left */
851 		pic_write_bits(pi, 2, 4);
852 		pi->data[ctr - 2] = 0xffffffff;
853 		ctr += pi->width - 2;
854 	    }else if(x < pi->width - 2 && pi->data[ctr + 2] == c){/* 2-right */
855 		pic_write_bits(pi, 3, 4);
856 		pi->data[ctr + 2] = 0xffffffff;
857 		ctr += pi->width + 2;
858 	    }else						  /* nothing */
859 		break;
860 	}
861 	pic_write_bits(pi, 0, 3);
862     }else
863 	pic_write_bits(pi, 0, 1);
864 }
865 
866 
867 /*
868  * These 4 functions read or write a color.
869  *
870  * pic_read_rgb:
871  *	reads an RGB. Each bit length is [rgb]_bits, but
872  *	it is expanded to 8bits when returned.
873  *
874  * pic_read_color_code:
875  *	reads a color code, whose length is cbits.
876  *	It is the index to the colormap or RGB itself.
877  *
878  * pic_write_rgb:
879  *	writes an RGB value.
880  *
881  * pic_write_color_code:
882  *	writes a color code.
883  */
pic_read_rgb(pi)884 static data32 pic_read_rgb(pi)
885     struct pic_info *pi;
886 {
887     int rb = pi->r_bits, gb = pi->g_bits, bb = pi->b_bits;
888     byte r, g, b;
889     if(pi->inv_gr){
890 	r = pic_read_bits(pi, rb);
891 	g = pic_read_bits(pi, gb);
892     }else{
893 	g = pic_read_bits(pi, gb);
894 	r = pic_read_bits(pi, rb);
895     }
896     b = pic_read_bits(pi, bb);
897     if(pi->i_bits){
898 	byte i;
899 	i = pic_read_bits(pi, pi->i_bits);
900 	r = r << pi->i_bits | i;
901 	g = g << pi->i_bits | i;
902 	b = b << pi->i_bits | i;
903 	rb += pi->i_bits;
904 	gb += pi->i_bits;
905 	bb += pi->i_bits;
906     }
907     r = pic_pad_bit(rb, r);
908     g = pic_pad_bit(gb, g);
909     b = pic_pad_bit(bb, b);
910 
911     return (data32) r << 16 | (data32) g << 8 | (data32) b;
912 }
913 
pic_read_color_code(pi)914 static data32 pic_read_color_code(pi)
915     struct pic_info *pi;
916 {
917     if(pi->cmapped)
918 	return pic_read_bits(pi, pi->cbits);
919     return pic_read_rgb(pi);
920 }
921 
pic_write_rgb(pi,rgb)922 static void pic_write_rgb(pi, rgb)
923     struct pic_info *pi;
924     data32 rgb;
925 {
926     byte r = rgb >> 16;
927     byte g = rgb >> 8;
928     byte b = rgb;
929     if(pi->writing_grey)
930 	r = g = b = MONO(r, g, b);
931     pic_write_bits(pi, g, pi->g_bits);
932     pic_write_bits(pi, r, pi->r_bits);
933     pic_write_bits(pi, b, pi->b_bits);
934 }
935 
pic_write_color_code(pi,code)936 static void pic_write_color_code(pi, code)
937     struct pic_info *pi;
938     data32 code;
939 {
940     if(pi->cmapped){
941 	pic_write_bits(pi, code, pi->cbits);
942     }else{
943 	pic_write_rgb(pi, code);
944     }
945 }
946 
947 
948 /*
949  * These pic_cache_* functions are an implementation of the color cache.
950  *
951  * pic_cache_init:
952  *	initializes the cache.
953  *
954  * pic_cache_get_value:
955  *	gets a color indexed by the argument `idx'.
956  *	It updates the `most recently used' time.
957  *
958  * pic_cache_add_value:
959  *	adds a color to the top of the cache list.
960  */
pic_cache_init(pi)961 static void pic_cache_init(pi)
962     struct pic_info *pi;
963 {
964     int i;
965     pi->cache.node = pic_malloc(sizeof(struct cachenode_t) * 128,
966 				"pic_cache_init");
967     for(i = 0; i < 128; i++){
968 	pi->cache.node[i].newer = i + 1;
969 	pi->cache.node[i].older = i - 1;
970 	pi->cache.node[i].dat = 0;
971     }
972     pi->cache.node[  0].older = 127;
973     pi->cache.node[127].newer = 0;
974     pi->cache.newest = 0;
975 }
976 
pic_cache_get_value(pi,idx)977 static data32 pic_cache_get_value(pi, idx)
978     struct pic_info *pi;
979     int idx;
980 {
981     struct cachenode_t *p = pi->cache.node;
982     int n = pi->cache.newest;
983     if(n != idx){
984 	p[p[idx].newer].older = p[idx].older;
985 	p[p[idx].older].newer = p[idx].newer;
986 
987 	p[p[n].newer].older = idx;
988 	p[idx].newer = p[n].newer;
989 	p[n].newer = idx;
990 	p[idx].older = n;
991 
992 	pi->cache.newest = idx;
993     }
994     return pi->cache.node[idx].dat;
995 }
996 
pic_cache_add_value(pi,dat)997 static void pic_cache_add_value(pi, dat)
998     struct pic_info *pi;
999     data32 dat;
1000 {
1001     pi->cache.newest = pi->cache.node[pi->cache.newest].newer;
1002     pi->cache.node[pi->cache.newest].dat = dat;
1003 }
1004 
pic_cache_lookup(pi,dat)1005 static int pic_cache_lookup(pi, dat)
1006     struct pic_info *pi;
1007     data32 dat;
1008 {
1009     int i;
1010     for(i = 0; i < 128; i++){
1011 	if(pi->cache.node[i].dat == dat){
1012 	    pic_cache_get_value(pi, i);
1013 	    return i;
1014 	}
1015     }
1016     return -1;
1017 }
1018 
1019 
1020 /*
1021  * These pic_{read,write}_bits functions access the bit stream.
1022  * pic_read_bits:
1023  *	reads the specified bits from the file.
1024  *
1025  * pic_write_bits:
1026  *	writes the specified bits to the file.
1027  */
pic_read_bits(pi,bits)1028 static data32 pic_read_bits(pi, bits)
1029     struct pic_info *pi;
1030     int bits;
1031 {
1032     data32 r = 0;
1033 
1034     while(bits > 0){
1035 	while(pi->bs.rest > 0 && bits > 0){
1036 	    r = (r << 1) | (pi->bs.cur & 0x80 ? 1 : 0);
1037 	    pi->bs.cur <<= 1;
1038 	    pi->bs.rest--;
1039 	    bits--;
1040 	}
1041 	if(bits > 0){
1042 	    int c;
1043 	    if((c = fgetc(pi->fp)) == EOF){
1044 		pic_file_warning(pi, PIC_CORRUPT);
1045 		c = 0;
1046 	    }
1047 	    pi->bs.cur  = c;
1048 	    pi->bs.rest = 8;
1049 	}
1050     }
1051 
1052     return r;
1053 }
1054 
pic_write_bits(pi,dat,bits)1055 static void pic_write_bits(pi, dat, bits)
1056     struct pic_info *pi;
1057     data32 dat;
1058     int bits;
1059 {
1060     data32 dat_mask = 1 << (bits - 1);
1061     while(bits > 0){
1062 	while(pi->bs.rest < 8 && bits > 0){
1063 	    pi->bs.cur <<= 1;
1064 	    if(dat & dat_mask)
1065 		pi->bs.cur |= 1;
1066 	    pi->bs.rest++;
1067 	    bits--;
1068 	    dat_mask >>= 1;
1069 	}
1070 	if(pi->bs.rest >= 8){
1071 	    if(fputc((int)pi->bs.cur, pi->fp) == EOF)
1072 		pic_error(pi, PIC_WRITE);
1073 	    pi->bs.cur  = 0;
1074 	    pi->bs.rest = 0;
1075 	}
1076     }
1077 }
1078 
1079 
1080 /*
1081  * This function extends sub-8-bit data to 8-bit data using bit-replication.
1082  */
pic_pad_bit(bits,dat)1083 static byte pic_pad_bit(bits, dat)
1084     int bits;
1085     data32 dat;
1086 {
1087     switch(bits){
1088     case 1:
1089 	if(dat & 1)
1090 	    dat = 0xff;
1091 	else
1092 	    dat = 0;
1093 	break;
1094     case 2:
1095 	dat = dat << 6 | dat << 4 | dat << 2 | dat;
1096 	break;
1097     case 3:
1098 	dat = dat << 5 | dat << 2 | dat >> 1;
1099 	break;
1100     case 4:
1101 	dat = dat << 4 | dat;
1102 	break;
1103     case 5:
1104 	dat = dat << 3 | dat >> 2;
1105 	break;
1106     case 6:
1107 	dat = dat << 2 | dat >> 4;
1108 	break;
1109     case 7:
1110 	dat = dat << 1 | dat >> 6;
1111     }
1112 
1113     return dat;
1114 }
1115 
1116 /*
1117  * These functions initialize or clean up structures.
1118  * pic_init_info:
1119  *	initializes a pic_info structure.
1120  * pic_cleanup_pic_info:
1121  *	cleans up a pic_info structure.
1122  * pic_cleanup_pinfo:
1123  *	cleans up a PICINFO structure.
1124  */
pic_init_info(pi)1125 static void pic_init_info(pi)
1126     struct pic_info *pi;
1127 {
1128     pi->fp = NULL;
1129     pi->bs.rest = 0;
1130     pi->bs.cur = '\0';
1131     pi->type = pi->mode = 0;
1132     pi->width = pi->height = 0;
1133     pi->aspect = 1.0;
1134     pi->cbits = 0;
1135     pi->cmapped = pi->cached = 0;
1136     pi->cache.node = NULL;
1137     pi->cmap = NULL;
1138     pi->g_bits = pi->r_bits = pi->b_bits = pi->i_bits = 0;
1139     pi->inv_gr = 0;
1140     pi->tiled256 = 0;
1141     pi->numcols = 0;
1142     pi->writing_grey = 0;
1143 }
1144 
pic_cleanup_pic_info(pi,writing)1145 static void pic_cleanup_pic_info(pi, writing)
1146     struct pic_info *pi;
1147     int writing;
1148 {
1149     if(!writing && pi->fp)
1150 	fclose(pi->fp);
1151     if(pi->cmap)
1152 	free(pi->cmap);
1153     if(pi->cache.node)
1154 	free(pi->cache.node);
1155     if(pi->data)
1156 	free(pi->data);
1157     pi->fp = NULL;
1158     pi->cmap = NULL;
1159     pi->cache.node = NULL;
1160     pi->data = NULL;
1161 }
1162 
pic_cleanup_pinfo(pinfo)1163 static void pic_cleanup_pinfo(pinfo)
1164     PICINFO *pinfo;
1165 {
1166     if(pinfo->pic){
1167 	free(pinfo->pic);
1168 	pinfo->pic = NULL;
1169     }
1170     if(pinfo->comment){
1171 	free(pinfo->comment);
1172 	pinfo->comment = NULL;
1173     }
1174 }
1175 
1176 /*
1177  * Error Handlers.
1178  * pic_memory_error:
1179  *	shows an error message and terminates.
1180  * pic_error:
1181  *	shows a non-file error message and jumps to the entry for errors.
1182  * pic_file_error:
1183  *	shows a file error message and jumps to the entry for errors.
1184  * pic_file_warning:
1185  *	shows a file warning message.
1186  */
pic_memory_error(scm,fn)1187 static void pic_memory_error(scm, fn)
1188     char *scm, *fn;
1189 {
1190     char buf[128];
1191     sprintf(buf, "%s: can't allocate memory. (%s)", scm, fn);
1192     FatalError(buf);
1193 }
1194 
pic_error(pi,mn)1195 static void pic_error(pi, mn)
1196     struct pic_info *pi;
1197     int mn;
1198 {
1199     SetISTR(ISTR_WARNING, "%s", pic_msgs[mn]);
1200     longjmp(pi->jmp, 1);
1201 }
1202 
pic_file_error(pi,mn)1203 static void pic_file_error(pi, mn)
1204     struct pic_info *pi;
1205     int mn;
1206 {
1207     if(feof(pi->fp))
1208 	SetISTR(ISTR_WARNING, "%s (end of file)", pic_msgs[mn]);
1209     else
1210 	SetISTR(ISTR_WARNING, "%s (%s)", pic_msgs[mn], ERRSTR(errno));
1211     longjmp(pi->jmp, 1);
1212 }
1213 
pic_file_warning(pi,mn)1214 static void pic_file_warning(pi, mn)
1215     struct pic_info *pi;
1216     int mn;
1217 {
1218     if(feof(pi->fp))
1219 	SetISTR(ISTR_WARNING, "%s (end of file)", pic_msgs[mn]);
1220     else
1221 	SetISTR(ISTR_WARNING, "%s (%s)", pic_msgs[mn], ERRSTR(errno));
1222 }
1223 
pic_show_pic_info(pi)1224 static void pic_show_pic_info(pi)
1225     struct pic_info *pi;
1226 {
1227     fprintf(stderr, "  file size: %ld.\n", pi->fsize);
1228 
1229     fputs("  machine: ", stderr);
1230     switch(pi->type){
1231     case 0x0:
1232 	fputs("X68k", stderr);
1233 	break;
1234     case 0x1:
1235 	fputs("PC-88VA", stderr);
1236 	if(pi->mode & 1)
1237 	    fputs(",HR", stderr);
1238 	if(pi->mode & 2)
1239 	    fputs(",tiled256", stderr);
1240 	break;
1241     case 0x2:
1242 	fprintf(stderr,
1243 		"FM-TOWNS,%s-resolution", pi->mode == 5 ? "low" : "high");
1244 	break;
1245     case 0x3:
1246 	fputs("Macintosh", stderr);
1247 	break;
1248     case 0xf:
1249 	fputs("misc", stderr);
1250     }
1251     fputs("\n", stderr);
1252 
1253     fprintf(stderr, "  image size: %dx%d\n", pi->width, pi->height);
1254     fprintf(stderr, "  aspect: %f\n", pi->aspect);
1255     fprintf(stderr, "  cache: %s\n", pi->cached ? "on" : "off");
1256     fprintf(stderr, "  colormap: %s\n", pi->cmapped ? "on" : "off");
1257     fprintf(stderr, "  number of color bits: %d\n", pi->cbits);
1258     fprintf(stderr, "  number of RGB bits: R%d,G%d,B%d,I%d\n",
1259 	   pi->r_bits, pi->g_bits, pi->b_bits, pi->i_bits);
1260     fprintf(stderr, "  inverted G&R: %s\n", pi->inv_gr ? "true" : "false");
1261     fprintf(stderr, "  number of colors: %d\n", pi->numcols);
1262 }
1263 
1264 /* Memory related routines. */
pic_malloc(n,fn)1265 static void *pic_malloc(n, fn)
1266     size_t n;
1267     char *fn;
1268 {
1269     void *r = (void *) malloc(n);
1270     if(r == NULL)
1271 	pic_memory_error("malloc", fn);
1272     return r;
1273 }
1274 
pic_realloc(p,n,fn)1275 static void *pic_realloc(p, n, fn)
1276     void *p;
1277     size_t n;
1278     char *fn;
1279 {
1280     void *r = (p == NULL) ? (void *) malloc(n) : (void *) realloc(p, n);
1281     if(r == NULL)
1282 	pic_memory_error("realloc", fn);
1283     return r;
1284 }
1285 #endif /* HAVE_PIC */
1286