1 /*
2 *   image.c
3 *       Yet Another Osuwari Multi for X11
4 *       (Create Image Module)
5 */
6 
7 #include	<stdio.h>
8 #include	<stdlib.h>
9 #include	<string.h>
10 
11 #include	<X11/Xlib.h>
12 #include	<X11/Xutil.h>
13 #include	<X11/Xmd.h>	/* �ޥ����ͭ���������CARDPtr�ʤ� */
14 
15 /* ����Ū���֤���(̤����ʤ��Ȥ�����) */
16 #ifndef	EXIT_SUCCESS
17 #define	EXIT_SUCCESS	0
18 #endif
19 #ifndef	EXIT_FAILURE
20 #define	EXIT_FAILURE	1
21 #endif
22 
23 /******** External Value ********/
24 
25 extern Display	*Disp;
26 extern Colormap	MyColorMap;
27 
28 /******** Functions Prototype ********/
29 
30 unsigned int	GetXDepth( );
31 XImage  *CreateMyImage( );
32 static void	CopyImageFromData32( );
33 static void	CopyImageFromData16( );
34 static void	CopyImageFromData8( );
35 static void	PalettePix32( );
36 static void	PalettePix16( );
37 static void	PalettePix8( );
38 static int	PickNearColor( );
39 Cursor	CreateMyCursor( );
40 
41 /******** GetXDepth ********
42 * Xü���Υ��顼�⡼�ɤ�����
43 */
GetXDepth(disp)44 unsigned int	GetXDepth( disp )
45 	Display	*disp;
46 {
47 
48 	return DefaultDepth(disp, 0);
49 	XVisualInfo	xvi_template;
50 	XVisualInfo	*p_xvi;
51 	int		n_item, i;
52 	int		depth = 0;
53 
54 	/**** Visual Class ���� ****
55 	*	#define StaticGray      0
56 	*	#define GrayScale       1
57 	*	#define StaticColor     2
58 	*	#define PseudoColor     3
59 	*	#define TrueColor       4
60 	*	#define DirectColor     5
61 	****/
62 
63 	memset( &xvi_template, 0, sizeof(XVisualInfo) );
64 /*	xvi_template.depth = 8; /**/
65 /*	xvi_template.depth = PseudoColor; /**/
66 
67 	p_xvi = XGetVisualInfo( disp, VisualNoMask,
68 					&xvi_template, &n_item );
69 
70 	for( i=0; i<n_item; i++ )
71 	{
72 	/*	printf( "INFO: %d: depth=%d, class=%d\n",
73 				i, p_xvi[i].depth, p_xvi[i].class ); /* DEBUG */
74 
75 		if( depth < p_xvi[i].depth ) /* ����Τ�Τ����� */
76 		{	depth = p_xvi[i].depth;
77 		}
78 	}
79 
80 	XFree( p_xvi );
81 	return depth;
82 }
83 
84 /******** CreateMyImage ********
85 * �ӥåȥǡ������� XImage����������
86 */
87 
CreateMyImage(width,height,palette,ncolor,depth,data)88 XImage	*CreateMyImage( width, height, palette, ncolor, depth, data )
89 	int     width;
90 	int     height;
91 	unsigned char   *palette;
92 	int     ncolor;
93 	unsigned int	depth;
94 	unsigned char   *data;
95 {
96     XImage		*image;
97     XColor		*color_tbl;
98     int			index;
99     int			pixel_size, padding;
100 
101 	/* XImage���������� */
102 	{	int		bitmap_pad, line_bytes;
103 
104     	if( depth <= 8 )
105 		{	bitmap_pad = 8;
106 			line_bytes = width;
107     	}else
108 		{	bitmap_pad = 32;
109 			line_bytes = 0;
110     	}
111 
112     	image = XCreateImage( Disp,
113 					DefaultVisual( Disp, DefaultScreen(Disp) ),
114 					depth, ZPixmap, 0,
115 					None, /* <- �ޤ����Υǡ������������� */
116 					width, height,
117 					bitmap_pad, line_bytes
118 				);
119     	if( image == NULL )
120 		{	fprintf( stderr, "ERROR: Can't allocate memory for XImage.\n" );
121 			return NULL;
122     	}
123 
124     	image->data = (char*)malloc( image->bytes_per_line * height );
125    		if( image->data == NULL )
126 		{	fprintf( stderr, "ERROR: Can't allocate memory for image data.\n" );
127 			return NULL;
128    		}
129 	}
130 
131     pixel_size = image->bytes_per_line / width;
132     padding    = image->bytes_per_line - (width * pixel_size);
133 
134 	/* data -> image->data �˥��ԡ� */
135 	if( pixel_size >= 4 )
136 	{	CopyImageFromData32( image->data, data, width, height, padding );
137    	}
138 	else if( pixel_size >= 2 )
139 	{	CopyImageFromData16( image->data, data, width, height, padding );
140    	}
141 	else
142 	{	CopyImageFromData8( image->data, data, width, height, padding );
143 	}
144 
145     /* ��(���顼����)�γ��� */
146 	color_tbl = (XColor*)malloc( sizeof(XColor) * ncolor );
147  	if( color_tbl == NULL )
148 	{	fprintf( stderr, "ERROR: Can't allocate memory for XColor.\n" );
149 		return NULL;
150    	}
151 
152     for( index = 0; index < ncolor; index++ )
153 	{
154 		color_tbl[ index ].red   = palette[ index * 3     ] << 8;
155 		color_tbl[ index ].green = palette[ index * 3 + 1 ] << 8;
156 		color_tbl[ index ].blue  = palette[ index * 3 + 2 ] << 8;
157 
158 		if( XAllocColor( Disp, MyColorMap, &color_tbl[index] ) == 0 )
159 		{
160 	    	/* ��(���顼����)�γ��ݤ˼��Ԥ����� */
161 		/*	printf( "INFO: Not enough ColorCell, using Near Color.\n" ); /* DEBUG */
162 
163 			if( PickNearColor( &palette[index], &color_tbl[index] ) != EXIT_SUCCESS )
164 			{	fprintf( stderr, "ERROR: Internal Color Allocate Error!\n" );
165 			}
166 	   	}
167 	}
168 
169 	/* �ԥ�����ǡ����� XAllocColor �����ԥ������ֹ�˽������� */
170    	if( pixel_size >= 4 )
171 	{	PalettePix32( image->data, color_tbl, width, height, padding );
172    	}
173 	else if( pixel_size >= 2 )
174 	{	PalettePix16( image->data, color_tbl, width, height, padding );
175    	}
176 	else
177 	{	PalettePix8( image->data, color_tbl, width, height, padding );
178    	}
179 
180     /* ���Ȥ��ޤ� */
181     free( (char*)color_tbl );
182 
183     return( image );
184 }
185 
186 /******** CopyImageFromData ********
187 * data -> image->data �˥��ԡ�
188 * 8, 16, 32bit �Σ�����
189 * ��Ȥˤʤ�����ǡ����ϣ����� (4bit)
190 */
CopyImageFromData32(dst_data,src_data,width,height,pad)191 static void	CopyImageFromData32( dst_data, src_data, width, height, pad )
192 	CARD32	*dst_data;
193 	unsigned char	*src_data;
194 	int	width;
195 	int	height;
196 	int	pad;
197 {
198    	int		x, y;
199 	Bool	lower = 0;
200 
201    	for( y=0 ; y<height ; y++ )
202 	{	for( x=0; x<width; x++ )
203 		{
204 #if 0
205 			*dst_data++ = *src_data++; /* DEBUG * 256���ǡ����� */
206 #else
207 			if( lower == 0 )
208 			{	*dst_data++ = (*src_data >> 4);
209 			}else
210 			{	*dst_data++ = *src_data & 0x0F;
211 				src_data++;
212 			}
213 			lower ^= 0x01;
214 #endif
215 		}
216    		dst_data = (CARD32*)( (char*)dst_data + pad );
217    	}
218 }
219 
CopyImageFromData16(dst_data,src_data,width,height,pad)220 static void	CopyImageFromData16( dst_data, src_data, width, height, pad )
221 	CARD16	*dst_data;
222 	unsigned char	*src_data;
223 	int	width;
224 	int	height;
225 	int	pad;
226 {
227    	int		x, y;
228 	Bool	lower = 0;
229 
230    	for( y=0 ; y<height ; y++ )
231 	{	for( x=0; x<width; x++ )
232 		{
233 #if 0
234 			*dst_data++ = *src_data++; /* DEBUG * 256�ǡ������� */
235 #else
236 			if( lower == 0 )
237 			{	*dst_data++ = (*src_data >> 4);
238 			}else
239 			{	*dst_data++ = *src_data & 0x0F;
240 				src_data++;
241 			}
242 			lower ^= 0x01;
243 #endif
244 		}
245    		dst_data = (CARD16*)( (char*)dst_data + pad );
246    	}
247 }
248 
CopyImageFromData8(dst_data,src_data,width,height,pad)249 static void	CopyImageFromData8( dst_data, src_data, width, height, pad )
250 	CARD8	*dst_data;
251 	unsigned char	*src_data;
252 	int	width;
253 	int	height;
254 	int	pad;
255 {
256    	int		x, y;
257 	Bool	lower = 0;
258 
259    	for( y=0 ; y<height ; y++ )
260 	{	for( x=0; x<width; x++ )
261 		{
262 #if 0
263 			*dst_data++ = *src_data++; /* DEBUG * 256�ǡ������� */
264 #else
265 			if( lower == 0 )
266 			{	*dst_data++ = (*src_data >> 4);
267 			}else
268 			{	*dst_data++ = *src_data & 0x0F;
269 				src_data++;
270 			}
271 			lower ^= 0x01;
272 #endif
273 		}
274    		dst_data = (char*)dst_data + pad ;
275    	}
276 }
277 
278 /******** PalettePix ********
279 * �ԥ�����ǡ����� XAllocColor �����ԥ������ֹ�˽�������
280 * 8, 16, 32bit �Σ�����
281 */
PalettePix32(dst_data,color_tbl,width,height,pad)282 static void	PalettePix32( dst_data, color_tbl, width, height, pad )
283 	CARD32	*dst_data;
284     XColor	*color_tbl;
285 	int	width;
286 	int	height;
287 	int	pad;
288 {
289    	int		x, y;
290 
291    	for (y = 0; y < height; y++)
292 	{	for (x = 0; x < width; x++)
293 		{	*dst_data = color_tbl[ (CARD8)*dst_data ].pixel;
294 			dst_data++;
295 		}
296     	dst_data = (CARD32*)( (char*)dst_data + pad );
297 	}
298 }
299 
PalettePix16(dst_data,color_tbl,width,height,pad)300 static void	PalettePix16( dst_data, color_tbl, width, height, pad )
301 	CARD16	*dst_data;
302     XColor	*color_tbl;
303 	int	width;
304 	int	height;
305 	int	pad;
306 {
307    	int			x, y;
308 
309    	for (y = 0; y < height; y++)
310 	{	for (x = 0; x < width; x++)
311 		{	*dst_data = color_tbl[ (CARD8)*dst_data ].pixel;
312 			dst_data++;
313 		}
314     	dst_data = (CARD16*)( (char*)dst_data + pad );
315 	}
316 }
317 
PalettePix8(dst_data,color_tbl,width,height,pad)318 static void	PalettePix8( dst_data, color_tbl, width, height, pad )
319 	CARD8 	*dst_data;
320     XColor	*color_tbl;
321 	int	width;
322 	int	height;
323 	int	pad;
324 {
325    	int			x, y;
326 
327    	for (y = 0; y < height; y++)
328 	{	for (x = 0; x < width; x++)
329 		{	*dst_data = color_tbl[ (CARD8)*dst_data ].pixel;
330 			dst_data++;
331 		}
332     	dst_data = (char*)dst_data + pad ;
333 	}
334 }
335 
336 /******** PickNearColor ********
337 * ���顼�ޥåפˤ���Ǥ�ᤤ��������
338 * ��(���顼����)�γ��ݤ˼��Ԥ������ν���
339 */
PickNearColor(palette,color_return)340 static int	PickNearColor( palette, color_return )
341 	unsigned char	*palette;
342 	XColor	*color_return;
343 {
344 	XColor	color_tbl[ 256 ];
345 	int		n_cmap_color;
346 	long	dist, nearest;
347 	int		nearest_index;
348 	int		red_dist, green_dist, blue_dist;
349 	int		i;
350 
351 	/* ���ԤΥ��顼�ޥå׾�ο�����Ф� */
352 	{	int dCells = DisplayCells( Disp, DefaultScreen(Disp) );
353 		n_cmap_color = (dCells < 256) ? dCells : 256 ;
354 	}
355 	for( i = 0; i < n_cmap_color; i++ )
356 	{	color_tbl[i].pixel = (unsigned long) i;
357 	}
358 
359 	XQueryColors( Disp, MyColorMap, color_tbl, n_cmap_color );
360 
361    	/* ��ΥŪ�˺Ǥ�ᤤ���Υԥ������ͤ��� */
362    	nearest = 0xFF * 0xFF * 3 + 1;
363    	nearest_index = -1;
364 
365    	for( i=0; i< n_cmap_color; i++ )
366 	{
367 		red_dist   = palette[ 0 ] - (color_tbl[i].red   >> 8);
368 		green_dist = palette[ 1 ] - (color_tbl[i].green >> 8);
369 		blue_dist  = palette[ 2 ] - (color_tbl[i].blue  >> 8);
370 
371 		dist = (red_dist * red_dist) +
372 					(green_dist * green_dist) +
373 					(blue_dist * blue_dist);
374 
375 		if( dist < nearest )
376 		{	nearest = dist;
377     		nearest_index = i;
378 		}
379    	}
380 
381    	if( nearest_index < 0 )
382 	{	return EXIT_FAILURE ;
383    	}
384 
385    	color_return->pixel = color_tbl[ nearest_index ].pixel;
386    	color_return->red   = color_tbl[ nearest_index ].red;
387    	color_return->green = color_tbl[ nearest_index ].green;
388    	color_return->blue  = color_tbl[ nearest_index ].blue;
389 
390 	return EXIT_SUCCESS ;
391 }
392 
393 /******** CreateMyCursor *******
394 * �ӥåȥޥåץǡ������饫���������������
395 * (�������ϣ�������������)
396 */
CreateMyCursor(win,f_bits,b_bits)397 Cursor	CreateMyCursor( win, f_bits, b_bits )
398 	Window	win;
399 	unsigned char	*f_bits;
400 	unsigned char	*b_bits;
401 {
402 	Cursor	cur;
403 	Pixmap	front;
404 	Pixmap	mask;
405 	XColor	c1, c2, cc;
406 #define	CURSOR_SIZE	32
407 
408 	XAllocNamedColor( Disp, MyColorMap, "black", &c1, &cc );
409 	XAllocNamedColor( Disp, MyColorMap, "white", &c2, &cc );
410 
411 	front = XCreateBitmapFromData( Disp, win,
412 					f_bits, CURSOR_SIZE, CURSOR_SIZE );
413 	mask = XCreateBitmapFromData( Disp, win,
414 					b_bits, CURSOR_SIZE, CURSOR_SIZE );
415 
416 	cur = XCreatePixmapCursor( Disp, front, mask, &c1, &c2, 0, 0 );
417 
418 	XFreePixmap( Disp, front );
419 	XFreePixmap( Disp, mask );
420 
421 	return cur;
422 }
423 
424 /******** End of File ********/
425