#!/usr/bin/perl

$LOG2 =	0.693147180559945309417232121458176568075500134360255254120680009;
$PI =	3.141592653589793238462643383279502884197169399375105820974944592;

$InFile =	$ARGV[0].".raw";
$OutFile =	$ARGV[0].".wavelet.raw";
$NewFile =	$ARGV[0].".recovered.raw";

print ("decoding $OutFile -> $NewFile ...\n");


################
## UN-WAVELET ##
################

$Power = log(sqrt(-s $OutFile))/$LOG2;

$Recreate;
open(IN, $OutFile);
$Size =	sqrt(-s IN);
binmode(IN);
for my $A (0 .. 2**$Power - 1) {
	for my $B (0 .. 2**$Power - 1) {
		read(IN, $Char, 1);
		if($A == 0 && $B == 0) {
			$Recreate->[0][0] =		ord($Char);
		} else {
## n^3 ##
			my $Cube =	ord($Char) - 128;
			$Cube =	$Cube**5 / 128**4;
			$Recreate->[$A][$B] =	$Cube;
## SQRT ##
#			my $Sqrtized =	ord($Char) - 128;
#			if($Sqrtized < 0) {
#				$Sqrtized =	-($Sqrtized**2) / 128;
#			} else {
#				$Sqrtized =	$Sqrtized**2 / 128;
#			}
#			$Recreate->[$A][$B] =	$Sqrtized;
## Linear ##
##			$Recreate->[$A][$B] =	ord($Char) - 128;
		}
	}
}

print "\nDone reading the transformed file...";

$UnWavelet;
#$CurrentS->[0][0] =	$Recreate->[0][0];
$S->[0][0][0] =		$Recreate->[0][0];
for my $M (0 .. $Power - 1) {
#	$LastS =	$CurrentS;
	if($M > 0) {
		undef($S->[$M - 1]);
	}
	for my $A (0 .. 2**$M - 1) {
		for my $B (0 .. 2**$M - 1) {
#print "M:\t$M\nA:\t$A\nB:\t$B\n";
#Displayer($LastS);
#print "Looking at numbers ", 2**$M, " to ", 2**$M + 2**$M - 1, "\n";
			my $NowA =	$S->[$M][$A][$B] - $Recreate->[$A][$B + 2**$M] - $Recreate->[$A + 2**$M][$B] - $Recreate->[$A + 2**$M][$B + 2**$M];
			my $NowB =	$S->[$M][$A][$B] + $Recreate->[$A][$B + 2**$M] - $Recreate->[$A + 2**$M][$B] + $Recreate->[$A + 2**$M][$B + 2**$M];
#			my $NowC =	$S->[$M][$A][$B] - $Recreate->[$A][$B + 2**$M] + $Recreate->[$A + 2**$M][$B] - $Recreate->[$A + 2**$M][$B + 2**$M];
			my $NowC =	$S->[$M][$A][$B] - $Recreate->[$A][$B + 2**$M] + $Recreate->[$A + 2**$M][$B] + $Recreate->[$A + 2**$M][$B + 2**$M];
			my $NowD =	$S->[$M][$A][$B] + $Recreate->[$A][$B + 2**$M] + $Recreate->[$A + 2**$M][$B] - $Recreate->[$A + 2**$M][$B + 2**$M];
#print "$NowA\t$NowB\n$NowC\t$NowD\n\n";
			$S->[$M+1][2*$A][2*$B] =			$NowA;
			$S->[$M+1][2*$A][2*$B + 1] =		$NowB;
			$S->[$M+1][2*$A + 1][2*$B] =		$NowC;
			$S->[$M+1][2*$A + 1][2*$B + 1] =	$NowD;
		}
	}
}

print "\nDone inverse transforming...";

#Displayer($S);

open(NEW, '>'.$NewFile);
binmode(NEW);
for my $A (0 .. $Size - 1) {
	for my $B (0 .. $Size - 1) {
#		if($A == 0 && $B == 0) {
			print NEW chr(Chop($S->[$Power][$A][$B]));
#		} else {
#			print OUT chr(Chop($Out->[$A][$B] + 128));
#		}
	}
}
close(NEW);

print "\nDone writing reconstructed file!\n";

##########
## 5UB5 ##
##########

sub Chop {
	if($_[0] > 255) {
		return 255;
	} elsif($_[0] < 0) {
		return 0;
	} else {
		return int($_[0]);
	}
}
