1 /*
2 XMascot Ver 2.5 image-lib
3 Copyright(c)1996 Go Watanabe go@cclub.tutcc.tut.ac.jp
4 Tsuyoshi IIda iida@cclub.tutcc.tut.ac.jp
5 */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14
15 #include "image.h"
16
17 extern int verbose;
18
19 extern int mag_read_stream(ImageData *, FILE *fp);
20 extern int gif_read_stream(ImageData *, FILE *fp);
21 extern int bmp_read_stream(ImageData *, FILE *fp);
22 extern int pnm_read_stream(ImageData *, FILE *fp);
23
24 static struct {
25 int (*read_stream)(ImageData *, FILE *fp);
26 } loadors[] = {
27 { gif_read_stream },
28 { mag_read_stream },
29 { bmp_read_stream },
30 { pnm_read_stream },
31 };
32
33 /* ������������ */
34 ImageData*
image_new(void)35 image_new(void)
36 {
37 ImageData *img;
38
39 if ((img = malloc(sizeof(*img))) == NULL) {
40 perror("image_new");
41 exit(1);
42 }
43
44 img->display = NULL;
45 img->window = None;
46 img->colormap = None;
47 img->depth = 0;
48
49 img->pixel_allocated = 0;
50 img->allocated_pixel = NULL;
51 img->npixel = 0;
52
53 img->width = 0;
54 img->height = 0;
55 img->data = NULL;
56
57 img->pal = NULL;
58 img->npal = 0;
59 img->trans_flag = TRANS_AUTO;
60
61 img->pixmap = None;
62 img->mask = None;
63
64 img->ref_count = 1;
65
66 return img;
67 }
68
69 /* Ʊ����������֤� */
70 ImageData *
image_attach(ImageData * img)71 image_attach(ImageData *img)
72 {
73 img->ref_count++;
74 return img;
75 }
76
77 /* ������ǡ����β��� */
78 void
image_delete(ImageData * img)79 image_delete(ImageData *img)
80 {
81 if (img) {
82 img->ref_count--;
83 if (img->ref_count <= 0) {
84 image_free_pixmap(img);
85 image_free_pixels(img);
86 image_free_data(img);
87 free(img);
88 }
89 }
90 }
91
92 /* pixel/pixmap ��������ʤ� */
93 void
image_delete_only_data(ImageData * img)94 image_delete_only_data(ImageData *img)
95 {
96 if (img) {
97 img->ref_count--;
98 if (img->ref_count <= 0) {
99 image_free_data(img);
100 free(img);
101 }
102 }
103 }
104
105 /* �ǡ�����ʬ��������� */
106 void
image_free_data(ImageData * img)107 image_free_data(ImageData *img)
108 {
109 if (img) {
110 if (img->data != NULL) {
111 free(img->data);
112 img->data = NULL;
113 }
114 if (img->pal != NULL){
115 free(img->pal);
116 img->npal = 0;
117 img->pal = NULL;
118 }
119 }
120 }
121
122 /* ����������� */
123 void
image_free_pixels(ImageData * img)124 image_free_pixels(ImageData *img)
125 {
126 if (img && img->allocated_pixel) {
127 int i;
128 if (verbose) {
129 fprintf(stderr,"free pixels: %zu\n",img->npixel);
130 for(i=0;i<img->npixel;i++)
131 fprintf(stderr,"%d:%lx\n",i,img->allocated_pixel[i]);
132 }
133 XFreeColors(img->display,img->colormap,
134 img->allocated_pixel,img->npixel,0);
135 free(img->allocated_pixel);
136 img->allocated_pixel = NULL;
137 img->npixel = 0;
138 }
139 }
140
141 void
image_free_pixmap(ImageData * img)142 image_free_pixmap(ImageData *img)
143 {
144 if (img) {
145 if (img->pixmap != None) {
146 XFreePixmap(img->display, img->pixmap);
147 img->pixmap = None;
148 }
149 if (img->mask != None) {
150 XFreePixmap(img->display, img->mask);
151 img->mask = None;
152 }
153 }
154 }
155
156 /*
157 original: ximage.cc,v 1.4 1997/05/05 04:48:07 watanabe Exp
158
159 reformed by watanabe@dsl.tutics.tut.ac.jp
160
161 ���Υե�����ˤ�Vissual Class��Pseudo Color�Ǥ��륵���Ф�
162 XImage���������뤿��Υץ���ब�ޤޤ�Ƥ��ޤ���
163
164 University of Pennsylvania �� John Bradley��������줿
165 xv�Υץ����ͤ˵��Ҥ��Ƥ��ޤ���
166
167 * Author: John Bradley, University of Pennsylvania
168 * (bradley@cis.upenn.edu)
169
170 */
171
172 /*
173 ��������Τ����ơ��ԥ�����ñ�̤Υҥ��ȥ�����������롣
174 �ؿ����֤��ͤϲ����ǡ����Ǽºݤ����Ѥ���Ƥ��뿧�ο���
175 hist�˥ҥ��ȥ���ब�֤���롣
176 */
177 static int
make_histogram(ImageData * img,int hist[MAX_COL])178 make_histogram(ImageData *img, int hist[MAX_COL])
179 {
180 int i, ncols;
181
182 u_char *p = img->data;
183 int n = img->width * img->height;
184
185 if (verbose)
186 fprintf(stderr,"making histgram...");
187
188 /* initialize histogram and compute it */
189 for(i = 0; i < MAX_COL; i++)
190 hist[i] = 0;
191
192 for(i = n; i; i--, p++)
193 hist[*p]++;
194
195 ncols = 0;
196 for(i = 0; i < MAX_COL; i++) {
197 if(!hist[i]) continue;
198 ncols++;
199 }
200
201 if (verbose)
202 fprintf(stderr," get color num: %d\n",ncols);
203
204 return ncols;
205 }
206
207 struct color_table{
208 u_char r,g,b,pad;
209 u_long pixel;
210 };
211
212 /*
213 �������顼�ޥå�(map)��ɬ�פʿ���ͥ���̤�Ĥ��Ƴ�Ǽ���롣ͥ���٤ϡ�
214 �������٤ȳ��ݤ���Ƥ������Ƥο��Ȥο��٥��ȥ�ε�Υ(�ʤ�٤���
215 �Τ�ͥ��)���Ȥ˷�����롣
216 �ؿ����֤��ͤ�map�˳�Ǽ���줿���顼�������
217 order�ˤϸ��β����ͤȤ��Ѵ��ơ��֥뤬�֤���롣
218 */
219 static void
sort_colors(ImageData * img,int hist[256],int order[256],struct color_table c_tbl[256],int ncols)220 sort_colors(ImageData *img,
221 int hist[256],int order[256], struct color_table c_tbl[256],
222 int ncols)
223 {
224 struct cent {
225 int r,g,b; /* actual value of color */
226 int rtrans; /* its index in the old colormap */
227 int use; /* # of pixels of this color */
228 int min_dist; /* min distance to a selected color */
229 };
230 struct cent c0[256], c1[256], *c;
231
232 int nmap = img->npal;
233 int i, j, entry, d;
234
235 c = c0;
236 for (i = 0; i < MAX_COL ; i++) {
237 if(!hist[i])
238 continue;
239 c->rtrans = i;
240 c->use = hist[i];
241
242 if (i >= nmap)
243 c->r = c->g = c->b = 0;
244 else {
245 c->r = c_tbl[i].r;
246 c->g = c_tbl[i].g;
247 c->b = c_tbl[i].b;
248 }
249 c->min_dist = 1000000; /* 255^2 * 3 = 195075 */
250 c++;
251 }
252
253 /* find most-used color, put that in c1[0] */
254
255 {
256 int max_use = c0[entry = 0].use;
257 for(i = 1; i < ncols; i++) {
258 if(max_use < c0[i].use)
259 max_use = c0[entry = i].use;
260 }
261 }
262
263 c1[0] = c0[entry];
264 c0[entry].use = 0; /* dealt with */
265 /*
266 sort rest of colormap. Half of the entries are allocated on the
267 basis of distance from already allocated colors, and half on the
268 basis of usage. (NB: 'taxicab' distance is used throughout this file.)
269
270 Mod: pick first 10 colors based on maximum distance. pick remaining
271 colors half by distance and half by usage -- JHB
272
273 To obtain O(n^2) performance, we keep each unselected color
274 (in c[], with use>0) marked with the minimum distance to any of
275 the selected colors(in c1[]). Each time we select a color, we
276 can update the minimum distances in O(n) time.
277
278 mod by Tom Lane Tom.Lane@g.gp.cs.cmu.edu
279 */
280
281 for (i = 1; i < ncols; i++) {
282 int r, g, b;
283
284 /* Get RGB of color last selected and choose selection method */
285 r = c1[i-1].r;
286 g = c1[i-1].g;
287 b = c1[i-1].b;
288
289 /* Now find the i'th most different color */
290
291 if((i & 1) || i < 10) {
292 /* select the unused color that has the greatest min_dist */
293 int max_min_dist = -1;
294 entry = -1;
295
296 for (j = 0, c = c0; j < ncols; j++,c++) {
297 if (!c->use) continue;
298 /* this color has not been marked already */
299
300 /* update min_dist */
301
302 d = (c->r - r) * (c->r - r) +
303 (c->g - g) * (c->g - g) +
304 (c->b - b) * (c->b - b);
305 if (d < c->min_dist)
306 c->min_dist = d;
307
308 if (max_min_dist < c->min_dist)
309 max_min_dist = c->min_dist, entry = j;
310 }
311 } else {
312 /* select the unused color that has the greatest usage */
313 int max_use = -1;
314 entry = -1;
315
316 for (j = 0, c = c0; j < ncols; j++,c++) {
317 if (!c->use) continue;
318 /* this color has not been marked already */
319
320 /* update min_dist */
321 d = (c->r - r) * (c->r - r) +
322 (c->g - g) * (c->g - g) +
323 (c->b - b) * (c->b - b);
324 if(d < c->min_dist)
325 c->min_dist = d;
326
327 if(max_use < c->use)
328 max_use = c->use, entry = j;
329
330
331 }
332 }
333
334 /* c0[entry] is the next color to put in the map. do so */
335 c1[i] = c0[entry];
336 c0[entry].use = 0;
337 }
338
339 for (i = 0; i < ncols; i++) {
340 order[i] = c1[i].rtrans;
341 c_tbl[i].r = c1[i].r;
342 c_tbl[i].g = c1[i].g;
343 c_tbl[i].b = c1[i].b;
344 }
345 }
346
347 /*
348 �������顼�ޥå�map�ξ���ˡ��ɤ߹������ѤΥ��顼����ݤ��롣
349 */
350 static void
alloc_read_only_colors(ImageData * img,struct color_table c_tbl[256],int ncols)351 alloc_read_only_colors(ImageData *img,
352 struct color_table c_tbl[256],
353 int ncols)
354 {
355 int i, j, unique;
356 XColor defs[MAX_COL], *ctab;
357 int failed[MAX_COL],index[MAX_COL];
358 unsigned long pixel;
359
360 u_long *alloced_pixel;
361 Display *display = img->display;
362 Colormap colormap = img->colormap;
363 int ncells = img->vinfo.colormap_size;
364
365 if ((img->allocated_pixel = malloc(sizeof(u_long)* ncols + 1)) == NULL) {
366 perror("alloc_read_only_colors");
367 exit(1);
368 }
369 img->npixel = 0;
370 alloced_pixel = img->allocated_pixel;
371
372 /*
373 FIRST PASS COLOR ALLOCATION:
374 for each color in the 'desired colormap', try to get it via
375 XAllocColor(). If for any reason it fails, mark that pixel
376 'unallocated' and worry about it later. Repeat.
377 */
378
379 /*
380 attempt to allocate first ncols entries in colormap
381 note: On displays with less than 8 bits per RGB gun, it's quite
382 possible that different colors in the original picture will be
383 mapped to the same color on the screen. X does this for you
384 silently. However, this is not-desirable for this application,
385 because when I say 'allocate me 32 colors' I want it to allocate
386 32 different colors, not 32 instances of the same 4 shades...
387 */
388
389 unique = 0;
390
391 for (i = 0; i < ncols; i++) {
392 defs[i].red = c_tbl[i].r << 8;
393 defs[i].green = c_tbl[i].g << 8;
394 defs[i].blue = c_tbl[i].b << 8;
395 defs[i].flags = DoRed | DoGreen | DoBlue;
396
397 if (!XAllocColor(display,colormap,&defs[i]))
398 failed[i] = 1;
399 else {
400 failed[i] = 0;
401 pixel = c_tbl[i].pixel = defs[i].pixel;
402
403 /* see if the newly allocated color is new and different */
404
405 for (j = 0; j < img->npixel; j++)
406 if (alloced_pixel[j] == pixel) break;
407
408 if (j == img->npixel)
409 unique++;
410
411 index[img->npixel] = i;
412 alloced_pixel[img->npixel++] = pixel;
413 }
414 }
415
416 if(img->npixel == ncols)
417 return;
418
419 /*
420 SECOND PASS COLOR ALLOCATION:
421
422 Allocating 'exact' colors failed.
423 Now try to allocate 'closest' colors.
424
425 Read entire X colormap(or first 256 entries) in from display.
426 for each unallocated pixel, find the closest color that actually
427 is in the X colormap. Try to allocate that color(read only).
428 If that fails, the THIRD PASS will deal with it
429 */
430
431 /* only do SECOND PASS if there IS a colormap to read */
432 if ((ctab = (XColor *)alloca(sizeof ctab[0] * ncells)) == NULL) {
433 perror("alloca");
434 fprintf(stderr,"panic:alloc_read_only_colors failed.\n");
435 abort();
436 }
437
438 /* read entire colormap into 'ctab' */
439 /* assume StaticGray, Grayscale, Pseudo, Static Visual */
440
441 for (i = 0; i < ncells; i++)
442 ctab[i].pixel = i;
443 XQueryColors(display,colormap,ctab,ncells);
444
445 for (i = 0; i < ncols; i++) {
446 int min_dist, close;
447 int ri, gi, bi;
448
449 if(!failed[i])
450 continue; /* an allocated pixel */
451
452 min_dist = 1000000;
453 close = -1;
454 ri = c_tbl[i].r;
455 gi = c_tbl[i].g;
456 bi = c_tbl[i].b;
457
458 for (j = 0; j < ncells; j++) {
459 int d, rd, gd, bd;
460
461 rd = ri - (ctab[j].red >> 8);
462 gd = gi - (ctab[j].green >> 8);
463 bd = bi - (ctab[j].blue >> 8);
464
465 d = rd * rd + gd * gd + bd * bd;
466 if(d < min_dist)
467 min_dist = d, close = j;
468 }
469 if (XAllocColor(display, colormap, &ctab[close])) {
470 defs[i] = ctab[close];
471 failed[i] = 0;
472 pixel = c_tbl[i].pixel = ctab[close].pixel;
473
474 index[img->npixel] = i;
475 alloced_pixel[img->npixel++] = pixel;
476 unique++;
477 }
478
479 } /* SECOND PASS */
480
481 if(img->npixel == ncols)
482 return;
483
484 /*
485 THIRD PASS COLOR ALLOCATION:
486
487 We've alloc'ed all the colors we can. Now, we have to map any
488 remaining unalloced pixels into either the colors that we DID get
489 */
490
491 for (i = 0; i < ncols; i++) {
492 int min_dist, close;
493 int ri, gi, bi;
494
495 if (!failed[i])
496 continue; /* an allocated pixel */
497
498 min_dist = 1000000;
499 close = -1;
500 ri = c_tbl[i].r;
501 gi = c_tbl[i].g;
502 bi = c_tbl[i].b;
503
504 /* search the alloc'd colors */
505
506 for (j = 0; j < img->npixel; j++) {
507 int k, d, rd, gd, bd;
508
509 k = index[j];
510 rd = ri - (defs[k].red >> 8);
511 gd = gi - (defs[k].green >> 8);
512 bd = bi - (defs[k].blue >> 8);
513
514 d = rd * rd + gd * gd + bd * bd;
515 if(d < min_dist)
516 min_dist = d,close = k;
517 }
518
519 defs[i] = defs[close];
520 c_tbl[i].pixel = defs[i].pixel;
521
522 } /* THIRD PASS */
523 }
524
525 #ifndef ULONG_HIGH_BITS
526 #define ULONG_HIGH_BITS 32
527 #endif
528
529 static inline int
highbit(u_long mask)530 highbit(u_long mask)
531 {
532 unsigned long hb = 1UL << (ULONG_HIGH_BITS - 1);
533 int i;
534 /* printf("%lx\n",hb); */
535 for (i = ULONG_HIGH_BITS - 1; i >= 0; i--, mask <<= 1)
536 if (mask & hb) break;
537 return i;
538 }
539
540 void
image_set_col(ImageData * img,Display * dpy,Window win)541 image_set_col(ImageData *img, Display *dpy, Window win)
542 {
543 struct palette *pal = img->pal;
544 u_long *pixel_value = img->pixel_value;
545
546 /* �Ƴ�����Ƥ��褦�Ȥ��Ƥ��� */
547 if (img->pixel_allocated) {
548 #ifdef DEBUG
549 fprintf(stderr,"image_set_col: allocate again...");
550 #endif
551 if (dpy != img->display || win != img->window) {
552 image_free_pixels(img);
553 image_free_pixmap(img);
554 #ifdef DEBUG
555 fprintf(stderr,"allocated\n");
556 #endif
557 } else {
558 #ifdef DEBUG
559 fprintf(stderr,"not allocated\n");
560 #endif
561 return;
562 }
563 }
564
565 img->display = dpy;
566 img->window = win;
567
568 /* colormap setup */
569 {
570 XWindowAttributes attr;
571 XGetWindowAttributes(dpy, win, &attr);
572 img->depth = attr.depth;
573 img->colormap = attr.colormap;
574 /* ���ɤ��������� Visual ��¤�Τ���ȤϤߤ������ */
575 {
576 int matched;
577 XVisualInfo *vinfolist;
578 XVisualInfo vinfo;
579 vinfo.visualid = XVisualIDFromVisual(attr.visual);
580 vinfolist =
581 XGetVisualInfo(img->display,VisualIDMask,&vinfo,&matched);
582 if (!matched) {
583 fprintf(stderr,"can't get visual info.");
584 exit(1);
585 }
586 img->vinfo = vinfolist[0];
587 XFree(vinfolist);
588 }
589 }
590
591 switch (img->type) {
592 case 2:
593 fprintf(stderr,"no supported depth...\n");
594 exit(1);
595 break;
596 case 8:
597 if (img->vinfo.class == TrueColor) {
598 int i;
599 u_long rmask, gmask, bmask;
600 int rshift, gshift, bshift;
601
602 msg_out("8bit true color\n");
603
604 rshift = highbit(rmask = img->vinfo.red_mask ) - 7;
605 gshift = highbit(gmask = img->vinfo.green_mask) - 7;
606 bshift = highbit(bmask = img->vinfo.blue_mask ) - 7;
607
608 msg_out("shift r:[%d] g:[%d] b:[%d]\n", rshift, gshift, bshift);
609
610 for (i = 0; i < img->npal; i++, pal++) {
611 u_long rv, gv, bv;
612 rv = rshift < 0 ? pal->r >> -rshift : pal->r << rshift;
613 gv = gshift < 0 ? pal->g >> -gshift : pal->g << gshift;
614 bv = bshift < 0 ? pal->b >> -bshift : pal->b << bshift;
615 pixel_value[i] = (rv & rmask)|(gv & gmask)|(bv & bmask);
616 }
617 for (; i < 256; i++)
618 pixel_value[i] = 0L;
619
620 } else {
621 /* for 8-bit pseudo colors */
622 int i, ncols, hist[MAX_COL], order[MAX_COL];
623 struct color_table c_tbl[MAX_COL];
624
625 msg_out("8bit pseudo color\n");
626
627 ncols = make_histogram(img,hist);
628 for (i=0; i< img->npal; i++, pal++) {
629 c_tbl[i].r = pal->r;
630 c_tbl[i].g = pal->g;
631 c_tbl[i].b = pal->b;
632 }
633 sort_colors(img, hist, order, c_tbl, ncols);
634 alloc_read_only_colors(img, c_tbl, ncols);
635
636 for (i=0; i<ncols; i++)
637 pixel_value[order[i]] = c_tbl[i].pixel;
638 }
639 break;
640 case 24:
641 if (img->vinfo.class != TrueColor) {
642 fprintf(stderr,"no supported mode...\n");
643 exit(1);
644 }
645 break;
646 }
647 img->pixel_allocated = 1;
648 }
649
650 int
image_read_stream(ImageData * img,FILE * fp)651 image_read_stream(ImageData *img, FILE *fp)
652 {
653 size_t n_loador = sizeof loadors / sizeof loadors[0];
654 int i;
655 for (i=0; i< n_loador; i++) {
656 if (!loadors[i].read_stream(img,fp))
657 return 0;
658 rewind(fp);
659 }
660 return -1;
661 }
662
663
664 /* ������ǡ����μ��� */
665 void
image_load(ImageData * img,char * name,int c0,int r0)666 image_load(ImageData *img, char *name, int c0, int r0)
667 {
668 FILE *fp;
669 char *fname;
670 int i;
671
672 size_t n_loador = sizeof loadors / sizeof loadors[0];
673
674 /* already loaded */
675 if (img->data != NULL)
676 return;
677
678 if ((fname = search(name))== NULL)
679 return;
680
681 if ((fp = fopen(fname,"r"))== NULL) {
682 perror(fname);
683 return;
684 }
685
686 if (c0 >= 0) {
687 img->trans_flag = TRANS_INDEX;
688 img->trans_index = c0;
689 }
690 #if 0
691 else if (r0 >= 0) {
692 img->trans_flag = TRANS_RGB;
693 img->trans_rgb = r0;
694 }
695 #endif
696 for (i=0; i< n_loador; i++) {
697 if (!loadors[i].read_stream(img,fp))
698 return;
699 rewind(fp);
700 }
701
702 fprintf(stderr,"can't load %s.\n", fname);
703 exit(1);
704
705 #if 0
706 fclose(fp);
707 if ((suffix = strrchr(name,'.'))== NULL) {
708 err_out("File \"%s\" has no suffix.\n",name);
709 return;
710 }
711 suffix++;
712
713 {
714 char cmdline[100];
715 int fd[2];
716 pid_t pid;
717
718 if (pipe(fd)< 0) {
719 perror("pipe"); exit(1);
720 }
721 if ((pid = fork())< 0) {
722 perror("fork"); exit(1);
723 }
724 if (pid == 0) {
725 if (close(1)< 0) {
726 perror("close"); exit(1);
727 }
728 if (dup(fd[1])!= 1) {
729 perror("dup"); exit(1);
730 }
731 close(fd[1]);
732 sprintf(cmdline,"%stopnm",suffix);
733 execlp(cmdline, cmdline, fname, (char*)NULL);
734 sprintf(cmdline,"%stoppm",suffix);
735 execlp(cmdline, cmdline, fname, (char*)NULL);
736 sprintf(cmdline,"%stopgm",suffix);
737 execlp(cmdline, cmdline, fname, (char*)NULL);
738 sprintf(cmdline,"%stopbm",suffix);
739 execlp(cmdline, cmdline, fname, (char*)NULL);
740 perror("execlp");
741 err_out("Can't find %s\n",cmdline);
742 err_out("Bad suffix \"%s\".\n",suffix);
743 exit(1);
744 }
745 close(fd[1]);
746 if ((fp = fdopen(fd[0], "r"))== NULL) {
747 perror("fdopen");
748 exit(1);
749 }
750 pnm_read_stream(img,fp);
751 }
752 #endif
753
754 }
755
756 #ifdef SHADOW
757
758 /* �������pixmap���Ѵ����� */
759 Pixmap
image_pixmap_with_shadow(ImageData * img,Pixmap * m,int shadow_len)760 image_pixmap_with_shadow(ImageData *img, Pixmap *m, int shadow_len)
761 {
762 int i,j;
763 GC gc;
764
765 unsigned w = img->width;
766 unsigned h = img->height;
767 u_long *pixels = img->allocated_pixel;
768 u_long *pixel_value = img->pixel_value;
769 u_char *data = (u_char*)img->data;
770
771 XImage *img_data;
772 Pixmap p;
773 u_long black;
774
775 #ifdef SHAPE
776 XImage *img_mask;
777 Pixmap b;
778 int trans_index = img->trans_index;
779 int make_mask;
780 make_mask = (m && img->trans_flag == TRANS_INDEX)?1:0;
781 #endif
782
783 /* �Ƴ�����Ƥ��褦�Ȥ��Ƥ��� */
784 if (img->pixmap != None) {
785 if (m)
786 *m = img->mask;
787 return img->pixmap;
788 }
789
790 if (make_mask && shadow_len) {
791 if (img->vinfo.class != TrueColor) {
792 XColor col;
793 col.red = col.blue = col.green = 0;
794 col.flags = DoRed | DoGreen | DoBlue;
795 if (XAllocColor(img->display,img->colormap,&col)) {
796 black = pixels[img->npixel++] = col.pixel;
797 } else {
798 err_out("black allocation failed\n");
799 black = 0;
800 }
801 }else
802 black = 0;
803 }
804
805 p = XCreatePixmap(img->display, img->window,
806 w+shadow_len,h+shadow_len,img->depth);
807 img_data = XGetImage(img->display,p,0,0,w+shadow_len,h+shadow_len,
808 AllPlanes,ZPixmap);
809
810 #ifdef SHAPE
811 if (make_mask) {
812 b = XCreatePixmap(img->display, img->window,
813 w+shadow_len,h+shadow_len,1);
814 img_mask = XGetImage(img->display,b,0,0,w+shadow_len,h+shadow_len,
815 1,ZPixmap);
816 }
817 #endif /* SHAPE */
818
819 #ifdef SHAPE
820 if (make_mask) {
821 if (shadow_len) {
822 for(i=h+shadow_len-1;i>=0;i--)
823 for(j=w+shadow_len-1;j>=0;j--)
824 if (i<h && j<w && data[i*w+j] != trans_index) {
825 XPutPixel(img_data,j,i,pixel_value[data[i*w+j]]);
826 XPutPixel(img_mask,j,i,1);
827 if ((i+j)& 1)
828 XPutPixel(img_mask,j+shadow_len,i+shadow_len,1);
829 } else {
830 XPutPixel(img_data,j,i,black);
831 XPutPixel(img_mask,j,i,0);
832 }
833 } else {
834 for (i=0;i<h;i++)
835 for (j=0;j<w;j++)
836 if (data[i*w+j] != trans_index) {
837 XPutPixel(img_data,j,i,pixel_value[data[i*w+j]]);
838 XPutPixel(img_mask,j,i,1);
839 }else{
840 XPutPixel(img_mask,j,i,0);
841 }
842 }
843 }else
844 #endif /* SHAPE */
845 {
846 for(i=0;i<h;i++)
847 for(j=0;j<w;j++)
848 XPutPixel(img_data,j,i,pixel_value[data[i*w+j]]);
849 }
850
851 gc = XCreateGC(img->display,p,0,NULL);
852 XPutImage(img->display,p,gc,img_data,0,0,0,0,w+shadow_len,h+shadow_len);
853 XFreeGC(img->display,gc);
854 XDestroyImage(img_data);
855
856 #ifdef SHAPE
857 if (m) {
858 if(make_mask) {
859 gc = XCreateGC(img->display,b,0,NULL);
860 XPutImage(img->display,b,gc,img_mask,0,0,0,0,
861 w+shadow_len,h+shadow_len);
862 *m = img->mask = b;
863 XFreeGC(img->display,gc);
864 XDestroyImage(img_mask);
865 } else
866 *m = img->mask = None;
867 }
868 #endif /* SHAPE */
869
870 if (verbose)
871 fprintf(stderr,"convert image -> pixmap done.\n");
872
873 img->pixmap = p;
874 return p;
875 }
876
877 #endif /* SHADOW */
878
879
880 /* �������pixmap���Ѵ����� */
881 Pixmap
image_pixmap(ImageData * img,Pixmap * m)882 image_pixmap(ImageData *img, Pixmap *m)
883 {
884 int i,j;
885 GC gc;
886 unsigned w = img->width;
887 unsigned h = img->height;
888 u_long *pixel_value = img->pixel_value;
889
890 u_char *data = img->data;
891 XImage *img_data;
892 Pixmap p;
893
894 #ifdef SHAPE
895 XImage *img_mask;
896 Pixmap b;
897 int trans_index = img->trans_index;
898 int make_mask;
899 make_mask = (m && img->trans_flag == TRANS_INDEX)?1:0;
900 #endif /* SHAPE */
901
902 /* �Ƴ�����Ƥ��褦�Ȥ��Ƥ��� */
903 if (img->pixmap != None) {
904 if (m)
905 *m = img->mask;
906 return img->pixmap;
907 }
908
909 p = XCreatePixmap(img->display, img->window, w, h, img->depth);
910 img_data = XGetImage(img->display,p,0,0,w,h,AllPlanes,ZPixmap);
911
912 #ifdef SHAPE
913 if (make_mask) {
914 b = XCreatePixmap(img->display, img->window, w, h, 1);
915 img_mask = XGetImage(img->display,b,0,0,w,h,1,ZPixmap);
916 }
917 #endif /* SHAPE */
918
919 #ifdef SHAPE
920 if (make_mask) {
921 for (i=0;i<h;i++)
922 for (j=0;j<w;j++)
923 if (data[i*w+j] != trans_index) {
924 XPutPixel(img_data,j,i,pixel_value[data[i*w+j]]);
925 XPutPixel(img_mask,j,i,1);
926 }else{
927 XPutPixel(img_mask,j,i,0);
928 }
929 }else
930 #endif /* SHAPE */
931 {
932 for (i=0;i<h;i++)
933 for (j=0;j<w;j++)
934 XPutPixel(img_data,j,i,pixel_value[data[i*w+j]]);
935 }
936
937 gc = XCreateGC(img->display,p,0,NULL);
938 XPutImage(img->display,p,gc,img_data,0,0,0,0,w,h);
939 XFreeGC(img->display,gc);
940 XDestroyImage(img_data);
941
942 #ifdef SHAPE
943 if (m) {
944 if (make_mask) {
945 gc = XCreateGC(img->display,b,0,NULL);
946 XPutImage(img->display,b,gc,img_mask,0,0,0,0,w,h);
947 *m = b;
948 img->mask = b;
949
950 XFreeGC(img->display,gc);
951 XDestroyImage(img_mask);
952 }else
953 *m = img->mask = None;
954 }
955 #endif /* SHAPE */
956
957 if (verbose)
958 fprintf(stderr,"convert image -> pixmap done.\n");
959
960 img->pixmap = p;
961 return p;
962 }
963
964 void *
image_alloc_palette(ImageData * img,size_t n)965 image_alloc_palette(ImageData *img, size_t n)
966 {
967 struct palette *p;
968 size_t size = sizeof p[0] * n ;
969
970 p = img->pal ? realloc(img->pal,size) : malloc(size);
971 if (p) {
972 img->pal = p;
973 img->npal = n;
974 } else {
975 perror(img->pal ? "realloc" : "malloc");
976 fprintf(stderr,"image-lib:alloc_palette failed."
977 "%zu,%zu(%#zx) bytes\n", n, size, size);
978 exit(1);
979 }
980 return p;
981 }
982
983 void *
image_alloc_data(ImageData * img,int w,int h,int t)984 image_alloc_data(ImageData *img, int w, int h, int t)
985 {
986 size_t size;
987 void *p;
988
989 switch(t) {
990 case 2:
991 size = (w + 7)/8 * h;
992 break;
993 case 8:
994 size = w * h;
995 break;
996 case 24:
997 size = w * h * 3;
998 break;
999 default:
1000 fprintf(stderr,"Warning:no support image type:%d\n",t);
1001 return NULL;
1002 }
1003
1004 if ((p = img->data ? realloc(img->data,size) : malloc(size)) == NULL) {
1005 perror(img->data ? "realloc" : "malloc");
1006 fprintf(stderr,"image:alloc_data "
1007 "%dx%d %zu(%#zx) bytes failed.\n", w,h,size,size);
1008 exit(1);
1009 }
1010
1011 img->width = w;
1012 img->height = h;
1013 img->data = p;
1014 img->type = t;
1015
1016 return p;
1017 }
1018