home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / general / convrtrs / pbmplus / ntpbmsrc.lha / netpbm / ppm / xpmtoppm.c < prev    next >
C/C++ Source or Header  |  1993-12-03  |  14KB  |  418 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. /* prototypes */
  34. void ReadXPMFile ARGS((FILE *stream, int *widthP, int *heightP, int *ncolorsP,
  35.                         int *chars_per_pixelP, pixel **colorsP, int **dataP));
  36. static void getline ARGS((char *line, int size, FILE *stream));
  37.  
  38.  
  39. /* number of xpmColorKeys */
  40. #define NKEYS 5
  41.  
  42. char *xpmColorKeys[] =
  43. {
  44.  "s",                                   /* key #1: symbol */
  45.  "m",                                   /* key #2: mono visual */
  46.  "g4",                                  /* key #3: 4 grays visual */
  47.  "g",                                   /* key #4: gray visual */
  48.  "c",                                   /* key #5: color visual */
  49. };
  50.  
  51. int
  52. main(argc, argv)
  53.     int argc;
  54.     char *argv[];
  55.  
  56. {
  57.     FILE *ifp;
  58.     pixel *pixrow, *colors;
  59.     register pixel *pP;
  60.     int rows, cols, ncolors, chars_per_pixel, row;
  61.     register int col;
  62.     int *data;
  63.     register int *ptr;
  64.  
  65.     ppm_init(&argc, argv);
  66.  
  67.     if (argc > 2)
  68.         pm_usage("[xpmfile]");
  69.  
  70.     if (argc == 2)
  71.         ifp = pm_openr(argv[1]);
  72.     else
  73.         ifp = stdin;
  74.  
  75.     ReadXPMFile(
  76.             ifp, &cols, &rows, &ncolors, &chars_per_pixel, &colors, &data);
  77.  
  78.     pm_close(ifp);
  79.  
  80.     ppm_writeppminit(stdout, cols, rows, (pixval) PPM_MAXMAXVAL, 0);
  81.     pixrow = ppm_allocrow(cols);
  82.  
  83.     for (row = 0, ptr = data; row < rows; ++row) {
  84.         for (col = 0, pP = pixrow; col < cols; ++col, ++pP, ++ptr)
  85.             *pP = colors[*ptr];
  86.         ppm_writeppmrow(stdout, pixrow, cols, (pixval) PPM_MAXMAXVAL, 0);
  87.     }
  88.  
  89.     exit(0);
  90. }
  91.  
  92. #define MAX_LINE 2048
  93.  
  94. void
  95. ReadXPMFile(stream, widthP, heightP, ncolorsP,
  96.             chars_per_pixelP, colorsP, dataP)
  97.     FILE *stream;
  98.     int *widthP;
  99.     int *heightP;
  100.     int *ncolorsP;
  101.     int *chars_per_pixelP;
  102.     pixel **colorsP;
  103.     int **dataP;
  104. {
  105.     char line[MAX_LINE], str1[MAX_LINE], str2[MAX_LINE];
  106.     char *t1;
  107.     char *t2;
  108.     int format, v, datasize;
  109.     int *ptr;
  110.     int *ptab;
  111.     register int i, j;
  112.     int flag;
  113.  
  114.     unsigned int curkey, key, highkey;  /* current color key */
  115.     unsigned int lastwaskey;            /* key read */
  116.     char curbuf[BUFSIZ];                /* current buffer */
  117.  
  118.     *widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1;
  119.     flag = 0;                           /* to avoid getting twice a line */
  120.  
  121.     /* First try to read as an XPM version 3 file */
  122.  
  123.     /* Read the header line */
  124.     getline(line, sizeof(line), stream);
  125.     if (sscanf(line, "/* %s */", str1) == 1
  126.         && !strncmp(str1, "XPM", 3)) {
  127.  
  128.         /* Read the assignment line */
  129.         getline(line, sizeof(line), stream);
  130.         if (strncmp(line, "static char", 11))
  131.             pm_error("error scanning assignment line", 0, 0, 0, 0, 0);
  132.  
  133.         /* Read the hints line */
  134.         getline(line, sizeof(line), stream);
  135.         /* skip the comment line if any */
  136.         if (!strncmp(line, "/*", 2)) {
  137.             while (!strstr(line, "*/"))
  138.                 getline(line, sizeof(line), stream);
  139.             getline(line, sizeof(line), stream);
  140.         }
  141.         if (sscanf(line, "\"%d %d %d %d\",", widthP, heightP,
  142.                    ncolorsP, chars_per_pixelP) != 4)
  143.             pm_error("error scanning hints line", 0, 0, 0, 0, 0);
  144.  
  145.         /* Allocate space for color table. */
  146.         if (*chars_per_pixelP <= 2) {
  147.             /* Up to two chars per pixel, we can use an indexed table. */
  148.             v = 1;
  149.             for (i = 0; i < *chars_per_pixelP; ++i)
  150.                 v *= 256;
  151.             *colorsP = ppm_allocrow(v);
  152.         } else {
  153.             /* Over two chars per pixel, we fall back on linear search. */
  154.             *colorsP = ppm_allocrow(*ncolorsP);
  155.             ptab = (int *) malloc(*ncolorsP * sizeof(int));
  156.         }
  157.  
  158.         /* Read the color table */
  159.         for (i = 0; i < *ncolorsP; i++) {
  160.             getline(line, sizeof(line), stream);
  161.             /* skip the comment line if any */
  162.             if (!strncmp(line, "/*", 2))
  163.                 getline(line, sizeof(line), stream);
  164.  
  165.             /* read the chars */
  166.             if ((t1 = index(line, '"')) == NULL)
  167.                 pm_error("error scanning color table", 0, 0, 0, 0, 0);
  168.             else
  169.                 t1++;
  170.             strncpy(str1, t1, *chars_per_pixelP);
  171.             str1[*chars_per_pixelP] = '\0';
  172.             t1++; t1++;
  173.  
  174.             v = 0;
  175.             for (j = 0; j < *chars_per_pixelP; ++j)
  176.                 v = (v << 8) + str1[j];
  177.             /*
  178.              * read color keys and values
  179.              */
  180.             curkey = 0;
  181.             highkey = 1;
  182.             lastwaskey = 0;
  183.             t2 = t1;
  184.             while ( 1 ) {
  185.                 for (t1=t2 ;; t1++)
  186.                     if (*t1 != ' ' && *t1 != '\t')
  187.                         break;
  188.                 for (t2 = t1;; t2++)
  189.                     if (*t2 == ' ' || *t2 == '\t' || *t2 == '"')
  190.                         break;
  191.                 if (t2 == t1) break;
  192.                 strncpy(str2, t1, t2 - t1);
  193.                 str2[t2 - t1] = '\0';
  194.  
  195.                 if (!lastwaskey) {
  196.                     for (key = 1; key < NKEYS + 1; key++)
  197.                         if (!strcmp(xpmColorKeys[key - 1], str2))
  198.                             break;
  199.                 } else
  200.                     key = NKEYS + 1;
  201.                 if (key > NKEYS) {                      /* append name */
  202.                     if (!curkey)
  203.                         pm_error("error scanning color table", 0, 0, 0, 0, 0);
  204.                     if (!lastwaskey)
  205.                         strcat(curbuf, " ");            /* append space */
  206.                     strcat(curbuf, str2);               /* append buf */
  207.                     lastwaskey = 0;
  208.                 }
  209.                 if (key <= NKEYS) {                     /* new key */
  210.                     if (curkey > highkey) {     /* flush string */
  211.                         if (*chars_per_pixelP <= 2)
  212.                             /* Index into table. */
  213.                             (*colorsP)[v] = ppm_parsecolor(curbuf,
  214.                                                 (pixval) PPM_MAXMAXVAL);
  215.                         else {
  216.                             /* Set up linear search table. */
  217.                             (*colorsP)[i] = ppm_parsecolor(curbuf,
  218.                                                 (pixval) PPM_MAXMAXVAL);
  219.                             ptab[i] = v;
  220.                         }
  221.                         highkey = curkey;
  222.                     }
  223.                     curkey = key;                       /* set new key  */
  224.                     curbuf[0] = '\0';           /* reset curbuf */
  225.                     lastwaskey = 1;
  226.                 }
  227.             if (*t2 == '"') break;
  228.             }
  229.             if (curkey > highkey) {
  230.                 if (*chars_per_pixelP <= 2)
  231.                     /* Index into table. */
  232.                     (*colorsP)[v] = ppm_parsecolor(curbuf,
  233.                                         (pixval) PPM_MAXMAXVAL);
  234.                 else {
  235.                     /* Set up linear search table. */
  236.                     (*colorsP)[i] = ppm_parsecolor(curbuf,
  237.                                         (pixval) PPM_MAXMAXVAL);
  238.                     ptab[i] = v;
  239.                 }
  240.                 highkey = curkey;
  241.             }
  242.             if (highkey == 1)
  243.                 pm_error("error scanning color table", 0, 0, 0, 0, 0);
  244.         }
  245.         /* Read pixels. */
  246.         getline(line, sizeof(line), stream);
  247.         /* skip the comment line if any */
  248.         if (!strncmp(line, "/*", 2))
  249.             getline(line, sizeof(line), stream);
  250.  
  251.     } else {                            /* try as an XPM version 1 file */
  252.  
  253.         /* Read the initial defines. */
  254.         for (;;) {
  255.             if (flag)
  256.                 getline(line, sizeof(line), stream);
  257.             else
  258.                 flag++;
  259.  
  260.             if (sscanf(line, "#define %s %d", str1, &v) == 2) {
  261.                 if ((t1 = rindex(str1, '_')) == NULL)
  262.                     t1 = str1;
  263.                 else
  264.                     ++t1;
  265.                 if (!strcmp(t1, "format"))
  266.                     format = v;
  267.                 else if (!strcmp(t1, "width"))
  268.                     *widthP = v;
  269.                 else if (!strcmp(t1, "height"))
  270.                     *heightP = v;
  271.                 else if (!strcmp(t1, "ncolors"))
  272.                     *ncolorsP = v;
  273.                 else if (!strcmp(t1, "pixel"))
  274.                     *chars_per_pixelP = v;
  275.             } else if (!strncmp(line, "static char", 11)) {
  276.                 if ((t1 = rindex(line, '_')) == NULL)
  277.                     t1 = line;
  278.                 else
  279.                     ++t1;
  280.                 break;
  281.             }
  282.         }
  283.         if (format == -1)
  284.             pm_error("missing or invalid format", 0, 0, 0, 0, 0);
  285.         if (format != 1)
  286.             pm_error("can't handle XPM version %d", format, 0, 0, 0, 0);
  287.         if (*widthP == -1)
  288.             pm_error("missing or invalid width", 0, 0, 0, 0, 0);
  289.         if (*heightP == -1)
  290.             pm_error("missing or invalid height", 0, 0, 0, 0, 0);
  291.         if (*ncolorsP == -1)
  292.             pm_error("missing or invalid ncolors", 0, 0, 0, 0, 0);
  293.         if (*chars_per_pixelP == -1)
  294.             pm_error("missing or invalid chars_per_pixel", 0, 0, 0, 0, 0);
  295.         if (*chars_per_pixelP > 2)
  296.             pm_message("warning, chars_per_pixel > 2 uses a lot of memory"
  297.                        ,0, 0, 0, 0, 0);
  298.  
  299.         /* If there's a monochrome color table, skip it. */
  300.         if (!strncmp(t1, "mono", 4)) {
  301.             for (;;) {
  302.                 getline(line, sizeof(line), stream);
  303.                 if (!strncmp(line, "static char", 11))
  304.                     break;
  305.             }
  306.         }
  307.         /* Allocate space for color table. */
  308.         if (*chars_per_pixelP <= 2) {
  309.             /* Up to two chars per pixel, we can use an indexed table. */
  310.             v = 1;
  311.             for (i = 0; i < *chars_per_pixelP; ++i)
  312.                 v *= 256;
  313.             *colorsP = ppm_allocrow(v);
  314.         } else {
  315.             /* Over two chars per pixel, we fall back on linear search. */
  316.             *colorsP = ppm_allocrow(*ncolorsP);
  317.             ptab = (int *) malloc(*ncolorsP * sizeof(int));
  318.         }
  319.  
  320.         /* Read color table. */
  321.         for (i = 0; i < *ncolorsP; ++i) {
  322.             getline(line, sizeof(line), stream);
  323.  
  324.             if ((t1 = index(line, '"')) == NULL)
  325.                 pm_error("error scanning color table", 0, 0, 0, 0, 0);
  326.             if ((t2 = index(t1 + 1, '"')) == NULL)
  327.                 pm_error("error scanning color table", 0, 0, 0, 0, 0);
  328.             if (t2 - t1 - 1 != *chars_per_pixelP)
  329.                 pm_error("wrong number of chars per pixel in color table",
  330.                          0, 0, 0, 0, 0);
  331.             strncpy(str1, t1 + 1, t2 - t1 - 1);
  332.             str1[t2 - t1 - 1] = '\0';
  333.  
  334.             if ((t1 = index(t2 + 1, '"')) == NULL)
  335.                 pm_error("error scanning color table", 0, 0, 0, 0, 0);
  336.             if ((t2 = index(t1 + 1, '"')) == NULL)
  337.                 pm_error("error scanning color table", 0, 0, 0, 0, 0);
  338.             strncpy(str2, t1 + 1, t2 - t1 - 1);
  339.             str2[t2 - t1 - 1] = '\0';
  340.  
  341.             v = 0;
  342.             for (j = 0; j < *chars_per_pixelP; ++j)
  343.                 v = (v << 8) + str1[j];
  344.             if (*chars_per_pixelP <= 2)
  345.                 /* Index into table. */
  346.                 (*colorsP)[v] = ppm_parsecolor(str2,
  347.                                                (pixval) PPM_MAXMAXVAL);
  348.             else {
  349.                 /* Set up linear search table. */
  350.                 (*colorsP)[i] = ppm_parsecolor(str2,
  351.                                                (pixval) PPM_MAXMAXVAL);
  352.                 ptab[i] = v;
  353.             }
  354.         }
  355.  
  356.         /* Read pixels. */
  357.         for (;;) {
  358.             getline(line, sizeof(line), stream);
  359.             if (!strncmp(line, "static char", 11))
  360.                 break;
  361.         }
  362.     }
  363.     datasize = *widthP * *heightP;
  364.     *dataP = (int *) malloc(datasize * sizeof(int));
  365.     if (*dataP == 0)
  366.         pm_error("out of memory", 0, 0, 0, 0, 0);
  367.     i = 0;
  368.     ptr = *dataP;
  369.     for (;;) {
  370.         if (flag)
  371.             getline(line, sizeof(line), stream);
  372.         else
  373.             flag++;
  374.  
  375.         /* Find the open quote. */
  376.         if ((t1 = index(line, '"')) == NULL)
  377.             pm_error("error scanning pixels", 0, 0, 0, 0, 0);
  378.         ++t1;
  379.  
  380.         /* Handle pixels until a close quote or the end of the image. */
  381.         while (*t1 != '"') {
  382.             v = 0;
  383.             for (j = 0; j < *chars_per_pixelP; ++j)
  384.                 v = (v << 8) + *t1++;
  385.             if (*chars_per_pixelP <= 2)
  386.                 /* Index into table. */
  387.                 *ptr++ = v;
  388.             else {
  389.                 /* Linear search into table. */
  390.                 for (j = 0; j < *ncolorsP; ++j)
  391.                     if (ptab[j] == v)
  392.                         goto gotit;
  393.                 pm_error("unrecognized pixel in line \"%s\"", line,
  394.                          0, 0, 0, 0);
  395.         gotit:
  396.                 *ptr++ = j;
  397.             }
  398.             ++i;
  399.             if (i >= datasize)
  400.                 return;
  401.         }
  402.     }
  403. }
  404.  
  405.  
  406. static void
  407. getline(line, size, stream)
  408.     char *line;
  409.     int size;
  410.     FILE *stream;
  411. {
  412.     if (fgets(line, MAX_LINE, stream) == NULL)
  413.         pm_error("EOF / read error", 0, 0, 0, 0, 0);
  414.     if (strlen(line) == MAX_LINE - 1)
  415.         pm_error("line too long", 0, 0, 0, 0, 0);
  416. }
  417.  
  418.