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

It seems that even though there were replies to my last submission. They did not directly address my issue, so I am reposting here to hope for a specific answer to my question.

Does anyone know how to reduce the image file size using image magick. It seems when I use the Scale method the dimensions are reduced but the file size does not get reduced enough. For instance, a 400k image is only reduced to 160k which is not acceptable for web download. I have tried using the Sample method but do not see any difference when compared to the Scale method. I would like to take a 400k+ image and resample to 35 to 40k. The image is JPG format. Below is a snippet of how I am trying to sample:

$imgfile = "photo.jpg"; $geometry = ($newwidth x $newheight); $im->Sample(geometry => $geometry); $im->Write("JPG:../images/$imgfile");
Thank you for your input.

David K.

Replies are listed 'Best First'.
Re: Image Magick - Sample vs. Scale
by steves (Curate) on Mar 01, 2003 at 10:15 UTC

    You can reduce the quality of a JPEG to reduce its file size. This does not affect its dimensions. Here's an ImageMagick based method I have that reduces an image's quality step-wise until it hits a given target size. Note that when reducing quality you want to start with the same image each time -- not reduce one that's already been reduced. Doing the latter will lead to very poor quality.

    use File::Copy; use Image::Magick; sub compress_image { my $image_file = shift; my $desired_size = shift; my $target_file = shift; my $min_quality = shift; my $step = shift; my $verbose_level = shift; my $image; my $status; my $size; my $quality; my $last_quality; local *IMAGE; my $blob; die __PACKAGE__ . " compress_image() required image file name miss +ing.\n" if (!defined($image_file)); die __PACKAGE__ . " compress_image() required image file size miss +ing.\n" if (!defined($desired_size)); $target_file = $image_file if (!defined($target_file)); $min_quality = 1 if (!defined($min_quality)); if (!defined($step)) { $step = 5; } elsif ($step < 0) { $step = -$step; } die "Can't compress $image_file: No such file or directory.\n" if (! -e $image_file); if ($verbose_level > 0) { print "Compressing $image_file.\n"; print "Resulting image will be in $target_file.\n"; } $image = Image::Magick->new(); $status = $image->Read($image_file); warn "$status" if "$status"; $size = $image->Get('filesize'); $last_quality = $quality = $image->Get('quality'); if ($verbose_level > 1) { print "Initial image size: $size\n"; print "Initial image quality: $quality\n"; } while ( ($size > $desired_size) && ($size > 0) && (($quality -= $step) >= $min_quality) ) { $blob = $image->ImageToBlob(quality => $quality); $size = length($blob); $last_quality = $quality; if ($verbose_level > 1) { print "Current image size: $size\n"; print "Current image quality: $quality\n"; } } $size = $image->Get('filesize'); if ($verbose_level > 1) { print "Final image size: $size\n"; print "Final image quality: $last_quality\n"; } undef $image; if (defined($blob)) { open(IMAGE, ">$target_file") or die "Can't open $target_file for writing: $!\n"; print IMAGE $blob; close(IMAGE) or die "Failed to close $target_file: $!\n"; } elsif ($image_file ne $target_file) { copy($image_file, $target_file) or die "Failed to copy $image_file to $target_file: $!\n"; } return ( ($size > 0) && ($size <= $desired_size) ) ? 1 : 0; }
      Thank you! I will try the code.

      David K.

        Windows users might want to add the line binmode IMAGE; before the line print IMAGE $blob;
Re: Image Magick - Sample vs. Scale
by caedes (Pilgrim) on Mar 01, 2003 at 13:22 UTC
    Perhapse you didn't get any help from the earlier post not because you didn't receive it but because you didn't understand it. If that is the case then you should just respond to the comments that you got earlier instead of starting a new thread.

    As it is, I think the above response once again answers your question satisfactorily.

    -caedes

      Actually, I did respond but did not receive any follow-up from anyone. And you are right, I did not understand the answer given since it was very vague without any direction for me. PNG did not solve the problem, and as a matter of fact, made the image size larger than JPG. The other suggestion stating that compression varies does not help me since it is so generalized. Maybe an example would have helped.

      The first response to my new question looks more promising and I will be testing it out.

      David K.

Re: Image Magick - Sample vs. Scale
by shotgunefx (Parson) on Mar 01, 2003 at 22:32 UTC
    As far as your original post, well to understand the problem you needed to give more info. When you said you had a 400K image, it's not very helpful. Is this the compressed size? The size of a raw 24 bit image or an 8 bit palette indexed image? If you detailed the raw size (X,Y) of the image, the color depth (assuming 24-bit but...) and an idea of what the image was (photo, or computer generated such as text for nav buttons or other image with long runs of continuous color) it would help point out what might work best or even if 40K was a reasonable target.

    Having said that, steves approach should work. Though it would help if you described what it was type of image content it contained and what the dimensions are.

    -Lee

    "To be civilized is to deny one's nature."