IXPM.c
资源名称:ilib [点击查看]
上传用户:changbiao
上传日期:2007-01-13
资源大小:141k
文件大小:9k
源码类别:

图片显示

开发平台:

C/C++

  1. /*
  2.  * IXPM.c
  3.  *
  4.  * Image library
  5.  *
  6.  * Description:
  7.  * Read and write XPM files.
  8.  * The reading of XPM files is not all that robust.  It handles
  9.  * XPMs generated from xv and The GIMP, but it does not handle
  10.  * the use of X11 rgb names (like "grey2") in the XPM file.
  11.  *
  12.  * These routines are terribly slow, but hey, if you're using XPM
  13.  * you're obviously not that concerned about speed ;-)
  14.  *
  15.  * History:
  16.  * 27-Aug-99 Craig Knudsen cknudsen@radix.net
  17.  * Updated to read XPM and also handle transparency
  18.  * when writing.
  19.  * 20-May-96 Craig Knudsen cknudsen@radix.net
  20.  * Created
  21.  *
  22.  ****************************************************************************/
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <memory.h>
  27. #include <string.h>
  28. #include "Ilib.h"
  29. #include "IlibP.h"
  30. #define colors_match(color,r,g,b) 
  31.  (color->red == red && color->green == green && color->blue == blue )
  32. #define MAX_COLORMAP_SIZE (256*256)
  33. IError _IWriteXPM ( fp, image, options )
  34. FILE *fp;
  35. IImageP *image;
  36. IOptions options;
  37. {
  38.   int r, c;
  39.   unsigned char *ptr;
  40.   unsigned int red, green, blue;
  41.   IColorP *colormap[MAX_COLORMAP_SIZE];
  42.   int num_colors = 0;
  43.   int loop, loop2;
  44.   int offset;
  45.   unsigned short *data;
  46.   int color_found, chars_per_pixel;
  47.   static char *xpm_chars = 
  48.     ".#abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  49.   char colorstr[20];
  50.   data = (unsigned short *) calloc ( image->width * image->height, 
  51.     sizeof ( unsigned short ) );
  52.   memset ( data, '', image->width * image->height * sizeof ( short ) );
  53.   for ( r = 0; r < image->height; r++ ) {
  54.     for ( c = 0; c < image->width; c++ ) {
  55.       offset = ( r * image->width ) + c;
  56.       if ( image->greyscale ) {
  57.         ptr = image->data + ( r * image->width ) + c;
  58.         red = green = blue = (unsigned int) *ptr;
  59.       }
  60.       else {
  61.         ptr = image->data + ( r * image->width * 3 ) + ( c * 3 );
  62.         red = (unsigned int) *ptr;
  63.         green = (unsigned int) *( ptr + 1 );
  64.         blue = (unsigned int) *( ptr + 2 );
  65.       }
  66.       color_found = 0;
  67.       for ( loop = 0; loop < num_colors; loop++ ) {
  68.         if ( colors_match ( colormap[loop], red, green, blue ) ) {
  69.           data[offset] = loop;
  70.           color_found = 1;
  71.           break;
  72.         }
  73.       }
  74.       if ( ! color_found ) {
  75.         if ( num_colors < MAX_COLORMAP_SIZE ) {
  76.           colormap[num_colors] = (IColorP *) malloc ( sizeof ( IColorP ) );
  77.           colormap[num_colors]->red = red;
  78.           colormap[num_colors]->green = green;
  79.           colormap[num_colors]->blue = blue;
  80.           data[offset] = num_colors;
  81.           num_colors++;
  82.         }
  83.       }
  84.     }
  85.   }
  86.   fprintf ( fp, "/* XPM */n" );
  87.   if ( image->comments )
  88.     fprintf ( fp, "/* %s */n", image->comments );
  89.   fprintf ( fp, "static char *image[] = {n" );
  90.   fprintf ( fp, "/* width height num_colors chars_per_pixel */n" );
  91.   if ( num_colors > strlen ( xpm_chars ) )
  92.     chars_per_pixel = 2;
  93.   else
  94.     chars_per_pixel = 1;
  95.   fprintf ( fp, ""%d %d %d %d",n", image->width, image->height,
  96.     num_colors, chars_per_pixel );
  97.   fprintf ( fp, "/* colors */n" );
  98.   for ( loop = 0; loop < num_colors; loop++ ) {
  99.     if ( image->transparent != NULL &&
  100.       ( image->transparent->red == colormap[loop]->red &&
  101.       image->transparent->green == colormap[loop]->green &&
  102.       image->transparent->blue == colormap[loop]->blue ) )
  103.       strcpy ( colorstr, "None" );
  104.     else
  105.       sprintf ( colorstr, "#%02X%02X%02X", colormap[loop]->red,
  106.         colormap[loop]->green, colormap[loop]->blue );
  107.     switch ( chars_per_pixel ) {
  108.       case 1:
  109.         fprintf ( fp, ""%c c %s",n", xpm_chars[loop], colorstr );
  110.         break;
  111.       case 2:
  112.         fprintf ( fp, ""%c%c c %s",n",
  113.           xpm_chars[loop/strlen(xpm_chars)],
  114.           xpm_chars[loop%strlen(xpm_chars)], colorstr );
  115.         break;
  116.     }
  117.   }
  118.   fprintf ( fp, "/* pixels */n" );
  119.   for ( loop = 0; loop < image->height; loop++ ) {
  120.     fprintf ( fp, """ );
  121.     for ( loop2 = 0; loop2 < image->width; loop2++ ) {
  122.       switch ( chars_per_pixel ) {
  123.         case 1:
  124.           fprintf ( fp, "%c", xpm_chars[data[loop*image->width+loop2]] );
  125.           break;
  126.         case 2:
  127.           fprintf ( fp, "%c%c",
  128.             xpm_chars[data[loop*image->width+loop2]/strlen(xpm_chars)],
  129.             xpm_chars[data[loop*image->width+loop2]%strlen(xpm_chars)] );
  130.           break;
  131.       }
  132.     }
  133.     fprintf ( fp, "",n" );
  134.   }
  135.   fprintf ( fp, "};n" );
  136.   /* free up allocated resources */
  137.   free ( data );
  138.   for ( loop = 0; loop < num_colors; loop++ ) {
  139.     free ( colormap[loop] );
  140.   }
  141.   return ( INoError );
  142. }
  143. static unsigned char hextochar ( hex )
  144. char hex;
  145. {
  146.   switch ( toupper ( hex ) ) {
  147.     case '0': return 0;
  148.     case '1': return 1;
  149.     case '2': return 2;
  150.     case '3': return 3;
  151.     case '4': return 4;
  152.     case '5': return 5;
  153.     case '6': return 6;
  154.     case '7': return 7;
  155.     case '8': return 8;
  156.     case '9': return 9;
  157.     case 'A': return 10;
  158.     case 'B': return 11;
  159.     case 'C': return 12;
  160.     case 'D': return 13;
  161.     case 'E': return 14;
  162.     case 'F': return 15;
  163.   }
  164.   return 0;
  165. }
  166. static int parse_color ( str, r, g, b, is_transparent )
  167. char *str;
  168. unsigned char *r, *g, *b;
  169. int *is_transparent;
  170. {
  171.   char *ptr;
  172.   int w;
  173.   for ( ptr = str; *ptr != ''; ptr++ )
  174.     *ptr = tolower ( *ptr );
  175.   *is_transparent = 0;
  176.   if ( *str == '#' ) {
  177.     ptr = str + 1;
  178.     w = strlen ( str ) / 3;
  179.     *r = hextochar ( ptr[0] ) * 16 + hextochar ( ptr[1] );
  180.     ptr += w;
  181.     *g = hextochar ( ptr[0] ) * 16 + hextochar ( ptr[1] );
  182.     ptr += w;
  183.     *b = hextochar ( ptr[0] ) * 16 + hextochar ( ptr[1] );
  184.     return 0;
  185.   } else if ( strcmp ( str, "none" ) == 0 ||
  186.     strcmp ( str, "transparent" ) == 0 ) {
  187.     *r = *g = *b = 254; /* don't make white since it might already exist */
  188.     *is_transparent = 1;
  189.     return 0;
  190.   } else {
  191.     /* name like "blue" */
  192.     return 1;
  193.   }
  194. }
  195. typedef struct {
  196.   char *abbrev;
  197.   unsigned char r;
  198.   unsigned char g;
  199.   unsigned char b;
  200.   int transparent;
  201. } xpmcolor;
  202. IError _IReadXPM ( fp, options, image_return )
  203. FILE *fp;
  204. IOptions options;
  205. IImageP **image_return;
  206. {
  207.   IImageP *image = NULL;
  208.   char line[1024], *ptr, *r, *g, *b, *cur;
  209.   xpmcolor *colors = NULL;
  210.   int w, h, num_colors, colorw, loop, loop2, loop3;
  211.   int found;
  212.   IColor t;
  213.   /* look for first line that starts with " */
  214.   while ( fgets ( line, 1024, fp ) ) {
  215.     if ( line[0] == '"' )
  216.       break;
  217.   }
  218.   if ( line[0] != '"' )
  219.     return IInvalidFormat;
  220.   ptr = strtok ( line + 1, " " );
  221.   if ( ! ptr )
  222.     return IInvalidFormat;
  223.   w = atoi ( ptr );
  224.   ptr = strtok ( NULL, " " );
  225.   if ( ! ptr )
  226.     return IInvalidFormat;
  227.   h = atoi ( ptr );
  228.   ptr = strtok ( NULL, " " );
  229.   if ( ! ptr )
  230.     return IInvalidFormat;
  231.   num_colors = atoi ( ptr );
  232.   ptr = strtok ( NULL, " " );
  233.   if ( ! ptr )
  234.     return IInvalidFormat;
  235.   colorw = atoi ( ptr );
  236.   colors = (xpmcolor *) malloc ( sizeof ( xpmcolor ) * num_colors );
  237.   for ( loop = 0; loop < num_colors; loop++ ) {
  238.     while ( 1 ) {
  239.       if ( ! fgets ( line, 1024, fp ) )
  240.         return IInvalidFormat; /* small memory leak */
  241.       if ( line[0] == '"' )
  242.         break;
  243.     }
  244.     colors[loop].abbrev = (char *) malloc ( colorw + 1 );
  245.     strncpy ( colors[loop].abbrev, line + 1, colorw );
  246.     colors[loop].abbrev[colorw] = '';
  247.     for ( ptr = line + 1 + colorw; *ptr != 'c' && *ptr != ''; ptr++ ) ;
  248.     if ( *ptr != 'c' )
  249.       return IInvalidFormat; /* small memory leak */
  250.     do {
  251.       ptr++;
  252.     } while ( *ptr == ' ' );
  253.     strtok ( ptr, """ );
  254.     /* parse color */
  255.     if ( parse_color ( ptr, &colors[loop].r, &colors[loop].g, &colors[loop].b,
  256.       &colors[loop].transparent ) )
  257.       return IInvalidFormat; /* small memory leak */
  258.   }
  259.   image = (IImageP *) ICreateImage ( w, h, options );
  260.   /* now read row by row of data */
  261.   ptr = (char *) malloc ( colorw * w + 20 );
  262.   for ( loop = 0; loop < h; loop++ ) {
  263.     if ( ! fgets ( ptr, colorw * w + 20, fp ) )
  264.       return IInvalidFormat; /* small memory leak */
  265.     while ( ptr[0] != '"' ) {
  266.       if ( ! fgets ( ptr, colorw * w + 20, fp ) )
  267.         return IInvalidFormat; /* small memory leak */
  268.     }
  269.     for ( loop2 = 0; loop2 < w; loop2++ ) {
  270.       cur = ptr + 1 + loop2 * colorw;
  271.       /* find color in colormap */
  272.       for ( loop3 = 0, found = 0; loop3 < num_colors && ! found; loop3++ ) {
  273.         if ( strncmp ( colors[loop3].abbrev, cur, colorw ) == 0 ) {
  274.           r = image->data + ( loop * w * 3 ) + ( loop2 * 3 );
  275.           g = r + 1;
  276.           b = r + 2;
  277.           *r = colors[loop3].r;
  278.           *g = colors[loop3].g;
  279.           *b = colors[loop3].b;
  280.           found = 1;
  281.         }
  282.       }
  283.       if ( ! found )
  284.         return IInvalidFormat; /* small memory leak */
  285.     }
  286.   }
  287.   free ( ptr );
  288.   *image_return = image;
  289.   for ( loop = 0; loop < num_colors; loop++ ) {
  290.     if ( colors[loop].transparent ) {
  291.       t = IAllocColor ( colors[loop].r, colors[loop].g, colors[loop].b );
  292.       ISetTransparent ( image, t );
  293.     }
  294.     free ( colors[loop].abbrev );
  295.   }
  296.   free ( colors );
  297.   return ( INoError );
  298. }