#!/usr/bin/perl ############################################################################### ## ## The on line Image Converter 1.0 ## ## This CGI will take an uploaded file from the browser and use ## UNIX image conversion utilities to convert to another format. ## It will accept virtually any image format as input. ## ## The official URL for this service is ## ## http://avi.alkalay.net/cgi-bin/imgcvt ## ## ## ## Distributed under the terms of the GPL as found at ## ## http://www.gnu.org/licenses/gpl.txt ## ## ## ## Copyright (C) 2001 by Avi Alkalay ## ## Avi Alkalay ## ## 08 Aug 2001 ## Made in Brazil ## use strict; use CGI qw(:push :standard); $|=1; $CGI::POST_MAX=3000000; ############################################################################### ## ## readCGIInput ## ## Uses the CGI.pm library to get parameters passed via the form or URL. ## Returns a hash containing the values needed by the program. ## ############################################################################### sub readCGIInput { my $query=new CGI; my %input; $input{fh}=$query->upload("src"); $input{fileName}=$query->param("src"); $input{outFormat}=$query->param("outFormat"); $input{inline}=$query->param("inline"); return %input; } ############################################################################### ## ## doConvert ## ## This is the program's most important method. ## It will analize the parameters and call the backend NETPBM programs to ## make the correct conversions. ## ############################################################################### sub doConvert { my (%cgiInput)=@_; my $CVT; my $srcType; my $targetType; my $srcImageInput; my $srcImageOutput; my $pid; my $returnedMimeType; my $sock; my $error; my $tmpDir="/var/tmp"; my $tmpSrcImg; my $tmpTargetImg; my $newFileName; # Some pipes my $targetImageInput; my $targetImageOutput; my $errorInput; my $errorOutput; # This structure is the core of the engine. # The key is a shortname for the image format, and its value is a list # that contains the NETPBM command and the mime-type. my %supported=( png => ["pnmtopng", "image/png"], gif => ["ppmquant 256 | ppmtogif", "image/gif"], pcx => ["ppmtopcx", "image/pcx"], bmp => ["ppmtobmp", "image/bmp"], jpeg => ["ppmtojpeg", "image/jpeg"], tiff => ["pnmtotiff", "image/tiff"], xpm => ["ppmtoxpm", "image/x-xpixmap"], xbm => ["pbmtoxbm", "image/x-xbitmap"], xwd => ["pnmtoxwd", "image/x-xwindowdump"], ps => ["pnmtops", "application/postscript"], pnm => ["anytopnm", "image/x-portable-anymap"] ); # Force PNG to be the default image format, if none is used. if ($cgiInput{outFormat} eq "") { $cgiInput{outFormat}="png"; } if (!exists($supported{$cgiInput{outFormat}})) { showForm("Unsupported output format !!"); exit(0); } # The engine converts first to PNM, and then use the NETPBM command # to convert to the specific format $CVT="anytopnm | $supported{$cgiInput{outFormat}}[0]"; #$newFileName=$cgiInput{fileName}; #$newFileName=~s/\..*$/\.$cgiInput{outFormat}/; $cgiInput{fileName}=~/\.(.*$)/; $srcType=$1; $targetType=$cgiInput{outFormat}; $tmpSrcImg="$$.srcImg.$srcType"; $tmpTargetImg="$$.targetImg.$targetType"; # $sock=$cgiInput{fh}; # open(OUT,">$tmpDir/$tmpSrcImg"); # while (<$sock>) { # print(OUT); # }; # close(OUT); # close($sock); # print multipart_init(-boundary=>'------------Image Converter 1.0'); # Use an agressive pipe aproach. This way, we almos don't need # temporary files. # Pipes a parent's file descriptor into child's STDIN. # Pipes child's STDOUT into a parent's file descriptor. # Pipes child's STDERR into a parent's file descriptor. pipe($srcImageInput,$srcImageOutput); pipe($targetImageInput,$targetImageOutput); pipe($errorInput,$errorOutput); if ($pid=fork()) { # Parent context close $errorOutput; close $srcImageInput; close $targetImageOutput; # Give the source image to the converter engine (the child) # using one of our pipes. $sock=$cgiInput{fh}; while (<$sock>) { print $srcImageOutput $_ ; } close($sock); close($srcImageOutput); # select(STDOUT); # print multipart_end; # If the user requested to see the image in the browser, # use the image correct mime-type. Else, use the # beautifull raw byte stream mime-type. if ($cgiInput{inline}==1) { $returnedMimeType=$supported{$cgiInput{outFormat}}[1]; } else { $returnedMimeType="application/octet-stream"; } print header(-type=>$returnedMimeType,-expires=>'now'); while (<$targetImageInput>) { # Take the converted image from one of our pipes. # See bellow (in the child context) to see who writes # in the other side of the pipe. print; } # print multipart_end; # Take the error messages from our error pipe. # I'm not handling error now. This is an issue... while (<$errorInput>) { $error.=$_; } } else { # child context close $errorInput; close $srcImageOutput; close $targetImageInput; open(STDERR,">&=" . fileno($errorOutput)); open(STDOUT,">&=" . fileno($targetImageOutput)); open(STDIN, "<&=" . fileno($srcImageInput)); exec("$CVT"); #exec("$CVT > $tmpDir/$tmpTargetImg"); } # Wait for the child (engine) to end. waitpid($pid,0); # Back to the parent. Analyze child's error output. # We are not handling this stuff... This is an issue if (!($error eq "")) { $error=~s/\n/\/g; showForm($error); } # Debug shit... # if (-r "$tmpDir/$tmpTargetImg") { # @info=lstat("$tmpDir/$tmpTargetImg"); # $size=$info[11]*$info[12]; # print header(-type=>"text/plain",-size=>$size); # print "File: $tmpDir/$tmpTargetImg\n"; # print "Size: $size\n"; # print "Stat Size: $#info\n"; # open(soock,"$tmpDir/$tmpTargetImg"); # while () { # print; # } # } else { # showForm("Security error"); # } } ############################################################################### ## ## showForm ## ## Displays the simple input form. ## Accepts one argument that will be used as a error message, printed with ## the form. ## ############################################################################### sub showForm { my ($msg)=@_; print header; print STDOUT < The OnLine Image Converter

The OnLine Image Converter

The following form allows you to convert an image file from one format to another.

$msg

Source image file:
Convert to Format:

OnLine Image Converter by Avi Alkalay <avi at alkalay.net>
The OpenSource for this program is available here.
EOF } ############################################################################### ## ## Main block ## ## Just call above functions in a special order. ## ############################################################################### # Get the parameters pre-processed by CGI.pm my %cgiInput=readCGIInput(); if (!($cgiInput{fileName} eq "")) { doConvert(%cgiInput); } else { showForm(); }