1 #   include	"bitmapConfig.h"
2 
3 #   include	<stdio.h>
4 #   include	<stdlib.h>
5 #   include	<string.h>
6 
7 #   include	<ctype.h>
8 
9 #   include	<appDebugon.h>
10 
11 #   include	"bmintern.h"
12 
13 #   if USE_LIBXPM
14 
15 #   include	<X11/xpm.h>
16 
17 /************************************************************************/
18 /*									*/
19 /*  Translate an XPM color to BMcoRGB8PALETTE format; update mapping.	*/
20 /*									*/
21 /*  1)  Translate transparent to white.					*/
22 /*									*/
23 /************************************************************************/
24 
bmXpmPaletteColor(const char * c_color,int * pTransparent,RGB8Color * rgb8)25 static int bmXpmPaletteColor(	const char *	c_color,
26 				int *		pTransparent,
27 				RGB8Color *	rgb8 )
28     {
29     char	ch;
30     unsigned	r, g, b;
31 
32     FILE *	f;
33 
34     /*  1  */
35     if  ( ! c_color				||
36 	  ! strcmp( c_color, "None" )		||
37 	  ! strcmp( c_color, "none" )		||
38 	  ! strcmp( c_color, "Transparent" )	||
39 	  ! strcmp( c_color, "transparent" )	)
40 	{
41 	*pTransparent= 1;
42 	rgb8->rgb8Red= 255;
43 	rgb8->rgb8Green= 255;
44 	rgb8->rgb8Blue= 255;
45 	rgb8->rgb8Alpha= 0;
46 
47 	return 0;
48 	}
49 
50     if  ( sscanf( c_color, "#%4x%4x%4x%c", &r, &g, &b, &ch ) == 3 )
51 	{
52 	*pTransparent= 0;
53 	rgb8->rgb8Red= r/ 256;
54 	rgb8->rgb8Green= g/ 256;
55 	rgb8->rgb8Blue= b/ 256;
56 	rgb8->rgb8Alpha= 255;
57 
58 	return 0;
59 	}
60 
61     if  ( sscanf( c_color, "#%2x%2x%2x%c", &r, &g, &b, &ch ) == 3 )
62 	{
63 	*pTransparent= 0;
64 	rgb8->rgb8Red= r;
65 	rgb8->rgb8Green= g;
66 	rgb8->rgb8Blue= b;
67 	rgb8->rgb8Alpha= 255;
68 
69 	return 0;
70 	}
71 
72     if  ( sscanf( c_color, "#%1x%1x%1x%c", &r, &g, &b, &ch ) == 3 )
73 	{
74 	*pTransparent= 0;
75 	rgb8->rgb8Red= r* 16;
76 	rgb8->rgb8Green= g* 16;
77 	rgb8->rgb8Blue= b* 16;
78 	rgb8->rgb8Alpha= 255;
79 
80 	return 0;
81 	}
82 
83     f= fopen( "/usr/lib/X11/rgb.txt", "r" );
84     if  ( f )
85 	{
86 	char	line[100];
87 	char	color[100];
88 
89 	while( fgets( line, 100, f ) )
90 	    {
91 	    if  ( sscanf( line, "%u %u %u %s", &r, &g, &b, color ) == 4 )
92 		{
93 		const char *	s1= color;
94 		const char *	s2= c_color;
95 
96 		for (;;)
97 		    {
98 		    char	c1;
99 		    char	c2;
100 
101 		    while( *s1 == ' ' )	{ s1++;	}
102 		    while( *s2 == ' ' )	{ s2++;	}
103 
104 		    c1= *s1; c2= *s2;
105 
106 		    if  ( ! c1 && ! c2 )
107 			{
108 			*pTransparent= 0;
109 			rgb8->rgb8Red= r;
110 			rgb8->rgb8Green= g;
111 			rgb8->rgb8Blue= b;
112 			rgb8->rgb8Alpha= 255;
113 
114 			fclose( f ); return 0;
115 			}
116 
117 		    if  ( isupper( c1 ) )	{ c1= tolower( c1 );	}
118 		    if  ( isupper( c2 ) )	{ c2= tolower( c2 );	}
119 
120 		    if  ( c1 != c2 )
121 			{ break;	}
122 
123 		    s1++; s2++;
124 		    }
125 		}
126 	    }
127 
128 	fclose( f );
129 	}
130 
131     SDEB(c_color); return -1;
132     }
133 
134 /************************************************************************/
135 /*									*/
136 /*  Read an XPM file.							*/
137 /*									*/
138 /************************************************************************/
139 
bmReadXpmFile(const MemoryBuffer * filename,unsigned char ** pBuffer,BitmapDescription * bd,int * pPrivateFormat)140 int bmReadXpmFile(	const MemoryBuffer *	filename,
141 			unsigned char **	pBuffer,
142 			BitmapDescription *	bd,
143 			int *			pPrivateFormat )
144     {
145     int			rval= 0;
146 
147     int			ret;
148     unsigned int	row;
149     unsigned int	col;
150     unsigned char *	buffer= (unsigned char *)0;
151 
152     XpmImage		image;
153 
154     int			bitsPerPixel= 8;
155 
156     const char *	fn= utilMemoryBufferGetString( filename );
157 
158     memset( &image, 0, sizeof(image) );
159 
160     ret= XpmReadFileToXpmImage( (char *)fn, &image, (XpmInfo *)0 );
161     if  ( ret != XpmSuccess )
162 	{ SSDEB(fn,XpmGetErrorString(ret)); rval= -1; goto ready;	}
163 
164     if  ( image.ncolors > 256* 256 )
165 	{ LDEB(image.ncolors); rval= -1; goto ready;	}
166 
167     bd->bdPixelsWide= image.width;
168     bd->bdPixelsHigh= image.height;
169 
170     if  ( image.ncolors > 256 && image.ncolors < 256* 256 )
171 	{ bitsPerPixel= 16;	}
172 
173     switch( bitsPerPixel )
174 	{
175 	case 8:
176 	case 16:
177 	    bd->bdBitsPerSample= 8;
178 	    bd->bdSamplesPerPixel= 3;
179 	    bd->bdBitsPerPixel= bitsPerPixel;
180 	    bd->bdBytesPerRow= ( bd->bdBitsPerPixel+ 7 )/8* bd->bdPixelsWide;
181 	    bd->bdBufferLength= bd->bdPixelsHigh* bd->bdBytesPerRow;
182 	    bd->bdColorEncoding= BMcoRGB8PALETTE;
183 	    bd->bdHasAlpha= 0;
184 	    if  ( utilPaletteSetCount( &(bd->bdPalette), image.ncolors ) )
185 		{ LDEB(image.ncolors); rval= -1; goto ready; }
186 
187 	    for ( col= 0; col < image.ncolors; col++ )
188 		{
189 		int		transparent= 0;
190 
191 		if  ( bmXpmPaletteColor( image.colorTable[col].c_color,
192 				&transparent, bd->bdPalette.cpColors+ col ) )
193 		    {
194 		    SSDEB(image.colorTable[col].string,
195 					    image.colorTable[col].c_color);
196 		    rval= -1; goto ready;
197 		    }
198 
199 		if  ( transparent && ! bd->bdHasAlpha )
200 		    {
201 		    bd->bdHasAlpha= 1;
202 		    bd->bdBitsPerPixel= 2* bitsPerPixel;
203 		    }
204 		}
205 
206 	    if  ( bmCalculateSizes( bd ) )
207 		{
208 		LDEB(bd->bdPalette.cpColorCount);
209 		rval= -1; goto ready;
210 		}
211 
212 	    buffer= (unsigned char *)malloc( bd->bdBufferLength );
213 	    if  ( ! buffer )
214 		{
215 		LXDEB(bd->bdBufferLength,buffer);
216 		rval= -1; goto ready;
217 		}
218 	    break;
219 
220 	default:
221 	    LDEB(bitsPerPixel);
222 	    LLDEB(image.cpp,image.ncolors);
223 	    rval= -1; goto ready;
224 	}
225 
226     bd->bdXResolution= bd->bdYResolution= 1;
227     bd->bdUnit= BMunPIXEL;
228 
229     switch( bd->bdBitsPerPixel )
230 	{
231 	case 8:
232 	    if  ( ! bd->bdHasAlpha )
233 		{
234 		unsigned int *	from= image.data;
235 
236 		for ( row= 0; row < bd->bdPixelsHigh; row++ )
237 		    {
238 		    unsigned char *	to= buffer+ row* bd->bdBytesPerRow;
239 
240 		    for ( col= 0; col < bd->bdPixelsWide; to++, from++, col++ )
241 			{ *to= *from; }
242 		    }
243 		}
244 	    else{
245 		LDEB(bd->bdHasAlpha);
246 		rval= -1; goto ready;
247 		}
248 
249 	    break;
250 
251 	case 16:
252 	    if  ( ! bd->bdHasAlpha )
253 		{
254 		const unsigned int *	from;
255 		BmUint16 *		to;
256 
257 		from= image.data;
258 		to= (BmUint16 *)buffer;
259 
260 		for ( col= 0; col < bd->bdBufferLength; col++ )
261 		    { *(to++)= *(from++);	}
262 		}
263 	    else{
264 		const unsigned int *	from;
265 		unsigned char *		to;
266 
267 		from= image.data;
268 		to= buffer;
269 
270 		for ( col= 0; col < bd->bdBufferLength; col += 2 )
271 		    {
272 		    int	c= *(from++);
273 
274 		    *(to++)= c;
275 		    *(to++)= bd->bdPalette.cpColors[c].rgb8Alpha;
276 		    }
277 		}
278 	    break;
279 
280 	case 32:
281 	    if  ( ! bd->bdHasAlpha )
282 		{ LDEB(bd->bdHasAlpha); rval= -1; goto ready; }
283 	    else{
284 		const unsigned int *	from;
285 		unsigned char *		to;
286 		ColorPalette * 		cp= &(bd->bdPalette);
287 
288 		/* expand palette and alpha */
289 		from= image.data;
290 		to= buffer;
291 
292 		for ( col= 0; col < bd->bdBufferLength; col += 4 )
293 		    {
294 		    int	c= *(from++);
295 
296 		    *(to++)= cp->cpColors[c].rgb8Red;
297 		    *(to++)= cp->cpColors[c].rgb8Green;
298 		    *(to++)= cp->cpColors[c].rgb8Blue;
299 		    *(to++)= cp->cpColors[c].rgb8Alpha;
300 		    }
301 
302 		utilPaletteSetCount( cp, 0 );
303 
304 		bd->bdColorEncoding= BMcoRGB;
305 		bd->bdHasAlpha= 1;
306 		bd->bdBitsPerSample= 8;
307 		bd->bdSamplesPerPixel= 4;
308 		bd->bdBitsPerPixel= 32;
309 		}
310 	    break;
311 
312 	default:
313 	    LLDEB(bd->bdBitsPerPixel,image.cpp); rval= -1; goto ready;
314 	}
315 
316     *pBuffer= buffer; buffer= (unsigned char *)0;
317     *pPrivateFormat= 0;
318 
319   ready:
320 
321     XpmFreeXpmImage( &image );
322 
323     if  ( buffer )
324 	{ free( buffer );	}
325 
326     return rval;
327     }
328 
329 /************************************************************************/
330 /*									*/
331 /*  Write an XPM file.							*/
332 /*									*/
333 /************************************************************************/
334 
bmXpmClean(XpmImage * xpmi)335 static void bmXpmClean(		XpmImage *	xpmi )
336     {
337     unsigned		col;
338 
339     if  ( xpmi->data )
340 	{ free( xpmi->data );	}
341 
342     for ( col= 0; col < xpmi->ncolors; col++ )
343 	{
344 	if  ( xpmi->colorTable[col].string )
345 	    { free( xpmi->colorTable[col].string );	}
346 	if  ( xpmi->colorTable[col].symbolic )
347 	    { free( xpmi->colorTable[col].symbolic );	}
348 	if  ( xpmi->colorTable[col].m_color )
349 	    { free( xpmi->colorTable[col].m_color );	}
350 	if  ( xpmi->colorTable[col].g4_color )
351 	    { free( xpmi->colorTable[col].g4_color );	}
352 	if  ( xpmi->colorTable[col].g_color )
353 	    { free( xpmi->colorTable[col].g_color );	}
354 	if  ( xpmi->colorTable[col].c_color )
355 	    { free( xpmi->colorTable[col].c_color );	}
356 	}
357 
358     if  ( xpmi->colorTable )
359 	{ free( xpmi->colorTable );	}
360 
361     return;
362     }
363 
bmXpmAllocColors(XpmImage * xpmi,int ncolors)364 static int bmXpmAllocColors(	XpmImage *	xpmi,
365 				int		ncolors )
366     {
367     int		col;
368 
369     xpmi->colorTable= (XpmColor *)malloc( xpmi->ncolors* sizeof(XpmColor) );
370     if  ( ! xpmi->colorTable )
371 	{ LXDEB(ncolors,xpmi->colorTable); return -1;	}
372 
373     for ( col= 0; col < ncolors; col++ )
374 	{
375 	xpmi->colorTable[col].string= (char *)0;
376 	xpmi->colorTable[col].symbolic= (char *)0;
377 	xpmi->colorTable[col].m_color= (char *)0;
378 	xpmi->colorTable[col].g4_color= (char *)0;
379 	xpmi->colorTable[col].g_color= (char *)0;
380 	xpmi->colorTable[col].c_color= (char *)0;
381 	}
382 
383     xpmi->ncolors= ncolors;
384 
385     return 0;
386     }
387 
bmXpmSetColor(XpmColor * xpmc,int charactersPerPixel,char * bytes,const RGB8Color * rgb8)388 static int bmXpmSetColor(	XpmColor *		xpmc,
389 				int			charactersPerPixel,
390 				char *			bytes,
391 				const RGB8Color *	rgb8 )
392     {
393     if  ( rgb8->rgb8Alpha >= 128 )
394 	{
395 	xpmc->c_color= (char *)malloc( 14 );
396 	if  ( ! xpmc->c_color )
397 	    { XDEB(xpmc->c_color); return -1;	}
398 
399 	sprintf( xpmc->c_color, "#%04x%04x%04x",
400 				    257* rgb8->rgb8Red,
401 				    257* rgb8->rgb8Green,
402 				    257* rgb8->rgb8Blue );
403 	}
404     else{
405 	xpmc->c_color= (char *)0;
406 
407 	/*strcpy( xpmc->xx_color, "None" );*/
408 	}
409 
410     xpmc->string= (char *)malloc( charactersPerPixel+ 1 );
411     if  ( ! xpmc->string )
412 	{ XDEB(xpmc->string); return -1;	}
413 
414     memcpy( xpmc->string, bytes, charactersPerPixel );
415     xpmc->string[charactersPerPixel]= '\0';
416 
417     return 0;
418     }
419 
420 /************************************************************************/
421 /*									*/
422 /*  Characters approximately in gray scale order.			*/
423 /*									*/
424 /************************************************************************/
425 
426 static char	BMXPMBytes[]=
427     " "
428     "."
429     "-,`'"
430     "_~:;"
431     "*^"
432     "!=+<>?1ijl|/"
433     "(){}"
434     "[]7"
435     "35"
436     "IJLT"
437     "CF"
438     "fcrst"
439     "Eea2SZ$G"
440     "69"
441     "K4AP"
442     "ovxyz"
443     "nuw"
444     "UYVXOkhQ"
445     "Bmg8D"
446     "bdpq"
447     "%&0N"
448     "@"
449     "RWHM"
450     "#"
451     ;
452 
453 const int BMXPMBase= sizeof(BMXPMBytes)- 1;
454 
455 /************************************************************************/
456 /*									*/
457 /*  Build the palette of the raster image.				*/
458 /*									*/
459 /************************************************************************/
460 
bmXpmFillPalette(XpmImage * image,const BitmapDescription * bd,const RGB8Color * palette)461 static int bmXpmFillPalette(	XpmImage *			image,
462 				const BitmapDescription *	bd,
463 				const RGB8Color *		palette )
464     {
465     int		col;
466     int		charactersPerPixel= 1;
467     int		block= BMXPMBase;
468 
469     while( block < image->ncolors )
470 	{
471 	charactersPerPixel++;
472 	block *= BMXPMBase;
473 	}
474 
475     image->cpp= charactersPerPixel;
476 
477     if  ( bmXpmAllocColors( image, image->ncolors ) )
478 	{ LDEB(image->ncolors); return -1; }
479 
480     for ( col= 0; col < image->ncolors; col++ )
481 	{
482 	int	b;
483 	int	c= ( ( block- 1 )* col )/ ( image->ncolors-1 );
484 	int	idx= 0;
485 	int	blk= block/ BMXPMBase;
486 	char	scratch[20];
487 
488 	for ( b= 0; b < charactersPerPixel; b++ )
489 	    {
490 	    idx= c/ blk;
491 
492 	    if  ( idx < 0 || idx >= BMXPMBase )
493 		{ LLDEB(idx,BMXPMBase); return -1;	}
494 
495 	    scratch[b]= BMXPMBytes[idx];
496 
497 	    c -= blk* idx;
498 	    blk /= BMXPMBase;
499 	    }
500 
501 	scratch[b]= '\0';
502 
503 	if  ( bmXpmSetColor( image->colorTable+ col, charactersPerPixel,
504 						scratch, palette+ col ) )
505 	    { XDEB(image->colorTable[col].c_color); return -1;	}
506 	}
507 
508     return 0;
509     }
510 
511 /************************************************************************/
512 /*									*/
513 /*  Emot the raster image in XPM format.				*/
514 /*									*/
515 /************************************************************************/
516 
bmWriteXpmFile(const MemoryBuffer * filename,const unsigned char * buffer,const BitmapDescription * bd,int privateFormat)517 int bmWriteXpmFile(	const MemoryBuffer *		filename,
518 			const unsigned char *		buffer,
519 			const BitmapDescription *	bd,
520 			int				privateFormat )
521     {
522     int				rval= 0;
523 
524     int				row;
525     XpmImage			image;
526 
527     unsigned int *		to;
528     int				transparentColor= -1;
529 
530     const char *		fn= utilMemoryBufferGetString( filename );
531 
532     const ColorPalette * 	cp= &(bd->bdPalette);
533 
534     image.width= bd->bdPixelsWide;
535     image.height= bd->bdPixelsHigh;
536     image.cpp= 1;
537     image.ncolors= 0;
538     image.colorTable= (XpmColor *)0;
539     image.data= (unsigned int *)0;
540 
541     switch( bd->bdColorEncoding )
542 	{
543 	RGB8Color	BWPalette[257];
544 	int		colorCount;
545 
546 	case BMcoRGB8PALETTE:
547 	    image.ncolors= cp->cpColorCount;
548 	    if  ( bmXpmFillPalette( &image, bd, cp->cpColors ) )
549 		{ LDEB(cp->cpColorCount); bmXpmClean( &image ); rval= -1; goto ready; }
550 
551 	    break;
552 
553 	case BMcoBLACKWHITE:
554 	case BMcoWHITEBLACK:
555 	    if  ( bd->bdBitsPerSample > 8 )
556 		{ LDEB(bd->bdBitsPerSample); rval= -1; goto ready;	}
557 
558 	    if  ( bmMakeGrayPalette( bd, &colorCount,
559 					&transparentColor, BWPalette, 257 ) )
560 		{ LDEB(bd->bdBitsPerPixel); rval= -1; goto ready;	}
561 	    image.ncolors= colorCount;
562 
563 	    if  ( bmXpmFillPalette( &image, bd, BWPalette ) )
564 		{ LDEB(colorCount); bmXpmClean( &image ); rval= -1; goto ready; }
565 
566 	    break;
567 
568 	default:
569 	    LDEB(bd->bdColorEncoding); bmXpmClean( &image ); rval= -1; goto ready;
570 	}
571 
572     {
573     int size= ( image.width* image.height+ 7 )* sizeof( unsigned int );
574     image.data= (unsigned int *)malloc( size );
575     if  ( ! image.data )
576 	{ LXDEB(size,image.data); rval= -1; goto ready;	}
577     }
578 
579     to= image.data;
580     for ( row= 0; row < bd->bdPixelsHigh; row++ )
581 	{
582 	const unsigned char *	from= buffer+ row* bd->bdBytesPerRow;
583 
584 	if  ( bmInflateToInt( to, from, bd, transparentColor, bd->bdHasAlpha ) )
585 	    { LDEB(bd->bdHasAlpha); rval= -1; goto ready;	}
586 
587 	to += image.width;
588 	}
589 
590     {
591     int ret= XpmWriteFileFromXpmImage( (char *)fn, &image, (XpmInfo *)0 );
592     if  ( ret != XpmSuccess )
593 	{ SSDEB(fn,XpmGetErrorString(ret)); rval= -1; goto ready;	}
594     }
595 
596   ready:
597 
598     bmXpmClean( &image );
599 
600     return rval;
601     }
602 
bmCanWriteXpmFile(const BitmapDescription * bd,int privateFormat)603 int bmCanWriteXpmFile(	const BitmapDescription *	bd,
604 			int				privateFormat )
605     {
606     if  ( bd->bdColorEncoding == BMcoBLACKWHITE	||
607 	  bd->bdColorEncoding == BMcoWHITEBLACK	)
608 	{
609 	if  ( bd->bdBitsPerSample <= 8 )
610 	    { return 0; }
611 	}
612 
613     if  ( bd->bdColorEncoding != BMcoRGB8PALETTE )
614 	{ return -1;	}
615 
616     return 0;
617     }
618 
619 #   endif
620