Fred's ImageMagick Tidbits


 



Image Information



Image Aspect Ratio (Width/Height)

convert rose: -format "%[fx:w/h]" info:

1.52174

top



Average RGB Color Of An Image

Note: %% is an escape of %

Method 1

convert rose: -colorspace rgb -scale 1x1 -format "%[pixel:p{0,0}]" info:

rgb(146,89,80)

Method 2

convert rose: -colorspace rgb -scale 1x1 -fx "debug(u)" null:

ROSE[0,0].red: u=0.57142
ROSE[0,0].red: u=0.57142
ROSE[0,0].red: u=0.57142
ROSE[0,0].green: u=0.350042
ROSE[0,0].blue: u=0.315557

Method 3

convert rose: -colorspace rgb -scale 1x1 -depth 8 txt:

# ImageMagick pixel enumeration: 1,1,255,rgb
0,0: (145, 89, 80) #915950 rgb(145,89,80)

Method 4

convert rose: -colorspace rgb -scale 1x1 -depth 16 txt:

# ImageMagick pixel enumeration: 1,1,65535,rgb
0,0: (37448,22940,20680) #9248599C50C8 rgb(57.142%,35.0042%,31.5557%)

Method 5

Fraction

convert rose: -colorspace rgb -scale 1x1 \
-format "%[fx:r],%[fx:g],%[fx:b]" info:

0.57142,0.350042,0.315557

Percent

convert rose: -colorspace rgb -scale 1x1 \
-format "%[fx:100*r]%%,%[fx:100*g]%%,%[fx:100*b]%%" info:

57.142%,35.0042%,31.5557%

Range 0 to 255

convert rose: -colorspace rgb -scale 1x1 \
-format "%[fx:floor(255*r)],%[fx:floor(255*g)],%[fx:floor(255*b)]" info:

145,89,80

Range 0 to QuantumRange (Q16)

convert rose: -colorspace rgb -scale 1x1 \
-format "%[fx:floor(quantumrange*r)],%[fx:floor(quantumrange*g)],%[fx:floor(quantumrange*g)]" info:

37448,22940,22940

top



Grayscale Minimum, Maximum, Mean And Standard Deviation Of An Image (Percent)

Note 1: %% is an escape of %

Note 2: Statistics for any single channel can be extracted by substituting "-channel xxx" for "-colorspace gray", where xxx can be either red or green or blue.

Method 1 (Any IM Version)

data=`convert rose: -colorspace gray -verbose info:`

min=`echo "$data" | sed -n '/^.*[Mm]in:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
convert xc: -format "%[fx:100*$min]%%" info:

14.6151%

max=`echo "$data" | sed -n '/^.*[Mm]ax:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
convert xc: -format "%[fx:100*$max]%%" info:

100%

mean=`echo "$data" | sed -n '/^.*[Mm]ean:.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
convert xc: -format "%[fx:100*$mean]%%" info:

41.2302%

std=`echo "$data" | sed -n '/^.*[Ss]tandard.*[(]\([0-9.]*\).*$/{ s//\1/; p; q; }'`
convert xc: -format "%[fx:100*$std]%%" info:

18.581%

Method 2 (IM Version 6.3.9-1 Or Higher)

(note: as of version 6.4.2-6, one can use either "%[standard-deviation]" or "%[standard_deviation]")

min=`convert rose: -colorspace gray -format "%[min]" info:`
convert xc: -format "%[fx:100*$min/quantumrange]%%" info:

or

convert xc: -format "%[fx:100*$(convert rose: -colorspace gray -format "%[min]" info:)/quantumrange]%%" info:

14.6151%

max=`convert rose: -colorspace gray -format "%[max]" info:`
convert xc: -format "%[fx:100*$max/quantumrange]%%" info:

or

convert xc: -format "%[fx:100*$(convert rose: -colorspace gray -format "%[max]" info:)/quantumrange]%%" info:

100%

mean=`convert rose: -colorspace gray -format "%[mean]" info:`
convert xc: -format "%[fx:100*$mean/quantumrange]%%" info:

or

convert xc: -format "%[fx:100*$(convert rose: -colorspace gray -format "%[mean]" info:)/quantumrange]%%" info:

41.2302%

std=`convert rose: -colorspace gray -format "%[standard-deviation]" info:`
convert xc: -format "%[fx:100*$std/quantumrange]%%" info:

or

convert xc: -format "%[fx:100*$(convert rose: -colorspace gray -format "%[standard-deviation]" info:)/quantumrange]%%" info:

18.5811%

Method 3 (IM Version 6.4.0-11 Or Higher)

convert rose: -colorspace gray -format "%[fx:100*image.minima]%%" info:

14.6151%

convert rose: -colorspace gray -format "%[fx:100*image.maxima]%%" info:

100%

convert rose: -colorspace gray -format "%[fx:100*image.mean]%%" info:

41.2302%

convert rose: -colorspace gray -format "%[fx:100*image.standard_deviation]%%" info:

18.5811%

Method 4 (IM Version 6.4.2-6 Or Higher)

convert rose: -colorspace gray -format "%[fx:100*minima]%%" info:

14.6151%

convert rose: -colorspace gray -format "%[fx:100*maxima]%%" info:

100%

convert rose: -colorspace gray -format "%[fx:100*mean]%%" info:

41.2302%

convert rose: -colorspace gray -format "%[fx:100*standard_deviation]%%" info:

18.5811%

top



All Channel Minimum, Maximum, Mean And Standard Deviation Of An Image (Percent)

Note: %% is an escape of %

Method 1: IM Version 6.4.0-11 Or Higher

(usage: image.minima, image.maxima, image.mean and image.standard_deviation)

convert rose: -colorspace rgb -separate -format "%[fx:100*image.minima]%%" info:

13.7255%
8.62745%
9.41176%

convert rose: -colorspace rgb -separate -format "%[fx:100*image.maxima]%%" info:

100%
100%
100%

convert rose: -colorspace rgb -separate -format "%[fx:100*image.mean]%%" info:

57.142%
35.004%
31.5563%

convert rose: -colorspace rgb -separate -format "%[fx:100*image.standard_deviation]%%" info:

27.1746%
20.5763%
21.6123%

Method 2: IM Version 6.4.2-6 Or Higher

(usage: minima, maxima, mean and standard_deviation)

convert rose: -colorspace rgb -separate -format "%[fx:100*minima]%%" info:

13.7255%
8.62745%
9.41176%

convert rose: -colorspace rgb -separate -format "%[fx:100*maxima]%%" info:

100%
100%
100%

convert rose: -colorspace rgb -separate -format "%[fx:100*mean]%%" info:

57.142%
35.004%
31.5563%

convert rose: -colorspace rgb -separate -format "%[fx:100*standard_deviation]%%" info:

27.1746%
20.5763%
21.6123%

Method 3: IM Version 6.4.2-6 Or Higher

(usage: minima.channel, maxima.channel, mean.channel and standard_deviation.channel)

convert rose: -format \
"\n red:\n min=%[fx:100*minima.r]%%\n max=%[fx:100*maxima.r]%%\n \
mean=%[fx:100*mean.r]%%\n std=%[fx:100*standard_deviation.r]%%\n\n \
green:\n min=%[fx:100*minima.g]%%\n max=%[fx:100*maxima.g]%%\n \
mean=%[fx:100*mean.g]%%\n std=%[fx:100*standard_deviation.g]%%\n\n \
blue:\n min=%[fx:100*minima.b]%%\n max=%[fx:100*maxima.b]%%\n \
mean=%[fx:100*mean.b]%%\n std=%[fx:100*standard_deviation.b]%%\n" \
info:

red:
min=13.7255%
max=100%
mean=57.142%
std=57.142%

green:
min=8.62745%
max=100%
mean=35.004%
std=35.004%

blue:
min=9.41176%
max=100%
mean=31.5563%
std=31.5563%

top



Custom Identify With Ticks And Quality

Example 1

Create GIF Animation

convert -delay 100 rose: -delay 50 rose: -delay 25 rose: -loop 0 rose_animation.gif

identify

identify rose_animation.gif

animation.gif[0] GIF 70x46 70x46+0+0 8-bit PseudoClass 256c 10.6kb
animation.gif[1] GIF 70x46 70x46+0+0 8-bit PseudoClass 256c 10.6kb
animation.gif[2] GIF 70x46 70x46+0+0 8-bit PseudoClass 256c 10.6kb

"custom" identify (showing ticks)

info="%f[%s] %m %Tticks %wx%h %P%O %r %z-bit %Q%%qual %bbytes\n"
identify -format "$info" rose_animation.gif

animation.gif[0] GIF 100ticks 70x46 70x46+0+0 8-bit PseudoClassRGB 256c 0%qual 10878bytes
animation.gif[1] GIF 50ticks 70x46 70x46+0+0 8-bit PseudoClassRGB 256c 0%qual 10878bytes
animation.gif[2] GIF 25ticks 70x46 70x46+0+0 8-bit PseudoClassRGB 256c 0%qual 10878bytes

Example 2

Create JPEG Image

convert rose: rose.jpg

identify (jpeg)

identify rose.jpg

rose.jpg JPEG 70x46 70x46+0+0 8-bit DirectClass 1.54kb

"custom" identify (jpeg showing quality)

info="%f[%s] %m %Tticks %wx%h %P%O %r %z-bit %Q%%qual %bbytes\n"
identify -format "$info" rose.jpg

rose.jpg[0] JPEG 0ticks 70x46 70x46+0+0 8-bit DirectClassRGB 85%qual 1580bytes

top



Test If Image Is Grayscale Or Color

Method 1 (Any IM Version)

test=`convert rose: -scale 1x1! -format "%[fx:r==g&&r==b?1:0]" info:`
[ $test -eq 1 ] && echo "Gray" || echo "Color"

Color

test=`convert rose: -colorspace gray -scale 1x1! -format "%[fx:r==g&&r==b?1:0]" info:`
[ $test -eq 1 ] && echo "Gray" || echo "Color"

Gray

Method 2 (Any IM Version)

convert rose: -verbose info: | sed -n 's/^.*Colorspace: \([^ ]*\).*$/\1/p'

RGB

convert rose: -colorspace gray -verbose info: | sed -n 's/^.*Colorspace: \([^ ]*\).*$/\1/p'

Gray

Method 3 (IM Version 6.3.9-2 Or Higher)

convert rose: -format "%[colorspace]" info:

RGB

convert rose: -colorspace gray -format "%[colorspace]" info:

Gray

top



Test If Image Has Alpha Channel

Method 1 (Any IM Version)

convert -size 100x100 xc:white white.png

[ "$(identify -verbose white.png | grep 'alpha')" = "" ] && echo "alpha off" || echo "alpha on"

alpha off

convert white.png -alpha on white_alpha.png

[ "$(identify -verbose white_alpha.png | grep 'alpha')" = "" ] && echo "alpha off" || echo "alpha on"

alpha on

Method 2 (IM Version 6.4.3-7 Or Higher)

convert -size 100x100 xc:white white.png

convert white.png -format "%A" info:

False

convert white.png -alpha on white_alpha.png

convert white_alpha.png -format "%A" info:

True

top



Measure The Average Opacity Or Transparency Of An Image

IM 6.4.3-7 To IM ?.?.?.?

-channel o and -channel a mean the same thing. Originally they both referred to opacity.


Set 60% Opacity (40% Transparency)

convert logo.jpg -alpha on -channel o -evaluate set 60% logo_opacity60.png

convert logo_opacity60.png -format "%[fx:u.o]" info:

returns opacity of 0.6

convert logo_opacity60.png -format "%[fx:u.a]" info:

returns alpha/transparency of 0.4

IM ?.?.?.? Or Higher

-channel o and -channel a mean the same thing. Originally they both referred to opacity.
But at some unknown point it switched so that they now both refer to transparency.


Set 60% Transparcy (40% Opacity)

convert logo.jpg -alpha on -channel a -evaluate set 60% logo_transparency60.png

convert logo_transparency60.png -format "%[fx:u.a]" info:

returns alpha/transparency of 0.6

convert logo_transparency60.png -format "%[fx:u.o]" info:

returns opacity of 0.4

top



Sending Results From Compare -Metric To A Variable Or Text File

Convert rose: To JPEG And GIF For Comparison

convert rose: rose.jpg

convert rose: rose.gif

Do Comparison And Save In Variable

str=`compare -metric rmse rose.jpg rose.gif null: 2>&1`
echo $str

2561.35 (0.0390838)

Do Comparison And Save In Text File

compare -metric rmse rose.jpg rose.gif null: 2> compare.txt
cat compare.txt

2561.35 (0.0390838)

top



Forcing An Image Histogram To Be Generated

Images with more than 1024 colors will not have a histogram. To generate a histogram one must reduce the number of colors to 1024 or less.

Due to a slight difference in values, two methods are presented. We will use an example with 10 colors for simplicity. I have highlighted one place where the color values differ slightly. This would appear to be a bug, which has, as of IM 6.4.2-5, been fixed so that the histogram generated by the first method matches that of the second method.

Method 1

convert rose: -colorspace rgb -colors 10 -format "%c" histogram:info:

575: ( 51, 50, 45) #33322D rgb(51,50,45)
544: (221, 54, 48) #DD3630 rgb(221,54,48)
376: (175, 65, 56) #AF4138 rgb(175,65,56)
289: ( 94, 93, 78) #5E5D4E rgb(94,93,78)
277: (110,146, 86) #6E9256 rgb(110,146,86)
277: (231, 81, 88) #E75158 rgb(231,81,88)
266: (212,211,217) #D4D3D9 rgb(212,211,217)
262: ( 98, 56, 47) #62382F rgb(98,56,47)
206: (139,133,145) #8B8591 rgb(139,133,145)
148: ( 83, 76, 55) #534C37 rgb(83,76,55)

Method 2

convert rose: -colorspace rgb -colors 10 miff:- | convert - -format "%c" histogram:info:

575: ( 51, 51, 45) #33332D rgb(51,51,45)
544: (221, 54, 48) #DD3630 rgb(221,54,48)
376: (175, 66, 57) #AF4239 rgb(175,66,57)
289: ( 94, 93, 79) #5E5D4F rgb(94,93,79)
277: (110,147, 86) #6E9356 rgb(110,147,86)
277: (232, 81, 89) #E85159 rgb(232,81,89)
266: (213,211,217) #D5D3D9 rgb(213,211,217)
262: ( 98, 57, 47) #62392F rgb(98,57,47)
206: (140,133,146) #8C8592 rgb(140,133,146)
148: ( 83, 76, 56) #534C38 rgb(83,76,56)

top



Find The Percentage Of Pixels In An Image With A Given Color

Method 1

Select Color From Histogram

convert rose: -colorspace rgb -colors 10 -format "%c" histogram:info:

575: ( 51, 50, 45) #33322D rgb(51,50,45)
544: (221, 54, 48) #DD3630 rgb(221,54,48)
376: (175, 65, 56) #AF4138 rgb(175,65,56)
289: ( 94, 93, 78) #5E5D4E rgb(94,93,78)
277: (110,146, 86) #6E9256 rgb(110,146,86)
277: (231, 81, 88) #E75158 rgb(231,81,88)
266: (212,211,217) #D4D3D9 rgb(212,211,217)
262: ( 98, 56, 47) #62382F rgb(98,56,47)
206: (139,133,145) #8B8591 rgb(139,133,145)
148: ( 83, 76, 55) #534C37 rgb(83,76,55)

Extract Percent

  • get historgram
  • filter histogram information using sed to extract count for given color
  • load above into variable
  • calculate percentage from variable and image size

str=`convert rose: -colorspace rgb -colors 10 -format "%c" histogram:info: | \
sed -n 's/^[ ]*\([0-9]*\):.*rgb(110,146,86)$/\1/p'`
convert rose: -format "%[fx:100*$str/(w*h)]%%" info:

8.60248%

Method 2

Select Color From Histogram

convert rose: -colorspace rgb -colors 10 miff:- | convert - -format "%c" histogram:info:

575: ( 51, 51, 45) #33332D rgb(51,51,45)
544: (221, 54, 48) #DD3630 rgb(221,54,48)
376: (175, 66, 57) #AF4239 rgb(175,66,57)
289: ( 94, 93, 79) #5E5D4F rgb(94,93,79)
277: (110,147, 86) #6E9356 rgb(110,147,86)
277: (232, 81, 89) #E85159 rgb(232,81,89)
266: (213,211,217) #D5D3D9 rgb(213,211,217)
262: ( 98, 57, 47) #62392F rgb(98,57,47)
206: (140,133,146) #8C8592 rgb(140,133,146)
148: ( 83, 76, 56) #534C38 rgb(83,76,56)

Extract Percent

  • put color into a variable
  • convert image to miff: to be consistent with histogram
  • replace selected color (from variable) with white
  • replace all non-white pixels with black
  • average image to 1 pixel and get percent grayscale value

color="rgb(110,147,86)"
convert rose: -colorspace rgb -colors 10 miff:- | \
convert - -fill white -opaque $color \
-fill black +opaque white \
-scale 1x1! -format "%[fx:100*u]%%" info:

8.60304%
note: rose: image is 70x46 pixels; thus count of 277 => 100*277/(70*46)%=8.60248

top



Find The Location Of Every Pixel In An Image With A Given Color

Select Color From Histogram

convert rose: -colorspace rgb -colors 256 -depth 8 -format "%c" histogram:info:

.
.
.
6: ( 60, 69, 75) #3C454B rgb(60,69,75)
6: (115, 59, 51) #733B33 rgb(115,59,51)
6: (121,119,165) #7977A5 rgb(121,119,165)
6: (137,168,119) #89A877 rgb(137,168,119)
6: (142,150,141) #8E968D rgb(142,150,141)
6: (149,144,204) #9590CC rgb(149,144,204)
6: (153, 68, 70) #994446 rgb(153,68,70)
.
.
.

Find All (6) X,Y Pixel Locations For Color (138,168,119)

  • use txt: format to list all pixels in the image
  • use grep to find only those lines of the txt file that contain the color
  • use cut to extract just the coordinates

color="( *137, *168, *119)"
convert rose: -colorspace rgb -colors 256 -depth 8 txt: | \
grep "$color" | cut -d: -f1

or

color="(137,168,119)"
convert rose: -colorspace rgb -colors 256 -depth 8 txt: | \
sed 's/ *,/,/g' | grep "$color" | cut -d: -f1

48,7
49,7
61,20
62,20
68,21
17,38

top