1 /* $Header: /home/yav/xpx/RCS/convert.c,v 1.40 1996/04/24 23:08:27 yav Exp $
2 * convert image data
3 * written by yav (UHD98984@pcvan.or.jp)
4 */
5
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8
9 #include "headers.h"
10 #include "xpx.h"
11 #include "work.h"
12 #include "infodef.h"
13 #define PUBLIC_CONVERT_C
14 #include "extern.h"
15
16 char rcsid_convert[] = "$Id: convert.c,v 1.40 1996/04/24 23:08:27 yav Exp $";
17 static unsigned char rbittbl[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
18 static char tilemask[8][8];
19
init_tilemask()20 int init_tilemask()
21 {
22 return 0;
23 }
24
set_tilemask(p)25 int set_tilemask(p)
26 char *p;
27 {
28 memcpy(tilemask, p, sizeof(tilemask));
29 return 0;
30 }
31
imgupdate(w,h)32 void imgupdate(w, h)
33 int w;
34 int h;
35 {
36 set_image_size(w, h);
37 image_update_all();
38 }
39
40 /* return pnm type number */
read_pnm_header(fp,data,colorhints,nhints)41 int read_pnm_header(fp, data, colorhints, nhints)
42 FILE *fp;
43 int *data;
44 COL *colorhints;
45 int *nhints;
46 {
47 int i, result, r, g, b;
48 int datan, maxcol, datan0;
49 char buf[256], *p;
50
51 if (fgets(buf, sizeof(buf), fp) == NULL)
52 return 0;
53 if (buf[0] != 'P')
54 return 0; /* Not pnm file */
55 switch (buf[1]) {
56 case '1':
57 result = 1;
58 datan0 = 2;
59 data[2] = 1;
60 break;
61 case '2':
62 result = 2;
63 datan0 = 3;
64 break;
65 case '3':
66 result = 3;
67 datan0 = 3;
68 break;
69 case '4':
70 result = 4;
71 datan0 = 2;
72 data[2] = 1;
73 break;
74 case '5':
75 result = 5;
76 datan0 = 3;
77 break;
78 case '6':
79 result = 6;
80 datan0 = 3;
81 break;
82 default:
83 return 0; /* Not supported pnm file */
84 }
85 maxcol = -1;
86 datan = 0;
87 while (datan < datan0 && fgets(buf, sizeof(buf), fp) != NULL) {
88 if (buf[0] == '#') {
89 if (colorhints != NULL && nhints != NULL) {
90 if (sscanf(buf, "# color:%d %d %d %d", &i, &r, &g, &b) == 4) {
91 if (i < *nhints) {
92 (colorhints+i)->rgb.red = r;
93 (colorhints+i)->rgb.green = g;
94 (colorhints+i)->rgb.blue = b;
95 if (maxcol < i)
96 maxcol = i;
97 }
98 }
99 }
100 } else {
101 for (p = buf; (i = strtol(p, &p, 10)) != 0 && datan < 3; datan++)
102 data[datan] = i;
103 }
104 }
105 if (colorhints != NULL && nhints != NULL)
106 *nhints = maxcol+1;
107 return result;
108 }
109
110 static unsigned char bitpos;
111 static unsigned char rddata;
112 static int pnmmaxval;
113
read_pnm_pixels(fp,t,cp,n)114 int read_pnm_pixels(fp, t, cp, n)
115 FILE *fp;
116 int t;
117 COL *cp;
118 int n;
119 {
120 int i, x, rgbsw;
121 int c;
122 unsigned char *p, buf[256];
123
124 switch(t) {
125 case 1: /* P1 pbm ascii */
126 case 2: /* P2 pgm ascii */
127 case 3: /* P3 ppm ascii */
128 x = rgbsw = 0;
129 while (x < n) {
130 i = 0;
131 p = buf;
132 for (;;) {
133 c = fgetc(fp);
134 if (c == EOF)
135 return x;
136 else if (c == '\n')
137 break;
138 else if (c == ' '||c == '\t') {
139 if (i)
140 break;
141 } else {
142 *p++ = c;
143 i = 1;
144 }
145 }
146 *p = '\0';
147 i = strtol((char *)buf, (char **)&p, 10);
148 if (p == buf)
149 continue;
150 i = (i * 255) / pnmmaxval;
151 switch(t) {
152 case 3:
153 switch(rgbsw) {
154 case 0:
155 cp->rgb.red = i;
156 break;
157 case 1:
158 cp->rgb.green = i;
159 break;
160 case 2:
161 cp->rgb.blue = i;
162 break;
163 }
164 if (++rgbsw >= 3) {
165 cp->rgb.padding = 0;
166 cp++;
167 rgbsw = 0;
168 x++;
169 }
170 break;
171 case 1:
172 case 2:
173 cp->rgb.red = cp->rgb.green = cp->rgb.blue = i;
174 cp->rgb.padding = 0;
175 cp++;
176 x++;
177 break;
178 }
179 }
180 return x;
181 case 4: /* P4 pbm raw */
182 while (n--) {
183 if (bitpos == 0x01) {
184 i = fgetc(fp);
185 if (i == EOF)
186 return 0;
187 rddata = i;
188 bitpos = 0x80;
189 } else {
190 bitpos >>= 1;
191 }
192 cp->rgb.red = cp->rgb.green = cp->rgb.blue = rddata & bitpos ? 0 : 255;
193 cp++;
194 }
195 return 1;
196 case 5: /* P5 pgm raw */
197 while (n) {
198 i = sizeof(buf) > n ? n : sizeof(buf);
199 if (!fread(buf, i, 1, fp))
200 return 0;
201 p = buf;
202 x = i;
203 while (x--) {
204 cp->rgb.red = cp->rgb.green = cp->rgb.blue = (*p++ * 255) / pnmmaxval;
205 cp->rgb.padding = 0;
206 cp++;
207 }
208 n -= i;
209 }
210 return 1;
211 case 6: /* P6 ppm raw */
212 while (n) {
213 i = sizeof(buf)/3 > n ? n : sizeof(buf)/3;
214 if (!fread(buf, i*3, 1, fp))
215 return 0;
216 p = buf;
217 x = i;
218 while (x--) {
219 cp->rgb.red = (*p++ * 255) / pnmmaxval;
220 cp->rgb.green = (*p++ * 255) / pnmmaxval;
221 cp->rgb.blue = (*p++ * 255) / pnmmaxval;
222 cp->rgb.padding = 0;
223 cp++;
224 }
225 n -= i;
226 }
227 return 1;
228 default:
229 /* unknown pnm type ??? */
230 return 0;
231 }
232 /* NOT REACHED */
233 }
234
235 static COL lastcol;
236 static int lastcol_pixel;
237
color_pixel(col)238 int color_pixel(col)
239 COL *col;
240 {
241 int i;
242 COL *tbl;
243
244 if (lastcol_pixel >= 0) {
245 if (memcmp(&lastcol.rgb, &col->rgb, 3) == 0)
246 return lastcol_pixel;
247 }
248 tbl = color_buf;
249 for (i = 0; i < MAXCOLSET*MAXPALSET; i++) {
250 if (memcmp(&col->rgb, &tbl->rgb, 3) == 0 &&
251 (coltbl[i] & (CM_ALLOCED|CM_REQUEST))) {
252 lastcol = *col;
253 return lastcol_pixel = i;
254 }
255 tbl++;
256 }
257 return -1;
258 }
259
260 typedef struct {
261 int i;
262 int n;
263 int pn;
264 } CLN;
265
colcnt(p,len,ctbl,ntbl,n,itbl)266 int colcnt(p, len, ctbl, ntbl, n, itbl)
267 COL *p;
268 int len;
269 COL *ctbl;
270 CLN *ntbl;
271 int n;
272 unsigned char *itbl;
273 {
274 int i, x, max;
275
276 max = 0;
277 for (x = 0; x < len; x++) {
278 i = 0;
279 for (;;) {
280 if (i >= max) {
281 if (++max > n)
282 return -1;
283 *(ctbl+i) = *p;
284 }
285 if (memcmp(&(ctbl+i)->rgb, &p->rgb, 3) == 0)
286 break;
287 i++;
288 }
289 *itbl++ = i;
290 ++((ntbl+i)->n);
291 p++;
292 }
293 return max;
294 }
295
ncolcmp(p1,p2)296 int ncolcmp(p1, p2)
297 CLN *p1;
298 CLN *p2;
299 {
300 return p2->n - p1->n;
301 }
302
icolcmp(p1,p2)303 int icolcmp(p1, p2)
304 CLN *p1;
305 CLN *p2;
306 {
307 return p1->i - p2->i;
308 }
309
slow_convert(px,w,h)310 void slow_convert(px, w, h)
311 COL *px;
312 int w;
313 int h;
314 {
315 int i, n, len, x, y;
316 unsigned char *itbl, *ip;
317 COL ctbl[256];
318 CLN ntbl[256];
319
320 if (debug_mode)
321 fprintf(stderr, "slow_convert %dx%d\n", w, h);
322 len = w*h;
323 itbl = (unsigned char *)malloc(len);
324 for (i = 256; i; --i) {
325 bzero(ctbl, sizeof(*ctbl)*i);
326 bzero(ntbl, sizeof(*ntbl)*i);
327 n = colcnt(px, len, ctbl, ntbl, i, itbl);
328 if (n >= 0)
329 break;
330 }
331 message("phase-1 %d colors.\n", n);
332 for (i = 0; i < 256; i++)
333 ntbl[i].i = i;
334 qsort(ntbl, n, sizeof(*ntbl), ncolcmp);
335 for (i = 0; i < n; i++)
336 ntbl[i].pn = i;
337 for (;;) {
338 free_color_all();
339 message("try %d colors.\n", n);
340 for (i = 0; i < n; i++)
341 request_color2(i, ctbl+ntbl[i].i);
342 i = get_requested_colors();
343 message("get %d/%d request colors.\n", i, n);
344 if (i == n)
345 break;
346 n -= 16;
347 if (n < 0) {
348 message("!too few color!\n");
349 free(itbl);
350 return;
351 }
352 }
353 qsort(ntbl, n, sizeof(*ntbl), icolcmp);
354 ip = itbl;
355 for (y = 0; y < h; y++) {
356 for (x = 0; x < w; x++) {
357 *(imgdata+y*imgmaxw+x) = ntbl[*ip++].pn;
358 }
359 }
360 free(itbl);
361 }
362
363 /* read portable bitmap/graymap/pixmap */
rd_pnm(fp)364 int rd_pnm(fp)
365 FILE *fp;
366 {
367 int c, i, n, f, x, y, pnmtype;
368 int data[3], w, h;
369 int colcnt;
370 COL *px0, *px, *px1;
371
372 colcnt = MAXPALSET*MAXCOLSET;
373 pnmtype = read_pnm_header(fp, data, color_buf, &colcnt);
374 if (pnmtype == 0)
375 return 1;
376 if (pnmtype == 1||pnmtype == 4)
377 imgfiledepth = 1;
378 if (debug_mode) {
379 fprintf(stderr, "rd_pnm: width %d, height %d max %d\n",
380 data[0], data[1], data[2]);
381 fprintf(stderr, "rd_pnm: %d color hints\n", colcnt);
382 }
383
384 free_color_all();
385 /* magtoppm commented color information set */
386 get_color(color_buf, colcnt);
387
388 w = data[0];
389 h = data[1];
390 pnmmaxval = data[2];
391 if (w > imgmaxw) {
392 w = imgmaxw;
393 message("!\nwidth %d trancate to %d.\n", data[0], w);
394 }
395 if (h > imgmaxh) {
396 h = imgmaxh;
397 message("!\nheight %d trancate to %d.\n", data[1], h);
398 }
399 px = (COL *)malloc(sizeof(*px)*w);
400 if (!quick_convert)
401 px1 = px0 = (COL *)malloc(sizeof(*px0)*w*h);
402 lastcol_pixel = -1;
403 for (y = 0; y < h; y++) {
404 f = 1;
405 bitpos = 0x01;
406 for (n = data[0]; n; n -= i) {
407 i = n > w ? w : n;
408 read_pnm_pixels(fp, pnmtype, px, i);
409 if (!f)
410 continue; /* skip x over pixels */
411 if (quick_convert) {
412 if (colcnt && pnmtype == 5) {
413 /* color infomation contained portable graymap */
414 for (x = 0; x < i; x++)
415 *(imgdata+y*imgmaxw+x) = (px+x)->rgb.red;
416 } else {
417 for (x = 0; x < i; x++) {
418 c = color_pixel(px+x);
419 if (c < 0)
420 c = request_color(px+x);
421 *(imgdata+y*imgmaxw+x) = c;
422 }
423 }
424 } else {
425 memcpy(px1, px, sizeof(*px)*i);
426 px1 += i;
427 }
428 f = 0;
429 }
430 }
431 if (!quick_convert) {
432 slow_convert(px0, w, h);
433 free(px0);
434 } else {
435 get_requested_colors();
436 }
437 free(px);
438 imgupdate(w, h);
439 return 0;
440 }
441
442 static char kiss_magic_number[] = "KiSS";
443
444 /* read KISS kcf */
rd_kcf(fp)445 int rd_kcf(fp)
446 FILE *fp;
447 {
448 int i, s, bpc, cc, col, set, preload;
449 COL *cp;
450 unsigned char *p, buf[4096];
451
452 preload = strlen(kiss_magic_number);
453 if (!fread(buf, preload, 1, fp))
454 return 1;
455 if (strncmp(buf, kiss_magic_number, preload) == 0) {
456 /* read new style kcf header section */
457 if (!fread(buf+preload, 32-preload, 1, fp))
458 return 1;
459 /* check color file mark */
460 if (buf[4] != 0x10)
461 return 1;
462 bpc = buf[5];
463 col = buf[8]|(buf[9]<<8);
464 set = buf[10]|(buf[11]<<8);
465 preload = 0;
466 infomenu[INFOMENU_GSKCF].mode |= MenuModeMaskOn;
467 } else {
468 /* old style kcf */
469 bpc = 12;
470 col = 16;
471 set = 10;
472 infomenu[INFOMENU_GSKCF].mode &= ~MenuModeMaskOn;
473 }
474 redraw_window(infomenu[INFOMENU_GSKCF].win);
475 cp = color_buf;
476 cc = ((bpc+7)>>3)*col;
477 for (s = 0; s < set; s++) {
478 if (!fread(buf+preload, cc-preload, 1, fp))
479 return 1;
480 p = buf;
481 for (i = 0; i < col; i++) {
482 if (bpc == 12) {
483 cp->rgb.red = (*p&0xf0)|(*p>>4);
484 cp->rgb.blue = (*p&0x0f)|((*p&0x0f)<<4);
485 p++;
486 cp->rgb.green = (*p&0x0f)|((*p&0x0f)<<4);
487 p++;
488 } else {
489 cp->rgb.red = *p++;
490 cp->rgb.green = *p++;
491 cp->rgb.blue = *p++;
492 }
493 cp++;
494 }
495 preload = 0;
496 }
497 free_color();
498 get_color(color_buf+16*current_pal, col);
499 image_update_col();
500 return 0;
501 }
502
503 /* write KISS kcf */
wr_kcf(fp)504 int wr_kcf(fp)
505 FILE *fp;
506 {
507 int i, s, bpc, col, set, cc;
508 COL *cp;
509 unsigned char *p, buf[4096];
510
511 /* old style kcf spec set */
512 bpc = 12; /* red:4 blue:4 green:4 = 12bits/color */
513 col = 16;
514 set = 10;
515 if (infomenu[INFOMENU_GSKCF].mode & MenuModeMaskOn) {
516 bpc = 24; /* red:8 green:8 blue:8 = 24bits/color */
517 bzero(buf, 32);
518 memcpy(buf, kiss_magic_number, strlen(kiss_magic_number));
519 buf[4] = 0x10; /* color file mark */
520 buf[5] = bpc;
521 buf[8] = col;
522 buf[9] = col>>8;
523 buf[10] = set;
524 buf[11] = set>>8;
525 if (!fwrite(buf, 32, 1, fp))
526 return 1;
527 }
528 cp = color_buf;
529 cc = ((bpc+7)>>3)*col;
530 for (s = 0; s < set; s++) {
531 p = buf;
532 for (i = 0; i < col; i++) {
533 if (bpc == 12) {
534 *p++ = (cp->rgb.red & 0xf0)|(cp->rgb.blue >> 4);
535 *p++ = cp->rgb.green >> 4;
536 } else {
537 *p++ = cp->rgb.red;
538 *p++ = cp->rgb.green;
539 *p++ = cp->rgb.blue;
540 }
541 cp++;
542 }
543 if (!fwrite(buf, cc, 1, fp))
544 return 1;
545 }
546 return 0;
547 }
548
549 /* read KISS cel */
rd_cel(fp)550 int rd_cel(fp)
551 FILE *fp;
552 {
553 int c, x, y, w, h, preload, bpp;
554 int dataw, datah;
555 int ofsx, ofsy;
556 unsigned char buf[4096];
557
558 preload = strlen(kiss_magic_number);
559 if (!fread(buf, preload, 1, fp))
560 return 1;
561 if (strncmp(buf, kiss_magic_number, preload) == 0) {
562 /* read new style cel file header section */
563 if (!fread(buf+preload, 32-preload, 1, fp))
564 return 1;
565 /* check cel file mark */
566 if (buf[4] != 0x20)
567 return 1;
568 bpp = buf[5];
569 w = buf[8]|(buf[9]<<8);
570 h = buf[10]|(buf[11]<<8);
571 ofsx = buf[12]|(buf[13]<<8);
572 ofsy = buf[14]|(buf[15]<<8);
573 infomenu[INFOMENU_GSCEL].mode |= MenuModeMaskOn;
574 } else {
575 bpp = 4;
576 w = buf[0]|(buf[1]<<8);
577 h = buf[2]|(buf[3]<<8);
578 ofsx = ofsy = 0;
579 infomenu[INFOMENU_GSCEL].mode &= ~MenuModeMaskOn;
580 }
581 redraw_window(infomenu[INFOMENU_GSCEL].win);
582 imgfiledepth = bpp;
583 dataw = w;
584 datah = h;
585 if (ofsx+w > imgmaxw) {
586 w = imgmaxw-ofsx;
587 message("!\nwidth %d trancate to %d.\n", dataw+ofsx, w+ofsx);
588 }
589 if (ofsy+h > imgmaxh) {
590 h = imgmaxh-ofsy;
591 message("!\nheight %d trancate to %d.\n", datah+ofsy, h+ofsy);
592 }
593 for (y = 0; y < ofsy; y++) {
594 for (x = 0; x < ofsx+w; x++) {
595 *(imgdata+y*imgmaxw+x) = 0;
596 }
597 }
598 for (y = ofsy; y < ofsy+h; y++) {
599 if (!fread(buf, bpp==4?((dataw+1)>>1):dataw, 1, fp))
600 return 1;
601 for (x = 0; x < ofsx; x++)
602 *(imgdata+y*imgmaxw+x) = 0;
603 for (x = 0; x < w; x++) {
604 if (bpp == 4) {
605 c = buf[x>>1];
606 if ((x & 1) == 0)
607 c >>= 4;
608 else
609 c &= 0x0f;
610 } else {
611 c = buf[x];
612 }
613 *(imgdata+y*imgmaxw+ofsx+x) = c;
614 }
615 }
616 hotspotx = ofsx;
617 hotspoty = ofsy;
618 imgupdate(ofsx+w, ofsy+h);
619 return 0;
620 }
621
get_celofs_y()622 int get_celofs_y()
623 {
624 int x, y;
625
626 for (y = 0; y < imgfileh; y++) {
627 for (x = 0; x < imgfilew; x++) {
628 if (*(imgdata+y*imgmaxw+x) != 0)
629 return y;
630 }
631 }
632 return 0;
633 }
634
get_celofs_x()635 int get_celofs_x()
636 {
637 int x, y;
638
639 for (x = 0; x < imgfilew; x++) {
640 for (y = 0; y < imgfileh; y++) {
641 if (*(imgdata+y*imgmaxw+x) != 0)
642 return x;
643 }
644 }
645 return 0;
646 }
647
648 /* write KISS cel */
wr_cel(fp)649 int wr_cel(fp)
650 FILE *fp;
651 {
652 int c, x, y, w, h, bpp, headersize;
653 unsigned char buf[4096];
654
655 w = imgfilew;
656 h = imgfileh;
657 bpp = 4; /* 4bits/pixel */
658 if (infomenu[INFOMENU_GSCEL].mode & MenuModeMaskOn) {
659 headersize = 32;
660 bzero(buf, headersize);
661 memcpy(buf, kiss_magic_number, strlen(kiss_magic_number));
662 hotspotx = get_celofs_x();
663 hotspoty = get_celofs_y();
664 w -= hotspotx;
665 h -= hotspoty;
666 buf[4] = 0x20; /* cel file mark */
667 buf[5] = bpp;
668 buf[8] = w;
669 buf[9] = w >> 8;
670 buf[10] = h;
671 buf[11] = h >> 8;
672 buf[12] = hotspotx;
673 buf[13] = hotspotx >> 8;
674 buf[14] = hotspoty;
675 buf[15] = hotspoty >> 8;
676 } else {
677 headersize = 4;
678 hotspotx = hotspoty = 0;
679 buf[0] = w;
680 buf[1] = w >> 8;
681 buf[2] = h;
682 buf[3] = h >> 8;
683 }
684 if (!fwrite(buf, headersize, 1, fp))
685 return 1;
686 for (y = hotspoty; y < hotspoty+h; y++) {
687 for (x = 0; x < w; x++) {
688 c = *(imgdata+y*imgmaxw+hotspotx+x);
689 if (bpp == 4) {
690 if ((x & 1) == 0)
691 buf[x>>1] = c<<4;
692 else
693 buf[x>>1] |= c;
694 } else {
695 buf[x] = c;
696 }
697 }
698 if (!fwrite(buf, bpp==4?((w+1)>>1):w, 1, fp))
699 return 1;
700 }
701 return 0;
702 }
703
704 /* write portable pixmap */
wr_ppm(fp)705 int wr_ppm(fp)
706 FILE *fp;
707 {
708 int i, x, y;
709 COL *cp;
710 unsigned char c, buf[3];
711
712 fprintf(fp, "P6\n");
713 fprintf(fp, "#Saved by %s %s\n", myname, xpx_version);
714 /* color information */
715 cp = color_buf;
716 for (i = 0; i < alloced_color; i++) {
717 fprintf(fp, "# color:%3d %3d %3d %3d\n", i,
718 cp->rgb.red, cp->rgb.green, cp->rgb.blue);
719 cp++;
720 }
721 fprintf(fp, "%d %d\n", imgfilew, imgfileh);
722 fprintf(fp, "255\n");
723
724 for (y = 0; y < imgfileh; y++) {
725 for (x = 0; x < imgfilew; x++) {
726 c = *(imgdata+y*imgmaxw+x);
727 buf[0] = color_buf[c].rgb.red;
728 buf[1] = color_buf[c].rgb.green;
729 buf[2] = color_buf[c].rgb.blue;
730 if (!fwrite(buf, 3, 1, fp))
731 return 1;
732 }
733 }
734 return 0;
735 }
736
write_xbm_out(fp,data,datalen,end)737 int write_xbm_out(fp, data, datalen, end)
738 FILE *fp;
739 unsigned char *data;
740 int datalen;
741 int end;
742 {
743 int i;
744 char *p;
745 char buf[256];
746
747 strcpy(buf, " ");
748 p = buf+2;
749 for (i = 0; i < datalen; i++) {
750 sprintf(p, " 0x%02x,", *data++);
751 p += strlen(p);
752 }
753 if (end)
754 strcpy(p-1, "};");
755 strcat(buf, "\n");
756 return fputs(buf, fp);
757 }
758
759 /* write X11 bitmap */
wr_xbm(fp,name)760 int wr_xbm(fp, name)
761 FILE *fp;
762 char *name;
763 {
764 int i, x, y, w, h;
765 int outcount;
766 unsigned char c;
767 unsigned char outbuf[12];
768 char namebuf[MAXPATH], *p;
769
770 strcpy(namebuf, name);
771 p = basefilename(namebuf);
772 w = imgfilew;
773 h = imgfileh;
774 fprintf(fp, "#define %s_width %d\n", p, w);
775 fprintf(fp, "#define %s_height %d\n", p, h);
776 if (hotspotx >= 0 && hotspoty >= 0) {
777 fprintf(fp, "#define %s_x_hot %d\n", p, hotspotx);
778 fprintf(fp, "#define %s_y_hot %d\n", p, hotspoty);
779 }
780 fprintf(fp, "static unsigned char %s_bits[] = {\n", p);
781 outcount = 0;
782 for (y = 0; y < h; y++) {
783 for (x = 0; x < w; x += 8) {
784 c = 0;
785 for (i = 0; i < 8; i++) {
786 if ((x + i < w)&& *(imgdata+y*imgmaxw+x+i))
787 c |= rbittbl[i];
788 }
789 if (outcount >= sizeof(outbuf)) {
790 write_xbm_out(fp, outbuf, outcount, 0);
791 outcount = 0;
792 }
793 outbuf[outcount++] = c;
794 }
795 }
796 write_xbm_out(fp, outbuf, outcount, 1);
797 return 0;
798 }
799
strcmp_tail(p,tail)800 int strcmp_tail(p, tail)
801 char *p;
802 char *tail;
803 {
804 int pl, tl;
805
806 tl = strlen(tail);
807 pl = strlen(p);
808 if (pl < tl)
809 return 1;
810 return strcmp(p+pl-tl, tail);
811 }
812
813 /* read X11 bitmap */
rd_xbm(fp)814 int rd_xbm(fp)
815 FILE *fp;
816 {
817 int i, x, y, w, h, c, hotx, hoty;
818 char buf[1024], *p;
819 char namebuf[MAXPATH];
820
821 w = h = 0;
822 hotx = hoty = -1;
823 while (fgets(buf, sizeof(buf), fp) != NULL) {
824 if (strncmp(buf, "static", 6) == 0||
825 strncmp(buf, "unsigned", 8) == 0||
826 strncmp(buf, "char", 4) == 0)
827 break;
828 if (sscanf(buf, "#define %s %d", namebuf, &c) == 2) {
829 if (strcmp_tail(namebuf, "width") == 0)
830 w = c;
831 else if (strcmp_tail(namebuf, "height") == 0)
832 h = c;
833 else if (strcmp_tail(namebuf, "x_hot") == 0)
834 hotx = c;
835 else if (strcmp_tail(namebuf, "y_hot") == 0)
836 hoty = c;
837 }
838 }
839 if (!w || !h)
840 return 1;
841 y = x = 0;
842 p = buf;
843 *p = '\0';
844 for (;;) {
845 while (*p && (*p == ' ' || *p == '\t' || *p == ','))
846 p++;
847 if (*p == '\0' || *p == '\n') {
848 if (fgets(buf, sizeof(buf), fp) == NULL)
849 break;
850 p = buf;
851 }
852 if (sscanf(p, "0x%02x", &c)) {
853 p += 4;
854 for (i = 0; i < 8; i++) {
855 if (x+i < w)
856 *(imgdata+y*imgmaxw+x+i) = ((c & rbittbl[i]) ? 1 : 0);
857 }
858 x += 8;
859 if (x >= w) {
860 if (++y >= h)
861 break;
862 x = 0;
863 }
864 } else {
865 p++;
866 }
867 }
868 imgfiledepth = 1;
869 hotspotx = hotx;
870 hotspoty = hoty;
871 imgupdate(w, h);
872 return 0;
873 }
874
875 /* set XImage from imgdata */
setpixel_sub2(x0,y0,pixel)876 void setpixel_sub2(x0, y0, pixel)
877 int x0;
878 int y0;
879 unsigned long pixel;
880 {
881 int x, y, x1, y1;
882
883 x0 *= zoomfactor;
884 y0 *= zoomfactor;
885 x1 = x0+zoomfactor;
886 y1 = y0+zoomfactor;
887 for (y = y0; y < y1; y++)
888 for (x = x0; x < x1; x++)
889 XPutPixel(img, x, y, pixel);
890 }
891
892 /* set XImage from imgdata */
setpixel_sub(x0,y0,pixel)893 void setpixel_sub(x0, y0, pixel)
894 int x0;
895 int y0;
896 unsigned long pixel;
897 {
898 int x, y, x1, y1;
899
900 if (vimg != NULL)
901 XPutPixel(vimg, x0, y0, pixel);
902 x0 *= zoomfactor;
903 y0 *= zoomfactor;
904 x1 = x0+zoomfactor;
905 y1 = y0+zoomfactor;
906 for (y = y0; y < y1; y++)
907 for (x = x0; x < x1; x++)
908 XPutPixel(img, x, y, pixel);
909 }
910
911 /* set view image */
912 #define setpixel_subv(x0,y0,px) XPutPixel(vimg,(x0),(y0),(px))
913
setpixelcolor(x,y,col)914 void setpixelcolor(x, y, col)
915 int x;
916 int y;
917 int col;
918 {
919 unsigned char *p;
920
921 /* check masked color */
922 p = imgdata+y*imgmaxw+x;
923 if (!*(colmask + current_pal*MAXCOLSET + *p) && tilemask[y&7][x&7]) {
924 *p = col;
925 setpixel_sub2(x, y, pixtbl[col]);
926 if (vimg != NULL)
927 setpixel_subv(x, y, pixtbl[col]);
928 }
929 }
930
gen_image_subv(x0,y0,w,h)931 void gen_image_subv(x0, y0, w, h)
932 int x0;
933 int y0;
934 int w;
935 int h;
936 {
937 int x, y;
938 unsigned char *ip;
939
940 for (y = y0; y < y0+h; y++) {
941 ip = imgdata+y*imgmaxw+x0;
942 for (x = x0; x < x0+w; x++) {
943 setpixel_subv(x, y, pixtbl[*ip++]);
944 }
945 }
946 }
947
948 /* set XImage from imgdata */
gen_image_sub(x0,y0,w,h)949 void gen_image_sub(x0, y0, w, h)
950 int x0;
951 int y0;
952 int w;
953 int h;
954 {
955 int x, y, xs, ys, xe, ye, zx, zy;
956 unsigned char *ip;
957 unsigned char pix;
958
959 xs = x0 * zoomfactor;
960 ys = y0 * zoomfactor;
961 xe = xs + w * zoomfactor;
962 ye = ys + h * zoomfactor;
963 for (y = ys; y < ye; y += zoomfactor) {
964 ip = imgdata+(y/zoomfactor)*imgmaxw+x0;
965 for (x = xs; x < xe; x += zoomfactor) {
966 pix = pixtbl[*ip++];
967 for (zy = 0; zy < zoomfactor; zy++)
968 for (zx = 0; zx < zoomfactor; zx++)
969 XPutPixel(img, x+zx, y+zy, pix);
970 }
971 }
972 }
973
update_area(x,y,w,h)974 void update_area(x, y, w, h)
975 int x;
976 int y;
977 int w;
978 int h;
979 {
980 gen_image_sub(x, y, w, h);
981 if (vimg != NULL)
982 gen_image_subv(x, y, w, h);
983 }
984
fill_area2(dstx,dsty,w,h,c)985 void fill_area2(dstx, dsty, w, h, c)
986 int dstx;
987 int dsty;
988 int w;
989 int h;
990 int c;
991 {
992 int x, y, xe, ye;
993 unsigned char *p;
994 char *mp;
995
996 mp = colmask + current_pal*MAXCOLSET;
997 xe = dstx + w;
998 ye = dsty + h;
999 for (y = dsty; y < ye; y++) {
1000 p = imgdata+y*imgmaxw+dstx;
1001 for (x = dstx; x < xe; x++) {
1002 if (!*(mp+*p))
1003 *p = c;
1004 p++;
1005 }
1006 }
1007 update_area(dstx, dsty, w, h);
1008 }
1009
fill_area(dstx,dsty,w,h,c)1010 void fill_area(dstx, dsty, w, h, c)
1011 int dstx;
1012 int dsty;
1013 int w;
1014 int h;
1015 int c;
1016 {
1017 int x, y, xe, ye;
1018 unsigned char *p;
1019 char *mp;
1020
1021 mp = colmask + current_pal*MAXCOLSET;
1022 xe = dstx + w;
1023 ye = dsty + h;
1024 for (y = dsty; y < ye; y++) {
1025 p = imgdata+y*imgmaxw+dstx;
1026 for (x = dstx; x < xe; x++) {
1027 if (!*(mp+*p) && tilemask[y&7][x&7])
1028 *p = c;
1029 p++;
1030 }
1031 }
1032 update_area(dstx, dsty, w, h);
1033 }
1034
copy_area(dstx,dsty,srcx,srcy,w,h)1035 void copy_area(dstx, dsty, srcx, srcy, w, h)
1036 int dstx;
1037 int dsty;
1038 int srcx;
1039 int srcy;
1040 int w;
1041 int h;
1042 {
1043 int x, y;
1044 int lastnocopypixel;
1045 unsigned char *srcp, *dstp;
1046 char *mp;
1047
1048 lastnocopypixel = nocopypixel;
1049 if (!nocopypixel_mode)
1050 nocopypixel = -1;
1051 mp = colmask+current_pal*MAXPALSET;
1052 if (dsty*imgmaxw+dstx > srcy*imgmaxw+srcx) {
1053 for (y = h-1; y >= 0; y--) {
1054 dstp = imgdata+(dsty+y)*imgmaxw+dstx;
1055 srcp = imgdata+(srcy+y)*imgmaxw+srcx;
1056 for (x = w-1; x >= 0; x--) {
1057 if (!*(mp+*(dstp+x)) && *(srcp+x) != nocopypixel)
1058 *(dstp+x) = *(srcp+x);
1059 }
1060 }
1061 } else {
1062 for (y = 0; y < h; y++) {
1063 dstp = imgdata+(dsty+y)*imgmaxw+dstx;
1064 srcp = imgdata+(srcy+y)*imgmaxw+srcx;
1065 for (x = 0; x < w; x++) {
1066 if (!*(mp+*(dstp+x)) && *(srcp+x) != nocopypixel)
1067 *(dstp+x) = *(srcp+x);
1068 }
1069 }
1070 }
1071 update_area(dstx, dsty, w, h);
1072 nocopypixel = lastnocopypixel;
1073 }
1074
1075
gen_image_col(x0,y0,w,h)1076 void gen_image_col(x0, y0, w, h)
1077 int x0;
1078 int y0;
1079 int w;
1080 int h;
1081 {
1082 int x, y;
1083 unsigned char *ip;
1084
1085 for (y = y0; y < y0+h; y++) {
1086 ip = imgdata+y*imgmaxw+x0;
1087 for (x = x0; x < x0+w; x++) {
1088 if (coltbl[*ip] & CM_UPDATING) {
1089 coltbl[*ip] |= CM_UPDATED;
1090 setpixel_sub2(x, y, pixtbl[*ip++]);
1091 }
1092 }
1093 }
1094 if (vimg != NULL) {
1095 for (y = y0; y < y0+h; y++) {
1096 ip = imgdata+y*imgmaxw+x0;
1097 for (x = x0; x < x0+w; x++) {
1098 if (coltbl[*ip] & CM_UPDATING) {
1099 coltbl[*ip] |= CM_UPDATED;
1100 setpixel_subv(x, y, pixtbl[*ip++]);
1101 }
1102 }
1103 }
1104 }
1105 for (x = 0; x < MAXPALSET*MAXCOLSET; x++) {
1106 if (coltbl[x] & CM_UPDATED)
1107 coltbl[x] &= ~(CM_UPDATED|CM_UPDATING);
1108 }
1109 }
1110
1111 /* End of file */
1112