/*****************************************************************
 * flrot.c: FBM Release 1.0 25-Feb-90 Michael Mauldin
 *
 * Copyright (C) 1989,1990 by Michael Mauldin.  Permission is granted
 * to use this file in whole or in part for any purpose, educational,
 * recreational or commercial, provided that this copyright notice
 * is retained unchanged.  This software is available to all free of
 * charge by anonymous FTP and in the UUNET archives.
 *
 * flrot.c: 
 *
 * CONTENTS
 *	rotate_fbm (input, output, rot)
 *
 * EDITLOG
 *	LastEditDate = Mon Jun 25 00:17:59 1990 - Michael Mauldin
 *	LastFileName = /usr2/mlm/src/misc/fbm/flrot.c
 *
 * HISTORY
 * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
 *	Package for Release 1.0
 *
 * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
 *	Beta release (version 0.9) mlm@cs.cmu.edu
 *
 * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
 *	Created.
 *****************************************************************/

# include <stdio.h>
# include <math.h>
# include <ctype.h>
# include "fbm.h"

/****************************************************************
 * rotate_fbm: Rotate input bitmap
 ****************************************************************/

#ifndef lint
static char *fbmid =
"$FBM flrot.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
code available free from MLM@CS.CMU.EDU and from UUNET archives$";
#endif

rotate_fbm (input, output, rot)
FBM *input, *output;
int rot;
{
  switch (rot)
  { case 90:	return (rot90_fbm  (input, output));
    case 180:	return (rot180_fbm (input, output));
    case 270:	return (rot270_fbm (input, output));
    default:	fprintf (stderr, "%s %d degrees, must be 90, 180, or 270\n",
			 "invalid rotation", rot);
		return (0);
  }
}

/****************************************************************
 * rot90_fbm: Rotate input bitmap 90 degrees clockwise
 ****************************************************************/

rot90_fbm (input, output)
FBM *input, *output;
{ register int i, j, k, oi, oj;
  int iw, ow, ih, oh, irow, orow, ipln, opln;

  if (input->hdr.physbits != 8)
  { fprintf (stderr,
	    "Can't handle images %d physical bits per pixel\n",
	    input->hdr.physbits);
    exit (1);
  }

  oh = iw = input->hdr.cols;
  ow = ih = input->hdr.rows;
  
  irow = input->hdr.rowlen;
  ipln = input->hdr.plnlen;

  /* Calculate row length (input height padded to even byte boundary) */
  if (input->hdr.bits == 1)
  { orow = 16 * ((ow + 15) / 16); }
  else
  { orow = 2 * ((ow * input->hdr.physbits + 15) / 16); }

  opln = orow * oh; 

  /* Now build header for output bit map */
  output->hdr = input->hdr;
  output->hdr.cols = ow;
  output->hdr.rows = oh;
  output->hdr.rowlen = orow;
  output->hdr.plnlen = opln;
  output->hdr.aspect = 1.0 / input->hdr.aspect;
  
  /* Allocate space for output bits */
  alloc_fbm (output);
  
  copy_clr (input, output);

  for (k=0; k<output->hdr.planes; k++)
  { for (j=0; j<ih; j++)
    { for (i=0; i<iw; i++)
      { oj = i; oi = ih - (j+1);
        output->bm[k*opln + oj*orow + oi] = input->bm[k*ipln + j*irow + i];
      }
    }
  }

  return (1);
}

/****************************************************************
 * rot180_fbm: Rotate input bitmap 180 degrees clockwise
 ****************************************************************/

rot180_fbm (input, output)
FBM *input, *output;
{ register int i, j, k, oi, oj;
  int w, h, row, pln;

  if (input->hdr.physbits != 8)
  { fprintf (stderr,
	     "Can't handle images %d physical bits per pixel\n",
	     input->hdr.physbits);
    exit (1);
  }

  /* Now build header for output bit map */
  output->hdr = input->hdr;
  w = input->hdr.cols;
  h = input->hdr.rows;
  row = input->hdr.rowlen;
  pln = input->hdr.plnlen;
  
  /* Allocate space for output bits */
  alloc_fbm (output);
  
  copy_clr (input, output);

  for (k=0; k<output->hdr.planes; k++)
  { for (j=0; j<h; j++)
    { for (i=0; i<w; i++)
      { oj = h - (j+1); oi = w - (i+1);
        output->bm[k*pln + oj*row + oi] = input->bm[k*pln + j*row + i];
      }
    }
  }

  return (1);
}

/****************************************************************
 * rot270_fbm: Rotate input bitmap 270 degrees clockwise
 ****************************************************************/

rot270_fbm (input, output)
FBM *input, *output;
{ register int i, j, k, oi, oj;
  int iw, ow, ih, oh, irow, orow, ipln, opln;

  if (input->hdr.physbits != 8)
  { fprintf (stderr,
	    "Can't handle images %d physical bits per pixel\n",
	    input->hdr.physbits);
    exit (1);
  }

  oh = iw = input->hdr.cols;
  ow = ih = input->hdr.rows;
  
  irow = input->hdr.rowlen;
  ipln = input->hdr.plnlen;

  /* Calculate row length (input height padded to even byte boundary) */
  if (input->hdr.bits == 1)
  { orow = 16 * ((ow + 15) / 16); }
  else
  { orow = 2 * ((ow * input->hdr.physbits + 15) / 16); }

  opln = orow * oh;
  
  /* Now build header for output bit map */
  output->hdr = input->hdr;
  output->hdr.cols = ow;
  output->hdr.rows = oh;
  output->hdr.rowlen = orow;
  output->hdr.plnlen = opln;
  output->hdr.aspect = 1.0 / input->hdr.aspect;
  
  /* Allocate space for output bits */
  alloc_fbm (output);
  
  copy_clr (input, output);

  for (k=0; k<output->hdr.planes; k++)
  { for (j=0; j<ih; j++)
    { for (i=0; i<iw; i++)
      { oj = iw - (i+1); oi = j;
        output->bm[k*opln + oj*orow + oi] = input->bm[k*ipln + j*irow + i];
      }
    }
  }

  return (1);
}
