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