kohabug 2404 This patch removes Image::Magick and adds GD
authorChris Nighswonger <chris.nighswonger@liblime.com>
Mon, 28 Jul 2008 16:35:46 +0000 (11:35 -0500)
committerJoshua Ferraro <jmf@liblime.com>
Wed, 30 Jul 2008 08:38:18 +0000 (03:38 -0500)
This patch removes Image::Magick as a dependency and replaces it with
the (much) lighter GD. Functionality of patronimage code has not changed with
this conversion.

Adding errorhandling for corrupted image file and link to return to moremember.pl when called from there

Added notes about supported image mime types.

Signed-off-by: Galen Charlton <galen.charlton@liblime.com>
Signed-off-by: Joshua Ferraro <jmf@liblime.com>
C4/Members.pm
Makefile.PL
about.pl
koha-tmpl/intranet-tmpl/prog/en/modules/help/members/moremember.tmpl
koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/picture-upload.tmpl
koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl
koha-tmpl/intranet-tmpl/prog/en/modules/tools/picture-upload.tmpl
tools/picture-upload.pl

index 70a85c3..1f03282 100644 (file)
@@ -1783,7 +1783,7 @@ sub GetPatronImage {
     my ($cardnumber) = @_;
     warn "Cardnumber passed to GetPatronImage is $cardnumber" if $debug;
     my $dbh = C4::Context->dbh;
-    my $query = "SELECT mimetype, imagefile FROM patronimage WHERE cardnumber = ?;";
+    my $query = 'SELECT mimetype, imagefile FROM patronimage WHERE cardnumber = ?';
     my $sth = $dbh->prepare($query);
     $sth->execute($cardnumber);
     my $imagedata = $sth->fetchrow_hashref;
index 167fc9c..743ea33 100644 (file)
@@ -548,6 +548,7 @@ WriteMakefile(
                             'Date::Manip'                      => 5.44,
                             'Digest::MD5'                      => 2.36,
                             'File::Temp'                       => 0.16,
+                                                       'GD'                                                            => 2.34, #optional
                             'GD::Barcode::UPCE'                => 1.1,
                             'Getopt::Long'                     => 2.35,
                             'Getopt::Std'                      => 1.05,
@@ -555,7 +556,6 @@ WriteMakefile(
                             'HTML::Scrubber'                   => 0.08,
                             'HTTP::Cookies'                    => 1.39,
                             'HTTP::Request::Common'            => 1.26,
-                            'Image::Magick'                    => 6.2, # optional
                             'LWP::Simple'                      => 1.41,
                             'LWP::UserAgent'                   => 2.033,
                             'Lingua::Stem'                     => 0.82,
index a31b0a0..6cff96d 100755 (executable)
--- a/about.pl
+++ b/about.pl
@@ -78,6 +78,7 @@ Data::ICal
 Date::Manip
 Digest::MD5
 File::Temp
+GD
 GD::Barcode::UPCE
 Getopt::Long
 Getopt::Std
@@ -85,7 +86,6 @@ HTML::Template::Pro
 HTTP::Cookies
 HTTP::Request::Common
 HTML::Scrubber
-Image::Magick
 LWP::Simple
 LWP::UserAgent
 Lingua::Stem
index b8158cb..ebabcfc 100644 (file)
@@ -1,3 +1,3 @@
 <!-- TMPL_INCLUDE NAME="help-top.inc" -->
-<h1>Member Information Screen</h1> <p>This screen shows the information associated with a given patron.</p> <p>On the top left is their address and card number.</p> <p>A patron's annual membership fee payment status also shows on this screen.</p><p>At the bottom of the patron information page you will find quick access to items the patron has checked out, overdue and on hold. </p><p>You can get information on what a patron has read in the past by clicking on the Circulation History button.</p>  <p>If you would like to edit a patron's information, click the 'Edit' button.&nbsp; You can also click one of the 'Edit' links below each section on the patron record. </p> <p>If you would like to PERMANENTLY delete a user, click 'Delete' under 'More'. A confirmation box will appear, so don't worry about accidentally deleting a record. Just be absolutely sure before you delete!</p>   <p>If no patron image exists for this patron, click the &quot;Add Patron Images&quot; link to add an image or images. The pixel dimensions should not exceed 120 X 200. </p> 
+<h1>Member Information Screen</h1> <p>This screen shows the information associated with a given patron.</p> <p>On the top left is their address and card number.</p> <p>A patron's annual membership fee payment status also shows on this screen.</p><p>At the bottom of the patron information page you will find quick access to items the patron has checked out, overdue and on hold. </p><p>You can get information on what a patron has read in the past by clicking on the Circulation History button.</p>  <p>If you would like to edit a patron's information, click the 'Edit' button.&nbsp; You can also click one of the 'Edit' links below each section on the patron record. </p> <p>If you would like to PERMANENTLY delete a user, click 'Delete' under 'More'. A confirmation box will appear, so don't worry about accidentally deleting a record. Just be absolutely sure before you delete!</p>   <p>If no patron image exists for this patron, click the &quot;Add Patron Images&quot; link to add an image or images. The pixel dimensions should not exceed 120 X 200. Only PNG, GIF, JPEG, XPM formats are supported.</p> 
 <!-- TMPL_INCLUDE NAME="help-bottom.inc" -->
index 21be765..6916593 100644 (file)
@@ -1,5 +1,5 @@
 <!-- TMPL_INCLUDE NAME="help-top.inc" -->
 <div class="main">
-                                                                                                   <h1 id="hc1v"><font size="5" id="wi2o"><font size="4" id="gotr">Upload Patron Images</font></font></h1>This tool allows you to upload multiple patron images as a batch.<br /><br /><font id="hh140" color="#ff0000">IMPORTANT: Requires that the 'patronimages' system preference is set to 'ON' to use this feature.</font><br /><ul><li><em>Get there: </em>More &gt; Administration &gt; Global System Preferences &gt; Patrons &gt; patronimages</li></ul><br /><h2>Upload images in bulk</h2><ul><li>Go to the 'Tools' module (usually under 'More' in your Global Nav)</li><li>Choose 'Upload patron images' </li><li>You can choose to upload images in bulk by making a zip file with the images and a text file entitled &quot;DATALINK.TXT&quot; or &quot;IDLINK.TXT&quot;</li><li>For each group of pictures that has the cardnumber of the patron and the file containing that patrons picture. One patron per line separated by either commas or tabs. <br /><ul><li style="background-color: #ffffff"><font id="ux6f" color="#ff0000">IMPORTANT: Make sure that your TXT file is a plain text document, not RTF.</font></li><li><font id="sm7j" color="#ff0000"><span style="background-color: #ffffff">IMPORTANT: Make sure that you use either a comma or a tab to separate IDs from image names</span></font></li></ul></li><li>Add the images and the TXT file to a .ZIP file</li><li>Browse for the file from the Koha interface</li><li>Click 'Unpack' and you will receive a confirmation screen</li><li>To see the image(s) you imported search for the patron(s) and view their profile</li><li>If you'd like to change the image, just upload a new image</li><li>If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'</li></ul><br /><font size="4" id="zr_8"><strong>Uploading Single Images</strong></font><br /><br />If you only have one patron image you might want to upload it via the patron information page instead of using this bulk tool.<br /><br /><ul><li>Go to the Patrons menu at the top of the staff client</li><li>Search for the patron you have the image for</li><li>If there is more than one result, click on the name of the patron you'd like to add an image to</li><li>Scroll down to the image upload form</li><li>Browse for the image on your computer and click 'Upload'</li><li>If you'd like to change the image, just upload a new image</li><li>If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'</li></ul><strong><br /><br /><br />Why can't I upload patron images?</strong><br /><br />First you will need <span class="ex">a patronimages/</span> directory.&nbsp; If you do not have this directory you will see an error.<br /><div id="brc:" style="padding: 1em 0pt; text-align: left"><ul><li>Contact your system administrator to create this directory and you'll be set to go.</li></ul><br /><strong>What size should my images be?</strong><br /><br />There is a limit of 100K on the size of the picture uploaded and it is recommended that the image be 120x200 pixels, but smaller images will work as well.<br /></div><br />             
+                                                                                                   <h1 id="hc1v"><font size="5" id="wi2o"><font size="4" id="gotr">Upload Patron Images</font></font></h1>This tool allows you to upload multiple patron images as a batch.<br /><br /><font id="hh140" color="#ff0000">IMPORTANT: Requires that the 'patronimages' system preference is set to 'ON' to use this feature.</font><br /><ul><li><em>Get there: </em>More &gt; Administration &gt; Global System Preferences &gt; Patrons &gt; patronimages</li></ul><br /><h2>Upload images in bulk</h2><ul><li>Go to the 'Tools' module (usually under 'More' in your Global Nav)</li><li>Choose 'Upload patron images' </li><li>You can choose to upload images in bulk by making a zip file with the images and a text file entitled &quot;DATALINK.TXT&quot; or &quot;IDLINK.TXT&quot;</li><li>For each group of pictures that has the cardnumber of the patron and the file containing that patrons picture. One patron per line separated by either commas or tabs. <br /><ul><li style="background-color: #ffffff"><font id="ux6f" color="#ff0000">IMPORTANT: Make sure that your TXT file is a plain text document, not RTF.</font></li><li><font id="sm7j" color="#ff0000"><span style="background-color: #ffffff">IMPORTANT: Make sure that you use either a comma or a tab to separate IDs from image names</span></font></li></ul></li><li>Add the images and the TXT file to a .ZIP file</li><li>Browse for the file from the Koha interface</li><li>Click 'Unpack' and you will receive a confirmation screen</li><li>To see the image(s) you imported search for the patron(s) and view their profile</li><li>If you'd like to change the image, just upload a new image</li><li>If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'</li></ul><br /><font size="4" id="zr_8"><strong>Uploading Single Images</strong></font><br /><br />If you only have one patron image you might want to upload it via the patron information page instead of using this bulk tool.<br /><br /><ul><li>Go to the Patrons menu at the top of the staff client</li><li>Search for the patron you have the image for</li><li>If there is more than one result, click on the name of the patron you'd like to add an image to</li><li>Scroll down to the image upload form</li><li>Browse for the image on your computer and click 'Upload'</li><li>If you'd like to change the image, just upload a new image</li><li>If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'</li></ul><strong><br /><br /><br />Why can't I upload patron images?</strong><br /><br />First you will need <span class="ex">a patronimages/</span> directory.&nbsp; If you do not have this directory you will see an error.<br /><div id="brc:" style="padding: 1em 0pt; text-align: left"><ul><li>Contact your system administrator to create this directory and you'll be set to go.</li></ul><br /><strong>What size should my images be?</strong><br /><br />There is a limit of 100K on the size of the picture uploaded and it is recommended that the image be 120x200 pixels, but smaller images will work as well.<br /><br /><strong>What image formats are supported?</strong><br /><br />Only PNG, GIF, JPEG, XPM formats are supported.i<br />
 </div>
 <!-- TMPL_INCLUDE NAME="help-bottom.inc" -->
index 0da1c48..9133705 100644 (file)
@@ -203,11 +203,11 @@ if (nodename =="barcodes[]"){
                <form method="post" action="/cgi-bin/koha/tools/picture-upload.pl" enctype="multipart/form-data">
                 <!-- TMPL_IF NAME="picture" -->
                     <fieldset class="brief"><legend>Manage Patron Image</legend>
-                        <div class="hint">To update the image for <!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="surname" -->, enter the name of the new image file to upload and click 'Upload.' <br />Click the 'Delete' button to remove the current image.</div>
+                        <div class="hint">To update the image for <!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="surname" -->, enter the name of the new image file to upload and click 'Upload.' <br />Click the 'Delete' button to remove the current image. <br /> Only PNG, GIF, JPEG, XPM formats are supported.</div>
                 <!-- /TMPL_IF -->
                 <!-- TMPL_UNLESS NAME="picture" -->
                     <fieldset class="brief"><legend>Upload Patron Image</legend>
-                        <div class="hint"><!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> does not currently have an image available. To import an image for <!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="surname" -->, enter the name of an image file to upload.</div>
+                        <div class="hint"><!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> does not currently have an image available. To import an image for <!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="surname" -->, enter the name of an image file to upload. <br /> Only PNG, JPEG, XPM formats are supported.</div>
                 <!-- /TMPL_UNLESS -->
                    <input type="hidden" id="image" name="filetype" value="image" />
                    <input type="hidden" id="cardnumber" name="cardnumber" value="<!-- TMPL_VAR NAME="cardnumber" -->" />
index 7bb47b3..f2750e3 100644 (file)
         <div class="yui-g">
             <div class="yui-u first">
             <!-- TMPL_IF name="ERRORS" -->
-                <div class="dialog alert">
-                <h3>Patron Image(s) Uploaded With Some Errors</h3>
+                               <!-- TMPL_IF name = "TCOUNTS" -->
+                                       <div class="dialog alert">
+                                       <h3>Patron Image(s) Uploaded With Some Errors</h3>
+                               <!-- TMPL_ELSE -->
+                                       <div class="dialog alert">
+                                       <h3>Patron Image Failed to Upload</h3>
+                               <!-- /TMPL_IF -->
             <!-- TMPL_ELSE -->
                 <div class="dialog message">
                 <h3>Patron Image(s) Successfully Uploaded</h3>
             <!-- /TMPL_IF -->
                <ul class="data">
                    <li>Unpacking completed</li>
-                  <li><!-- TMPL_VAR NAME ="TOTAL" --> directories scanned.</li>
-                    <li><!-- TMPL_VAR NAME="HANDLED" --> directories processed.</li>
+                  <li><!-- TMPL_VAR NAME ="TOTAL" --> directorie(s) scanned.</li>
+                    <li><!-- TMPL_VAR NAME="HANDLED" --> directorie(s) processed.</li>
                 </ul>
                 <!-- TMPL_LOOP name="COUNTS" -->
                    <ul class="data">
-                        <li><!-- TMPL_VAR name="TCOUNTS" --> image(s) moved into the database:</li>
+                        <!-- TMPL_IF name = "TCOUNTS" --><li><!-- TMPL_VAR name="TCOUNTS" --> image(s) moved into the database:</li><!-- /TMPL_IF -->
                         <!-- TMPL_LOOP name="filenames" -->
                             <li><!-- TMPL_VAR name="source" --> - Cardnumber: <!-- TMPL_VAR name="cardnumber" -->
                                     <!-- TMPL_IF NAME="filerrors" --><br /> <b>WARNING:</b> This image <i>not</i> imported because 
@@ -48,6 +53,7 @@
                                         <!-- TMPL_IF NAME="DBERR" -->the database returned an error. Please refer to the error log for more details.</li>
                                         <!-- TMPL_ELSIF NAME="IMGEXISTS" -->this patron does not exist in the database.</li>
                                         <!-- TMPL_ELSIF NAME="MIMERR" -->the image format is unrecognized.</li>
+                                        <!-- TMPL_ELSIF NAME="CORERR" -->the image file is corrupted.</li>
                                         <!-- TMPL_ELSIF NAME="OPNERR" -->Koha was unable to open the image for reading.</li>
                                         <!-- TMPL_ELSIF NAME="OVRSIZ" -->the image file is too big.</li>
                                         <!-- TMPL_ELSIF NAME="CRDFIL" -->the <!-- TMPL_VAR NAME="CRDFIL" --> is missing.</li>
                 <!-- /TMPL_LOOP -->
 
                                </div>
-                <a id="uploadmore" href="/cgi-bin/koha/tools/picture-upload.pl">Upload More Images</a>
-                <a id="doneupload" href="/cgi-bin/koha/tools/tools-home.pl">Return to Tools</a>
+                               <!-- TMPL_IF name = "borrowernumber" -->
+                                       <a id="member" href="/cgi-bin/koha/members/moremember.pl?borrowernumber=<!-- TMPL_VAR name = "borrowernumber" -->">Return to Patron Detail</a>
+                               <!-- TMPL_ELSE -->
+                                       <a id="uploadmore" href="/cgi-bin/koha/tools/picture-upload.pl">Upload More Images</a>
+                                       <a id="doneupload" href="/cgi-bin/koha/tools/tools-home.pl">Return to Tools</a>
+               <!-- /TMPL_IF -->
             </div>
 <!-- TMPL_ELSE -->
     <div class="yui-b">
                         <!-- TMPL_ELSIF name="OPNIMG" --><li><b>Cannot open <!-- TMPL_VAR NAME="OPNIMG" --> to read.<br />Please verify that it exists.</b></li>
                         <!-- TMPL_ELSIF name="DELERR" --><li><b>Unrecognized or missing field delimeter.<br />Please verify that you are using either a single quote or a tab.</b></li>
                         <!-- TMPL_ELSIF name="UZIPFAIL" --><li><b><!-- TMPL_VAR name="UZIPFAIL" --> failed to unpack.<br />Please verify the integrity of the zip file and retry.</b></li>
-                        <!-- TMPL_ELSE --><li><b>An unknown error has occurred.<br />Please review the error log for more details.</b></li><!-- /TMPL_IF -->
+                        <!-- TMPL_ELSE --><li><b><!-- TMPL_VAR name ="CORERR" --> An unknown error has occurred.<br />Please review the error log for more details.</b></li><!-- /TMPL_IF -->
                     <!-- /TMPL_LOOP -->
                 </div>
                 <!-- /TMPL_IF -->
                <form method="post" action="/cgi-bin/koha/tools/picture-upload.pl" enctype="multipart/form-data">
                    <fieldset class="brief">
+                        <div class="hint"><b>NOTE:</b> Only PNG, GIF, JPEG, XPM formats are supported.</div>
                         <ol class="radio">
                             <li class="radio">
                                 <label for="zipfile"><input type="radio" id="zipfile" name="filetype" value="zip" checked="checked" /> zip file</label></li>
index 6f29eaa..e63747a 100755 (executable)
 use File::Temp;
 use File::Copy;
 use CGI;
-use Image::Magick;
+use GD;
 use C4::Context;
 use C4::Auth;
 use C4::Output;
 use C4::Members;
 use C4::Debug;
-#use Data::Dumper;
 
 my $input = new CGI;
 
@@ -91,7 +90,6 @@ if ( ($op eq 'Upload') && $uploadfile ) {       # Case is important in these ope
        while ( <$uploadfile> ) {
            print $tfh $_;
         }
-
         close $tfh;
         if ( $filetype eq 'zip' ) {
             unless (system("unzip $tempfile -d $dirname") == 0) {
@@ -124,14 +122,17 @@ if ( ($op eq 'Upload') && $uploadfile ) {       # Case is important in these ope
         if ( %$results || %errors ) {
             $template->param( ERRORS => [ \%$results ] );
         } else {
-            $debug and warn "Total files processed: $total";
-            warn "Errors in \$errors." if $errors;
+                       my $filecount;
+                       map {$filecount += $_->{count}} @counts;
+            $debug and warn "Total directories processed: $total";
+            $debug and warn "Total files processed: $filecount";
             $template->param(
-                TOTAL => $total,
-                HANDLED => $handled,
-                COUNTS => \@counts,
-                TCOUNTS => scalar(@counts),
+                       TOTAL => $total,
+                       HANDLED => $handled,
+                       COUNTS => \@counts,
+                       TCOUNTS => ($filecount > 0 ? $filecount : undef),
             );
+                       $template->param( borrowernumber => $borrowernumber ) if $borrowernumber;
         }   
     }
 } elsif ( ($op eq 'Upload') && !$uploadfile ) {
@@ -210,76 +211,86 @@ sub handle_file {
         $debug and warn "Source: $source";
         my $size = (stat($source))[7];
             if ($size > 100000) {    # This check is necessary even with image resizing to avoid possible security/performance issues...
-                warn "$filename is TOO BIG!!! I refuse to beleagur my database with that much data. Try reducing the pixel dimensions and I\'ll reconsider.";
                 $filerrors{'OVRSIZ'} = 1;
                 push my @filerrors, \%filerrors;
                 push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
                 $template->param( ERRORS => 1 );
                 return %count;    # this one is fatal so bail here...
             }
-        my $image = Image::Magick->new;
+        my ($srcimage, $image);
         if (open (IMG, "$source")) {
-            $image->Read(file=>\*IMG);
+            $srcimage = GD::Image->new(*IMG);
             close (IMG);
-            my $mimetype = $image->Get('mime');
-            # Check the pixel size of the image we are about to import...
-            my ($height, $width) = $image->Get('height', 'width');
-            $debug and warn "$filename is $width pix X $height pix.";
-            if ($width > 140 || $height > 200) {    # MAX pixel dims are 140 X 200...
-                warn "$filename exceeds the maximum pixel dimensions of 140 X 200. Resizing...";
-                my $percent_reduce;    # Percent we will reduce the image dimensions by...
-                if ($width > 140) {
-                    $percent_reduce = sprintf("%.5f",(140/$width));    # If the width is oversize, scale based on width overage...
-                } else {
-                    $percent_reduce = sprintf("%.5f",(200/$height));    # otherwise scale based on height overage.
-                }
-                my $width_reduce = sprintf("%.0f", ($width * $percent_reduce));
-                my $height_reduce = sprintf("%.0f", ($height * $percent_reduce));
-                warn "Reducing $filename by " . ($percent_reduce * 100) . "\% or to $width_reduce pix X $height_reduce pix";
-                $image->Resize(width=>$width_reduce, height=>$height_reduce);
-                my @img = $image->ImageToBlob();
-                $imgfile = $img[0];
-                warn "$filename is " . length($imgfile) . " bytes after resizing.";
-                undef $image;    # This object can get big...
-            } else {
-                my @img = $image->ImageToBlob();
-                $imgfile = $img[0];
-                $debug and warn "$filename is " . length($imgfile) . " bytes.";
-                undef $image;
-            }
-            $debug and warn "Image is of mimetype $mimetype";
-            my $dberror = PutPatronImage($cardnumber,$mimetype, $imgfile) if $mimetype;
-           if ( !$dberror && $mimetype ) { # Errors from here on are fatal only to the import of a particular image, so don't bail, just note the error and keep going
-               $count{count}++;
-               push @{ $count{filenames} }, { source => $filename, cardnumber => $cardnumber };
-           } elsif ( $dberror ) {
-                warn "Database returned error: $dberror";
-                ($dberror =~ /patronimage_fk1/) ? $filerrors{'IMGEXISTS'} = 1 : $filerrors{'DBERR'} = 1;
-                push my @filerrors, \%filerrors;
-               push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
-                $template->param( ERRORS => 1 );
-            } elsif ( !$mimetype ) {
-                warn "Unable to determine mime type of $filename. Please verify mimetype and add to \%mimemap if necessary.";
-                $filerrors{'MIMERR'} = 1;
-                push my @filerrors, \%filerrors;
-               push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
-                $template->param( ERRORS => 1 );
-            }
-        } else {
-            warn "Opening $dir/$filename failed!";
-            $filerrors{'OPNERR'} = 1;
-            push my @filerrors, \%filerrors;
-           push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
-            $template->param( ERRORS => 1 );
-        }
+                       if (defined $srcimage) {
+                               my $mimetype = 'image/jpeg';    # GD autodetects three basic image formats: PNG, JPEG, XPM; we will convert all to JPEG...
+                               # Check the pixel size of the image we are about to import...
+                               my ($width, $height) = $srcimage->getBounds();
+                               $debug and warn "$filename is $width pix X $height pix.";
+                               if ($width > 140 || $height > 200) {    # MAX pixel dims are 140 X 200...
+                                       $debug and warn "$filename exceeds the maximum pixel dimensions of 140 X 200. Resizing...";
+                                       my $percent_reduce;    # Percent we will reduce the image dimensions by...
+                                       if ($width > 140) {
+                                               $percent_reduce = sprintf("%.5f",(140/$width));    # If the width is oversize, scale based on width overage...
+                                       } else {
+                                               $percent_reduce = sprintf("%.5f",(200/$height));    # otherwise scale based on height overage.
+                                       }
+                                       my $width_reduce = sprintf("%.0f", ($width * $percent_reduce));
+                                       my $height_reduce = sprintf("%.0f", ($height * $percent_reduce));
+                                       $debug and warn "Reducing $filename by " . ($percent_reduce * 100) . "\% or to $width_reduce pix X $height_reduce pix";
+                                       $image = GD::Image->new($width_reduce, $height_reduce, 1); #'1' creates true color image...
+                                       $image->copyResampled($srcimage,0,0,0,0,$width_reduce,$height_reduce,$width,$height);
+                                       $imgfile = $image->jpeg(100);
+                                       $debug and warn "$filename is " . length($imgfile) . " bytes after resizing.";
+                                       undef $image;
+                                       undef $srcimage;    # This object can get big...
+                               } else {
+                                       $image = $srcimage;
+                                       $imgfile = $image->jpeg();
+                                       $debug and warn "$filename is " . length($imgfile) . " bytes.";
+                                       undef $image;
+                                       undef $srcimage;    # This object can get big...
+                               }
+                               $debug and warn "Image is of mimetype $mimetype";
+                               my $dberror = PutPatronImage($cardnumber,$mimetype, $imgfile) if $mimetype;
+                               if ( !$dberror && $mimetype ) { # Errors from here on are fatal only to the import of a particular image, so don't bail, just note the error and keep going
+                                       $count{count}++;
+                                       push @{ $count{filenames} }, { source => $filename, cardnumber => $cardnumber };
+                               } elsif ( $dberror ) {
+                                               warn "Database returned error: $dberror";
+                                               ($dberror =~ /patronimage_fk1/) ? $filerrors{'IMGEXISTS'} = 1 : $filerrors{'DBERR'} = 1;
+                                               push my @filerrors, \%filerrors;
+                                               push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
+                                               $template->param( ERRORS => 1 );
+                               } elsif ( !$mimetype ) {
+                                       warn "Unable to determine mime type of $filename. Please verify mimetype.";
+                                       $filerrors{'MIMERR'} = 1;
+                                       push my @filerrors, \%filerrors;
+                                       push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
+                                       $template->param( ERRORS => 1 );
+                               }
+                       } else {
+                               warn "Contents of $filename corrupted!";
+                       #       $count{count}--;
+                               $filerrors{'CORERR'} = 1;
+                               push my @filerrors, \%filerrors;
+                               push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
+                               $template->param( ERRORS => 1 );
+                       }
+               } else {
+                       warn "Opening $dir/$filename failed!";
+                       $filerrors{'OPNERR'} = 1;
+                       push my @filerrors, \%filerrors;
+                       push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
+                       $template->param( ERRORS => 1 );
+               }
     } else {    # The need for this seems a bit unlikely, however, to maximize error trapping it is included
         warn "Missing " . ($cardnumber ? "filename" : ($filename ? "cardnumber" : "cardnumber and filename"));
         $filerrors{'CRDFIL'} = ($cardnumber ? "filename" : ($filename ? "cardnumber" : "cardnumber and filename")); 
         push my @filerrors, \%filerrors;
-       push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
+               push @{ $count{filenames} }, { filerrors => \@filerrors, source => $filename, cardnumber => $cardnumber };
         $template->param( ERRORS => 1 );
     }
-    return %count;
+    return (%count);
 }
 
 =back