home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / netpbm_src.lzh / NETPBM / PPM / xpmtoppm.c < prev    next >
C/C++ Source or Header  |  1996-11-18  |  11KB  |  434 lines

  1. /* xpmtoppm.c - read an X11 pixmap file and produce a portable pixmap
  2. **
  3. ** Copyright (C) 1991 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. **
  12. ** Upgraded to support XPM version 3 by
  13. **   Arnaud Le Hors (lehors@mirsa.inria.fr)
  14. **   Tue Apr 9 1991
  15. **
  16. ** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91:
  17. **  - Bug fix, no advance of read ptr, would not read 
  18. **    colors like "ac c black" because it would find 
  19. **    the "c" of "ac" and then had problems with "c"
  20. **    as color.
  21. **    
  22. **  - Now understands multword X11 color names
  23. **  
  24. **  - Now reads multiple color keys. Takes the color
  25. **    of the hightest available key. Lines no longer need
  26. **    to begin with key 'c'.
  27. **    
  28. **  - expanded line buffer to from 500 to 2048 for bigger files
  29. */
  30.  
  31. #include "ppm.h"
  32.  
  33. void ReadXPMFile();
  34. static void getline();
  35.  
  36. /* number of xpmColorKeys */
  37. #define NKEYS 5
  38.  
  39. char *xpmColorKeys[] =
  40. {
  41.  "s",                    /* key #1: symbol */
  42.  "m",                    /* key #2: mono visual */
  43.  "g4",                    /* key #3: 4 grays visual */
  44.  "g",                    /* key #4: gray visual */
  45.  "c",                    /* key #5: color visual */
  46. };
  47.  
  48. #ifdef NEED_STRSTR
  49. /* for systems which do not provide it */
  50. static char *
  51. strstr(s1, s2)
  52.     char *s1, *s2;
  53. {
  54.     int ls2 = strlen(s2);
  55.  
  56.     if (ls2 == 0)
  57.     return (s1);
  58.     while (strlen(s1) >= ls2) {
  59.     if (strncmp(s1, s2, ls2) == 0)
  60.         return (s1);
  61.     s1++;
  62.     }
  63.     return (0);
  64. }
  65.  
  66. #endif
  67.  
  68. void
  69. main(argc, argv)
  70.     int argc;
  71.     char *argv[];
  72.  
  73. {
  74.     FILE *ifp;
  75.     pixel *pixrow, *colors;
  76.     register pixel *pP;
  77.     int rows, cols, ncolors, chars_per_pixel, row;
  78.     register int col;
  79.     int *data;
  80.     register int *ptr;
  81.  
  82.     ppm_init(&argc, argv);
  83.  
  84.     if (argc > 2)
  85.     pm_usage("[xpmfile]");
  86.  
  87.     if (argc == 2)
  88.     ifp = pm_openr(argv[1]);
  89.     else
  90.     ifp = stdin;
  91.  
  92.     ReadXPMFile(
  93.         ifp, &cols, &rows, &ncolors, &chars_per_pixel, &colors, &data);
  94.  
  95.     pm_close(ifp);
  96.  
  97.     ppm_writeppminit(stdout, cols, rows, (pixval) PPM_MAXMAXVAL, 0);
  98.     pixrow = ppm_allocrow(cols);
  99.  
  100.     for (row = 0, ptr = data; row < rows; ++row) {
  101.     for (col = 0, pP = pixrow; col < cols; ++col, ++pP, ++ptr)
  102.         *pP = colors[*ptr];
  103.     ppm_writeppmrow(stdout, pixrow, cols, (pixval) PPM_MAXMAXVAL, 0);
  104.     }
  105.  
  106.     exit(0);
  107. }
  108.  
  109. #define MAX_LINE 2048
  110.  
  111. void
  112. ReadXPMFile(stream, widthP, heightP, ncolorsP,
  113.         chars_per_pixelP, colorsP, dataP)
  114.     FILE *stream;
  115.     int *widthP;
  116.     int *heightP;
  117.     int *ncolorsP;
  118.     int *chars_per_pixelP;
  119.     pixel **colorsP;
  120.     int **dataP;
  121. {
  122.     char line[MAX_LINE], str1[MAX_LINE], str2[MAX_LINE];
  123.     char *t1;
  124.     char *t2;
  125.     int format, v, datasize;
  126.     int *ptr;
  127.     int *ptab;
  128.     register int i, j;
  129.     int flag;
  130.  
  131.     unsigned int curkey, key, highkey;    /* current color key */
  132.     unsigned int lastwaskey;        /* key read */
  133.     char curbuf[BUFSIZ];        /* current buffer */
  134.  
  135.     *widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1;
  136.     flag = 0;                /* to avoid getting twice a line */
  137.  
  138.     /* First try to read as an XPM version 3 file */
  139.  
  140.     /* Read the header line */
  141.     getline(line, sizeof(line), stream);
  142.     if (sscanf(line, "/* %s */", str1) == 1
  143.     && !strncmp(str1, "XPM", 3)) {
  144.  
  145.     /* Read the assignment line */
  146.     getline(line, sizeof(line), stream);
  147.     if (strncmp(line, "static char", 11))
  148.         pm_error("error scanning assignment line", 0, 0, 0, 0, 0);
  149.  
  150.     /* Read the hints line */
  151.     getline(line, sizeof(line), stream);
  152.     /* skip the comment line if any */
  153.     if (!strncmp(line, "/*", 2)) {
  154.         while (!strstr(line, "*/"))
  155.         getline(line, sizeof(line), stream);
  156.         getline(line, sizeof(line), stream);
  157.     }
  158.     if (sscanf(line, "\"%d %d %d %d\",", widthP, heightP,
  159.            ncolorsP, chars_per_pixelP) != 4)
  160.         pm_error("error scanning hints line", 0, 0, 0, 0, 0);
  161.  
  162.     /* Allocate space for color table. */
  163.     if (*chars_per_pixelP <= 2) {
  164.         /* Up to two chars per pixel, we can use an indexed table. */
  165.         v = 1;
  166.         for (i = 0; i < *chars_per_pixelP; ++i)
  167.         v *= 256;
  168.         *colorsP = ppm_allocrow(v);
  169.     } else {
  170.         /* Over two chars per pixel, we fall back on linear search. */
  171.         *colorsP = ppm_allocrow(*ncolorsP);
  172.         ptab = (int *) malloc(*ncolorsP * sizeof(int));
  173.     }
  174.  
  175.     /* Read the color table */
  176.     for (i = 0; i < *ncolorsP; i++) {
  177.         getline(line, sizeof(line), stream);
  178.         /* skip the comment line if any */
  179.         if (!strncmp(line, "/*", 2))
  180.         getline(line, sizeof(line), stream);
  181.  
  182.         /* read the chars */
  183.         if ((t1 = index(line, '"')) == NULL)
  184.         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  185.         else
  186.         t1++;
  187.         strncpy(str1, t1, *chars_per_pixelP);
  188.         str1[*chars_per_pixelP] = '\0';
  189.         t1++; t1++;
  190.  
  191.         v = 0;
  192.         for (j = 0; j < *chars_per_pixelP; ++j)
  193.         v = (v << 8) + str1[j];
  194.         /*
  195.          * read color keys and values 
  196.          */
  197.         curkey = 0; 
  198.         highkey = 1;
  199.         lastwaskey = 0;
  200.         t2 = t1;
  201.         while ( 1 ) {
  202.         for (t1=t2 ;; t1++)
  203.             if (*t1 != ' ' && *t1 != '    ')
  204.             break;
  205.         for (t2 = t1;; t2++)
  206.             if (*t2 == ' ' || *t2 == '    ' || *t2 == '"')
  207.             break;
  208.         if (t2 == t1) break;
  209.         strncpy(str2, t1, t2 - t1);
  210.         str2[t2 - t1] = '\0';
  211.             
  212.         if (!lastwaskey) {
  213.             for (key = 1; key < NKEYS + 1; key++)
  214.             if (!strcmp(xpmColorKeys[key - 1], str2))
  215.                 break;
  216.         } else 
  217.             key = NKEYS + 1;
  218.         if (key > NKEYS) {            /* append name */
  219.             if (!curkey) 
  220.             pm_error("error scanning color table", 0, 0, 0, 0, 0);
  221.             if (!lastwaskey) 
  222.             strcat(curbuf, " ");        /* append space */
  223.             strcat(curbuf, str2);        /* append buf */
  224.             lastwaskey = 0;
  225.         }
  226.         if (key <= NKEYS) {             /* new key */
  227.             if (curkey > highkey) {    /* flush string */
  228.             if (*chars_per_pixelP <= 2)
  229.                 /* Index into table. */
  230.                 (*colorsP)[v] = ppm_parsecolor(curbuf,
  231.                         (pixval) PPM_MAXMAXVAL);
  232.             else {
  233.                 /* Set up linear search table. */
  234.                 (*colorsP)[i] = ppm_parsecolor(curbuf,
  235.                         (pixval) PPM_MAXMAXVAL);
  236.                 ptab[i] = v;
  237.             }
  238.             highkey = curkey;
  239.             }
  240.             curkey = key;            /* set new key  */
  241.             curbuf[0] = '\0';        /* reset curbuf */
  242.             lastwaskey = 1;
  243.         }
  244.         if (*t2 == '"') break;
  245.         }
  246.         if (curkey > highkey) {
  247.         if (*chars_per_pixelP <= 2)
  248.             /* Index into table. */
  249.             (*colorsP)[v] = ppm_parsecolor(curbuf,
  250.                     (pixval) PPM_MAXMAXVAL);
  251.         else {
  252.             /* Set up linear search table. */
  253.             (*colorsP)[i] = ppm_parsecolor(curbuf,
  254.                     (pixval) PPM_MAXMAXVAL);
  255.             ptab[i] = v;
  256.         }
  257.         highkey = curkey;
  258.         }
  259.         if (highkey == 1) 
  260.         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  261.     }
  262.     /* Read pixels. */
  263.     getline(line, sizeof(line), stream);
  264.     /* skip the comment line if any */
  265.     if (!strncmp(line, "/*", 2))
  266.         getline(line, sizeof(line), stream);
  267.  
  268.     } else {                /* try as an XPM version 1 file */
  269.  
  270.     /* Read the initial defines. */
  271.     for (;;) {
  272.         if (flag)
  273.         getline(line, sizeof(line), stream);
  274.         else
  275.         flag++;
  276.  
  277.         if (sscanf(line, "#define %s %d", str1, &v) == 2) {
  278.         if ((t1 = rindex(str1, '_')) == NULL)
  279.             t1 = str1;
  280.         else
  281.             ++t1;
  282.         if (!strcmp(t1, "format"))
  283.             format = v;
  284.         else if (!strcmp(t1, "width"))
  285.             *widthP = v;
  286.         else if (!strcmp(t1, "height"))
  287.             *heightP = v;
  288.         else if (!strcmp(t1, "ncolors"))
  289.             *ncolorsP = v;
  290.         else if (!strcmp(t1, "pixel"))
  291.             *chars_per_pixelP = v;
  292.         } else if (!strncmp(line, "static char", 11)) {
  293.         if ((t1 = rindex(line, '_')) == NULL)
  294.             t1 = line;
  295.         else
  296.             ++t1;
  297.         break;
  298.         }
  299.     }
  300.     if (format == -1)
  301.         pm_error("missing or invalid format", 0, 0, 0, 0, 0);
  302.     if (format != 1)
  303.         pm_error("can't handle XPM version %d", format, 0, 0, 0, 0);
  304.     if (*widthP == -1)
  305.         pm_error("missing or invalid width", 0, 0, 0, 0, 0);
  306.     if (*heightP == -1)
  307.         pm_error("missing or invalid height", 0, 0, 0, 0, 0);
  308.     if (*ncolorsP == -1)
  309.         pm_error("missing or invalid ncolors", 0, 0, 0, 0, 0);
  310.     if (*chars_per_pixelP == -1)
  311.         pm_error("missing or invalid chars_per_pixel", 0, 0, 0, 0, 0);
  312.     if (*chars_per_pixelP > 2)
  313.         pm_message("warning, chars_per_pixel > 2 uses a lot of memory"
  314.                ,0, 0, 0, 0, 0);
  315.  
  316.     /* If there's a monochrome color table, skip it. */
  317.     if (!strncmp(t1, "mono", 4)) {
  318.         for (;;) {
  319.         getline(line, sizeof(line), stream);
  320.         if (!strncmp(line, "static char", 11))
  321.             break;
  322.         }
  323.     }
  324.     /* Allocate space for color table. */
  325.     if (*chars_per_pixelP <= 2) {
  326.         /* Up to two chars per pixel, we can use an indexed table. */
  327.         v = 1;
  328.         for (i = 0; i < *chars_per_pixelP; ++i)
  329.         v *= 256;
  330.         *colorsP = ppm_allocrow(v);
  331.     } else {
  332.         /* Over two chars per pixel, we fall back on linear search. */
  333.         *colorsP = ppm_allocrow(*ncolorsP);
  334.         ptab = (int *) malloc(*ncolorsP * sizeof(int));
  335.     }
  336.  
  337.     /* Read color table. */
  338.     for (i = 0; i < *ncolorsP; ++i) {
  339.         getline(line, sizeof(line), stream);
  340.  
  341.         if ((t1 = index(line, '"')) == NULL)
  342.         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  343.         if ((t2 = index(t1 + 1, '"')) == NULL)
  344.         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  345.         if (t2 - t1 - 1 != *chars_per_pixelP)
  346.         pm_error("wrong number of chars per pixel in color table",
  347.              0, 0, 0, 0, 0);
  348.         strncpy(str1, t1 + 1, t2 - t1 - 1);
  349.         str1[t2 - t1 - 1] = '\0';
  350.  
  351.         if ((t1 = index(t2 + 1, '"')) == NULL)
  352.         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  353.         if ((t2 = index(t1 + 1, '"')) == NULL)
  354.         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  355.         strncpy(str2, t1 + 1, t2 - t1 - 1);
  356.         str2[t2 - t1 - 1] = '\0';
  357.  
  358.         v = 0;
  359.         for (j = 0; j < *chars_per_pixelP; ++j)
  360.         v = (v << 8) + str1[j];
  361.         if (*chars_per_pixelP <= 2)
  362.         /* Index into table. */
  363.         (*colorsP)[v] = ppm_parsecolor(str2,
  364.                            (pixval) PPM_MAXMAXVAL);
  365.         else {
  366.         /* Set up linear search table. */
  367.         (*colorsP)[i] = ppm_parsecolor(str2,
  368.                            (pixval) PPM_MAXMAXVAL);
  369.         ptab[i] = v;
  370.         }
  371.     }
  372.  
  373.     /* Read pixels. */
  374.     for (;;) {
  375.         getline(line, sizeof(line), stream);
  376.         if (!strncmp(line, "static char", 11))
  377.         break;
  378.     }
  379.     }
  380.     datasize = *widthP * *heightP;
  381.     *dataP = (int *) malloc(datasize * sizeof(int));
  382.     if (*dataP == 0)
  383.     pm_error("out of memory", 0, 0, 0, 0, 0);
  384.     i = 0;
  385.     ptr = *dataP;
  386.     for (;;) {
  387.     if (flag)
  388.         getline(line, sizeof(line), stream);
  389.     else
  390.         flag++;
  391.  
  392.     /* Find the open quote. */
  393.     if ((t1 = index(line, '"')) == NULL)
  394.         pm_error("error scanning pixels", 0, 0, 0, 0, 0);
  395.     ++t1;
  396.  
  397.     /* Handle pixels until a close quote or the end of the image. */
  398.     while (*t1 != '"') {
  399.         v = 0;
  400.         for (j = 0; j < *chars_per_pixelP; ++j)
  401.         v = (v << 8) + *t1++;
  402.         if (*chars_per_pixelP <= 2)
  403.         /* Index into table. */
  404.         *ptr++ = v;
  405.         else {
  406.         /* Linear search into table. */
  407.         for (j = 0; j < *ncolorsP; ++j)
  408.             if (ptab[j] == v)
  409.             goto gotit;
  410.         pm_error("unrecognized pixel in line \"%s\"", line,
  411.              0, 0, 0, 0);
  412.     gotit:
  413.         *ptr++ = j;
  414.         }
  415.         ++i;
  416.         if (i >= datasize)
  417.         return;
  418.     }
  419.     }
  420. }
  421.  
  422.  
  423. static void
  424. getline(line, size, stream)
  425.     char *line;
  426.     int size;
  427.     FILE *stream;
  428. {
  429.     if (fgets(line, MAX_LINE, stream) == NULL)
  430.     pm_error("EOF / read error", 0, 0, 0, 0, 0);
  431.     if (strlen(line) == MAX_LINE - 1)
  432.     pm_error("line too long", 0, 0, 0, 0, 0);
  433. }
  434.