/* TGA to interlaced conversion program */ #include #include #include #include #define LINE_SIZE 320 #define TOT_LINES 200 #define VGA_MEM 0xa0000000 #define BIOSVID 0x10 #define VGA256 0x13 #define TEXT 0x3 #define SETMODE 0 /* avg takes the average of two values a and b */ #define avg(a,b) ((a + b) / 2) /* diff takes the difference of two values a and b, modulo 256 */ #define diff(a,b) (a - b) /* Declare a variable type that holds the image information */ typedef struct { char identsize; char colormaptype; char imagetype; unsigned int colormapstart; unsigned int colormaplength; char colormapbits; unsigned int xstart; unsigned int ystart; unsigned int width, depth; char bits; char descriptor; } TGAHEAD; /* Declare variable types for various buffers */ typedef char linebuffer[LINE_SIZE]; typedef unsigned char avgbuffer[LINE_SIZE]; typedef char palbuffer[768]; /* Function declarations */ void graphics (void); void text (void); void convert (FILE *fp, FILE *out); void paletteset (char *buffer); void putline(char *buffer, unsigned int n, int width); void getline(char *buffer, unsigned int n, int width); void error (char *message); void main (int argc, char *argv[]) { FILE *fp, *out; /* Make sure two filenames were entered */ if(argc > 2) { /* Open the files */ if((fp = fopen (argv[1], "rb")) != NULL) { if((out = fopen (argv[2], "wb")) != NULL) { graphics(); /* Convert the file to Haar format */ convert(fp, out); /* Close the files */ fclose(fp); fclose(out); getch(); text(); puts("Done.\n"); } else printf("Error opening %s for output\n", argv[2]); } else printf("Error opening %s for input\n", argv[1]); } else puts("Must specify a filename for both input and output\n"); } /* The graphics function puts the screen in graphics mode */ void graphics (void) { union REGS regs; regs.h.ah = SETMODE; regs.h.al = VGA256; int86(BIOSVID, ®s, ®s); } /* The text function returns the screen to text mode */ void text (void) { union REGS regs; regs.h.ah = SETMODE; regs.h.al = TEXT; int86(BIOSVID, ®s, ®s); } /* The decode function reads and displays the TGA file */ void convert (FILE *fp, FILE * out) { TGAHEAD tga; int bytes, i, n, startline, endline, incline; char *ptr; char temp; linebuffer buf1, buf2, diffbuf; avgbuffer avgbuf, avgbuf1, avgbuf2; palbuffer buffer; /* Read the header for the file */ if (fread((char *)&tga, 1, sizeof(TGAHEAD), fp)==sizeof(TGAHEAD)) { if(tga.imagetype == 0x01 || tga.imagetype == 0x02 || tga.imagetype == 0x03 || tga.imagetype == 0x09 || tga.imagetype == 0x0a || tga.imagetype == 0x0b) { /* Change the image type so that the reader will know that the file it is reading is an interlaced file */ tga.imagetype = 129 + tga.imagetype; /* Make sure the image in the output file is 0 bytes away */ tga.identsize = 0; /* Write the header to the output file */ fwrite((char *)&tga, 1, sizeof(TGAHEAD), out); /* Make sure the dimensions of the image are all right */ if(tga.width > LINE_SIZE) error("Can only handle images of dimension 320x200\n"); if(tga.depth > TOT_LINES) error("Can only handle images of dimension 320x200\n"); /* Read until the beginning of the image is reached */ fseek(fp, (long)tga.identsize, SEEK_CUR); /* See if the file has an valid number of colors */ if(tga.colormaptype) { switch(tga.colormapbits) { case 24: for(i = tga.colormapstart; i < tga.colormaplength; i++) { if(i >= 256) break; buffer[i * 3 + 2] = fputc(fgetc(fp), out); buffer[i * 3 + 1] = fputc(fgetc(fp), out); buffer[i * 3] = fputc(fgetc(fp), out); } break; case 16: for(i = tga.colormapstart; i < tga.colormaplength; i++) { if(i >= 256) break; n = ((fputc(fgetc(fp), fp) & 0xff) + ((fputc(fgetc(fp), fp) & 0xff) << 8)); buffer[i * 3 + 2] = ((n >> 10) & 0x1f) << 3; buffer[i * 3 + 1] = ((n >> 5 ) & 0x1f) << 3; buffer[i * 3] = (n & 0x1f) << 3; } break; } paletteset(buffer); } else { if(tga.imagetype==3) { for(i=0; i<=255; i++) { buffer[i * 3] = i; buffer[i * 3 + 1] = i; buffer[i * 3 + 2] = i; } paletteset(buffer); } error("Image must be greyscale or have a palette\n"); } /* Set up the options for what is to be converted */ startline = 0; endline = tga.depth; incline = 1; /* Convert the image */ for(i = startline; i < endline; i += incline) { fread(&buf1, 1, tga.width, fp); putline(buf1, (i % 4) * tga.depth / 4 + (i / 4), tga.width); } /* Finally, write the converted image to disk */ for(i = startline; i < endline; i++) { getline(buf1, i, tga.width); fwrite(&buf1, 1, tga.width, out); } } } } /* The paletteset function sets the color palette */ void paletteset (char *buffer) { union REGS regs; int i; outp(0x3c6, 0xff); for(i = 0; i < 255; i++) { outp(0x3c8, i); outp(0x3c9, (*buffer++) >> 2); outp(0x3c9, (*buffer++) >> 2); outp(0x3c9, (*buffer++) >> 2); } } /* The putline function displays one line of the image */ void putline(char *buffer, unsigned int n, int width) { char far *ScreenMemory = (char far *)(VGA_MEM + n * LINE_SIZE); int j; for(j = 0; j < width; j++) *(ScreenMemory + j) = buffer[j]; } /* The getline function reads a line of the image from screen memory */ void getline(char *buffer, unsigned int n, int width) { char far *ScreenMemory = (char far *)(VGA_MEM + n * LINE_SIZE); int j; for(j = 0; j < width; j++) *(buffer + j) = *(ScreenMemory + j); } /* The error function displays an error message and halts the program */ void error (char *message) { puts(message); exit(1); }