#!/usr/local/vol/perl/5.00503/bin/perl -w

use strict;
use Getopt::Long;
use File::Basename;

# These variables you should change if installing on another system.

# $convert is the location of the program convert of ImageMagick
# $mapdir is where you have put all your default maps. 

my $convert    = "/usr/local/ImageMagick/4.2.7/bin/convert";
my $mapdir     = "/usr/local/lib/tozwgc/";

# These default values might be different on some systems.

# Geometry should be calculated as following:
#   1) See how many rows and colums you can use in a zwrite 
#      on your screen. On my screen I could fit 1240 by 300.
#   2) Divide by the x-value by $width and let the y-value be.
#   3) Squeeze an x in between the values.
#
# The following $geometry is based on @basegeom and $width

my $font       = "nil2";
my @basegeom   = (1240, 300);
my $width      = 3;               # A value of 2 or 3 is good.
my $geometry   = int (($basegeom[0])/$width) . "x" . int($basegeom[1]);

# These are probably not too good to change.

my $solidchar  = "#";
my $whitechar  = " ";
my $limit      = 300000;          # How large messages can zhm handle?

# These you shouldn't change!

my $quiet      = undef; 
my $map        = undef; 
my $in         = "-"; 
my $out        = undef;
my $noofcolors = 0;
my $lastcolor  = undef;
my $tempch     = undef;
my $progname   = (fileparse($0, ''))[0];
my $imagedata  = "";
my @trans      = ();
my $printed    = 0;

my ($xres, $yres, $colors, $cpp, @rest, $name, $value, 
    $i, $j, $k, $ucol, %colorhash, $cstring);

# Do GetOptions twice so not to "disturb" the default values
# when printing the helppage.

GetOptions(
	   "h" => \&showhelp, 
           "help" => \&showhelp,
           "version" => sub { print " $progname version 0.1\n"; exit; },
           "quiet" => \$quiet,
           "infile=s" => \$in,
           "outfile=s" => \$out,
           "transparent=s" => \@trans,
	   "map=s" => \$map,
	   "geometry=s" => \$geometry,
           "withconvert=s" => \$convert,
	   "font=s" => \$font,
	   "width=i" => \$width,
	   "solidchar=s" => \$solidchar,
	   "whitechar=s" => \$whitechar,
	   );

if ( $geometry !~ /^[0-9]+x[0-9]+$/ ) {
    if (! $quiet ) {
	print STDERR "Geometry must be of the form 'XXxYY' where\n";
	print STDERR "XX and YY are integers.\n";
    }
    exit(1);
}

unless ((-f $convert) && (-x $convert )) {
    if ( ! $quiet ) {
	print STDERR "The file '" . $convert . "' is not a valid\n";
	print STDERR "location of ImageMagick's convert.\n";
    }
    exit(1);
}

if ((defined $map) && (!-f $map)) {
    if ( !(-f $mapdir . $map)) {
	if ( ! $quiet ) {
	    print STDERR "The file '" . $map . "' doesn't exist.\n";
	}
	exit(1);  
    } else {
	$map = $mapdir . $map;
    }
}

if ($width < 0) {
    print STDERR "Width must be greater than zero.\n" if ( ! $quiet );
    exit(1);  
}

$cstring  = $convert . " -antialias -geometry '" . $geometry . ">' ";
$cstring .= "-map $map " if (defined $map);
$cstring .= $in . " xpm:- |";

if (defined $out) {
    open (OUT, ">" . $out) || die "Couldn't open outfile ";
} else {
    *OUT = *STDOUT;
}

open (CONVERT, $cstring) || die "Error when converting picture ";

# Read the header
while (<CONVERT>)
{
    chomp;
    unless ( m/(\/\*(.*?)\*\/)|static/ )
    {
	s/\"(.*)\",/$1/g;
	if( !defined($xres)) {
	    ($xres, $yres, $colors, $cpp, @rest) = split(/\ /, $_, 5);
	    next;
	} else {
	    ($name, $value) = /(.*)[ \t][m|s|g4|g|c][ \t](.*)/; #split /\ /;
            #  If $value is a member of @trans then $value should be
            #  exchanged for "none".
	    if (scalar(grep(/$value/, @trans))) {
		$colorhash{$name} = "none";
	    } else {
		$colorhash{$name} = $value;
	    }
	    $noofcolors++;
	    if ($noofcolors == $colors)
	    {
		last;
	    }
	}	
    }
}

# Read the image data.
while (<CONVERT>) {
    chomp;
    if (/^\"(.*)\",?$/) {
	$imagedata .= $1;
    }
}

my @imagedata = split //, $imagedata;

# Convert the image data
print OUT "\@font(" . $font . ")\n";
$printed += 8 + length($font);
for($i = 0; $i < $yres; $i++) {
    for ($j = 0; $j < $xres; $j++) {
	my $colval = "";
	for($k = 0; $k < $cpp; $k++)
	{
	    $tempch = shift @imagedata;
	    $colval = $colval . $tempch;
	}
	$ucol = $colorhash{$colval};

	if ($ucol eq "none") {
	    print OUT $whitechar x $width;
	    $printed += $width * length($whitechar);
	} elsif ((!defined $lastcolor) || ($ucol ne $lastcolor)) {
	    print OUT "\@color($ucol)";
	    $printed += 8 + length($ucol);
	    $lastcolor = $ucol;
	    print OUT $solidchar x $width;
	    $printed += $width * length($solidchar);
	} else {
	    print OUT $solidchar x $width;
	    $printed += $width * length($solidchar);
	}
    }
    print OUT "\n";
    $printed += 1;
}

if (($printed > $limit) && (!$quiet)) {
    print STDERR "WARNING! The output file is quite large (" . $printed;
    print STDERR " chars)\n";
    print STDERR "         This might be a problem with zhm.\n";
    exit 1;
}

sub showhelp
{
    print <<EOT;

NAME

  $progname - converts a picture to a message suitable for sending with zephyr

SYNOPSIS

  $progname [--h | --help | --version]

  $progname [--quiet] [--infile=filename] [--outfile=filename]
            [--transparent=color] [--map=image] [--font=fontname]
            [--geometry=geom] [--withconvert=path] [--width=integer]
            [--solidchar=char] [--whitechar=char]

  The $progname program converts, using ImageMagick, any image and outputs a 
  message suitable for sending with zephyr.

FLAGS

  --h
  --help     Show this screen.

  --version  Show the version number and exits.

  --quiet    Dont print any errormessages to STDERR. (This doesn\'t 
             stop convert from complaining though)

  --infile   Reads input from the specified filename. If no filename
             is specified, input is read from stdin.

  --outfile  Writes output to specified filename. If no filename is 
             specified, output is written to stdout.

  --map      Reduce colors in the output image to the colors in the
             specified file. The file can be any valid image that
             ImageMagick is able to read.

  --geometry  Specifies the geometry constraints put on the output image.
             The geometry must be of the form <WIDTH>x<HEIGHT> where
             <WIDTH> and <HEIGHT> are integers. The default value is
             $geometry and works fine with the font $font on a 1280x1024
             screen. Please note that just because a zwrite can fit on 
             the screen it doesn\'t say that it can be sent. Too large 
             messages will not be handled by the hostmanager.

  --withconvert  Uses the another convert instead of the default. Convert
             must be a ImageMagick compatible convert able to understand
             the options geometry, antialias and map, being able to write
             to stdout, read from file or stdin and outputting to XPM.
             The default is $convert

  --transparent  Specifies which colors should be transparent, that is
             to be written in the output using whitechar and not solidchar.
             You can specify multiple transparent flags to "remove" several
             colors. See solidchar and whitechar. The colors should be 
             valid X-colors (eg lavendel or #ff83ab). The colors are removed
             from the output images colormap and thus relative to it.

  --font     Specifies X-font to use for output. The font should be very 
             small (possiby unreadable). The default is $font.

  --width    Specifies how many chars each pixel should be translated into.
             The default is $width. This should be value should be 1 or 
             more since many fonts are taller than wide.

  --solidchar  Specifies which character should be used for "pixels". The 
             character should be as "black" as possible. The default is '$solidchar'.
	     Note that you may have a string and not just a separate char
             as this value but I am not responsible for the outcome.

  --whitechar  Specifies which character should be used for transparent 
             "pixels". The character should be as "white" as possible. The 
             default is '$whitechar'. Note that you may have a string and 
	     not just a separate char as this value but I am not responsible 
             for the outcome.

NOTES

  The options may be given with double dashes instead of single dashes and
  the equalsigns may be omitted. Also the options may be invoked with unique
  abbreviations.

REQUIREMENTS

  Perl 5 and ImageMagick that can output XPM-files.

RETURN VALUES

  The program returns 1 if the outputted message exceeds \$limit ($limit).

KNOWN BUGS

  If the output image is larger than approximately $limit bytes the hostmanager
  might not send the message. Please send small messages :-) The program
  warn you if the message is too large.

  The default values shown on this page is affected by command line options
  thus not making the term "default" an entirely good choice.

  There are spelling and grammatical errors in this text.

  Zwgc cannot allocate enough colors and the message looks horrible. Yuck!
  This is zwgc\'s problem but you can specify a mapfile to reduce the amount
  of colors used.

AUTHOR

  Max Zomborszki <max\@e.kth.se>  who is quite unresponsible for this program.

EOT
    exit;
}

