#!/usr/bin/perl

# Programa en PERL para rotar una imagen
# alrededor del centro de la imagen.

# El tono de gris de la imagen de salida corresponde
# al pixel más cercano
#

# A test image of size 256x256 pixels
$rows = 200;
$cols = 200;

# Limpio la imagen
for( $i=0; $i<$rows; $i++ ){
	for( $j=0; $j<$cols; $j++ ){
		$imgA[ $i * $cols + $j ] = 255;
	}
}
# Ponemos un cuadrado blanco en el centro
$c=40;
$d=80;
for( $i=$c; $i<$rows-$c; $i++ ){
	for( $j=$d; $j<$cols-$d; $j++ ){
		$imgA[ $i * $cols + $j ] = 0;
	}
}

# Limpio la imagen de salida
for( $i=0; $i<$rows; $i++ ){
	for( $j=0; $j<$cols; $j++ ){
		$imgB[ $i * $cols + $j ] = 0;
	}
}

rotar( \@imgA, \@imgB, $rows, $cols, 30 ); 
$r = save_pgm_img ( \@imgB, $rows, $cols, "rotada.pgm" );
if ( $r ) {
	print "Error saving image!\n";
}

# Subroutine to save an image in raw PGM format
# (see pgm man pages on NETPBM package)
sub save_pgm_img (\@$$$) {  # ( @img, $rows, $cols, $filename );
	my $myimg = shift(@_);  # $myimg es  un puntero
	my $myrows = shift(@_);
	my $mycols = shift(@_);
	my $filename = shift(@_);

	my $n = @$myimg;
	printf "$n $mycols $myrows $filename\n";

	open ( MYFILE, ">$filename" ) or return 1;

	select MYFILE;
	$| = 1;
	print MYFILE "P5\n";
	print MYFILE "# file: $filename\n";
	print MYFILE "$mycols $myrows\n";
	print MYFILE "255\n";

	my @data;
	for ( my $i=0; $i<$myrows; $i++ ){
		for ( my $j=0; $j<$mycols; $j++ ){
			$data[$j] = $myimg->[ $mycols*$i + $j ];
		}

		my $bytes = pack( "C$mycols", @data );
		syswrite ( MYFILE, $bytes, $n );
	}

	close MYFILE;
	select STDOUT;
	return 0;
}

sub rotar ( \@\@$$$ )
{
	my $imgent = shift( @_ );
	my $imgsal = shift( @_ );
	my $rens = shift( @_ );
	my $cols = shift( @_ );
	my $ang  = shift( @_ );

	$cx = ($cols - 1)/2.0; 
	$cy = ($rens - 1)/2.0; 

	$micos = cos ( $ang * 3.141592654/180 );
	$misen = sin ( $ang * 3.141592654/180 );

	$xp = -$cx;	
	$yp = -$cy;	

	$xi = $xp*$micos + $yp*$misen; 
	$yi =-$xp*$misen + $yp*$micos; 

	for( my $i=0; $i<$rens; $i++ ){
		$xk = $xi;
		$yk = $yi;
		for( my $j=0; $j<$cols; $j++ ){
			$x = int( $xk + $cx + 0.5 );
			$y = int( $yk + $cy + 0.5 );

			if ( $x>=0 && $x < $cols ) {
				if ( $y>=0 && $y < $rens ) {
					$imgsal->[$cols*$i + $j] = $imgent->[$cols*$y + $x]; 
				}
			}
			$xk += $micos;
			$yk -= $misen;
		}
		$xi += $misen;
		$yi += $micos;
	}
}

