home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume14 / ataritoppm / part01 / spctoppm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-15  |  3.6 KB  |  257 lines

  1. #include <stdio.h>
  2.  
  3. /*
  4.  *  spctoppm.c - Reads a compressed Spectrum file on stdin and writes
  5.  *  a portable pixmap (ppm) file on stdout.
  6.  *
  7.  *  Copyright (C) 1990, Steve Belczyk
  8.  */
  9.  
  10. /* Remove the following definition if you don't want raw ppm files */
  11. #define RAWBITS
  12.  
  13. char    screen[32000];
  14. short    sscreen[16000];
  15. int    pal[200][48];
  16. long    colormap_length, bitmap_length;
  17.  
  18. main (argc, argv)
  19. int argc;
  20. char *argv[];
  21. {
  22.     char c1, c2;
  23.  
  24.     /* Check for bogus arguments */
  25.     if (argc > 1)
  26.     {
  27.         fprintf (stderr, "usage: %s <spcfile >ppmfile\n",
  28.              argv[0]);
  29.         exit (-1);
  30.     }
  31.  
  32.     /* Check SPC file header */
  33.     c1 = getchar();
  34.     c2 = getchar();
  35.  
  36.     if ( ('S' != c1) || ('P' != c2) )
  37.     {
  38.         fprintf (stderr, "Not a Spectrum picture.\n");
  39.         exit (-1);
  40.     }
  41.  
  42.     /* Skip reserved bytes */
  43.     getchar(); getchar();
  44.  
  45.     /* Get length of bitmap data */
  46.     bitmap_length = GetLong();
  47.  
  48.     /* and colormap */
  49.     colormap_length = GetLong();
  50.  
  51.     /* Process bitmap */
  52.     DoBitmap();
  53.  
  54.     /* Process colormap */
  55.     DoColormap();
  56.  
  57.     /* Write the PPM file */
  58.     WritePPM();
  59. }
  60.  
  61. long GetLong()
  62. {
  63.     long l;
  64.  
  65.     l  = (0xff & getchar()) << 24;
  66.     l |= (0xff & getchar()) << 16;
  67.     l |= (0xff & getchar()) << 8;
  68.     l |=  0xff & getchar();
  69.  
  70.     return (l);
  71. }
  72.  
  73. int GetWord()
  74. {
  75.     int w;
  76.  
  77.     w  = (0xff & getchar()) << 8;
  78.     w |=  0xff & getchar();
  79.  
  80.     return (w);
  81. }
  82.  
  83. DoBitmap()
  84. {
  85.     int i;
  86.     long count, data;
  87.     char h, c;
  88.  
  89.     /* Zero out first scan line */
  90.     for (i=0; i<160; screen[i++]=0);
  91.  
  92.     /* 'count' counts number of input bytes */
  93.     count = 0;
  94.  
  95.     /* 'data' counts just data bytes */
  96.     data = 0;
  97.  
  98.     while (count < bitmap_length)
  99.     {
  100.         /* Get next record header */
  101.         h = getchar(); count++;
  102.  
  103.         if ( (h >= 0) && (count < bitmap_length) )
  104.         {
  105.             for (i=0; i<=h; i++)
  106.             {
  107.                 c = getchar(); count++;
  108.                 DoChar (data, c);
  109.                 data++;
  110.             }
  111.         }
  112.         else if ( (h < 0) && (count < bitmap_length) )
  113.         {
  114.             c = getchar(); count++;
  115.  
  116.             for (i=0; i<(2-h); i++)
  117.             {
  118.                 DoChar (data, c);
  119.                 data++;
  120.             }
  121.         }
  122.     }
  123.  
  124.     /* Convert the char version of the screen to short */
  125.     for (i=0; i<16000; i++)
  126.     {
  127.         sscreen[i] = (screen[i<<1] << 8) +
  128.                      (0xff & screen[(i<<1)+1]);
  129.     }
  130. }
  131.  
  132. DoChar (n, c)
  133. int n;
  134. char c;
  135. {
  136.     int i;
  137.  
  138.     /* Compute screen index */
  139.     i = 160 + 2*(n/7960) + 8*((n%7960)/2) + (n&1);
  140.     screen[i] = c;
  141. }
  142.  
  143. DoColormap()
  144. {
  145.     int i, j, mask, bit, count;
  146.  
  147.     count = 0;
  148.  
  149.     /* Clear first three palettes */
  150.     for (i=0; i<48; pal[0][i++]=0);
  151.  
  152.     for (i=1; i<200; i++)
  153.     {
  154.         for (j=0; j<3; j++)
  155.         {
  156.             mask = GetWord(); count+=2;
  157.             for (bit=0; bit<15; bit++)
  158.             {
  159.                 if (mask & (1 << bit))
  160.                 {
  161.                     pal[i][(j*16)+bit] = GetWord();
  162.                     count += 2;
  163.                 }
  164.             }
  165.         }
  166.     }
  167. }
  168.  
  169. WritePPM()
  170. {
  171.     int x, y;
  172.  
  173.     /* Write the PPM header */
  174. #ifdef RAWBITS
  175.     printf ("P6\n320 200\n255\n"); /* Magic, resolution, maxpix */
  176. #else
  177.     printf ("P3\n320 200\n255\n");
  178. #endif
  179.  
  180.     /* Loop through pixels */
  181.     for (y=0; y<200; y++)
  182.     {
  183.         for (x=0; x<320; x++)
  184.         {
  185.             DoPixel (x, y);
  186.         }
  187.     }
  188. }
  189.  
  190. DoPixel (x, y)
  191. int x, y;
  192. {
  193.     int c, x1;
  194.  
  195.     c = GetPixel (x, y);
  196.  
  197.     /* Compute palette index */
  198.     x1 = 10 * c;
  199.  
  200.     if (1 & c)
  201.     {
  202.         x1 -= 5;
  203.     }
  204.     else
  205.     {
  206.         x1++;
  207.     }
  208.  
  209.     if ( (x >= x1) && (x < (x1+160)) ) c += 16;
  210.     if (x >= (x1+160)) c += 32;
  211.  
  212.     /* Write the proper color */
  213.     DoColor (pal[y][c]);
  214. }
  215.  
  216. DoColor (p)
  217. int p;
  218. {
  219.     int r, g, b;
  220.  
  221.     r = (0x700 & p) >> 3;
  222.     g = (0x070 & p) << 1;
  223.     b = (0x007 & p) << 5;
  224.  
  225. #ifdef RAWBITS
  226.     putchar (0xff & r);
  227.     putchar (0xff & g);
  228.     putchar (0xff & b);
  229. #else
  230.     printf ("%d %d %d\n", r, g, b);
  231. #endif
  232. }
  233.  
  234. int GetPixel (x, y)
  235. int x, y;
  236. {
  237.     int c, index, bit, plane;
  238.  
  239.     c = 0;
  240.  
  241. /*    index = (80*y) + 4*(x/16);    */
  242.     index = (y << 6) + (y << 4) + ((x >> 4) << 2);
  243.  
  244. /*    bit = 0x8000 >> (x % 16);    */
  245.     bit = 0x8000 >> (x & 0x0f);
  246.  
  247.     for (plane=0; plane<4; plane++)
  248.     {
  249.         if (bit & sscreen[index+plane])
  250.         {
  251.             c |= (1 << plane);
  252.         }
  253.     }
  254.     return (c);
  255. }
  256.  
  257.