/*
 * This software is copyrighted as noted below.  It may be freely copied,
 * modified, and redistributed, provided that the copyright notice is
 * preserved on all copies.
 *
 * There is no warranty or other guarantee of fitness for this software,
 * it is provided solely "as is".  Bug reports or fixes may be sent
 * to the author, who may or may not act on them as he desires.
 *
 * You may not include this software in a program or other software product
 * without supplying the source, or without informing the end-user that the
 * source is available for no extra charge.
 *
 * If you modify this software, you should include a notice giving the
 * name of the person performing the modification, the date of modification,
 * and the reason for such modification.
 */
/*
 * rotate.c - rotate an image.
 *
 * Author:      Raul Rivero
 *              Mathematics Dept.
 *              University of Oviedo
 * Date:        Thu Jan 16 1992
 * Copyright (c) 1992, Raul Rivero
 *
 */

#include <lug.h>
#include <lugfnts.h>

extern int LUGverbose;

rotate_bitmap( inbitmap, outbitmap, degrees )
bitmap_hdr *inbitmap, *outbitmap;
double degrees;
{
  register int x, y;
  int totalsize;
  byte *r, *g, *b;
  double theta;
  double c, s, c_s_2;
  int ox, oy;
  int offset;

  if ( inbitmap->magic != LUGUSED )
    error( 19 );

  if ( inbitmap->depth < 24 )
    error( 7 );

  /* Fill our new header */
  outbitmap->magic = LUGUSED;
  outbitmap->xsize = inbitmap->xsize;
  outbitmap->ysize = inbitmap->ysize;
  outbitmap->depth = inbitmap->depth;
  outbitmap->colors = inbitmap->colors;
  totalsize = outbitmap->xsize * outbitmap->ysize;

  /* Allocate memory */
  r = outbitmap->r = (byte *) Malloc( totalsize );
  g = outbitmap->g = (byte *) Malloc( totalsize );
  b = outbitmap->b = (byte *) Malloc( totalsize );

  /* Precalculate */
  theta = degrees * M_PI / 180.; 
  c = cos( theta );
  s = sin( theta );
  c_s_2 = c*c + s*s;

  for ( y = 0; y < outbitmap->ysize; y++ ) {
    for ( x = 0; x < outbitmap->xsize; x++ ) {
      ox = ( (double)x * c - (double)y * s ) / c_s_2;
      oy = ( (double)x * s + (double)y * c ) / c_s_2;
      if ( ox >= 0 && ox < outbitmap->xsize &&
           oy >= 0 && oy < outbitmap->ysize ) {
        offset = oy * outbitmap->xsize + ox;
        *r = inbitmap->r[ offset ];
        *g = inbitmap->g[ offset ];
        *b = inbitmap->b[ offset ];
      }
      r++, g++, b++;
    }
  }
}

rotate90_image(inbitmap, outbitmap)
bitmap_hdr *inbitmap;
bitmap_hdr *outbitmap;
{
  VPRINTF(stderr, "Rotating image\n");

  if ( inbitmap->magic != LUGUSED )
    error( 19 );

  /* Fill our header */
  outbitmap->magic = LUGUSED;
  outbitmap->xsize = inbitmap->ysize;
  outbitmap->ysize = inbitmap->xsize;
  outbitmap->depth = inbitmap->depth;
  outbitmap->colors = inbitmap->colors;

  outbitmap->r = rotate90( inbitmap->r, inbitmap->xsize, inbitmap->ysize );
  if ( outbitmap->depth > 8 ) {
    /* 24 planes */
    outbitmap->g = rotate90( inbitmap->g, inbitmap->xsize, inbitmap->ysize );
    outbitmap->b = rotate90( inbitmap->b, inbitmap->xsize, inbitmap->ysize );
  }else outbitmap->cmap = inbitmap->cmap;
}

byte *rotate90(buffer, xsize, ysize)
byte *buffer;
int xsize, ysize;
{
  register int i, j;
  int twolines;
  byte *image, *ptr;
  byte *buf;

  image = (byte *) Malloc( xsize * ysize );
  ptr = image + xsize * ysize - ysize;
  twolines = 2 * ysize;

  for ( i = 0; i < xsize; i++ ) {
    /* Offset to this column */
    buf = buffer + i;
    for ( j = 0; j < ysize; j++ ) {
      *ptr++ = *buf;
      buf += xsize;
    }
    /* Set ptr to line before current */
    ptr -= twolines;
  }

  return image;
}
