Convert images and show result using Image Magick - imagemagick

I am manipulating images using Image Magick. Here is the command that I use:
convert source.png -resize 1200 -quality 75 result.jpg
It works as expected. I am no wondering whether there is a way to report a conversion result showing how much compression has been done (in percentage or kilobyte or just by showing the sizes of original and converted images)?
I have tried -monitor switch, but it only shows a progress kind of report during conversion.
(I am using Linux)

The quality setting you use tells ImageMagick how much to compress the image. Alternately, you can compute the ratio of the output file size by the input size. Or the ratio of the output file size with -quality 75 to that when using -quality 100, even though -quality 100 still compresses some.
You can get the size of the image by
convert image -precision 16 -format "%b\n" info:
Setting a large precision will forces the result to be in Bytes, but you will have to remove the B character from the end. So you can do the following to get the percent of output/input file sizes:
outsize=$(convert output -precision 16 -format "%b\n" info: | sed 's/B//g')
insize=$(convert input -precision 16 -format "%b\n" info: | sed 's/B//g')
percent_size=$(convert xc: -format "%[fx:100*$outsize/$insize]\n" info:)

Related

convert doesn't conserve size when scaling down and up

In order to make applying blur faster I'm first scaling my image down and then scale it back up:
convert - -scale 10% -blur 0x2.5 -resize 1000% RGB:-
This works most of the time but sometimes the output resolution is slightly different from the original input. Is there a way to force the pipeline to be size-preserving?
You should be able to access the original geometry of the image via %G, so you can do:
convert input.jpg -scale 10% -blur 0x2.5 -resize '%G!' RGB:-
If you are using Windows, you probably want "%G!" in double rather than single quotes.
If you are using v7 ImageMagick, replace convert with magick.
I think you are getting errors because if you take 10% of 72 pixels (say), you will get a whole number of pixels, i.e. 7 pixels and then when you scale back up by a factor of 10 you'll get 70 rather than your initial 72.
If you are using Imagemagick 7, you can do the following:
magick input.jpg -set option:wd "%w" -set option:ht "%h" -scale "%[fx:wd/10]x%[fx:ht/10]" -blur 0x2.5 -resize "%[fx:wd]x%[fx:ht]\!" RGB:-
This stores the input width and height. Then uses the stored values to scale by 1/10 of those dimensions, then does the blur, then resizes exactly back to the origin input size. Note the ! that forces the resize to the exact dimensions.
or simpler without storing the input width and height:
magick lena.jpg -scale "%[fx:w/10]x%[fx:h/10]" -blur 0x2.5 -resize "%[fx:w]x%[fx:h]\!" lena_x.jpg

Algorithm for determining if a particular image would be smaller as a PNG or JPG

I am writing a script to optimize a bunch of images. I want to determine which format to convert the image in — PNG or JPG. Goal is small file size without compromising on quality.
Is there an algorithmic way of determining this? I can convert into both, compare sizes, and discard the bigger one, but I was wondering if there is a way to determine it based on number of colors, etc.
You can tell the size of a converted file without writing it to disk like this:
convert -size 1000x1000! xc:gray +noise random JPEG: | wc -c
1742282
convert -size 1000x1000! xc:gray +noise random PNG: | wc -c
6010785
Obviously you may want to set the quality factors and colour depth and other parameters to tune the space, but this will tell you the size. For example, you may want to specify the maximum JPEG size:
convert -size 1000x1000! xc:gray +noise random -define jpeg:extent=300k JPEG: | wc -c
286103

Image Magick - trim and repage - loss of quality

When I use this command to trim a PDF file:
convert -fuzz 1% -trim +repage multi0.pdf multi0new.pdf
The result is very disappointing and the trimmed image size becomes more than 10 times lower than the source.
Is there any way to make a clean image trimming without loss of quality?
(here it is, before and after)
You probably have to use the -density option with a higher value than the default of 72 dpi. Try 300 for a start:
convert -density 300 -fuzz 1% -trim +repage multi0.pdf multi0new.pdf
Note that higher density values will increase the output file size.

Resizing an Image using Imagemagick convert

I have a YUV420 image of size 1280x720. I am trying to resize it to 720x576 using convert (Imagemagick) using below commandline options. But the generated output file doesnot seem to be a proper resized YUV420 image(I want the resized output also to be in YUV420 format):
convert -size 1280x720 -depth 8 -sampling-factor 2x2 test_1280x720_yuv420.yuv -filter lanczos -resize 720x576 -depth 8 -sampling-factor 2x2 720x576_yuv420.yuv //Here the output file size is not what it should be of a 720x576 YUV420 file which is 720x576x1.5 bytes.
Qiestion: What is the format of this output file then?
Also tried -sample option as, but same result. Incorrect sized output file. I even tried to display the generated resized file, but it sure is not a YUV420 file, as could not view it correctly at all.
convert -size 1280x720 -depth 8 -sampling-factor 2x2 test_1280x720_yuv420.yuv -sample 720x576 -depth 8 -sampling-factor 2x2 720x576_yuv420.yuv
Question: Would convert be able to do what I am trying to get done? IF yes, what are the options?
Question: Any other tool(freeware,shareware) which could help me resize YUV files(different formats YUV420, YUV444) to YUV format output files?
Try to ignore aspect ration!
Ignore Aspect Ratio ('!' flag)
If you want you can force "-resize" to ignore the aspect ratio and distort the image so it always generates an image exactly the size specified. This is done by adding the character '!' to the size. Unfortunately this character is also sometimes used for special purposes by various UNIX command line shells. So you may have to escape the character somehow to preserve it.
Example:
convert image.gif -resize 64x64\! resized_image.gif //Resized Image with ignore ratio option

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?
I use always:
quality in 85
progressive (comprobed compression)
a very tiny gausssian blur to optimize the size (0.05 or 0.5 of radius) depends on the quality and size of the picture, this notably optimizes the size of the jpeg.
Strip any comment or EXIF metadata
in imagemagick should be
convert -strip -interlace Plane -gaussian-blur 0.05 -quality 85% source.jpg result.jpg
or in the newer version:
magick source.jpg -strip -interlace Plane -gaussian-blur 0.05 -quality 85% result.jpg
Source.
From #Fordi in the comments (Don't forget to upvote him if you like this):
If you dislike blurring, use -sampling-factor 4:2:0 instead. What this does is reduce the chroma channel's resolution to half, without messing with the luminance resolution that your eyes latch onto. If you want better fidelity in the conversion, you can get a slight improvement without an increase in filesize by specifying -define jpeg:dct-method=float - that is, use the more accurate floating point discrete cosine transform, rather than the default fast integer version.
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.
Just saying for those who using Imagick class in PHP:
$im -> gaussianBlurImage(0.8, 10); //blur
$im -> setImageCompressionQuality(85); //set compress quality to 85
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).
#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.
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).
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.
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);
}
}
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.
An very old but helpful answer.
I need to say, to serious large photography, -gaussian-blur is not acceptable, rather than compress ratio.
Comparing below, %95 with -gaussian-blur 0.05 vs. %85 without blurring. Original 17.5MB (8MP with much defail), %95 without blurring 5MB, %85 without blurring 3036KB, %95 with blurring 3365KB.
Comparing between blurring and compress ratio
Maybe lower blurring like 0.02 will work better.
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

Resources