ImageMagick: scale JPEG image with a maximum file-size - imagemagick

I have a number of JPEG pictures which I would like to scale down. Another requirement is that the file size should not be larger than say 300kByte.
Is that possible, please help me with an example =)

To restrict the resulting image to a maximum file size, you can use the commandline parameter -define jpeg:extent=max_value, like this:
convert original.jpeg -define jpeg:extent=300kb output.jpg
convert original.jpeg -define jpeg:extent=300kb -scale 50% output.jpg
convert original.jpeg -define jpeg:extent=300kb [...other options...] output.jpg
Note, this will not always work to match the exact size you wanted. You may have asked for 40kb output size, where input is 300kb, and get a result of 48kb.
(Update/Clarification: Output file size may be a bit lower or higher than your file requested size.)

The jpegoptim tool (actual homepage is for multiple programs) works better for me:
jpegoptim -s -S8 *.JPG
-s means to strip all metadata (EXIF, JFIF, XMP, etc.)
-S8 means to target a filesize of about 8 KiB
You can crunch them even better by running it twice, because empirically, most images are smaller as progressive:
jpegoptim -s --all-progressive -S8 *.JPG; jpegoptim -s --all-normal -S8 *.JPG
jpegoptim will normally refuse to write an image that increases the size, so this will give you optimum quality/size.
As for the image dimensions part: You normally define a target size in terms of dimensions first and scale there, only then you define the target file size. This is because, when you display it, you ideally want the image dimensions being an integer multiple or fraction of the final display dimensions, to make scaling easier, or even unnecessary. So, scale to the target dimensions first (with quality 100, and possibly other things like 4:4:4 chroma, and most certainly with dct float), then downsize the file. If you can’t get to the file size range you want, choose smaller target dimensions and restart (from the original image, not the one you scaled down first).

Related

ImageMagick convert from pdf to image shrinks image and places it in bottom left corner

I am using this command to convert pages from a pdf to jpeg images:
magick convert -density 300 sample.pdf output.jpeg
I see a white background and the content of the PDF appears as a smaller image stuck to the bottom left corner of the white "canvas". Can anyone help with why this might be happening and how to prevent this "shrinking"?
My PDF has 14 pages. Here is the metadata for a few of those pages:
>magick identify sample.pdf
sample.pdf[0] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 6458B 0.016u 0:00.017
sample.pdf[1] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 6018B 0.016u 0:00.020
sample.pdf[2] PDF 2286x3600 2286x3600+0+0 16-bit sRGB 5732B 0.016u 0:00.023
And here are the actual and expected outputs for one of the pages:
actual output:
expected output:
edit: here is a sample PDF:
https://www.dropbox.com/s/0bzu5brfzbedd7i/sample.pdf?dl=0
I am not sure why you have that behavior. There is something in the PDF, perhaps a crop box, that Imagemagick/Ghostscript is not picking up. But you can get rid of the excess white using -trim
magick sample.pdf -trim sample_%d.jpg
Thanks for the example
> magick identify sample.pdf
> sample.pdf[0] PDF 2286x3600
Apears to be wrong as there is no match
from the PDF contents
/Width 1531
/Im0
/Height 2454
/MediaBox [0 0 1531 2454]
on
Page Size:
/CropBox [0 0 919 1473]
919 pt x 1473 pt
32.42 x 51.96 cm
12.76 x 20.45 inches
Therefore no problems when the images were inserted as # 120 dpi
We can check the image by copy when zoom to 100% in a viewer and paste into say paint, which agrees the image is 1531 x 2454 pixels.
As a result of comments with #fmw42, it was decided to see if GhostScript (which ImageMagick depends on for PDF handling) was having an affect, and certainly processing that PDF using GS v 9.55 without any special switches gave warnings and produced the output below left So the issue seems to be caused by recent GhostScript method of calling/scaling. since using simple GhostScript based image apps (Irfanview using GS plugin on the left) behave the same whilst other viewers have less of a problem even sister product MuPDF as previewed on the right. So the file Media Box as seen and probably used for scaling by Ghostscript seems to be the culprit, but was processed by two other PDF handlers during generation.
One solution would be to use a simpler method of extracting images as PNG thus look at Xpdf command line tools "pdftopng" which gives a good result but you need to calculate that the optimum resolution in this case is 120 (or 240), Typical windows command line does not need .exe but its best to use that when prefixing with a path for use from another location.
pdftopng.exe -r 120 -f 1 -l 1 sample.pdf

Optimize size of DZI rendered

I am currently testing magickSlicer for converting large jpeg files to DZI. It works nice.
However, i am facing a problem with the size of rendered DZI. For exemple, for an orginal jpeg file weighting 10Mo, the rendred DZI folder weight 26.2Mo with default option (-w 256 -h 256).
If I change options width and height to 512x512 the DZI folder weight 18.3Mo. It is yet too big because I have to deal with a huge repository of large files.
I wish to know how can I manage options of conversion for getting a DZI folder weighting less or equals to the weight of original files.
Best regards.
You might be able to change the image quality (to make the JPEG files smaller) by playing with the --options command line argument:
https://github.com/VoidVolker/MagickSlicer#--p---options-imagemagick-options-string-
You'll have to look at the ImageMagick command line options to find the right value:
http://imagemagick.org/script/command-line-processing.php#option
That said, because DZI contains a pyramid of tiles, you are making more pixels than you started with. To be precise, you're ending up with 1.333 times as many pixels. All other things (like image quality settings) being equal, for your 10MB file you should end up with a 13MB set of tiles.

With ImageMagick, how can a JPEG image be reduced in quality until it is below a certain file size?

A JPEG image can be reduced in quality and, thus, in file size using ImageMagick in a way such as the following:
convert -quality 85% image.jpg image_small.jpg
How can the quality of an image be reduced such that the resulting image is below a certain file size (e.g. 3 MB)? A scenario in which this would be useful would be preparing a large number of images for upload to a site like Imgur.
I thought there was a post about this last week but can not find it. There was another here: ImageMagick: scale JPEG image with a maximum file-size
Anyway you want to use: -define jpeg:extent=400KB https://www.imagemagick.org/script/command-line-options.php#define
Out of interest your code is wrong as the input comes after convert and your quality goes before the output image.
So you want something like this:
convert image.jpg -define jpeg:extent=3000KB image_small.jpg
If you have an old version of Imagemagick it may not work that is why it is always good to include your imagemagick version in your question.
The results are a bit hit and miss on exact filesize.

Any way to batch resize png's canvas size keeping the image top left, but making the size divisible by 12

We need to have huge amounts of png's resized to be divisible by 12, each png is variable in size and the image needs to stay 1:1 in the top left.
At the moment were having to manually bring in each file into Photoshop and enlarge the canvas on the x+y to be divisible by 12 and keep the image in the top left corner. With the amount of png's we need doing now and in future we need an automated process.
I would do this with ImageMagick, which is free and installed on most Linux distros and also available for OSX and Windows from here.
This little bash script will resize all the PNG files in the current directory and save them with the original name in the subdirectory called output. It is pretty easy to read - it basically loops through all the PNG files in the directory. It then uses ImageMagick's built-in calculator to work out the size of your output file as nearest multiple of 12. Then it loads the image and extends the background using transparent pixels (-background none) to that size (using -extent) and leaves the original image in the top-left corner (-gravity NorthWest).
#!/bin/bash
# Make output directory - ignore errors
mkdir output 2> /dev/null
# Make sure we don't barf if there are no files
shopt -s nullglob
# Make sure we process *.png, *.PNG, *.pNg etc
shopt -s nocaseglob
# Loop through all pngs in current directory
for f in *.png; do
# Calculate new extent as nearest multiple of 12
# In general, to round x to nearest n, you do ((x+n-1)/n)*n
extent=$(convert "$f" -format "%[fx:12*round(((w+11)/12)-0.5)]x%[fx:12*round(((h+11)/12)-0.5)]" info: )
# Now extend canvas transparently to new size and leave original image in top-left
convert "$f" -background none -gravity northwest -extent $extent output/"$f"
done
P.S. If installing ImageMagick on OSX, please ask for advice before trying.
P.P.S. If you have 10,000+ images to resize, and you do it often, and you are on OSX or Linux (probably not Windows), I would recommend GNU Parallel. If that is likely, please ask.
Never mind, this is a possible solution for your problem. This script will run in MATLAB or Octave (Octave is an open-source alternative to MATLAB, so you might want to use that.)
Copy the following function into a file and call it resizeIm.m. Then start Octave and call this function for every image you have.
function resizeIm(fileName)
% Read image
origIm = imread(fileName);
% Get size and calculate new size
origSize = size(origIm);
div = ceil(origSize ./ 12);
% Create new, padded image
newIm = zeros(12*div,class(origIm));
newIm(1:origSize(1),1:origSize(2)) = origIm;
% Write image to new file
[dir, name, ext] = fileparts(fileName);
newFileName = [dir,name,"_resized",ext];
imwrite(newIm,newFileName);
end
The function can be called by
resizeIm("C:\path\to\file\myimage.png")

How to batch convert images to a specific megapixel with Imagemagick?

I'm sorting my photos and want to resize them to something reasonable. Now the input files are a wild mix of small and big images, some landscape, some tower.
I want to resize them all (above a threshold) to a specific megapixel size, but all descriptions I found so far only resize to either a fixed size / aspect ratio (e.g. 1024x786) or a fixed percentage (e.g. 50%). None of these seem to apply with a folder that has some small images (e.g. 300x400) and images mixed in the range of 3-12 megapixel.
I'm looking for an aspect ratio independent option that puts them all in the same megapixel ballpark. Any suggestions?
Add \> at the end of your resize to only down-res larger images and not affect smaller ones and maintain aspect ratio too.
convert -resize 1200X800\> image.jpg
Or if you want a specific number of pixels, regardless of whether landscape or portrait, you can do
convert -resize 1000000#\> image.jpg
so you get a million pixels max, which may be 400x2,500 or 2,500x400 for example.
EDITED
I should maybe point out that the backslash in front of the greater than symbol is a shell escape to stop the shell deciding to redirect output like it normally does when it sees a greater than symbol. You could equally enclose the resize specification in single quotes to prevent the shell seeing it. If that doesn't make sense, then the following two commands are identical:
convert -resize 1000000#\> image.jpg
convert -resize '1000000#>' image.jpg

Resources