home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
-
- /*
- * spctoppm.c - Reads a compressed Spectrum file on stdin and writes
- * a portable pixmap (ppm) file on stdout.
- *
- * Copyright (C) 1990, Steve Belczyk
- */
-
- /* Remove the following definition if you don't want raw ppm files */
- #define RAWBITS
-
- char screen[32000];
- short sscreen[16000];
- int pal[200][48];
- long colormap_length, bitmap_length;
-
- main (argc, argv)
- int argc;
- char *argv[];
- {
- char c1, c2;
-
- /* Check for bogus arguments */
- if (argc > 1)
- {
- fprintf (stderr, "usage: %s <spcfile >ppmfile\n",
- argv[0]);
- exit (-1);
- }
-
- /* Check SPC file header */
- c1 = getchar();
- c2 = getchar();
-
- if ( ('S' != c1) || ('P' != c2) )
- {
- fprintf (stderr, "Not a Spectrum picture.\n");
- exit (-1);
- }
-
- /* Skip reserved bytes */
- getchar(); getchar();
-
- /* Get length of bitmap data */
- bitmap_length = GetLong();
-
- /* and colormap */
- colormap_length = GetLong();
-
- /* Process bitmap */
- DoBitmap();
-
- /* Process colormap */
- DoColormap();
-
- /* Write the PPM file */
- WritePPM();
- }
-
- long GetLong()
- {
- long l;
-
- l = (0xff & getchar()) << 24;
- l |= (0xff & getchar()) << 16;
- l |= (0xff & getchar()) << 8;
- l |= 0xff & getchar();
-
- return (l);
- }
-
- int GetWord()
- {
- int w;
-
- w = (0xff & getchar()) << 8;
- w |= 0xff & getchar();
-
- return (w);
- }
-
- DoBitmap()
- {
- int i;
- long count, data;
- char h, c;
-
- /* Zero out first scan line */
- for (i=0; i<160; screen[i++]=0);
-
- /* 'count' counts number of input bytes */
- count = 0;
-
- /* 'data' counts just data bytes */
- data = 0;
-
- while (count < bitmap_length)
- {
- /* Get next record header */
- h = getchar(); count++;
-
- if ( (h >= 0) && (count < bitmap_length) )
- {
- for (i=0; i<=h; i++)
- {
- c = getchar(); count++;
- DoChar (data, c);
- data++;
- }
- }
- else if ( (h < 0) && (count < bitmap_length) )
- {
- c = getchar(); count++;
-
- for (i=0; i<(2-h); i++)
- {
- DoChar (data, c);
- data++;
- }
- }
- }
-
- /* Convert the char version of the screen to short */
- for (i=0; i<16000; i++)
- {
- sscreen[i] = (screen[i<<1] << 8) +
- (0xff & screen[(i<<1)+1]);
- }
- }
-
- DoChar (n, c)
- int n;
- char c;
- {
- int i;
-
- /* Compute screen index */
- i = 160 + 2*(n/7960) + 8*((n%7960)/2) + (n&1);
- screen[i] = c;
- }
-
- DoColormap()
- {
- int i, j, mask, bit, count;
-
- count = 0;
-
- /* Clear first three palettes */
- for (i=0; i<48; pal[0][i++]=0);
-
- for (i=1; i<200; i++)
- {
- for (j=0; j<3; j++)
- {
- mask = GetWord(); count+=2;
- for (bit=0; bit<15; bit++)
- {
- if (mask & (1 << bit))
- {
- pal[i][(j*16)+bit] = GetWord();
- count += 2;
- }
- }
- }
- }
- }
-
- WritePPM()
- {
- int x, y;
-
- /* Write the PPM header */
- #ifdef RAWBITS
- printf ("P6\n320 200\n255\n"); /* Magic, resolution, maxpix */
- #else
- printf ("P3\n320 200\n255\n");
- #endif
-
- /* Loop through pixels */
- for (y=0; y<200; y++)
- {
- for (x=0; x<320; x++)
- {
- DoPixel (x, y);
- }
- }
- }
-
- DoPixel (x, y)
- int x, y;
- {
- int c, x1;
-
- c = GetPixel (x, y);
-
- /* Compute palette index */
- x1 = 10 * c;
-
- if (1 & c)
- {
- x1 -= 5;
- }
- else
- {
- x1++;
- }
-
- if ( (x >= x1) && (x < (x1+160)) ) c += 16;
- if (x >= (x1+160)) c += 32;
-
- /* Write the proper color */
- DoColor (pal[y][c]);
- }
-
- DoColor (p)
- int p;
- {
- int r, g, b;
-
- r = (0x700 & p) >> 3;
- g = (0x070 & p) << 1;
- b = (0x007 & p) << 5;
-
- #ifdef RAWBITS
- putchar (0xff & r);
- putchar (0xff & g);
- putchar (0xff & b);
- #else
- printf ("%d %d %d\n", r, g, b);
- #endif
- }
-
- int GetPixel (x, y)
- int x, y;
- {
- int c, index, bit, plane;
-
- c = 0;
-
- /* index = (80*y) + 4*(x/16); */
- index = (y << 6) + (y << 4) + ((x >> 4) << 2);
-
- /* bit = 0x8000 >> (x % 16); */
- bit = 0x8000 >> (x & 0x0f);
-
- for (plane=0; plane<4; plane++)
- {
- if (bit & sscreen[index+plane])
- {
- c |= (1 << plane);
- }
- }
- return (c);
- }
-
-