bash adjusting image dimensions to fit a certain size - bash

I searched everywhere but couldn't find an answer to this.
I would like to output all images of a folder in 50Kb exactly and maintain the original aspect ratio.
I tried ImageMagick and resizing to 250x250 e.g but it is not working for me, what it does is change the first dimension and adapt the other, so output images have not the same size.
for image in `ls $#*.jpg`; do
mogrify "${image}" -resize 250x250 "${image}"
done
How do it? Thanks

Updated Answer
If you want the file size of the images to be limited to 50kB, use:
convert input.jpg -define jpeg:extent=50KB output.jpg
Original Answer
Use mogrify, but be careful it will overwrite all your images:
mogrify -resize 250x250! *.jpg
In general, when using mogrify I like to use the -path option to specify an output directory for results, like this to avoid originals getting overwritten:
mkdir results
mogrify -path results ...
Your script will work if you add the ! after the resize which forces the resize even if it distorts the shape of the picture.
If you want a way to do something similar with Python, I wrote an answer that works pretty well here. It does a binary search for a JPEG quality that satisfies a maximum size requirement.

Related

Batch convert white background to transparent

Seeking to set a folder of PNG line drawings to background transparent and getting lost in examples and options recommended for other cases. Essentially when I find a line of command that seems to fit I don't know how to apply it to an entire folder. Also getting lost in options like fuzz and anti-alias which I'm not even sure would benefit my images, below. I'm on a Mac running v7 of Magick and really appreciate your kind help.
Simplest Sample
Most Complex Sample
This should do what you want in Imagemagick 7. You should use magick mogrify to process a whole folder of images. To convert white to transparent in an image you can use -fuzz XX% -transparent white, where XX is a percent tolerance for nearby colors. For JPG, typically about 15% seems to work due to jpg compression change of flat colors. So I put your images into a folder called drawings and create a new empty folder called drawings2 to hold the output image, which need to be PNG (or TIFF) so use transparency.
cd
cd desktop/drawings
magick mogrify -path ../drawings2 -format png -fuzz 15% -transparent white *.jpg
Results:
See https://imagemagick.org/Usage/basics/#mogrify

Image Magick Not Processing All Images

I'm currently trying to convert a batch of images to greyscale using:
convert "* .jpg" -set colorspace Gray -separate -average "*.jpg"
Right now I'm working on a couple of hundred images. When I run the command I get copies of all the images, but only the 1st is actually converted to greyscale. Anyone know how what the issue might be? Also, if anyone has a better way of working through a very large quantity of images (ultimately I'll need to convert several thousand) at a time I'd appreciate it.
Thanks!
As pointed out in the comments, you can not have wildcards as the output. If you want to overwrite the original files with the updated colorspace, you can try the mogrify utility.
mogrify -set colorspace Gray -separate -average *.jpg
But that can be risky as your destroying originals. A simple for-loop might be easy to schedule & manage.
for filename in $(ls *.jpg)
do
convert "$filename" -set colorspace Gray -separate -average "output_${filename}"
done
ultimately I'll need to convert several thousand
If you really are facing large quantities of tasks, I would suggest spreading the tasks over multiple CPU cores. Perhaps with GNU Parallel.
parallel convert {} -set colorspace Gray -separate -average output_{.} ::: *.jpg
Of course I'm assuming your working with BASH on a *nix system. YMMV elsewhere.

ImageJ - compare original and resized image on similarity

Dear Colleagues.
Could you help me please with next question.
I want to resize huge amount of images and substitute original images with resized for saving disk space. But before substitution I want to be sure, that resized image is the same original image but with different dimensions (not white list, not Malevich's square and so on).
Is there a way to check such similarity to be sure that resizing was successful?
Thanks.
One idea might be to downscale your image into a tentative down-resed version, then scale it back up to the original size and compare that with the original. If they seem pretty similar, overwrite the original with the tentative conversion, if not, report error.
Here's how you might do that in bash with comments. It can be rehashed into other languages of course, or you can use a system() to shell out and use this command line version from another language.
#!/bin/bash
# Downscale an image and check if correct
# Supply image name as parameter
original="$1"
tentative="t-$$-$original"
echo DEBUG: tentative filename=$tentative
# Get size of original so we can resize back up to that size
origsize=$(identify -format "%G" "$original")
echo DEBUG: origsize=$origsize
# Do downsizing of image, saving result tentatively
convert image.jpg -resize 800x800 "$tentative"
# Test quality/success of conversion by looking at PSNR
PSNR=$(convert "$tentative" -resize $origsize\! "$original" -metric PSNR -format "%[distortion]" -compare info:)
echo DEBUG: PSNR=$PSNR
# PSNR above 20 is pretty indicative of good similarity - use "bc" as shell doesn't do floats
if [ $(echo "$PSNR>20" | bc) -eq 1 ]; then
echo $original looks good
else
echo $original something wrong
fi
One thing to beware of is transparency - don't convert from a GIF or PNG (both of which support transparency) to a JPEG (which doesn't) and then resize and compare - you are asking for trouble. You will see in my script above that I retain the image extension and pre-pend bits to the front rather than the end of the filename.
well as far as the size is concerned you can simply check the dimensions
in matlab
[x,y]=size(im);
this will let you know that the if the image has been resized
To check if the image is the same you can use feature extraction such as SURF features.
Extract the surf features, match them if you get 100% ~ 90% match you have the same image!!

gimp: resize and "unsharp mask" via script

I need to do the same operations for more than 60 files:
scale image
unsharpen mask
Is it possible to execute this from a script possibly passing the scale value ? I'm on Ubuntu if this could influence the answer.
edit:
What I need to do is to resize some Android icons from 64x64 to 96x96 (as far, maybe other resolutions too).
But these icons have already been blurred so, just increasing the size, I don't get a nice result.
I've seen that if I resize to 96x96 and apply the "Unsharp Mask" filter with the default values (Radius: 5,0 - Amount: 0,50 - Threshold: 0),
I get an acceptable result.
As you are on Ubuntu, you likely already have ImageMagick installed - convert, identify and mogrify commands, amongst others.
So, make a copy of your data and try something like this on a copy:
mogrify -resize 640x480 -unsharp 6x3+1+0 *.jpg
or maybe this
mogrify -resize 1024x768 -sharpen 0x1.0 *.tif
to resize all JPEGs to 640x480 max and sharpen them, and in the second case to resize and sharpen a bunch of TIFFs.
If you specify your GIMP parameters I can probably make closer suggestions.

imagemagick resizing and quality PNG

In my application I need to resize and make the quality on PNG files poorer.
In full size the PNGs are 3100x4400px using 2,20MB disk space.
When running the following command:
convert -resize 1400 -quality 10 input.png output.png
the images are resized to 1400x2000 using 5,33MB disk space.
So my question is: How can I reduce the file size?
You can further reduce quality of PNG by using posterization:
https://github.com/pornel/mediancut-posterizer (Mac GUI)
This is a lossy operation that allows zlib to compress better.
Convert image to PNG8 using pngquant.
It reduces images to 256 colors, so quality depends on the type of image, but pngquant makes very good palettes, so you might be surprised how often it works.
Use Zopfli-png or AdvPNG to re-compress images better.
This is lossless and recommended for all images if you have CPU cycles to spare.
After using imagemagick to resize, you can compress the image using pngquant.
On mac (with homebrew) brew install pngquant then:
pngquant <filename.png>
This will create a new image filename-fs8.png that is normally much smaller in size.
Help page says, that -quality option used with PNG sets the compression level for zlib, where (roughly) 0 is the worst compression, 100 - is the best (default is 75). So try to set -quality to 100 or even remove the option.
Another method is to specify PNG:compression-level=N, PNG:compression-strategy=N and PNG:compression-filter=N to achieve even better results.
http://www.imagemagick.org/script/command-line-options.php#quality
For lazy people that arrived here wanting to paste in a one liner:
mogrify -resize 50% -quality 50 *.png && pngquant *.png --ext .png --force
This modifies all of the pngs in the current directory in place, so make sure you have a backup. Modify your resize and quality parameters as suits your needs. I did a quick experiment and mogrify first, then pngquant, resulted in significantly smaller image size.
The ubuntu package for pngquant is called "pngquant" but I had it installed already on 20.04LTS so seems like it may be there by default.
I found that the best way was to use the
- density [value]
parameter.

Resources