snibgo's ImageMagick pages

Fifty percent

The mid point of zero and an odd number is not an integer. 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.

%IMG7%magick ^
  xc:White xc:Black -append +repage ^
  +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 +repage ^
  fpc_blurbw.png 
fpc_blurbw.png
# ImageMagick pixel enumeration: 2,2,0,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.999076%,49.999076%,49.999076%)
1,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.999076%,49.999076%,49.999076%)
0,1: (32768,32768,32768)  #800080008000  srgb(50.000924%,50.000924%,50.000924%)
1,1: (32768,32768,32768)  #800080008000  srgb(50.000924%,50.000924%,50.000924%)
0.5
0.5
0.735357

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:

%IMG7%magick xc:gray(50%%) ( +clone ) -compose Plus -composite txt: 

%IMG7%magick xc:gray(50%%) ( +clone ) -evaluate-sequence Add txt: 

%IMG7%magick %PREC% xc:Black -evaluate Add 50%% -evaluate AddModulus 50%% txt:
# ImageMagick pixel enumeration: 1,1,0,65535,gray
0,0: (65535)  #FFFFFFFFFFFF  gray(255)
# ImageMagick pixel enumeration: 1,1,0,65535,gray
0,0: (65535)  #FFFFFFFFFFFF  gray(255)
# ImageMagick pixel enumeration: 1,1,0,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 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenCL 
Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib
Compiler: Visual Studio 2022 (193231332)
With Q16i and Q32f, these give #8000.
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50.0007629510948%,50.0007629510948%,50.0007629510948%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
 
With Q16i and Q32f, these give #7fff:
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.9992370489052%,49.9992370489052%,49.9992370489052%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32767,32767,32767)  #7FFF7FFF7FFF  srgb(49.9992370489052%,49.9992370489052%,49.9992370489052%)
# ImageMagick pixel enumeration: 1,1,0,65535,gray
0,0: (32768)  #800080008000  gray(50%)
 
With Q16i, these give #7fff, but with Q32f they give #8000:
# ImageMagick pixel enumeration: 1,1,0,65535,gray
0,0: (32768)  #800080008000  gray(50%)
# ImageMagick pixel enumeration: 1,1,0,65535,srgb
0,0: (32768,32768,32768)  #800080008000  srgb(50%,50%,50%)
 
These are arithmetically horrible in all Q:
# ImageMagick pixel enumeration: 1,1,0,65535,gray
0,0: (32639)  #7F7F7F7F7F7F  gray(127)
call %PICTBAT%testHalf %IM7DEV% half_dev.lis
Version: ImageMagick 7.1.0-20 Q32-HDRI x86_64 2021-12-29 https://imagemagick.org
Copyright: (C) 1999-2021 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP(4.5) 
Delegates (built-in): bzlib cairo fontconfig fpx freetype jbig jng jpeg lcms ltdl lzma pangocairo png raqm rsvg tiff webp wmf x xml zip zlib
Compiler: gcc (11.2)
With Q16i and Q32f, these give #8000.
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #7FFFFFFF7FFFFFFF7FFFFFFF  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
 
With Q16i and Q32f, these give #7fff:
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #7FFFFFFF7FFFFFFF7FFFFFFF  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #7FFFFFFF7FFFFFFF7FFFFFFF  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,gray
0,0: (2147483648.5)  #800000008000000080000000  gray(50.0000000116415%)
 
With Q16i, these give #7fff, but with Q32f they give #8000:
# ImageMagick pixel enumeration: 1,1,4294967295,gray
0,0: (2147483648.5)  #800000008000000080000000  gray(50.0000000116415%)
# ImageMagick pixel enumeration: 1,1,4294967295,srgb
0,0: (2147483648.5,2147483648.5,2147483648.5)  #800000008000000080000000  srgb(50.0000000116415%,50.0000000116415%,50.0000000116415%)
 
These are arithmetically horrible in all Q:
# ImageMagick pixel enumeration: 1,1,4294967295,gray
0,0: (2139062144.49804)  #7F7F7F7F7F7F7F7F7F7F7F7F  gray(127.000000059372)

Scripts

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

testHalf.bat

@rem
@rem Updated:
@rem   27-August-2022 for IM v7.
@rem

setlocal

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

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

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

set PREC=-precision 15

%I%magick -version>%OUTFILE%

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

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

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


type %OUTFILE%

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

%IMG7%magick -version
Version: ImageMagick 7.1.0-42 Q16-HDRI x64 396d87c:20220709 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenCL 
Delegates (built-in): bzlib cairo freetype gslib heic jng jp2 jpeg jxl lcms lqr lzma openexr pangocairo png ps raqm raw rsvg tiff webp xml zip zlib
Compiler: Visual Studio 2022 (193231332)

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 27-Aug-2022 18:28:29.

Copyright © 2022 Alan Gibson.