home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / pcxtoppm.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  8KB  |  357 lines

  1. /*
  2.  * pcxtoppm.c - Converts from a PC Paintbrush PCX file to a PPM file.
  3.  *
  4.  * Copyright (c) 1990 by Michael Davidson
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose and without fee is hereby granted,
  8.  * provided that the above copyright notice appear in all copies and that
  9.  * both that copyright notice and this permission notice appear in
  10.  * supporting documentation.
  11.  *
  12.  * This file is provided AS IS with no warranties of any kind.  The author
  13.  * shall have no liability with respect to the infringement of copyrights,
  14.  * trade secrets or any patents by this file or any part thereof.  In no
  15.  * event will the author be liable for any lost revenue or profits or
  16.  * other special, indirect and consequential damages.
  17.  *
  18.  */
  19.  
  20. #include    <stdio.h>
  21. #include    "ppm.h"
  22.  
  23. #define    PCX_MAGIC    0x0a        /* PCX magic number        */
  24. #define    PCX_HDR_SIZE    128        /* size of PCX header        */
  25. #define    PCX_256_COLORS    0x0c        /* magic number for 256 colors    */
  26.  
  27. #define    MAXCOLORS       256
  28. #define    MAXPLANES    4
  29. #define    PCX_MAXVAL    255
  30.  
  31. static void read_pcx_image ARGS(( FILE *fp, unsigned char *buf, int BytesPerLine, int Planes, int Height ));
  32. static void pcx_planes_to_pixels ARGS(( unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel ));
  33. static void pcx_unpack_pixels ARGS(( unsigned char *pixels, unsigned char *bitplanes, int bytesperline, int planes, int bitsperpixel ));
  34. static int GetByte ARGS(( FILE *fp ));
  35. static int GetWord ARGS(( FILE *fp ));
  36.  
  37. int
  38. main(argc, argv)
  39.     int        argc;
  40.     char    *argv[];
  41. {
  42.     register int    i;
  43.     FILE        *ifp;
  44.     char        *ifname;
  45.     int            Version;
  46.     int            Xmin, Ymin, Xmax, Ymax;
  47.     int            Width, Height;
  48.     register int    x, y;
  49.     int            Planes;
  50.     int            BitsPerPixel;
  51.     int            BytesPerLine;
  52.     unsigned char    Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  53.     unsigned char    *pcximage;
  54.     unsigned char    *pcxplanes;
  55.     unsigned char    *pcxpixels;
  56.     pixel        **pixels;
  57.  
  58.  
  59.     ppm_init( &argc, argv );
  60.  
  61.     switch (argc)
  62.     {
  63.      case 1:
  64.          ifname    = "standard input";
  65.          ifp    = stdin;
  66.          break;
  67.      case 2:
  68.          ifname    = argv[1];
  69.          ifp    = pm_openr(ifname);
  70.          break;
  71.      default:
  72.          pm_usage("[pcxfile]");
  73.          break;
  74.     }
  75.  
  76.     /*
  77.      * read the PCX header
  78.      */
  79.     if (GetByte(ifp) != PCX_MAGIC)
  80.      pm_error("%s is not a PCX file", ifname );
  81.  
  82.     Version    = GetByte(ifp);     /* get version #            */
  83.  
  84.     if (GetByte(ifp) != 1)     /* check for PCX run length encoding    */
  85.      pm_error("%s has unknown encoding scheme", ifname );
  86.  
  87.     BitsPerPixel= GetByte(ifp);
  88.     Xmin    = GetWord(ifp);
  89.     Ymin    = GetWord(ifp);
  90.     Xmax    = GetWord(ifp);
  91.     Ymax    = GetWord(ifp);
  92.  
  93.     Width    = (Xmax - Xmin) + 1;
  94.     Height    = (Ymax - Ymin) + 1;
  95.  
  96.     (void) GetWord(ifp);        /* ignore horizontal resolution    */
  97.     (void) GetWord(ifp);        /* ignore vertical resolution    */
  98.  
  99.     /*
  100.      * get the 16-color color map
  101.      */
  102.     for (i = 0; i < 16; i++)
  103.     {
  104.      Red[i]       = GetByte(ifp);
  105.      Green[i]  = GetByte(ifp);
  106.      Blue[i]   = GetByte(ifp);
  107.     }
  108.  
  109.     (void) GetByte(ifp);        /* skip reserved byte     */
  110.     Planes    = GetByte(ifp);        /* # of color planes     */
  111.     BytesPerLine= GetWord(ifp);        /* # of bytes per line     */
  112.     (void) GetWord(ifp);        /* ignore palette info     */
  113.  
  114.     /*
  115.      * check that we can handle this image format
  116.      */
  117.     switch (BitsPerPixel)
  118.     {
  119.     case 1:
  120.         if (Planes > 4)
  121.         pm_error("can't handle image with more than 4 planes");
  122.         break;
  123.  
  124.     case 2:
  125.     case 4:
  126.     case 8:
  127.         if (Planes == 1)
  128.         break;
  129.     default:
  130.         pm_error("can't handle %d bits per pixel image with %d planes",
  131.             BitsPerPixel,Planes);
  132.     }
  133.  
  134.  
  135.     /*
  136.      * read the pcx format image
  137.      */
  138.     fseek(ifp, (long)PCX_HDR_SIZE, 0);
  139.     pcximage    = (unsigned char *)pm_allocrow(BytesPerLine * Planes, Height);
  140.     read_pcx_image(ifp, pcximage, BytesPerLine, Planes, Height);
  141.  
  142.     /*
  143.      * 256 color images have their color map at the end of the file
  144.      * preceeded by a magic byte
  145.      */
  146.     if (BitsPerPixel == 8)
  147.     {
  148.     if (GetByte(ifp) != PCX_256_COLORS)
  149.         pm_error("bad color map signature" );
  150.  
  151.     for (i = 0; i < MAXCOLORS; i++)
  152.     {
  153.         Red[i]    = GetByte(ifp);
  154.         Green[i]    = GetByte(ifp);
  155.         Blue[i]    = GetByte(ifp);
  156.     }
  157.     }
  158.  
  159.     pixels    = ppm_allocarray(Width, Height);
  160.     pcxpixels    = (unsigned char *)pm_allocrow(Width+7, 1);
  161.  
  162.     /*
  163.      * convert the image
  164.      */
  165.     for (y = 0; y < Height; y++)
  166.     {
  167.      pcxplanes = pcximage + (y * BytesPerLine * Planes);
  168.  
  169.      if (Planes == 1)
  170.      {
  171.          pcx_unpack_pixels(pcxpixels, pcxplanes,
  172.           BytesPerLine, Planes, BitsPerPixel);
  173.      }
  174.      else
  175.      {
  176.          pcx_planes_to_pixels(pcxpixels, pcxplanes,
  177.           BytesPerLine, Planes, BitsPerPixel);
  178.      }
  179.  
  180.      for (x = 0; x < Width; x++)
  181.      {
  182.          i = pcxpixels[x];
  183.          PPM_ASSIGN(pixels[y][x], Red[i], Green[i], Blue[i]);
  184.      }
  185.     }
  186.  
  187.     pm_close(ifp);
  188.  
  189.     ppm_writeppm(stdout, pixels, Width, Height, (pixval) 255, 0 );
  190.  
  191.     pm_close(stdout);
  192.  
  193.     exit(0);
  194. }
  195.  
  196. static void
  197. read_pcx_image(fp, buf, BytesPerLine, Planes, Height)
  198.     FILE    *fp;
  199.     unsigned char   *buf;
  200.     int         BytesPerLine;
  201.     int         Planes;
  202.     int         Height;
  203. {
  204.     int        c;
  205.     int        nbytes;
  206.     int        count;
  207.  
  208.     nbytes    = BytesPerLine * Planes * Height;
  209.  
  210.     while (nbytes > 0)
  211.     {
  212.      c    = GetByte(fp);
  213.      if ((c & 0xc0) != 0xc0)
  214.      {
  215.          *buf++    = c;
  216.          --nbytes;
  217.          continue;
  218.      }
  219.  
  220.      count    = c & 0x3f;
  221.      c    = GetByte(fp);
  222.      if (count > nbytes)
  223.          pm_error("repeat count spans end of image, count = %d, nbytes = %d", count, nbytes);
  224.  
  225.      nbytes    -= count;
  226.      while (--count >= 0)
  227.          *buf++ = c;
  228.     }
  229. }
  230.  
  231. /*
  232.  * convert multi-plane format into 1 pixel per byte
  233.  */
  234. static void
  235. pcx_planes_to_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
  236. unsigned char    *pixels;
  237. unsigned char    *bitplanes;
  238. int        bytesperline;
  239. int         planes;
  240. int         bitsperpixel;
  241. {
  242.     int     i, j;
  243.     int     npixels;
  244.     unsigned char    *p;
  245.  
  246.     if (planes > 4)
  247.      pm_error("can't handle more than 4 planes" );
  248.     if (bitsperpixel != 1)
  249.      pm_error("can't handle more than 1 bit per pixel" );
  250.  
  251.     /*
  252.      * clear the pixel buffer
  253.      */
  254.     npixels = (bytesperline * 8) / bitsperpixel;
  255.     p    = pixels;
  256.     while (--npixels >= 0)
  257.      *p++ = 0;
  258.  
  259.     /*
  260.      * do the format conversion
  261.      */
  262.     for (i = 0; i < planes; i++)
  263.     {
  264.      int pixbit, bits, mask;
  265.  
  266.      p    = pixels;
  267.      pixbit    = (1 << i);
  268.      for (j = 0; j < bytesperline; j++)
  269.      {
  270.          bits = *bitplanes++;
  271.          for (mask = 0x80; mask != 0; mask >>= 1, p++)
  272.           if (bits & mask)
  273.               *p |= pixbit;
  274.      }
  275.      }
  276. }
  277.  
  278. /*
  279.  * convert packed pixel format into 1 pixel per byte
  280.  */
  281. static void
  282. pcx_unpack_pixels(pixels, bitplanes, bytesperline, planes, bitsperpixel)
  283. unsigned char   *pixels;
  284. unsigned char   *bitplanes;
  285. int        bytesperline;
  286. int         planes;
  287. int         bitsperpixel;
  288. {
  289.     register int    bits;
  290.  
  291.     if (planes != 1)
  292.      pm_error("can't handle packed pixels with more than 1 plane" );
  293.     if (bitsperpixel == 8)
  294.     {
  295.     while (--bytesperline >= 0)
  296.         *pixels++ = *bitplanes++;
  297.     }
  298.     else if (bitsperpixel == 4)
  299.     {
  300.     while (--bytesperline >= 0)
  301.     {
  302.         bits    = *bitplanes++;
  303.         *pixels++    = (bits >> 4) & 0x0f;
  304.         *pixels++    = (bits     ) & 0x0f;
  305.     }
  306.     }
  307.     else if (bitsperpixel == 2)
  308.     {
  309.     while (--bytesperline >= 0)
  310.     {
  311.         bits    = *bitplanes++;
  312.         *pixels++    = (bits >> 6) & 0x03;
  313.         *pixels++    = (bits >> 4) & 0x03;
  314.         *pixels++    = (bits >> 2) & 0x03;
  315.         *pixels++    = (bits     ) & 0x03;
  316.     }
  317.     }
  318.     else if (bitsperpixel == 1)
  319.     {
  320.     while (--bytesperline >= 0)
  321.     {
  322.         bits    = *bitplanes++;
  323.         *pixels++    = ((bits & 0x80) != 0);
  324.         *pixels++    = ((bits & 0x40) != 0);
  325.         *pixels++    = ((bits & 0x20) != 0);
  326.         *pixels++    = ((bits & 0x10) != 0);
  327.         *pixels++    = ((bits & 0x08) != 0);
  328.         *pixels++    = ((bits & 0x04) != 0);
  329.         *pixels++    = ((bits & 0x02) != 0);
  330.         *pixels++    = ((bits & 0x01) != 0);
  331.     }
  332.     }
  333. }
  334.  
  335. static int
  336. GetByte(fp)
  337. FILE    *fp;
  338. {
  339.     int    c;
  340.  
  341.     if ((c = getc(fp)) == EOF)
  342.      pm_error("unexpected end of file" );
  343.  
  344.     return c;
  345. }
  346.  
  347. static int
  348. GetWord(fp)
  349. FILE    *fp;
  350. {
  351.     int    c;
  352.  
  353.     c  = GetByte(fp);
  354.     c |= (GetByte(fp) << 8);
  355.     return c;
  356. }
  357.