Get offset from Imagemagick trim - bash

I am using Imagemagick to trim some png files (remove transparent border), I use the command below:
convert -debug Coder longyan_1.png -trim longyan_1.trimed.png
Then the tool gave me a trimed image as I wanted, but I want more information about the trim offset.
In the debug info I can see the line below:
2014-05-10T14:32:42+08:00 0:04.860 4.840u 6.8.7 Coder convert[49089]: png.c/WriteOnePNGImage/10747/Coder
Setting up oFFs chunk with x=181, y=118, units=0
The "x,y" info is exactly what I want, but the debug info is too much to deal with, is there any Imagick native API or any other tricks to get the offset info?

I think you actually need the %# trim box info, which you get like this:
convert image.png -format "%#" info:
233x375+60+51
or equally, maybe even more succinctly:
identify -format "%#" image.png
233x375+60+51
So, to test it out, I create an image like this:
convert -size 400x200 xc:red -size 80x40 xc:yellow -gravity center -composite image.png
And then ask ImageMagick how it would trim it:
convert image.png -format "%#" info:
80x40+160+80

I am sure that there are more complicated ways to do this but, if you just get the offset info, you can use grep:
$ convert -debug Coder longyan_1.png -trim longyan_1.trimed.png 2>&1 | grep "Setting up oFFs chunk"
Setting up oFFs chunk with x=181, y=118, units=0
If you want to shorten and/or reformat the output still more, you can use sed. For example:
$ convert -debug Coder longyan_1.png -trim longyan_1.trimed.png 2>&1 | sed -n '/Setting up oFFs chunk/ s/.*x=/x=/p'
x=181, y=118, units=0

Related

crop and keep the names on multiples images on magick

I would like to crop multiple images files and keep the same name or add a "_2" at the end of the name.
any idea how to do it?
I tried this
magick *jpg -set filename:base "%[basename]" -fuzz 90% "%[filename:base]_2.jpg"
To just keep the same name use magick mogrify. This works exactly like magick or magick convert but overwrites the input file, so there is no output specification. It is quite simple to use on a set of files:
magick mogrify [parameters] file [file...]

Detecting mostly empty images using imagemagick

I'd like to use imagemagick or graphicsmagick to detect whether an image has basically no content.
Here is an example:
https://s3-us-west-2.amazonaws.com/idelog/token_page_images/120c6af0-73eb-11e4-9483-4d4827589112_embed.png
I've scoured Fred's imagemagick scripts, but I can't figure out if there is a way to do this:
http://www.fmwconcepts.com/imagemagick/
Easiest way would be to use -edge detection followed by histogram: & text:. This will generate a large list of pixel information that can be passed to another process for evaluation.
convert 120c6af0-73eb-11e4-9483-4d4827589112_embed.png \
-edge 1 histogram:text:- | cut -d ' ' -f 4 | sort | uniq -c
The above example will generate a nice report of:
50999 #000000
201 #FFFFFF
As the count of white pixels is less then 1% of black pixels, I can say the image is empty.
This can probably be simplified by passing -fx information to awk utility.
convert 120c6af0-73eb-11e4-9483-4d4827589112_embed.png \
-format '%[mean] %[max]' info:- | awk '{print $1/$2}'
#=> 0.00684814
If you are talking about the amount of opaque pixels vs the amount of transparent pixels, then the following will tell you the percentage of opaque pixels.
convert test.png -alpha extract -format "%[fx:100*mean]\n" info:
39.0626
Or if you want the percentage of transparent pixels, use
convert test.png -alpha extract -format "%[fx:100*(1-mean)]\n" info:
60.9374

graphicsmagick composite and crop in the same command

I need to get a specific crop of an image and put it over another image at a certain position and resized.
I can crop the first image and save it to a file in one command and then I can composite the 2 images in another command.
However, I would like to do it in a single command - is this possible with graphicsmagick and how?
Here are the 2 commands I am using atm:
gm convert -crop 1457x973+254+413 amber.jpg tmp.jpg
gm composite -geometry 6000x4000+600+600 tmp.jpg lux_bg.png out.jpg
The reason for wanting this is to avoid writing to disk then reading again when all this could be done in memory.
With ImageMagick, for example, the same 2 commands would be written in a single command like this:
convert lux_bg.png \( amber.jpg -crop 1457x973+254+413 \) -geometry 6000x4000+600+600 -composite out.jpg
I am doing this with ImageMagick for now but would love to do it with GraphicsMagick.
If your reason is simply to avoid creating a temporary file, you can still do it with two commands by constructing 'pipelines' (a great concept invented by, afaik, Douglas McIlroy around 1964):
gm convert -crop 1457x973+254+413 amber.jpg - | gm composite -geometry 6000x4000+600+600 - lux_bg.png out.jpg
hint: note the two - dashes in the two commands, and the | pipe
since the - can be used to mean the standard output and input in the two commands respectively.
This means that no file is created, all should happen in the memory.
You can find this in the help (gm -help convert | grep -i -e out -B 1):
Specify 'file' as '-' for standard input or output.
The use of - is common in unix-likes and must have been inspired by, or by something related to, the POSIX standard's Utility Syntax Guidelines.
Have you tried && operator? Your command should become:
gm convert -crop 1457x973+254+413 amber.jpg tmp.jpg && gm composite -geometry 6000x4000+600+600 tmp.jpg lux_bg.png out.jpg

Command line batch image cropping tool

is there any lightweight command line batch image cropping tool(Linux or Windows) which can handle a variety of the formats ?
In Linux you can use
mogrify -crop {Width}x{Height}+{X}+{Y} +repage image.png
for CLI image manipulation
Imagemagick's convert does the trick for me (and much more than cropping):
convert -crop +100+10 in.jpg out.jpg
crops 100 pixels off the left border, 10 pixels from the top.
convert -crop -100+0 in.jpg out.jpg
crops 100 pixels off the right, and so on. The Imagemagick website knows more:
http://www.imagemagick.org/Usage/crop/#crop
Imagemagick is what you want -- tried and true.
I found nconvert pretty handy so far.
for f in final/**/*;
do
convert -crop 950x654+0+660 "$f" "${f%.jpg}".jpg
done
This script loops through all the sub-folders and crops the .jpg files.
macOS has sips image processing tool integrated. Cropping functions available are:
-c, --cropToHeightWidth pixelsH pixelsW
--cropOffset offsetY offsetH
Easy with sips: just set the offset to start the cropping:
sips --cropOffset 1 1 -c <height> <width> -o output.png input.png
I have scanned some pages and all ~130 pages needs the lower ~1/8 of the page cut off.
Using mogrify didn't work for me,
a#a-NC210-NC110:/media/a/LG/AC/Learn/Math/Calculus/Workshop/clockwise/aa$ mogrify -quality 100 -crop 2592×1850+0+0 *.jpg
mogrify.im6: invalid argument for option `2592×1850+0+0': -crop # error/mogrify.c/MogrifyImageCommand/4232.
However convert did:
a#a-NC210-NC110:~/Pictures/aa$ convert '*.jpg[2596x1825+0+0]' letter%01d.jpg
a#a-NC210-NC110:~/Pictures/aa$
I learnt this here under the Inline Image Crop section.
Notice my syntax: I had to put my geometry in brackets: [].
Using the successful syntax above but with mogrify simply didn't work, producing:
a#a-NC210-NC110:~/Pictures/aa$ mogrify '*.jpg[2596x1825+0+0]' letter%01d.jpg
mogrify.im6: unable to open image `letter%01d.jpg': No such file or directory # error/blob.c/OpenBlob/2638.
Linux a-NC210-NC110 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:12 UTC 2014 i686 i686 i686 GNU/Linux
Lubuntu 14.04 LTS

Can ImageMagick return the image size?

I'm using ImageMagick from the command line to resize images:
convert -size 320x240 image.jpg
However, I don't know how to determine the size of the final image. Since this is a proportional image scale, it's very possible that new image is 100x240 or 320x90 in size (not 320x240).
Can I call the 'convert' command to resize the image and return the new image dimensions? For example, pseudo code:
convert -size 320x240 -return_new_image_dimension image.jpg // returns the new resized image dimensions
-ping option
This option is also recommended as it prevents the entire image from being loaded to memory, as mentioned at: https://stackoverflow.com/a/22393926/895245:
identify -ping -format '%w %h' image.jpg
man identify says:
-ping efficiently determine image attributes
We can for example test it out with some of the humongous images present on Wikimedia's "Large image" category e.g. this ultra high resolution image of Van Gogh's Starry Night which Wikimedia claims is 29,696 × 29,696 pixels, file size: 175.67 MB:
wget -O image.jpg https://upload.wikimedia.org/wikipedia/commons/e/e8/Van_Gogh_-_Starry_Night_-_Google_Art_Project-x0-y0.jpg
time identify -ping -format '%w %h' image.jpg
time identify -format '%w %h' image.jpg
I however observed that -ping at least in this case did not make any difference on the time, maybe it only matters for other image formats?
Tested on ImageMagick 6.9.10, Ubuntu 20.04.
See also: Fast way to get image dimensions (not filesize)
You could use an extra call to identify:
convert -size 320x240 image.jpg; identify -format "%[fx:w]x%[fx:h]" image.jpg
I'm not sure with the %w and %h format. While Photoshop says my picture is 2678x3318 (and I really trust Photoshop), identify gives me:
identify -ping -format '=> %w %h' image.jpg
=> 643x796
(so does [fx:w] and [fx:h])
I had to use
identify -ping -format '=> %[width] %[height]' image.jpg
=> 2678x3318
I don't know what's going on here, but you can see both values on standard output (where the width and height before the => are the correct ones)
identify -ping image.jpg
image.jpg PAM 2678x3318=>643x796 643x796+0+0 16-bit ColorSeparation CMYK 2.047MB 0.000u 0:00.000
The documentation says %w is the current width and %[width] is original width. Confusing.
%w and %h may be correct for most uses, but not for every picture.
If you specify option -verbose, convert prints:
original.jpg=>scaled.jpg JPEG 800x600=>100x75 100x75+0+0 8-bit sRGB 4.12KB 0.020u 0:00.009
^^^^^^

Resources