#!/usr/bin/perl

# Copyright 1994 Brad Pitzel
#
# Feel free to use/distribute/modify as long as credit/copyrights for myself 
# are included.
#
# Generates 'C' code from xpaint format .xpm files.


# Note: all pixmaps must list the background as the first color.

$header = "Bitmap.h";
$out1      = ".BPtmp1";
$out2      = ".BPtmp2";
$PalPrefix = "BPbitmap";	# name for generated files & color arrays


# check command line for options
if ($ARGV[0]=="-p")
	{
	shift;			# shift off "-p"
	$PalPrefix = shift;	# shift off new prefix;
	}


# grouping factor will attempt cut the # of colors in a palette by merging 
# together 'close' colors.  The higher the factor, the smaller the palette.
# Usefull when you are combining together many different bitmaps into
# one '.c' file with one palette.
$grouping=1;
# if ($ARGV[0]=="-g")
# 	{
#	shift;			# shift off "-g"
#	$grouping = shift;	# shift off grouping factor;
#	}

$headerOut = $PalPrefix.".h";
$progOut   = $PalPrefix.".c";

$RedVar    = $PalPrefix.".color[%d].red";
$GreenVar  = $PalPrefix.".color[%d].green";
$BlueVar   = $PalPrefix.".color[%d].blue";

print "Generating '$progOut' and '$headerOut' \n";

# file handles
$input = "1";
$extDefs = $input++;
$outfile1= $input++;
$outfile2= $input++;

unless (open($extDefs,">".$headerOut)) {
	print STDERR "Can't open $headerOut: $!\n";
	exit -1;
	}

print $extDefs "\n";
print $extDefs "// This file generated by xpm2bit\n\n";
print $extDefs "#include \"$header\"\n";
print $extDefs "\n";
print $extDefs "/* Color palette for bitmaps */\n";
print $extDefs "extern Palette $PalPrefix; \n\n";
print $extDefs "/* call this routine once before trying to use the bitmaps */\n";
print $extDefs ("void ",$PalPrefix,"Init();\n\n");

print $extDefs "/* bitmaps declared in $progOut */\n";

# temp files used to create $progOut
unless (open($outfile1,">".$out1)) {
	print STDERR "Can't open $out1: $!\n";
	exit -1;
	}
unless (open($outfile2,">".$out2)) {
	print STDERR "Can't open $out2: $!\n";
	exit -1;
	}

print $outfile1 "// This file generated by xpm2bit\n";
print $outfile1 "\n";
print $outfile1 "#include \"$headerOut\"\n\n";
print $outfile1 "Palette $PalPrefix; \n\n";

print $outfile2 "\n\n";
print $outfile2 "/* call this routine once before trying to use the bitmaps */\n";
print $outfile2 ("void ",$PalPrefix,"Init() {\n\n");

$color{''}=0;
$colStart = 0;

print "\nProcessing:\n";
foreach $file (@ARGV) {
	print $file,"\n";
	$colStart = do process($file,$colStart);
	}

# reserve color 255 for WHITE 
printf $outfile2 ($RedVar."  = 63;\n", 255);
printf $outfile2 ($GreenVar."= 63;\n", 255);
printf $outfile2 ($BlueVar." = 63;\n", 255);
print $outfile2 "\n";

print $outfile2 "\n";
print $outfile2 "/* # of colors used: $colStart */\n";
print $outfile2 "}\n";
print $outfile2 "/* End of $progOut */\n";

print $extDefs "/* End of $headerOut */\n";

print "\n";

close $extDefs;
close $outfile1;
close $outfile2;

# concat out1,out2 together to create progOut
exec "/bin/cat $out1 $out2 > $progOut";
exec "rm $out1 $out2";


#########################################
# process one .xpm file			#
#########################################
sub process {
local($filename,$colStart) = @_;

# strip out extension to get bitmap name
($bitmap) = split(/\./,$filename,2);

$input++;
unless (open($input,$filename)) {
	print STDERR "Can't open $filename: $!\n";
	return $colStart;
	}

$flag=0;
while ($flag==0) {
	$_ = <$input>; 
	if (/\"/) 
		{
		$_ = substr($_,1);
		chop;chop;chop;

		($width,$height,$colors,$chars) = split(/ /);

		print $outfile1 "/* bitmap file $filename \n";
		print $outfile1 "   width  = $width \n";
		print $outfile1 "   heigth = $height \n";
		print $outfile1 "   colors = $colors \n";
		print $outfile1 "*/\n";
		$flag=1;
		}; 
	}

$chars;
$Roff = 5 + $chars-1;
$Goff = 9 + $chars-1;
$Boff = 13+ $chars-1;

# get the colors 
$index=$colStart;
for( $num=0 ; $num < $colors ; $num++ ) {
	$_ = <$input>;
	$_ = substr($_,1);

	$Red = int(hex(substr($_,$Roff,2))/(4*$grouping))*$grouping;
	$Gre = int(hex(substr($_,$Goff,2))/(4*$grouping))*$grouping;	
	$Blu = int(hex(substr($_,$Boff,2))/(4*$grouping))*$grouping;
	$RGB = $Red.$Blu.$Gre;

	# check for black - special case
	if ($Red<2 && $Gre<2 && $Blu<2)
		{
		$rep{substr($_,0,$chars)} = 0;

		if ($index==0)
			{
			printf $outfile2 ($RedVar."  = 0;\n", 0);
			printf $outfile2 ($GreenVar."= 0;\n", 0);
			printf $outfile2 ($BlueVar." = 0;\n", 0);
			print $outfile2 "\n";
			$index++;
			}
		}
	else	{
		# see if color has already been used
		if ( $color{$RGB}=="" )
			{
			$color{$RGB} = $index;
			$rep{substr($_,0,$chars)} = $index;
	
			printf $outfile2 ($RedVar."  = %d;\n", $index, $Red);
			printf $outfile2 ($GreenVar."= %d;\n", $index, $Gre);
			printf $outfile2 ($BlueVar." = %d;\n", $index, $Blu);
			print $outfile2 "\n";
			$index++;
			}
		else	{
			$rep{substr($_,0,$chars)} = $color{$RGB};
			}
		}
	}


# write 'extern' def to a separate .h file
print $extDefs "extern Bitmap $bitmap; \n";

print $outfile1 "Bitmap $bitmap($width,$height); \n\n";
print $outfile2 "\n";
print $outfile2 "$bitmap.setMap(BITMAP_$bitmap); \n";

print $outfile1 "unsigned char BITMAP_$bitmap[$width * $height] = { \n";

for(;$height>0;$height--)	{
	$_ = <$input>;
	$_ = substr($_,1);

	print $outfile1 "    ";

	$w = $width;
	for(;$w>0;$w=$w-1) {

		# calc index for pixels color; (use 0 for all backgrounds)
		$pos = $rep{substr($_,($width-$w)*$chars,$chars)};
	
		print $outfile1 $pos;

		if ($w > 1) { print $outfile1 ","; }
		# print $outfile1 " ";
		}
	if ($height>1) { print $outfile1 ","; }
	print $outfile1 "\n";
	}

print $outfile1 "    };\n\n";

close $input;

undef %rep;

$colStart = $index;
return $colStart;
}
