snibgo's ImageMagick pages

Fifty percent

The mid point of zero and an odd number is not an exact number. So 50% gray, with integer IM, cannot be exactly 50%.

Blurring black and white

If we blur black and white together, we get a gray. But what gray?

To experiment, we draw three squares. The middle one has alternating black and white lines. Then we blur this, and place it on the left. Then we again blur the black and white lines, but this time in linear RGB space, and place it on the right.

%IM%convert ^
  xc:White xc:Black -append ^
  +write mpr:TILE +delete ^
  -size 200x200 ^
  tile:mpr:TILE ^
  -virtual-pixel Tile ^
  ( -clone 0 -blur 0x4 ) ^
  ( -clone 0 -colorspace RGB -blur 0x4 -colorspace sRGB ) ^
  -swap 0,1 ^
  -precision 8 ^
  -format "%%[fx:mean]\n" ^
  ( -clone 0 ^
    -gravity center -crop 2x2+0+0 +write txt: ^
    +delete )^
  ( -clone 0 +write info: +delete )^
  ( -clone 1 +write info: +delete )^
  ( -clone 2 +write info: +delete )^
  +append ^
  fpc_blurbw.png 
fpc_blurbw.png
# ImageMagick pixel enumeration: 2,2,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.999237%,49.999237%,49.999237%)
1,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.999237%,49.999237%,49.999237%)
0,1: (32768,32768,32768)  #800080008000  srgb(50.000763%,50.000763%,50.000763%)
1,1: (32768,32768,32768)  #800080008000  srgb(50.000763%,50.000763%,50.000763%)
0.5
0.5
0.73535515

The middle square alternates black and white lines.

The left-hand square blurs the black and white lines. This results in lines that alternate between 49.9992% and 50.0008%. The overall average is 50%.

The right-hand square linearises the black and white lines, blurs this, then non-linearises the result. The overall gray is now 73.536%, which more accurately represents the visual average.

What value is 50%?

50% of 255 is 127.5, 50% of 65535 is 32767.5, and so on. These numbers cannot be represented with integer IM. This has some consequences:

100% / 2 == 50%

But:

50% + 50% != 100%

For example:

%IM%convert xc:gray(50%%) ( +clone ) -compose Add -composite txt: 

%IM%convert xc:gray(50%%) ( +clone ) -evaluate-sequence Add txt: 

%IM%convert %PREC% xc:Black -evaluate Add 50%% -evaluate AddModulus 50%% txt:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (65534,65534,65534)  #FFFEFFFEFFFE  srgb(99.9985%,99.9985%,99.9985%)
# ImageMagick pixel enumeration: 1,1,65535,gray
0,0: (65534,65534,65534)  #FFFEFFFEFFFE  gray(99.9985%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (0,0,0)  #000000000000  black

We can generate a 50% value from a large number of methods. See the script testHalf.bat.

call %PICTBAT%testHalf . half_q16.lis
Version: ImageMagick 6.9.2-5 Q16 x64 2015-10-31 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Visual C++: 180031101
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib cairo freetype jng jp2 jpeg lcms lqr openexr pangocairo png ps rsvg tiff webp xml zlib
With Q16i and Q32f, these give #8000.
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
 
With Q16i and Q32f, these give #7fff:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.9992370489052%,49.9992370489052%,49.9992370489052%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.9992370489052%,49.9992370489052%,49.9992370489052%)
# ImageMagick pixel enumeration: 1,1,65535,gray
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  gray(49.9992370489052%)
 
With Q16i, these give #7fff, but with Q32f they give #8000:
# ImageMagick pixel enumeration: 1,1,65535,gray
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  gray(49.9992370489052%)
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.9992370489052%,49.9992370489052%,49.9992370489052%)
 
These are arithmetically horrible in all Q:
# ImageMagick pixel enumeration: 1,1,65535,srgb
0,0: (32639,32639,32639)  #7F7F7F7F7F7F  grey50
call %PICTBAT%testHalf %IMDEV% half_dev.lis
Version: ImageMagick 6.9.3-7 Q32 x86_64 2016-04-03 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP 
Delegates (built-in): bzlib cairo fftw fontconfig freetype fpx jbig jng jpeg lcms ltdl lzma pangocairo png rsvg tiff webp wmf x xml zlib
With Q16i and Q32f, these give #8000.
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648,2147483648,2147483648)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648,2147483648,2147483648)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648,2147483648,2147483648)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
 
With Q16i and Q32f, these give #7fff:
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647,2147483647,2147483647)  #7FFFFFFF7FFFFFFF7FFFFFFF  srgb(49.9999999883585%,49.9999999883585%,49.9999999883585%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647,2147483647,2147483647)  #7FFFFFFF7FFFFFFF7FFFFFFF  srgb(49.9999999883585%,49.9999999883585%,49.9999999883585%)
# ImageMagick pixel enumeration: 1,1,4294967295,gray
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  gray(50%)
 
With Q16i, these give #7fff, but with Q32f they give #8000:
# ImageMagick pixel enumeration: 1,1,4294967295,gray
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  gray(50%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483647.5,2147483647.5,2147483647.5)  #800000008000000080000000  srgb(50%,50%,50%)
 
These are arithmetically horrible in all Q:
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2139062143,2139062143,2139062143)  #7F7F7F7F7F7F7F7F7F7F7F7F  grey50

Scripts

For convenience, .bat scripts are also available in a single zip file. See Zipped BAT files.

testHalf.bat

set I=%1
if "%I%"=="." set I=

if "%I%"=="" (
  set I=%IM%
)

set OUTFILE=half.txt
if not "%2"=="" set OUTFILE=%2

set PREC=-precision 15

%I%convert -version>%OUTFILE%

echo With Q16i and Q32f, these give #8000.>>%OUTFILE%

%I%convert %PREC% xc:Black -evaluate Add 50%% txt:>>%OUTFILE%

%I%convert %PREC% xc:Black -evaluate AddModulus 50%% txt:>>%OUTFILE%

%I%convert %PREC% xc:Black -evaluate Sin 0 txt:>>%OUTFILE%

%I%convert %PREC% xc:Black -evaluate Set 50%% txt:>>%OUTFILE%

%I%convert %PREC% xc:White -evaluate Divide 2 txt:>>%OUTFILE%

%I%convert %PREC% xc:White -evaluate Multiply 0.5 txt:>>%OUTFILE%

%I%convert %PREC% xc:Black -function Polynomial 0.5 txt:>>%OUTFILE%

%I%convert %PREC% xc:White -function Polynomial 0.5 txt:>>%OUTFILE%

%I%convert %PREC% xc:White -function Polynomial 0.5,0 txt:>>%OUTFILE%

%I%convert %PREC% xc:Black -function Sinusoid 1 txt:>>%OUTFILE%

%I%convert %PREC% xc:Black xc:White -evaluate-sequence Mean txt:>>%OUTFILE%

%I%convert %PREC% xc:Black xc:White -compose Mathematics -define compose:args=0,0.5,0.5,0 -composite txt:>>%OUTFILE%

%I%convert %PREC% xc:Black xc:White -compose Mathematics -define compose:args=0,0,0,0.5 -composite txt:>>%OUTFILE%

%I%convert %PREC% xc:Black xc:White +append -scale 1x1 txt:>>%OUTFILE%

%I%convert %PREC% xc:Black xc:White -evaluate-sequence Mean txt:>>%OUTFILE%

%I%convert %PREC% xc:Black -fx "0.5" txt:>>%OUTFILE%

%I%convert %PREC% -size 100x1 gradient: -scale 1x1 txt:>>%OUTFILE%


echo. >>%OUTFILE%
echo With Q16i and Q32f, these give #7fff:>>%OUTFILE%

%I%convert %PREC% xc:White -evaluate Subtract 50%% txt:>>%OUTFILE%

%I%convert %PREC% xc:White -evaluate AddModulus 50%% txt:>>%OUTFILE%

%I%convert %PREC% xc:gray(50%%) txt:>>%OUTFILE%


echo. >>%OUTFILE%
echo With Q16i, these give #7fff, but with Q32f they give #8000:>>%OUTFILE%

%I%convert %PREC% xc:gray(50%%) txt:>>%OUTFILE%

%I%convert %PREC% xc:srgb(50%%,50%%,50%%) txt:>>%OUTFILE%

echo. >>%OUTFILE%
echo These are arithmetically horrible in all Q:>>%OUTFILE%

%I%convert %PREC% xc:gray50 txt:>>%OUTFILE%


type %OUTFILE%

All images on this page were created by the commands shown, using:

%IM%convert -version
cmd /c exit /B 0
Version: ImageMagick 6.9.2-5 Q16 x64 2015-10-31 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Visual C++: 180031101
Features: Cipher DPC Modules OpenMP 
Delegates (built-in): bzlib cairo freetype jng jp2 jpeg lcms lqr openexr pangocairo png ps rsvg tiff webp xml zlib

Source file for this web page is fiftypc.h1. To re-create this web page, run "procH1 fiftypc".


This page, including the images, is my copyright. Anyone is permitted to use or adapt any of the code, scripts or images for any purpose, including commercial use.

Anyone is permitted to re-publish this page, but only for non-commercial use.

Anyone is permitted to link to this page, including for commercial use.


Page version v1.0 15-March-2015.

Page created 22-May-2016 23:22:45.

Copyright © 2016 Alan Gibson.