
/*
**
**  TARGA File 'show' program
**  Written by Brian Reed  Copyright 1988
**  This file is provided as a sample for reading TARGA 'type 2' images.
**
**  This program runs only from the CLI, and will prompt you for the
**  name of the TARGA file you wish to display.  This displays only
**  'type 2 (uncompressed RGB)' TARGA files.
**
**  -  Error checking (file i/o) could stand to be improved.
**  -  This will display an Opticks TARGA file.  It may display files
**     from other sources upside down, as it does not pay attention
**     to the ORIGIN bit for top/bottom image start line.
**
*/

/*  My MANX makefile:
CFLAGS = +l -s
LIBS = df0:lib32/m32.lib df0:lib32/c32.lib

.c.o:
      cc $(CFLAGS) -o $@ $*.c

tshow: tshow.o
  ln tshow.o $(LIBS)
*/

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

/*  Library return types  */
extern struct Screen *OpenScreen();
extern struct Window *OpenWindow();

/*  Global variables  */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *screen;
struct Window *window;
char in[82], out[82], input[82];
int  pixels_x, pixels_y;
unsigned char pixel_line[12000], buffer[1000], namebuffer[256];
struct TextAttr Font80 = {"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT};
FILE *fopen(), *infile;


/*  This is it...  */
main()
{
int  i;

  printf("Enter the TARGA file name - (Q=Quit) -  ");
  scanf("%s", &in[0]);
  if (in[0] == 'q' || in[0] == 'Q')
    done(NULL);

  read_targa_header();
  if (pixels_x > 640 || pixels_y > 400)
    done("Picture too big!");

  open_stuff();

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

  done(NULL);
}

read_targa_header(name)
char *name;
{
int  temp, namelen, i;
int size=1;
char string[84];

  /*  Open file  */
   strcpy(&string[0], in);
   strcat(&string[0], ".TGA");
   if ((infile = fopen(&string[0], "r")) == NULL)
     done("Couldn't open infile for reading.");

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

  /*************  Field 6:  Image ID field    *************/
  namelen = buffer[0];
  fread(namebuffer, namelen, 1L, infile);
  namebuffer[namelen] = 0;

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

  pixels_x = buffer[13] * 256 + buffer[12];
  pixels_y = buffer[15] * 256 + buffer[14];
  printf("Picture size is %d x %d\n", pixels_x, pixels_y);
}

read_targa_line()
{
int line_size;

  line_size = pixels_x * 3;
  fread(pixel_line, line_size, 1L, infile);
}

display_targa_line(line)
int line;
{
float r1, g1, b1, r2, g2, b2;
int x;

  /*  If an image has 640 pixels in X, pairs of pixels are combined
      and averaged  */
  /*  File pixels are in BGR order !!  */
  if (pixels_x == 640) {
    for (x=0; x<320; x++) {
      r1 = pixel_line[x*6+2];
      g1 = pixel_line[x*6+1];
      b1 = pixel_line[x*6+0];
      r2 = pixel_line[x*6+5];
      g2 = pixel_line[x*6+4];
      b2 = pixel_line[x*6+3];
      r1 = r1 + r2;
      g1 = g1 + g2;
      b1 = b1 + b2;
      r1 = r1 / 2;
      g1 = g1 / 2;
      b1 = b1 / 2;
      r1 = r1 / 16;       /*  reduce to 4 bit color space  */
      g1 = g1 / 16;
      b1 = b1 / 16;
      plot_to_graphic_screen((int)r1, (int)g1, (int)b1, x, line);
    }
  }
  else {
    for (x=0; x<320; x++) {
      r1 = pixel_line[x*3+2];
      g1 = pixel_line[x*3+1];
      b1 = pixel_line[x*3+0];
      r1 = r1 / 16;       /*  reduce to 4 bit color space  */
      g1 = g1 / 16;
      b1 = b1 / 16;
      plot_to_graphic_screen((int)r1, (int)g1, (int)b1, x, line);
    }
  }
}

open_stuff()
{
  static struct NewScreen new_screen = {
    0,0,
    320,200,     /*  Width / Height  */
    6,
    0,1,
    HAM,
    CUSTOMSCREEN,
    &Font80,
    "TARGA DISPLAY",
    NULL,
    NULL
  };

  static struct NewWindow new_window = {
    0,0,
    320,200,
    -1,-1,
    CLOSEWINDOW,
    ACTIVATE|WINDOWCLOSE|SMART_REFRESH,
    NULL,NULL,
    "TARGA DISPLAY",
    NULL, NULL,
    100,60,0,0, CUSTOMSCREEN
  };

  if ((IntuitionBase = (struct IntuitionBase *)
  OpenLibrary("intuition.library",0L)) == NULL)
    done("Couldn't open intuition.library");
  if ((GfxBase = (struct GfxBase *)
  OpenLibrary("graphics.library",0L)) == NULL)
    done("Couldn't open graphics.library");

  if (pixels_y > 200) {
    new_screen.Height = new_window.Height = 400;
    new_screen.ViewModes |= LACE;
  }

  if ((screen = OpenScreen(&new_screen)) == NULL)
    done("Couldn't open display screen");
  new_window.Screen = screen;
  if ((window = OpenWindow(&new_window)) == NULL)
    done("Couldn't open display window");
}

done(s)
char *s;
{
  if (window) CloseWindow(window);
  if (screen) CloseScreen(screen);
  if (GfxBase) CloseLibrary(GfxBase);
  if (IntuitionBase) CloseLibrary(IntuitionBase);
  if (infile)  fclose(infile);
  if (s)  printf("TSHOW: %s\n", s);
}



#define MODBLU 0x10L
#define MODRED 0x20L
#define MODGRN 0x30L

plot_to_graphic_screen(rval, gval, bval, screen_x, screen_y)
int rval, gval, bval;
int screen_x, screen_y;
{
static int    last_red=0, last_green=0, last_blue=0;
int  red, green, blue;
int  red_gap, green_gap, blue_gap;

  /*  If pixel is first on line, set last to black  */
  if (screen_x == 0) {
    last_red = 0;
    last_green = 0;
    last_blue = 0;
  }

  red = rval;
  green = gval;
  blue = bval;

  if (red > 15)    red = 15;
  if (green > 15)    green = 15;
  if (blue > 15)    blue = 15;
  if (red < 0) red = 0;
  if (green < 0) green = 0;
  if (blue < 0) blue = 0;

  if (red == 0 && green == 0 && blue == 0) {  /*  Black  */
    SetAPen(window->RPort, (long)0);
    last_red = 0;
    last_green = 0;
    last_blue = 0;
  }   
  else {
    if (red == last_red && green == last_green && blue == last_blue) {
      SetAPen(window->RPort, (long)(MODRED + red));/* no chng to color */
    }
    else {   /*  Regular HAM change  */
      red_gap = last_red - red;
      green_gap = last_green - green;
      blue_gap = last_blue - blue;
      if (red_gap < 0) red_gap = -red_gap;
      if (green_gap < 0) green_gap = -green_gap;
      if (blue_gap < 0) blue_gap = -blue_gap;

      if (red_gap > green_gap && red_gap > blue_gap) {
        SetAPen(window->RPort, (long)(MODRED + red));
        last_red = red;
      }
      else 
      if (green_gap > blue_gap) {
        SetAPen(window->RPort, (long)(MODGRN + green));
        last_green = green;
      }
      else {
        SetAPen(window->RPort, (long)(MODBLU + blue));
        last_blue = blue;
      }
    }
  }

  WritePixel(window->RPort, (long)screen_x, (long)screen_y);
}


