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