Hello,
I would like to execute a 'neutralize gray' effect at the pixel level. Is the following pseude function possible with GM command line ?
gm convert -neutralize-gray <threshold-value> input.jpg output.jpg
the command should loop over each RGB pixel and find the max(RGB) and the min(RGB)
If the max(RGB) minus min(RGB) is less than <threshold-value> then output pixel = average(RGB)
otherwise output pixel = original(RGB)</threshold-value>
example with numbers
gm convert -neutralize-gray 15 input.jpg output.jpg
pixel(x,y) = RGB(200,210,199)
max(RGB) = 210
min(RGB) =199
difference = 11 < threshold
set output pixel = (200+210+199)/3 = 203
pixel(x,y) = RGB(200,210,180)
max(RGB) = 210
min(RGB) =180
difference = 30 > threshold
set output pixel = RGB(200,210,180)
This effect will turn 'distorted' (or dirty) gray that still looks 'gray enough' to the human eye, into pure R=G=B gray which print devices need in order to determine if the page counts as color or grayscale
thank you in advance
On Wed, 11 Mar 2020, Hakan wrote:
It seems like your algorithm is a single-pass algorithm where each
pixel is analyzed/accessed just once. Is my interpretation correct?
If so, this is easily implemented in C/C++ using the GraphicsMagick
library, and could be implemented (albeit much more slowly) using
PerlMagick or another interpreted extension which allows updating
pixels. I lack sufficient imagination for how to implement it using
the existing command-line, but it might be possible.
Your command syntax is similar to the existing threshold commands
(-black-threshold, -threshold, and -white-threshold) and so the
implementation could copy one of those implementations and make minor
changes. If the algorithm works well, this seems useful to have in
GraphicsMagick.
Bob
Bob Friesenhahn
bfriesen@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
Public Key, http://www.simplesystems.org/users/bfriesen/public-key.txt
Yes, it is a single pass algorithm.
It is 1 read operation (from input) and 1 write (to output bitmap) to the same pixel location with no dependency on other pixels.
I experimented with
-operator channel operator rvalue[%] and was hoping it could be implemented with that structure
-operator all neutralize-gray rvalue[%]
there are very similar other commands but nothing that does a decision based on max(RGB)-min(RGB)
For someone familiar with the C/C++ interface it should be a few lines of code.
I am doing the same operation using C# but the looping is too slow and .NET cannot adress the large memory pool that GraphicsMagick can. I am convinced this will run extremely fast in GM because there are many other similar functions.
On Wed, 11 Mar 2020, Hakan wrote:
I thought about the -operator command but it is designed to handle an
arbitrary number of channels, which is not what you need
The work in the C code is relatively easy due to copying an existing
threshold implementation and then making a small change to the
implementation.
The C version would execute quite quickly.
You might consider if your algorithm would be improved or more generic
if the RGB color was converted to an RGB intensity value using a
standard algorithm and then the threshold is based on the computed
intensity rather than absolute peak in the R, G, or B channel. This
makes more sense to me since perception is based on intensity and the
contributions are highly non-linear.
There are these two standard conversions from RGB to intensity:
define PixelIntensityRec601(pixel) \
((unsigned int) \
(((double)306.0(pixel)->red+ \
(double)601.0(pixel)->green+ \
(double)117.0*(pixel)->blue) \
/ 1024.0))
define PixelIntensityRec709(pixel) \
((unsigned int) \
(0.2126(pixel)->red+ \
0.7152(pixel)->green+ \
0.0722*(pixel)->blue))
It is said that Rec709 should be the one used in the modern world
since it is what ATSC TV and modern displays are using.
If intensity can be used, then it might be possible to implement the
algorithm without modifying GraphicsMagick because a grayscale image
can be created and then perhaps a composite operator could be used to
implement the modification to the RGB image.
Bob
Bob Friesenhahn
bfriesen@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
Public Key, http://www.simplesystems.org/users/bfriesen/public-key.txt
can you suggest a command line(s) to create a grayscale image that can seperate 'perceived gray' from 'perceived color' based on a threshold on intensity and how to compose it back into the RGB original , if you think this can be done without modifications to GM ? I am not clear how that could be done.
Obviously your technical knowledge in this field is far more than mine and I cannot comment if your generic suggesting will work, or how well it works without testing an example.
I just know that the algorthim I explained with absolute numbers works very well on any kind of input (200/300dpi scans of largeformat drawings) because I use it, just with fairly slow code.
thank you
On Wed, 11 Mar 2020, Hakan wrote:
I am more like a race-car mechanic than a race-car driver. The
race-car driver is usually much better at driving than her mechanic.
:-)
There are other people who are far better at doing interesting things
with the available algorithms than I am.
To me it is easiest to implement the C source code.
Bob
Bob Friesenhahn
bfriesen@simple.dallas.tx.us, http://www.simplesystems.org/users/bfriesen/
GraphicsMagick Maintainer, http://www.GraphicsMagick.org/
Public Key, http://www.simplesystems.org/users/bfriesen/public-key.txt