home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the DOOM Programming Gurus / Tricks_of_the_Doom_Programming_Gurus.iso / bonus / linux / dm2ppm / raw2ppm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-24  |  5.1 KB  |  190 lines

  1.  
  2. /* This module converts the DOOM raw image format to PPM image format
  3.  
  4.     (PPM, mainly because I know its format)
  5.  
  6. */
  7.  
  8. #include    <stdio.h>
  9. #include    <assert.h>
  10. #include    "doomdefs.h"
  11. #include    "directory.h"
  12.  
  13.  
  14. struct raw_header {
  15.     two_byte width;            /* Picture width */
  16.     two_byte height;        /* Picture height */
  17.     two_byte l_offset;        /* Left offset from center (unused?) */
  18.     two_byte t_offset;        /* Top offset from center (unused?) */
  19.     };
  20.  
  21. struct color {
  22.     unsigned char red;
  23.     unsigned char green;
  24.     unsigned char blue;
  25.     } colormap[256];
  26.  
  27. /* The background color for the pictures */
  28. struct color cyan = { 0, 255, 255 };
  29.  
  30. int load_colormap(int fd) {
  31.     struct dir_entry entry;
  32.  
  33.     /* Set the fd to the start of the directory entries */
  34.     if ( set_directory(fd) < 0 )
  35.         return(-1);
  36.  
  37.     /* Now cycle through the entries, looking for PLAYMAP */
  38.     if ( get_entry(fd, "PLAYPAL", &entry) < 0 )
  39.         return(-1);
  40.  
  41.     /* Go to the entry and retrieve the first colormap (colormap 0) */
  42.     if ( lseek(fd, entry.res_start, SEEK_SET) < 0 )
  43.         return(-1);
  44.     if (read(fd, (char *)&colormap, sizeof(colormap)) != sizeof(colormap))
  45.         return(-1);
  46.  
  47.     return(0);
  48. }
  49.  
  50. int convert_rawpic(int fd, char *name)
  51. {
  52.     struct dir_entry entry;
  53.     struct raw_header header;
  54.     struct color *matrix;
  55.     four_byte *columns;
  56.     unsigned char post_row, num_pixels, pixel;
  57.     char outfile[BUFSIZ];
  58.     FILE *output;
  59.     int i, j, l, index;
  60.  
  61.     /* Load the default colormap first */
  62.     if ( load_colormap(fd) < 0 ) {
  63.         fprintf(stderr, "Couldn't load color map from doom.wad\n");
  64.         return(-1);
  65.     }
  66.  
  67.     /* Set the fd to the start of the directory entries */
  68.     if ( set_directory(fd) < 0 ) {
  69.         fprintf(stderr, "Can't find start of directories.\n");
  70.         return(-1);
  71.     }
  72.  
  73.     /* Now cycle through the entries, looking for the picture  */
  74.     if ( get_entry(fd, name, &entry) < 0 ) {
  75.         fprintf(stderr, "Couldn't find directory entry for %s\n", name);
  76.         return(-1);
  77.     }
  78.  
  79.     /* Go to the entry and retrieve the picture */
  80.     if ( lseek(fd, entry.res_start, SEEK_SET) < 0 ) {
  81.         perror("lseek()");
  82.         return(-1);
  83.     }
  84.     if (read(fd, (char *)&header, sizeof(header)) != sizeof(header)) {
  85.         perror("header read error");
  86.         return(-1);
  87.     }
  88.     /* Print out the header for now */
  89.     printf("Picture size: %dx%d  (left offset=%d, top offset=%d)\n", 
  90.         header.width, header.height, header.l_offset, header.t_offset);
  91.  
  92.     /* Allocate memory for the picture */
  93.     if ( (matrix=(struct color *)malloc(
  94.         sizeof(struct color)*(header.width*header.height))) == NULL ) {
  95.         perror("malloc(matrix)");
  96.         return(-1);
  97.     }
  98.     if ( (columns=(four_byte *)malloc(header.width*4)) == NULL ) {
  99.         perror("malloc(columns)");
  100.         return(-1);
  101.     }
  102.     
  103.     /* Set the default color to cyan */
  104.     for ( i=0; i<header.height; ++i )
  105.         for ( j=0; j<header.width; ++j )
  106.             matrix[(i*header.width)+j] = cyan;
  107.  
  108.     /* Convert the raw picture format into the pixel matrix */
  109.     /* Get all the columns pointers */
  110.     if ( read(fd, (char *)columns, header.width*4) != (header.width*4) ) {
  111.         perror("read(columns");
  112.         return(-1);
  113.     }
  114.     /* I tried using the offsets in the header, but they didn't seem
  115.        to be relevant.  Thus, I ignore them.
  116.      */
  117.     for ( i=0; i<header.width; ++i ) {
  118.         /* Each column is stored as a series of posts */
  119.         if ( lseek(fd, entry.res_start+columns[i], SEEK_SET) < 0 ) {
  120.             perror("lseek(columns)");
  121.             return(-1);
  122.         }
  123.         for ( ; ; ) {
  124.             /* The first byte is the starting row of the post */
  125.             if ( read(fd, &post_row, 1) != 1 ) {
  126.                 perror("read()");
  127.                 return(-1);
  128.             }
  129.             if ( post_row == 255 )  /* End of column marker */
  130.                 break;
  131.             /* The second byte is the number of pixels in the post */
  132.             if ( read(fd, &num_pixels, 1) != 1 ) {
  133.                 perror("read()");
  134.                 return(-1);
  135.             }
  136.             /* Skip first and last pixel bytes */
  137.             (void) read(fd, &pixel, 1);
  138.             for ( j=0; j<num_pixels; ++j ) {
  139.                 if ( read(fd, &pixel, 1) != 1 ) {
  140.                     perror("read()");
  141.                     return(-1);
  142.                 }
  143.                 index=((post_row*header.width)+i);
  144.                 assert(index > 0);
  145.                 matrix[index] = colormap[pixel];
  146.                 ++post_row;
  147.             }
  148.             (void) read(fd, &pixel, 1);
  149.         }
  150.     }
  151.  
  152.     /* Make sure we can write the output file */
  153.     sprintf(outfile, "%s.ppm", name);
  154.     if ( (output=fopen(outfile, "w")) == NULL ) {
  155.         fprintf(stderr, "Can't open %s for writing.\n", outfile);
  156.         return(-1);
  157.     }
  158.     /* Write the output file */
  159.     fprintf(output, "P3\n");    /* PPM Magic cookie */
  160.     fprintf(output, "# %s\n", outfile);
  161.     fprintf(output, "%d %d\n", header.width, header.height);
  162.     fprintf(output, "255\n");    /* The maximum color value */
  163.     /* Now the matrix itself */
  164.     for ( i=0; i<header.height; ++i ) {
  165.         fprintf(output, "# row %d\n", i);
  166.         for ( j=0, l=0; j<header.width; ++j ) {
  167.             index = ((i*header.width)+j);
  168.             sprintf(outfile, "%d %d %d  ", matrix[index].red, 
  169.                 matrix[index].green, matrix[index].blue);
  170.  
  171.             /* The line can be no longer than 70 chars */
  172.             l += strlen(outfile);
  173.             if ( l > 70 ) {
  174.                 fprintf(output, "\n");
  175.                 l = strlen(outfile);
  176.             }
  177.             fprintf(output, "%s", outfile);
  178.         }
  179.         fprintf(output, "\n");
  180.     }
  181.     fclose(output);
  182.  
  183.     /* Free malloc()'d data here.  It is not freed on errors */
  184.     (void) free(matrix);
  185.     (void) free(columns);
  186.  
  187.     /* Done! */
  188.     return(0);
  189. }
  190.