/********************************************************/
/* rs2fbm.c -- V1.3                                     */
/* Convert rayshade (3.0 or 4.0) output into fbm format */
/* (for non URT version of rayshade                     */
/* use -4 option for rayshade 4.0 format (PL 0..4)      */
/* need not use it for RS 4.0 since patchlevel 5        */
/********************************************************/

#include <stdio.h>

#define ILL_PAR 102
#define NO_MEM 100
#define NOT_INP 104
#define NOT_OUT 105

typedef unsigned char UBYTE;
typedef unsigned long ULONG;
typedef unsigned short UWORD;

#ifdef LATTICE_50
#define ANSI_C
#endif

#ifdef ANSI_C
#include <stdlib.h>
#include <string.h>

void WriteRGBplanes(FILE *, UWORD, UWORD);
#else
extern void *malloc();
void WriteRGBplanes();
#endif

UBYTE *BitMap[1024];

# define FBM_MAX_TITLE		80		/* For title and credits */

# define BLACK			0		/* For 8bit files */
# define WHITE			255		/* For 8bit files */
# define BYTE			256		/* For 8bit files */

# define BLANKS		"                                             "

# define FBM_MAGIC	"%bitmap"

/* FBM bitmap headers in files (null terminated 12 character ascii strings) */
typedef struct fbm_filehdr_struct {
	char	magic[8];		/* 8 bytes FBM_MAGIC number */
	char	cols[8];		/* Width in pixels */
	char	rows[8];		/* Height in pixels */
	char	planes[8];		/* Depth (1 for B+W, 3 for RGB) */
	char	bits[8];		/* Bits per pixel */
	char	physbits[8];		/* Bits to store each pixel */
	char	rowlen[12];		/* Length of a row in bytes */
	char	plnlen[12];		/* Length of a plane in bytes */
	char	clrlen[12];		/* Length of colormap in bytes */
	char	aspect[12];		/* ratio of Y to X of one pixel */
	char	title[FBM_MAX_TITLE];	/* Null terminated title */
	char	credits[FBM_MAX_TITLE];	/* Null terminated credits */
} FBMFILEHDR;

void WriteRGBplanes(fpo, yres, rowlen)
UWORD yres;
UWORD rowlen;
FILE *fpo;
{
  register UWORD i,k;

  /* Write RED plane */
  for (i=0; i<yres; i++) {
    for (k=0; k<rowlen*3; k += 3) {
      putc(*(BitMap[i] +(ULONG)(k)),fpo);
    };
  };
  /* Write GREEN plane */
  for (i=0; i<yres; i++) {
    for (k=0; k<rowlen*3; k += 3) {
      putc(*(BitMap[i] +(ULONG)(k+1)),fpo);
    };
  };
  /* Write BLUE plane */
  for (i=0; i<yres; i++) {
    for (k=0; k<rowlen*3; k += 3) {
      putc(*(BitMap[i] +(ULONG)(k+2)),fpo);
    };
  };
}

void Usage(CmdName)
char *CmdName;
{
  fprintf(stderr,"Usage: %s [-4] inputfile [outputfile]\n",CmdName);
  fprintf(stderr,"converts rayshade or mtv input to FBM format\n");
}

main(argc,argv)
int argc;
char *argv[];
{
  register short i,k;
  char *argstr;
  FILE *fpi, *fpo;
  static char InName[128], OutName[128];
  FBMFILEHDR *fbm_hdr;
  UWORD xres, yres;
  UWORD rowlen;
  char rs3fmt = !0;

  k=0;
  if (argc<2) {
    Usage(argv[0]);
    exit(2);
  };
  for (i=1; i<argc; i++) {
    argstr = argv[i];
    if (*argstr == '-') {
      argstr++;
      if (*argstr == 'h') { /* help wanted */
        Usage(argv[0]);
        exit(0);
      }
      if (*argstr == '4') { /* help wanted */
        rs3fmt = 0;
      }
      else fprintf(stderr,"Unknown option %s ignored\n",argv[i]);
    }
    else {
      k++;
      if (k==1) strcpy(InName,argstr);
      else if (k==2) strcpy(OutName,argstr);
      else fprintf(stderr,"Extraneous argument %s ignored\n",argstr);
    }
  };
  /* Args are parsed, let's do our job */
  if ((fpi=fopen(InName,"r")) == NULL) {
    fprintf(stderr,"Cannot open file %s for input\n",InName);
    exit(NOT_INP);
  };

  fscanf(fpi,"%hd %hd",&xres,&yres);
  if (yres > 1024) {
    fclose(fpi);
    fprintf(stderr,"Cannot handle images with more than 1024 rows\n");
    exit(20);
  };
  if (getc(fpi) != '\n') {
    fclose(fpi);
    fprintf(stderr,"A newline char should have been found after the header\n");
    fprintf(stderr,"Image is probably not in RS - format\n");
    exit(20);
  };

  rowlen = 2 * ((xres * 8 + 15) / 16);
  
  for (i=0; i<yres; i++) {
    if ((BitMap[i] = malloc((unsigned)rowlen*3)) == NULL) {
      fprintf(stderr,"not enough memory for malloc()\n");
      exit(101);
    };
    setmem(BitMap[i],(unsigned)rowlen*3,0);
  };

  if (rs3fmt) {
    for (i=0; i<yres; i++) {
      fread(BitMap[i],1,(unsigned)xres*3,fpi);
    };
  }
  else {
    for (i=yres-1; i>=0; i--) {
      fread(BitMap[i],1,(unsigned)xres*3,fpi);
    };
  };

  fclose(fpi);

  if (k==1) fpo = stdout;
  else if ((fpo=fopen(OutName,"w")) == NULL) {
    fprintf(stderr,"Cannot open file %s for output\n",OutName);
    exit(NOT_OUT);
  };

  if ((fbm_hdr=malloc(sizeof(FBMFILEHDR))) == NULL) {
    fprintf(stderr,"Not enough memory for malloc()\n");
    exit(NO_MEM);
  };

  strncpy(fbm_hdr->magic,FBM_MAGIC,8);
  sprintf(fbm_hdr->cols,"%7u",(unsigned)xres);
  sprintf(fbm_hdr->rows,"%7u",(unsigned)yres);
  sprintf(fbm_hdr->planes,"%7u",3);
  sprintf(fbm_hdr->bits,"%7u",8);
  sprintf(fbm_hdr->physbits,"%7u",8);

  sprintf(fbm_hdr->rowlen,"%11u",(unsigned)rowlen);
  sprintf(fbm_hdr->plnlen,"%11lu",(ULONG)rowlen*(ULONG)yres);
  sprintf(fbm_hdr->clrlen,"%11u",0);
  sprintf(fbm_hdr->aspect,"%11.6f",1.0);
  strncpy(fbm_hdr->title,"",80);
  strncpy(fbm_hdr->credits,"",80);
  fwrite(fbm_hdr,1,sizeof(FBMFILEHDR),fpo);

  fprintf(stderr,"Writing  %u * %u * 3  FBM-Bitmap\n",(unsigned)rowlen,(unsigned)yres);
  WriteRGBplanes(fpo,yres,rowlen);
  fclose(fpo);
  free(fbm_hdr);
  for (i=0; i<yres; i++) free(BitMap[i]);
}
