#!/usr/bin/perl
# $Header: /home/jcb/bin/share/autoscale,v 1.10 2009/09/17 14:30:20 jcb Exp $
# take postscript or pdf, scale it to fit on A4 with 1cm margins.
$debug = 0;

$margin = 75; # margin size in 1/100 in.

$dir = ($ENV{'TMPDIR'} || '/tmp' ) . "/autoscale$$";
mkdir($dir) or die("mkdir $!");

open(OUT,">$dir/c.pgm");
print OUT 'P2
3 3
18
2 2 2
2 2 2
2 2 2
'; close(OUT);

while ( $ARGV[0] =~ /^-/ ) {
  if ( $ARGV[0] eq '-crop' ) {
    print STDERR $ARGV[0], $ARGV[1] if $debug;
    shift;
    ($ct,$cb,$cl,$cr) = split(/ /,$ARGV[0]);
    print STDERR "$ct $cb $cr $cl\n" if $debug;
    shift;
    foreach $v ( \$ct, \$cb, \$cl, \$cr ) {
      print STDERR "\$\$v is $$v\n" if $debug;
      $$v = int(($$v / 2.54) * 100); # convert from cm to 100dpi pixels
    }
  } else { die("Bad args @ARGV") ; }
}

print STDERR "cropping $ct, $cb, $cl, $cr\n" if $debug;

if ( $#ARGV < 0 || $ARGV[0] eq '-' ) {
  system("cat >$dir/input");
  open(IN,"<$dir/input");
  if ( <IN> =~ /PDF/ ) {
    rename("$dir/input",$file = "$dir/input.pdf");
  } else {
    rename("$dir/input",$file = "$dir/input.ps");
  }
  close(IN);
} else {
  $file = $ARGV[0];
}

if ( $file =~ /pdf$/i ) { 
  system("pdftops '$file' " . ($file = "$dir/input.ps")); 
}



system("gs -dNOPAUSE -sOutputFile=$dir/p\%d.pbm -sDEVICE=pbmraw -sPAPERSIZE=a4 -r100 -g826x1169 -q $file quit.ps");

($top,$bottom,$left,$right) = (1000,1000,1000,1000); # big enough...

$cut = '' ;
if ( $ct || $ct || $cl || $cr ) {
  $cut = '| pamcut ' ;
  if ( $ct ) {
    $cut .= "-top $ct ";
  }
  if ( $cb ) {
    $cut .= "-bottom " . (-1 * ($cb+1)) . " ";
  }
  if ( $cl ) {
    $cut .= "-left $cl ";
  }
  if ( $cr ) {
    $cut .= "-right " . (-1 * ($cr+1)) . " ";
  }
}

$odd=0;
foreach $f ( <$dir/*.pbm> ) {
  $odd = 1 - $odd;
  open(IN,"pnmconvol -nooffset 2>/dev/null $dir/c.pgm $f | pgmtopbm $cut | pnmcrop -white -verbose 2>&1 >/dev/null |");
  while ( <IN> ) {
    if ( /Cropping (\d+).* (left|top|right|bottom)/i ) {
      push(@{"$2$odd"},$1);
    }
  }
}

foreach $odd ( 0, 1 ) {
  foreach $k ( 'left', 'right', 'top', 'bottom' ) {
    @{"$k$odd"} = sort { $a <=> $b } @{"$k$odd"};
    # take the 25th percentile to eliminate outliers such as
    # overfull hboxes and a cover page.
    ${"$k$odd"} = ${"$k$odd"}[int($#{"$k$odd"}/4)];
    printf STDERR "setting $k$odd to %d\n",${"$k$odd"} if $debug;
  }
  # account for cropping
  ${"left$odd"} += $cl;
  ${"right$odd"} += $cr;
  ${"top$odd"} += $ct;
  ${"bottom$odd"} += $cb;
  # at 100dpi, A4 is 826x1169 .
  ${"width$odd"} = 826 - ${"left$odd"} - ${"right$odd"};
  ${"height$odd"} = 1169 - ${"top$odd"} - ${"bottom$odd"};
  print STDERR "top $top, bottom $bottom, left $left, right $right\n" if $debug;
  # the target size has $margin pixel margins on each side.
  ${"hscale$odd"} = (826-2*$margin)/${"width$odd"};
  ${"vscale$odd"} = (1169-2*$margin)/${"height$odd"};
}

# it's unlikely that the even and odd scale factors will differ. In case
# they do, average them. (Should this be geometric mean?)
$hscale = ($hscale0 + $hscale1)/2;
$vscale = ($vscale0 + $vscale1)/2;

if ( $hscale > $vscale ) {
  $scale = $vscale;
  foreach $odd ( 0, 1 ) {
    # target vertical offset is now $margin, after scaling;
    # current offset is bottom, before scaling. So, in inches:
    ${"voff$odd"} = ($margin/$scale - ${"bottom$odd"})/100;
    # now centre horizontally.
    # target offset is $margin, after scaling, and after centring.
    # current offset is left, before scaling.
    # After scaling, the width is $width*$scale, and the target
    # width is (826-2*$margin). With pen and paper, this gives:
    ${"hoff$odd"} = (826/(2*$scale) - ${"width$odd"}/2 - ${"left$odd"})/100;
  }
} else {
  $scale = $hscale;
  # conversely
  foreach $odd ( 0, 1 ) {
    ${"hoff$odd"} = ($margin/$scale - ${"left$odd"})/100;
    ${"voff$odd"} = (1169/(2*$scale) - ${"height$odd"}/2 - ${"bottom$odd"})/100;
  }
}
print STDERR "now top $top, bottom $bottom, left $left, right $right\n" if $debug;

# I don't understand. ps to ps does not seem to work right
# with combined scaling and shifting. Look into it sometime.
#$cmd = "pstops -pa4 '0\@$scale(${hoff}in,${voff}in)' $file $dir/output.ps";
$cmd = "pstops -q -pa4 '2:0(${hoff1}in,${voff1}in),1(${hoff0}in,${voff0}in)' $file | pstops -pa4 -q '0\@$scale' >$dir/output.ps";
print STDERR "doing $cmd\n" if $debug;
system($cmd);
system("cat $dir/output.ps");
