
/*
**
**  TARGA File 'COMPress' program
**
**  Written by Brian Reed  Copyright 1989
**  This file is provided as a sample for reading TARGA 'type 2' images.
**
**  This program runs only from the CLI, and requires two parameters.
**  The parameters are the file names for the input and output files.
**  They MUST not be the same file.  This COMPs only 'uncompressed RGB
**  (type 2)' 24-bit TARGA files, to (type 10) RLE files.
**
**  -  Error checking (file i/o) could stand to be improved.
**
*/

/*  include files  */
#include <exec/types.h>
#include <stdio.h>

FILE *fopen(), *infile=0, *outfile=0;
char output[82], input[82];
int  pixels_x, pixels_y, offset_x, offset_y, file_id_len, header_len, bpl;
unsigned char pixel_line[20000], compressed_line[25000];
unsigned char header_buffer[20], file_id_buffer[256];

/*  This is it...  */
main(argc, argv)
int argc;
char *argv[];
{
int i, temp;
char choice[80];

  if (argc != 3 || (!strcmp(argv[1], "?")) ) {
    printf("Usage:  COMPRESS input output\n");
    exit(0);
  }
  if ( (!strcmp(argv[1], argv[2])) ) {
    printf("Filenames must be different.\n");
    exit(0);
  }

  read_targa_header(argv[1]);
  header_buffer[2] = 10;            /*  Compressed RGB (RLE)  */
  write_targa_header(argv[2]);

  for (i=0; i<pixels_y; i++) {
    if (read_targa_line())
      write_targa_line();
  }

  done("Done!");
}

read_targa_header(name)
char *name;
{
int size=1;

  /*  Open file  */
   if ((infile = fopen(name, "r")) == NULL)
     done("Couldn't open infile for reading.");

  /*************  Fields 1 thru 5:                *********/
    size = 18;
    fread(header_buffer, size, 1L, infile);

    if (header_buffer[2] != 2)
      done("Not a type 2 file.");
    if (header_buffer[16] != 24)
      done("Not a 24 bit/pixel file.");

  /*************  Field 6:  Image ID field    *************/
    file_id_len = header_buffer[0];
    header_len = file_id_len + 18;
    fread(file_id_buffer, file_id_len, 1L, infile);
    file_id_buffer[file_id_len] = 0;

  /*************  Set image stats  ***************/
    offset_x = header_buffer[9] * 256 + header_buffer[8];
    offset_y = header_buffer[11] * 256 + header_buffer[10];
    pixels_x = header_buffer[13] * 256 + header_buffer[12];
    bpl = pixels_x * 3;   /*  BytesPerLine  */
    pixels_y = header_buffer[15] * 256 + header_buffer[14];
    printf("Picture size is %d x %d\n", pixels_x, pixels_y);
}

read_targa_line()
{
ULONG offset;

  if (fread(pixel_line, bpl, 1L, infile) != 1)
    return(0);
  return(1);
}

write_targa_header(name)
char *name;
{
int size = 18;
int lsb, msb;

  if ((outfile = fopen(name, "w")) == NULL)
    done("Couldn't open outfile for writing.");
  /*  Write header and ID.  */
  fwrite(header_buffer, size, 1L, outfile);
  fwrite(file_id_buffer, file_id_len, 1L, outfile);
}

write_targa_line()
{
register char *source=0, *dest=0,  *sourcepos=0, *destpos=0;
char sr,sg, sb;
int rep_count;

  source = pixel_line;
  dest = compressed_line;

  /*  Put together a RAW or RLE packet.  */
  while (sourcepos < pixels_x*3) {
    sr = *(source + sourcepos + 2);
    sg = *(source + sourcepos + 1);
    sb = *(source + sourcepos + 0);
    rep_count = 1;
    while (rep_count < 128) {
      sourcepos += 3;
      if ( *(source + sourcepos + 2) != sr
       ||  *(source + sourcepos + 1) != sg
       ||  *(source + sourcepos + 0) != sb )
        break;
      rep_count++;
    }
    if (rep_count == 1)
      dest[destpos+0] = 0;                   /*  One byte RAW packet  */
    else
      dest[destpos+0] = 127 + rep_count;     /*  RLE packet  */
    dest[destpos+1] = sb;                  /*  Really it's 128 (bitON),  */
    dest[destpos+2] = sg;                  /*  + rep_count - 1.          */
    dest[destpos+3] = sr;
    destpos += 4;
  }

  if (fwrite(compressed_line, destpos, 1L, outfile) != 1)
    done("Couldn't write 24-bit line");
}

/*
write_uncompressed_targa_line()
{
  if (fwrite(pixel_line, bpl, 1L, outfile) != 1)
    done("Couldn't write 24-bit line");
}
*/

done(s)
char *s;
{
  if (infile)  fclose(infile);
  if (outfile)  fclose(outfile);
  if (s)  printf("COMPRESS: %s\n", s);
  exit(0);
}

