From 1baf6348cc38e4feeddad89332d78d08c81d5930 Mon Sep 17 00:00:00 2001 From: Chris Nighswonger Date: Mon, 28 Jul 2008 11:35:46 -0500 Subject: [PATCH] kohabug 2404 This patch removes Image::Magick and adds GD 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 Signed-off-by: Joshua Ferraro --- C4/Members.pm | 2 +- Makefile.PL | 2 +- about.pl | 2 +- .../en/modules/help/members/moremember.tmpl | 2 +- .../en/modules/help/tools/picture-upload.tmpl | 2 +- .../prog/en/modules/members/moremember.tmpl | 4 +- .../prog/en/modules/tools/picture-upload.tmpl | 27 +++- tools/picture-upload.pl | 141 ++++++++++-------- 8 files changed, 102 insertions(+), 80 deletions(-) diff --git a/C4/Members.pm b/C4/Members.pm index 70a85c3543..1f0328225a 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -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; diff --git a/Makefile.PL b/Makefile.PL index 167fc9c257..743ea3333e 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -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, diff --git a/about.pl b/about.pl index a31b0a0211..6cff96d5bc 100755 --- 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 diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/members/moremember.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/help/members/moremember.tmpl index b8158cbc98..ebabcfc468 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/members/moremember.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/members/moremember.tmpl @@ -1,3 +1,3 @@ -

Member Information Screen

This screen shows the information associated with a given patron.

On the top left is their address and card number.

A patron's annual membership fee payment status also shows on this screen.

At the bottom of the patron information page you will find quick access to items the patron has checked out, overdue and on hold.

You can get information on what a patron has read in the past by clicking on the Circulation History button.

If you would like to edit a patron's information, click the 'Edit' button.  You can also click one of the 'Edit' links below each section on the patron record.

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!

If no patron image exists for this patron, click the "Add Patron Images" link to add an image or images. The pixel dimensions should not exceed 120 X 200.

+

Member Information Screen

This screen shows the information associated with a given patron.

On the top left is their address and card number.

A patron's annual membership fee payment status also shows on this screen.

At the bottom of the patron information page you will find quick access to items the patron has checked out, overdue and on hold.

You can get information on what a patron has read in the past by clicking on the Circulation History button.

If you would like to edit a patron's information, click the 'Edit' button.  You can also click one of the 'Edit' links below each section on the patron record.

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!

If no patron image exists for this patron, click the "Add Patron Images" link to add an image or images. The pixel dimensions should not exceed 120 X 200. Only PNG, GIF, JPEG, XPM formats are supported.

diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/picture-upload.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/picture-upload.tmpl index 21be7653f9..6916593a4b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/picture-upload.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/help/tools/picture-upload.tmpl @@ -1,5 +1,5 @@
-

Upload Patron Images

This tool allows you to upload multiple patron images as a batch.

IMPORTANT: Requires that the 'patronimages' system preference is set to 'ON' to use this feature.
  • Get there: More > Administration > Global System Preferences > Patrons > patronimages

Upload images in bulk

  • Go to the 'Tools' module (usually under 'More' in your Global Nav)
  • Choose 'Upload patron images'
  • You can choose to upload images in bulk by making a zip file with the images and a text file entitled "DATALINK.TXT" or "IDLINK.TXT"
  • 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.
    • IMPORTANT: Make sure that your TXT file is a plain text document, not RTF.
    • IMPORTANT: Make sure that you use either a comma or a tab to separate IDs from image names
  • Add the images and the TXT file to a .ZIP file
  • Browse for the file from the Koha interface
  • Click 'Unpack' and you will receive a confirmation screen
  • To see the image(s) you imported search for the patron(s) and view their profile
  • If you'd like to change the image, just upload a new image
  • If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'

Uploading Single Images

If you only have one patron image you might want to upload it via the patron information page instead of using this bulk tool.

  • Go to the Patrons menu at the top of the staff client
  • Search for the patron you have the image for
  • If there is more than one result, click on the name of the patron you'd like to add an image to
  • Scroll down to the image upload form
  • Browse for the image on your computer and click 'Upload'
  • If you'd like to change the image, just upload a new image
  • If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'



Why can't I upload patron images?


First you will need a patronimages/ directory.  If you do not have this directory you will see an error.
  • Contact your system administrator to create this directory and you'll be set to go.

What size should my images be?

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.

+

Upload Patron Images

This tool allows you to upload multiple patron images as a batch.

IMPORTANT: Requires that the 'patronimages' system preference is set to 'ON' to use this feature.
  • Get there: More > Administration > Global System Preferences > Patrons > patronimages

Upload images in bulk

  • Go to the 'Tools' module (usually under 'More' in your Global Nav)
  • Choose 'Upload patron images'
  • You can choose to upload images in bulk by making a zip file with the images and a text file entitled "DATALINK.TXT" or "IDLINK.TXT"
  • 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.
    • IMPORTANT: Make sure that your TXT file is a plain text document, not RTF.
    • IMPORTANT: Make sure that you use either a comma or a tab to separate IDs from image names
  • Add the images and the TXT file to a .ZIP file
  • Browse for the file from the Koha interface
  • Click 'Unpack' and you will receive a confirmation screen
  • To see the image(s) you imported search for the patron(s) and view their profile
  • If you'd like to change the image, just upload a new image
  • If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'

Uploading Single Images

If you only have one patron image you might want to upload it via the patron information page instead of using this bulk tool.

  • Go to the Patrons menu at the top of the staff client
  • Search for the patron you have the image for
  • If there is more than one result, click on the name of the patron you'd like to add an image to
  • Scroll down to the image upload form
  • Browse for the image on your computer and click 'Upload'
  • If you'd like to change the image, just upload a new image
  • If you'd like to delete the patron image, click the 'Delete' button under 'Manage Patron Image'



Why can't I upload patron images?


First you will need a patronimages/ directory.  If you do not have this directory you will see an error.
  • Contact your system administrator to create this directory and you'll be set to go.

What size should my images be?

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.

What image formats are supported?

Only PNG, GIF, JPEG, XPM formats are supported.i
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl index 0da1c48d9c..9133705014 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tmpl @@ -203,11 +203,11 @@ if (nodename =="barcodes[]"){
Manage Patron Image -
To update the image for , enter the name of the new image file to upload and click 'Upload.'
Click the 'Delete' button to remove the current image.
+
To update the image for , enter the name of the new image file to upload and click 'Upload.'
Click the 'Delete' button to remove the current image.
Only PNG, GIF, JPEG, XPM formats are supported.
Upload Patron Image -
does not currently have an image available. To import an image for , enter the name of an image file to upload.
+
does not currently have an image available. To import an image for , enter the name of an image file to upload.
Only PNG, JPEG, XPM formats are supported.
" /> diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/picture-upload.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/picture-upload.tmpl index 7bb47b3d58..f2750e3116 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/picture-upload.tmpl +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/picture-upload.tmpl @@ -27,20 +27,25 @@
-
-

Patron Image(s) Uploaded With Some Errors

+ +
+

Patron Image(s) Uploaded With Some Errors

+ +
+

Patron Image Failed to Upload

+

Patron Image(s) Successfully Uploaded

  • Unpacking completed
  • -
  • directories scanned.
  • -
  • directories processed.
  • +
  • directorie(s) scanned.
  • +
  • directorie(s) processed.
    -
  • image(s) moved into the database:
  • +
  • image(s) moved into the database:
  • - Cardnumber:
    WARNING: This image not imported because @@ -48,6 +53,7 @@ the database returned an error. Please refer to the error log for more details.
  • this patron does not exist in the database. the image format is unrecognized. + the image file is corrupted. Koha was unable to open the image for reading. the image file is too big. the is missing. @@ -60,8 +66,12 @@
- Upload More Images - Return to Tools + + ">Return to Patron Detail + + Upload More Images + Return to Tools +
@@ -78,12 +88,13 @@
  • Cannot open to read.
    Please verify that it exists.
  • Unrecognized or missing field delimeter.
    Please verify that you are using either a single quote or a tab.
  • failed to unpack.
    Please verify the integrity of the zip file and retry.
  • -
  • An unknown error has occurred.
    Please review the error log for more details.
  • +
  • An unknown error has occurred.
    Please review the error log for more details.
  • +
    NOTE: Only PNG, GIF, JPEG, XPM formats are supported.
    1. diff --git a/tools/picture-upload.pl b/tools/picture-upload.pl index 6f29eaadac..e63747ae50 100755 --- a/tools/picture-upload.pl +++ b/tools/picture-upload.pl @@ -22,13 +22,12 @@ 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 -- 2.20.1