package Image::ASCII;
# by Nicholas Venturella

use strict;
use GD;

sub new ($$) {
	my ($self, $path, $max, $text) = @_;
	
	# Load image	
	my $image = GD::Image->new($path);
	my ($x, $y) = $image->getBounds();
	
	# Resize?
	$max = 175 unless($max);
	($image, $x, $y) = _imageResizeBicubic($image, $max) if ($x > $max || $y > $max);
	
	# Deal with text
	$text = '.:coCO8@' unless ($text);
	my @text = split //, $text;
	#@text = (@text, @text) while ($x*$y > scalar(@text));
	
	# Begin HTML document
	my ($R, $G, $B, $gray) = (0);
	my $result = qq�<html>\r\n<head>\r\n<title>BOT2K3 // Image To ASCII</title>\r\n<style>body, table { font-size: 6px; line-height: 4px; font-family: "Courier New", Courier, monospace; }</style>\r\n\r\n<body bgcolor="#000000" height="100%">\r\n<table align="center" width="100%" height="100%" cellpadding="0" cellspacing="0" border="0"><tr><td>\r\n<center>\r\n<pre><font color="#000000">�;
	
	my $j; for ($j = 0; $j < $y; $j += 1) {
		my $i; for ($i = 0; $i < $x; $i++) {
			my $index = $image->getPixel($i, $j);
			my ($r,$g,$b) = $image->rgb($index);
			unless (($r == $R) and ($g == $G) and ($b == $B)) {
				($R, $G, $B) = ($r, $g, $b);
				$gray = ($r*.3 + $g*.59 + $b*.11);
				my $color = '#' . sprintf("%.2X%.2X%.2X", $r, $g, $b);
				$result .= qq�</font><font color="$color">�;
			}
			my $which = int($gray * scalar(@text)/255);
			if ($which >= scalar(@text)) { $which = scalar(@text) - 1; }
			$result .= $text[$which];
		}
		$result .= "\n";
	}
	
	# End HTML document
	$result .= qq�</font></pre>\r\n</td></tr></table></body></html>�;
	return $result;
}

sub _imageResizeBicubic {
	my ($image, $max) = @_;
	my ($x, $y) = $image->getBounds();
	my $r = ($x > $y) ? ($x/$max) : ($y/$max);
	my $thumb = _imageCopyResampleBicubic($image, 0, 0, 0, 0, int($x/$r), int($y/$r), $x, $y);
	return $thumb, int($x/$r), int($y/$r);
}

sub _imageCopyResampleBicubic {
	my ($src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = @_;
	my $dst_img = GD::Image->new($dst_w, $dst_h, 1);
	
	my $scaleX = ($src_w - 1) / $dst_w;
	my $scaleY = ($src_h - 1) / $dst_h;
	my $scaleX2 = $scaleX / 2;
	my $scaleY2 = $scaleY / 2;
	my $tc = $src_img->isTrueColor();
	
	for (my $y = $src_y; $y < $src_y + $dst_h; $y++) {
		my $sY  = $y * $scaleY;
		my $siY  = int($sY);
		my $siY2 = int($sY + $scaleY2);
		
		for (my $x = $src_x; $x < $src_x + $dst_w; $x++) {
			my $sX  = $x * $scaleX;
			my $siX  = int($sX);
			my $siX2 = int($sX + $scaleX2);
			
			if ($tc) {
				my $c1 = $src_img->getPixel($siX, $siY2);
				my $c2 = $src_img->getPixel($siX, $siY);
				my $c3 = $src_img->getPixel($siX2, $siY2);
				my $c4 = $src_img->getPixel($siX2, $siY);
				
				my $r = (($c1 + $c2 + $c3 + $c4) >> 2) & 0xFF0000;
				my $g = ((($c1 & 0xFF00) + ($c2 & 0xFF00) + ($c3 & 0xFF00) + ($c4 & 0xFF00)) >> 2) & 0xFF00;
				my $b = ((($c1 & 0xFF)  + ($c2 & 0xFF)  + ($c3 & 0xFF)  + ($c4 & 0xFF))  >> 2);
				
				$dst_img->setPixel($dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b);
				
			} else {
				my @c1 = $src_img->rgb($src_img->getPixel($siX, $siY2));
				my @c2 = $src_img->rgb($src_img->getPixel($siX, $siY));
				my @c3 = $src_img->rgb($src_img->getPixel($siX2, $siY2));
				my @c4 = $src_img->rgb($src_img->getPixel($siX2, $siY));
				
				my $r = ($c1[0] + $c2[0] + $c3[0] + $c4[0])/4;
				my $g = ($c1[1] + $c2[1] + $c3[1] + $c4[1])/4;
				my $b = ($c1[2] + $c2[2] + $c3[2] + $c4[2])/4;
				
				$dst_img->setPixel($dst_x + $x - $src_x, $dst_y + $y - $src_y, ($r << 16)|($g << 8)|$b);
			}
		}
	}
	
	return $dst_img;
}

1;