[image-processing] Recommendation for compressing JPG files with ImageMagick

I want to compress a JPG image file with ImageMagick but can't get much difference in size. By default the output size is bigger than the input. I don't know why, but after adding some +profile options and setting down the quality I can get an smaller size but still similar to original.

The input image is 255kb, the processed image is 264kb (using +profile to remove profiles and setting quality to 70%). Is there any way to compress that image to 150kb at least? Is that possible? What ImageMagick options can I use?

This question is related to image-processing imagemagick

The answer is


If the image has big dimenssions is hard to get good results without resizing, below is a 60 percent resizing which for most of the purposes doesn't destroys too much of the image.

I use this with good result for gray-scale images (I convert from PNG):

ls ./*.png | xargs -L1 -I {} convert {} -strip -interlace JPEG -sampling-factor 4:2:0 -adaptive-resize 60%   -gaussian-blur 0.05 -colorspace Gray -quality 20  {}.jpg

I use this for scanned B&W pages get them to gray-scale images (the extra arguments cleans shadows from previous pages):

ls ./*.png | xargs -L1 -I {} convert {} -strip -interlace JPEG -sampling-factor 4:2:0 -adaptive-resize 60%   -gaussian-blur 0.05 -colorspace Gray -quality 20 -density 300 -fill white -fuzz 40% +opaque "#000000" -density 300 {}.jpg 

I use this for color images:

ls ./*.png | xargs -L1 -I {} convert {} -strip -interlace JPEG -sampling-factor 4:2:0 -adaptive-resize 60%   -gaussian-blur 0.05 -colorspace RGB -quality 20  {}.jpg 

Once I needed to resize photos from camera for developing:

  • Original filesize: 2800 kB
  • Resolution: 3264x2448

Command:

mogrify -quality "97%" -resize 2048x2048 -filter Lanczos -interlace Plane -gaussian-blur 0.05 
  • Result filesize 753 kB
  • Resolution 2048x2048

and I can't see any changes in full screen with my 1920x1080 resolution monitor. 2048 resolution is the best for developing 10 cm photos at maximum quality of 360 dpi. I don't want to strip it.

edit: I noticed that I even get much better results without blurring. Without blurring filesize is 50% of original, but quality is better (when zooming).


Just saying for those who using Imagick class in PHP:

$im -> gaussianBlurImage(0.8, 10);      //blur
$im -> setImageCompressionQuality(85);  //set compress quality to 85

@JavisPerez -- Is there any way to compress that image to 150kb at least? Is that possible? What ImageMagick options can I use?

See the following links where there is an option in ImageMagick to specify the desired output file size for writing to JPG files.

http://www.imagemagick.org/Usage/formats/#jpg_write http://www.imagemagick.org/script/command-line-options.php#define

-define jpeg:extent={size} As of IM v6.5.8-2 you can specify a maximum output filesize for the JPEG image. The size is specified with a suffix. For example "400kb".

convert image.jpg -define jpeg:extent=150kb result.jpg

You will lose some quality by decompressing and recompressing in addition to any loss due to lowering -quality value from the input.


Here's a complete solution for those using Imagick in PHP:

$im = new \Imagick($filePath);
$im->setImageCompression(\Imagick::COMPRESSION_JPEG);
$im->setImageCompressionQuality(85);
$im->stripImage();
$im->setInterlaceScheme(\Imagick::INTERLACE_PLANE);

// Try between 0 or 5 radius. If you find radius of 5 
// produces too blurry  pictures decrease to 0 until you 
// find a good balance between size and quality. 
$im->gaussianBlurImage(0.05, 5);



// Include this part if you also want to specify a maximum size for the images

$size = $im->getImageGeometry();
$maxWidth = 1920;
$maxHeight = 1080;


// ----------
// |        |
// ----------
if($size['width'] >= $size['height']){
  if($size['width'] > $maxWidth){
    $im->resizeImage($maxWidth, 0, \Imagick::FILTER_LANCZOS, 1);
  }
}


// ------
// |    |
// |    |
// |    |
// |    |
// ------
else{
  if($size['height'] > $maxHeight){
    $im->resizeImage(0, $maxHeight, \Imagick::FILTER_LANCZOS, 1);
  }
}

I'm using the Google Pagespeed Insights image optimization guidelines, and for ImageMagick they recommend the following:

-sampling-factor 4:2:0
-strip
-quality 85 [it can vary, I use range 60-80, lower number here means smaller file]
-interlace
-colorspace RGB

Command in ImageMagick:

convert image.jpg -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -colorspace RGB image_converted.jpg

With these options I get up to 40% savings in JPEG size without much visible loss.


I added -adaptive-resize 60% to the suggested command, but with -quality 60%.

convert -strip -interlace Plane -gaussian-blur 0.05 -quality 60% -adaptive-resize 60% img_original.jpg img_resize.jpg

These were my results

  • img_original.jpg = 13,913KB
  • img_resized.jpg = 845KB

I'm not sure if that conversion destroys my image too much, but I honestly didn't think my conversion looked like crap. It was a wide angle panorama and I didn't care for meticulous obstruction.


Did some experimenting myself here and boy does that Gaussian blur make a nice different. The final command I used was:

mogrify * -sampling-factor 4:2:0 -strip -quality 88 -interlace Plane -define jpeg:dct-method=float -colorspace RGB -gaussian-blur 0.05 

Without the Gaussian blur at 0.05 it was around 261kb, with it it was around 171KB for the image I was testing on. The visual difference on a 1440p monitor with a large complex image is not noticeable until you zoom way way in.


I would add an useful side note and a general suggestion to minimize JPG and PNG.

First of all, ImageMagick reads (or better "guess"...) the input jpeg compression level and so if you don't add -quality NN at all, the output should use the same level as input. Sometimes could be an important feature. Otherwise the default level is -quality 92 (see www.imagemagick.org)

The suggestion is about a really awesome free tool ImageOptim, also for batch process.
You can get smaller jpgs (and pngs as well, especially after the use of the free ImageAlpha [not batch process] or the free Pngyu if you need batch process).
Not only, these tools are for Mac and Win and as Command Line (I suggest installing using Brew and then searching in Brew formulas).