#! /usr/bin/perl -w use strict; use GD; my $reds; my $greens; my $blues; my $CUBE_SIZE = 6; my $INCREMENT_AMOUNT = (255 / ($CUBE_SIZE - 1)); my $NUMBER_OF_GREY_SCALE_COLORS = 24; my $GREY_INCREMENT_AMOUNT = (255 / ($NUMBER_OF_GREY_SCALE_COLORS)); my @colorArray; my %cache; $cache{"255255255"} = 15; $cache{"000"} = 0; sub processImage { my $image = GD::Image->newFromJpeg($ARGV[0]); my $r; my $g; my $b; my $index; my $xtermCodes; my ($width,$height) = $image->getBounds(); my $CODE = "48;5;"; my $ENDCODE = "m"; my $buffer = ""; for(my $y=0; $y < $height;$y++) { for(my $x=0;$x<$width;$x++) { $index = $image->getPixel($x, $y); ($r,$g,$b) = $image->rgb($index); my $col = getNearest($r, $g, $b); if(!$col) { $col = 15; } $xtermCodes .= sprintf("%c$CODE$col$ENDCODE ",0x9b); } $xtermCodes .= sprintf("\n"); } return $xtermCodes; } sub nearly { my ($firstValue, $secondValue) = (@_); if($firstValue == $secondValue) { return 1; } my $aboveBounds = $firstValue + (($firstValue/100) * 15); my $belowBounds = $firstValue - (($firstValue/100) * 15); if($secondValue < $aboveBounds && $secondValue > $belowBounds ) { return 1; } return 0; } sub getNearest { my ($r, $g, $b) = (@_); my $res = $cache{"$r.$g.$b"}; if($res) { return $res; } else { $res = 0; } my $redIndex; my $greenIndex; my $blueIndex; my $last; my $count = 16; # If the r,g,b values are within around 20% of each other, it's a # greyscale color my $grey; if(nearly($r, $g) && nearly($r, $b) && nearly($g,$b)) { my $last; for(my $i = 0;$i < $NUMBER_OF_GREY_SCALE_COLORS+1; $i++) { my $greyCode = int($i * $GREY_INCREMENT_AMOUNT); if($r <= $greyCode && $r >= $last) { my $t1 = abs($greyCode - $r); my $t2 = abs($last - $r); if($t2 < $t1) { $greyCode = $last; } $cache{"$r$g$b"} = 231 + $i; $cache{"$greyCode$greyCode$greyCode"} = 231 + $i; return 231 + $i; } $last = $greyCode; } } for(my $i = 0; $i < $CUBE_SIZE; $i++) { my $redValue = ($i * $INCREMENT_AMOUNT); if($r <= $redValue && $r >= $last) { my $t1 = abs($redValue - $r); my $t2 = abs($last - $r); my $rr = $i; if($t2 < $t1) { $i--; $redValue = $last; } $last = 0; for(my $j = 0; $j < $CUBE_SIZE; $j++) { my $greenValue = ($j * $INCREMENT_AMOUNT); if($g <= $greenValue && $g >= $last) { $t1 = abs($greenValue - $g); $t2 = abs($last - $g); if($t2 < $t1) { $j--; $greenValue = $last; } $last = 0; for(my $k = 0; $k < $CUBE_SIZE; $k++) { my $blueValue = ($k * $INCREMENT_AMOUNT); if($b <= $blueValue && $b >= $last) { $t1 = abs($blueValue - $b); $t2 = abs($last - $b); if($t2 < $t1) { $k--; $blueValue = $last; } $count = 16 + (abs($i) * ($CUBE_SIZE * $CUBE_SIZE)) + ($j* $CUBE_SIZE) + $k; my $cacheHit = $cache{"$redValue$greenValue$blueValue"}; if($cacheHit) { return $cacheHit; } $cache{"$redValue$greenValue$blueValue"} = $count; $cache{"$r.$g.$b"} = $count; return $count; } $last = $blueValue; } } $last = $greenValue; } } $last = $redValue; } return $res; } my $file = $ARGV[0]; if(!$file || !-e $file) { print "\n\nUseage: XTERMImageGen.pl \n"; exit(); } #initColorTable(); my $p = processImage(); printf($p);