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