#!/usr/bin/perl -w

# A spherical image slicer for patterning spheres
# Copyright 2001 Bruno Postle <bruno@postle.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

use Image::Magick;                                     # image stuff
use Math::Trig;                                        # math stuff
use Math::Trig ':radial';                              # more math stuff

if ( $#ARGV ne 2 ) {
    die "Incorrect number of arguments\nUsage $0 <number of panels> <circumference> <filename>\ne.g.  $0 16 1000 input.jpg\n";
    }

my $n = $ARGV[0];                                      # number of panels
my $out_size = $ARGV[1];                               # output circumference
my $out_filetype = "png";  # can be changed to tif, gif, jpg or whatever..
my $out_height = int ( $out_size / 2 );
my $out_width = int ( ( $out_size / pi ) * tan( pi / $n ) );
my $rho = $out_height / pi;                            # output radius

$in = Image::Magick->new();                            # get input image
$in->ReadImage( "$ARGV[2]" );
$in_width = $in->Get( 'width' );
$in_height = $in->Get( 'height' );
print "Input image is $in_width x $in_height.\n";

for ( $panel = 0; $panel < $n; $panel += 1 ) {         # do each panel
    $theta_offset = ( pi / $n ) * ( $panel + .5 ) * 2;

    $out = Image::Magick->new();                       # setup output image
    $out->Set( size=>"$out_width"."x"."$out_height" );
    $out->ReadImage( 'NULL:white' );                   # background colour

    for ( $u = 0; $u < $out_width; $u += 1 ) {         # do each column
        for ( $v = 0; $v < $out_height; $v += 1 ) {    # do each row
            my $y = $u - ( $out_width / 2 );
            my $phi = ( ( $v / $out_height ) * pi );   # phi is inclination
            my ( $x, $junk, $z ) = spherical_to_cartesian( $rho, 0, $phi );
            if ( ( $x > 0 ) && ( atan($y/$x) < (pi/$n) ) && ( 0 - atan($y/$x) < (pi/$n) ) ) {
                $colour = getcolour( $x,$y,$z );
                $out->Set( "pixel[$u,$v]"=>$colour );
                }
            }
        }
    print "Writing panel$panel.$out_filetype $out_width x $out_height..\n";
    $out->Write( "panel$panel.$out_filetype" );
}

sub getcolour {
    my ($rho, $theta, $phi) = cartesian_to_spherical( $_[0], $_[1], $_[2] );
    $theta += $theta_offset;
    my $u = int ( ( $theta / ( 2 * pi ) ) * $in_width );
    my $v = int ( $in_height - ( ( $phi / pi ) * $in_height ) );
    my $colour = $in->Get( "pixel[$u,$v]" );
    return $colour;
    }

