home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_C / TGE131.ZIP / UTIL / PCX2RAW.C < prev    next >
C/C++ Source or Header  |  1994-03-05  |  8KB  |  334 lines

  1. /**************************************************************************
  2. *  File:        PCX2RAW.C     Copyright (c) 1993-1994 by Matthew Hildebrand
  3. *
  4. *  Purpose:     Convert PCX files to RAW and PAL files.
  5. **************************************************************************/
  6.  
  7. #include <alloc.h>
  8. #include <dir.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12.  
  13. #define GENERAL_ERR     0
  14. #define OK        1
  15. #define OPEN_ERR    2
  16. #define SEEK_ERR    3
  17. #define READ_ERR    4
  18. #define WRITE_ERR    5
  19. #define MEM_ERR        6
  20.  
  21. typedef unsigned char   uchar;
  22. typedef unsigned int    uint;
  23. typedef unsigned long   ulong;
  24. typedef struct
  25. {
  26.   char manufacturer;
  27.   char version;
  28.   char encoding;
  29.   char bitsPerPixel;
  30.   int xmin, ymin;
  31.   int xmax, ymax;
  32.   int hres, vres;
  33.   char palette[48];
  34.   char reserved;
  35.   char colourPlanes;
  36.   int bytesPerLine;
  37.   int paletteType;
  38.   char filler[58];
  39. } PcxHeader;
  40.  
  41. void convertFile(char *filename);
  42. int openPcxFile(char *filename, int *wide, int *deep, uchar *palette);
  43. void closePcxFile(void);
  44. int translatePcxFile(FILE *outFile, void *lineBuf);
  45. void assumeExtension(char *filename, char *extension);
  46. void forceExtension(char *filename, char *extension);
  47. int readPcxLine(uchar *p, FILE *inFile);
  48.  
  49. uchar palette[768];
  50. PcxHeader header;
  51. int width, depth, bytes;
  52. FILE *inFile;
  53.  
  54.  
  55.  
  56. /****
  57. ***** Program entry point.
  58. ****/
  59.  
  60. void main(int argc, char *argv[])
  61. {
  62.   char fileDrive[MAXDRIVE];
  63.   char fileDir[MAXDIR];
  64.   char fileFile[MAXFILE];
  65.   char fileExt[MAXEXT];
  66.   char path[MAXPATH];
  67.   struct ffblk ffblk;
  68.   int done;
  69.  
  70.   /*** Ensure filespec specified ***/
  71.   printf("PCX2RAW 1.31  Copyright (c) 1993-1994 by Matthew Hildebrand\n\n");
  72.   if (argc < 2)
  73.   {
  74.     printf("        Usage:  PCX2RAW pcxfile[.pcx]\n\n"
  75.            "       Output:  pcxfile.raw -- TGE-format bitmap\n"
  76.            "                pcxfile.pal -- TGE-format palette\n\n"
  77.            "         Note:  PCX2RAW will only convert 256-colour PCX files.\n\n");
  78.     exit(EXIT_FAILURE);
  79.   }
  80.  
  81.   /*** Loop through, converting each file ***/
  82.   fnsplit(argv[1], fileDrive, fileDir, fileFile, fileExt);
  83.   assumeExtension(argv[1], ".PCX");
  84.   if ((done=findfirst(argv[1], &ffblk, 0)) != 0)
  85.     exit(EXIT_SUCCESS);
  86.   while (!done)
  87.   {
  88.     /*** Get the current filename ***/
  89.     strcpy(path, fileDrive);
  90.     strcat(path, fileDir);
  91.     strcat(path, ffblk.ff_name);
  92.  
  93.     /*** Convert the file ***/
  94.     strupr(path);
  95.     printf("\n\nProcessing file %s:\n", path);
  96.     convertFile(path);
  97.  
  98.     /*** Get the next filename ***/
  99.     done = findnext(&ffblk);
  100.   }
  101.  
  102.   printf("\n\n");
  103. }
  104.  
  105.  
  106.  
  107. /****
  108. ***** Convert a PCX file to a RAW file
  109. ****/
  110.  
  111. void convertFile(char *filename)
  112. {
  113.   uchar *lineBuf;
  114.   int wide, deep;
  115.   FILE *outFile;
  116.  
  117.   /*** Open the PCX file ***/
  118.   if (openPcxFile(filename, &wide, &deep, palette) != OK)
  119.   {
  120.     printf("Error processing file %s\n\n", filename);
  121.     exit(EXIT_FAILURE);
  122.   }
  123.  
  124.   /*** Allocate a line buffer ***/
  125.   if ((lineBuf=(uchar*)malloc(wide)) == NULL)
  126.   {
  127.     closePcxFile();                         /* close the PCX file */
  128.     printf("Out of memory\n\n");
  129.     exit(EXIT_FAILURE);
  130.   }
  131.  
  132.   /*** Create the output RAW file ***/
  133.   forceExtension(filename, ".RAW");
  134.   if ((outFile=fopen(filename,"wb")) == NULL)
  135.   {
  136.     closePcxFile();
  137.     printf("Error creating image file %s\n\n", filename);
  138.     exit(EXIT_FAILURE);
  139.   }
  140.  
  141.   /*** Translate the image data ***/
  142.   printf("Converting image data...");
  143.   fwrite(&wide, 2, 1, outFile);
  144.   fwrite(&deep, 2, 1, outFile);
  145.   if (translatePcxFile(outFile, lineBuf) != OK)
  146.   {
  147.     printf("\n\nError translating formats\n\n");
  148.     exit(EXIT_FAILURE);
  149.   }
  150.  
  151.   /*** Clean up ***/
  152.   free(lineBuf);
  153.   closePcxFile();
  154.   fclose(outFile);
  155.   printf(" Done.\n");
  156.  
  157.   /*** Open palette data file ***/
  158.   forceExtension(filename, ".PAL");
  159.   if ((outFile=fopen(filename,"wb")) == NULL)
  160.   {
  161.     printf("Error creating palette file %s\n\n", filename);
  162.     exit(EXIT_FAILURE);
  163.   }
  164.  
  165.   /*** Write palette data ***/
  166.   if (!fwrite(palette, 768, 1, outFile))
  167.   {
  168.     printf("Error writing palette file %s\n\n", filename);
  169.     fclose(outFile);
  170.     exit(EXIT_FAILURE);
  171.   }
  172.   fclose(outFile);
  173.   printf("Writing palette... Done.");
  174. }
  175.  
  176.  
  177.  
  178. /****
  179. ***** Filename manipulation routines.
  180. ****/
  181.  
  182. void assumeExtension(char *filename, char *defaultExt)
  183. {
  184.   char fileDrive[MAXDRIVE];
  185.   char fileDir[MAXDIR];
  186.   char fileFile[MAXFILE];
  187.   char fileExt[MAXEXT];
  188.   char newPath[MAXPATH];
  189.   int status;
  190.  
  191.   status = fnsplit(filename, fileDrive, fileDir, fileFile, fileExt);
  192.  
  193.   if (!(status&EXTENSION))
  194.     strcpy(fileExt, defaultExt);
  195.  
  196.   fnmerge(newPath, fileDrive, fileDir, fileFile, fileExt);
  197.   strcpy(filename, newPath);
  198. }
  199.  
  200. void forceExtension(char *filename, char *extention)
  201. {
  202.   char fileDrive[MAXDRIVE];
  203.   char fileDir[MAXDIR];
  204.   char fileFile[MAXFILE];
  205.   char fileExt[MAXEXT];
  206.  
  207.   fnsplit(filename, fileDrive, fileDir, fileFile, fileExt);
  208.  
  209.   if (strcmpi(fileExt, extention))
  210.     fnmerge(filename, fileDrive, fileDir, fileFile, extention);
  211. }
  212.  
  213.  
  214.  
  215. /****
  216. ***** Open a PCX file.
  217. ****/
  218.  
  219. int openPcxFile(char *filename, int *wide, int *deep, uchar *palette)
  220. {
  221.   /*** Open the file ***/
  222.   if ((inFile=fopen(filename,"rb")) == NULL)
  223.     return (OPEN_ERR);
  224.  
  225.   /*** Read in the header ***/
  226.   if (!fread((char *)&header, sizeof(PcxHeader), 1, inFile))
  227.   {
  228.     fclose(inFile);
  229.     return (READ_ERR);
  230.   }
  231.  
  232.   /*** Check to make sure it's a PCX ***/
  233.   if (header.manufacturer!=0x0A || header.version!=5)
  234.   {
  235.     fclose(inFile);
  236.     return (GENERAL_ERR);
  237.   }
  238.  
  239.   /*** Find the palette ***/
  240.   if (fseek(inFile, -769L, SEEK_END))
  241.   {
  242.     fclose(inFile);
  243.     return (SEEK_ERR);
  244.   }
  245.  
  246.   /*** Read in the palette data ***/
  247.   if (fgetc(inFile)!=0x0C || !fread(palette, 1, 768, inFile)==768)
  248.   {
  249.     fclose(inFile);
  250.     return (READ_ERR);
  251.   }
  252.  
  253.   /*** Seek to start of image data ***/
  254.   fseek(inFile, 128L, SEEK_SET);
  255.  
  256.   /*** Pass information back to caller ***/
  257.   width = (header.xmax - header.xmin) + 1;
  258.   depth = (header.ymax - header.ymin) + 1;
  259.   bytes = header.bytesPerLine;
  260.   *wide = width;
  261.   *deep = depth;
  262.   return (OK);
  263. }
  264.  
  265.  
  266.  
  267. /****
  268. ***** Translate a PCX file to a RAW file.
  269. ****/
  270.  
  271. int translatePcxFile(FILE *outFile, void *lineBuf)
  272. {
  273.   int i, status;
  274.  
  275.   /*** Convert the file, one line at a time ***/
  276.   for (i=0; i<depth; i++)
  277.   {
  278.     status = readPcxLine((uchar *)lineBuf, inFile);
  279.     if (status == OK)
  280.       fwrite(lineBuf, bytes, 1, outFile);   /* write the line */
  281.     else
  282.       return (status);                      /* return error code */
  283.   }
  284.  
  285.   /*** Return success or error code ***/
  286.   if (!ferror(outFile))
  287.     return (OK);
  288.   else
  289.     return (WRITE_ERR);
  290. }
  291.  
  292.  
  293.  
  294. /****
  295. ***** Read a single line of a PCX file.
  296. ****/
  297.  
  298. int readPcxLine(uchar *p, FILE *fp)
  299. {
  300.   int n=0;
  301.   register int c, i;
  302.  
  303.   /*** Null the buffer ***/
  304.   do
  305.   {
  306.     c = fgetc(fp) & 0xFF;                   /* get a key byte */
  307.     /*** If it's a run of bytes field ***/
  308.     if ((c&0xC0) == 0xC0)
  309.     {
  310.       i = c & 0x3F;                         /* AND off high bits */
  311.       c = fgetc(fp);                        /* get the run byte */
  312.       while (i--)                           /* run the byte */
  313.         p[n++] = c;
  314.     }
  315.     /*** Else just store it ***/
  316.     else
  317.       p[n++] = c;
  318.   }
  319.   while (n < bytes);
  320.  
  321.   return (ferror(fp) ? GENERAL_ERR : OK);
  322. }
  323.  
  324.  
  325.  
  326. /****
  327. ***** Close the PCX file.
  328. ****/
  329.  
  330. void closePcxFile(void)
  331. {
  332.   fclose(inFile);
  333. }
  334.