brianviehland has asked for the wisdom of the Perl Monks concerning the following question:

Oh perl monks, please show mercy on me and grant me an answer to my trouble.... I am trying to use the GD.pm function copyResized or copyResampled to create thumbnails of uploaded images. What seems to be happening is that 1/4 to 1/2 of the image data is being dropped prior to finishing the thumbnail file. To see the results, visit http://viehland.org/gd-images. The image files are being uploaded to the server correcty, and following that, the size is being determined correctly. The new thumbnail is created in the correct proportions with the maximum dimension set correctly, but when the copyResized or copyResampled function attempts to insert the image data into the thumbnail file, it gets half way through and seems to give up unexpectantly. I know the first answer is "use Image Magick" which I do on my own server, but I'm trying to write a GD.pm alternative for those people on shared hosting servers who cannot get ImageMagick installed. The code is below:
use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use GD; $maxThumbSize = "150"; $name = param('filename'); $imagePath = "/home/user/public_html/images/" . $name; if ($name =~ m/gif$/) { &error('GIF files are copyrighted through 2004 +'); } if (($name =~ m/jpg$/i) || ($file =~ m/jpeg$/i)) { $sourceImage = GD::Image->newFromJpeg($imagePath); $retype = "no"; } elsif ($name =~ m/png$/i) { open (PNG,imagePath) || &error('Cannot Open PNG File'); $sourceImage = newFromPng GD::Image(PNG) || &error('Cannot Read Fr +om PNG File'); close PNG; $retype = "yes"; } ($fileWidth,$fileHeight) = $sourceImage->getBounds(); if ((($fileWidth > $maxThumbSize) || ($fileHeight > $maxThumbSize)) || + ($retype eq "yes")) { if ($fileWidth > $fileHeight) { $scalefactor=$maxThumbSize/$fileWi +dth; } else { $scalefactor=$maxThumbSize/$fileHeight; } $thumbWidth = int($fileWidth*$scalefactor); $thumbHeight = int($fi +leHeight*$scalefactor); } else { $thumbWidth=$fileWidth; $thumbHeight=$fileHeight; } $thumbnailImage = new GD::Image($thumbWidth, $thumbHeight); $thumbnailImage->copyResampled($sourceImage,0,0,0,0,$thumbWidth,$thumb +Height,$fileWidth,$fileHeight); $thumbPath = $thumbFolder . $S . $imageBase . "-" . $fileWidth . "x" . + $fileHeight . ".jpg"; if (-f $thumbPath) { unlink("$thumbPath"); } open(THUMB, ">$thumbPath") or &error('Cannot Open New Thumbnail'); if ($opsys eq "dos") { binmode THUMB; } else { flock(THUMB, 2); } if ((($fileWidth gt $maxThumbSize) || ($fileHeight gt $maxThumbSize)) +|| ($retype eq "yes")) { print THUMB $thumbnailImage->jpeg(75); } else { print THUMB $sourceImage->jpeg(75); } close(THUMB) or &error('Cannot Close New Thumbnail'); chmod(0644, $thumbPath); }

Replies are listed 'Best First'.
Re: Corrupted data problem in copyResampled using GD.pm
by graff (Chancellor) on Feb 10, 2004 at 06:47 UTC
    What seems to be happening is that 1/4 to 1/2 of the image data is being dropped prior to finishing the thumbnail file.
    Does that imply that the extent of corruption varies depending on the image? (Or simply that you're not sure what the real amount of lossage is?)

    If it varies with the image, then maybe you should take a closer look at this line in your code:

    if ($opsys eq "dos") { binmode THUMB; }
    Are you sure that "$opsys" has been set appropriately? (Why aren't you just using "$^O" ?)

    Apart from that, I don't know about the GD::Image "jpeg" method... what does it mean to pass it a value of "75"?

      Better yet, just binmode THUMB; anyways, don't bother with the check. It only affects those operating systems it matters on.
        I know that $opsys is setting correctly. I use it instead of $^O because it sets some other variables in the script as well as this.

        The amount of corruption does vary from image to image and from browser to browser. I'm not sure what the reason is behind it. I wrote this script for a church and it's photos vary in corruption. You can see the images at http://mtziontrenton.com/cgi-bin/ezwebalbum.cgi With some images it was fine, with others it is a few lines, and others had major corruption.

        If you have any idea about why this is happening, please let me know!
Re: Corrupted data problem in copyResampled using GD.pm
by graff (Chancellor) on Feb 11, 2004 at 00:56 UTC
    You said your image files are being uploaded correctly, and the first example you cite (picture of a VW beetle) shows a correct full-size image and a "truncated" thumbnail. But then in one of your sub-replies, you cited another web page with bad thumbnails, and when I followed one of those through to a full-size image, that full-size image had the same symptom as the thumbnail -- the lower few scan lines were solid grey instead of being the photograph.

    Compare any of the thumbnails here against the full size image that is shown when you click on the thumbnail: http://mtziontrenton.com/cgi-bin/ezwebalbum.cgi?cgiAction=albumDisplay&category=Celebrations&album=Celebrations2

    If you're creating the full-size image by expanding the thumbnail, then ignore this reply. (But why would you do that?)

    Otherwise, recheck your process for uploading the images -- my guess would be there's a "dos text-mode" component somewhere in the transfer, and the image files tend to have a byte somewhere that equates to ^Z (EOF tag for dos text files), or else there's just a ^J ("new-line" in text files) where a text-mode transfer is prepending ^M ("carriage-return"), and that's screwing up the image stream. But that's just a guess.

      The full size image is being corrupted because it too was uploaded too large, and therefor was copyResized the same way to make it a max of 600 pixels. I didn't want the directories filling up with 1MB files, so they are all checked for size and shrunk to 600 pixels max, then a thumbnail is created at 150 pixels max. Both processes use the same code, so the corruption happening in the original and the thumbnail are stemming from the same problem.

      I'll look at any ^J or ^Z files in the data stream of the jpeg and see what I might find... -Brian