-fx airy, j0, and j1 functions

Questions and postings pertaining to the development of ImageMagick, feature enhancements, and ImageMagick internals. ImageMagick source code and algorithms are discussed here. Usage questions which are too arcane for the normal user list should also be posted here.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: -fx airy, j0, and j1 functions

Post by fmw42 »

jlettvin wrote:Thank you.

Using your command-line, I was able to duplicate the correct image character.
I will consider this issue closed.

Do you consider my pursuit of adding code for emulating human vision
a worthwile addition to ImageMagick?
Magick will have the airy function (normalized) in the next IM beta release, supposedly in about an hour. I can verify it tomorrow.

With regard to your pursuit, I think it is fine. Adding new functions to IM is always useful. The problem is that the IM folks are very busy with backlogs. So anyone who can program to help add new features is always welcome.

Unfortunately I know only a little about your endeavors, but do have some understanding of PSF and MTF as I was involved in bringing FFT and script applications to IM. See http://www.fmwconcepts.com/imagemagick/ ... urier.html. Certainly adding the Bessel functions, Airy function, sinc and jinc are useful as foundations for doing many such things.
jlettvin

Re: -fx airy, j0, and j1 functions

Post by jlettvin »

I closed the issue prematurely.

Here is how I generate a white point on a black background:
convert -size 128x128 xc:black -fill white -draw 'point 64,64' airy3.gif

Here I append the square of the jinc function to make an Airy pattern:
convert -size 128x128 xc:black -fill white -draw 'point 64,64' -fx "jinc(2*u)*jinc(2*u)" airy3.gif

Problem is, it doesn't do the same thing as your command:
convert -size 128x128 radial-gradient: -negate -fx "jinc(2*u)*jinc(2*u)" airy2_grad.gif

These elements of your command-line I do not understand:
radial-gradient really ought not to be involved in this process.
-negate I don't really understand what is being done with this.

The goal is to produce a fully bright single pixel in the center of a fully black image
and then convolve the entire image with the Airy function.
This should produce the Airy disk and rings.

It does not.
Am I using ImageMagick incorrectly?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: -fx airy, j0, and j1 functions

Post by fmw42 »

yes, you are using IM incorrectly.

The airy function is simply a mathematical expression. You must give it a range of x values and then get the corresponding airy values. The range of x values is a gradient from 0 to 1 and then scaled within the airy function argument to whatever value you want to supply.

You cannot produce an airy function from a point source. That involves the physics (Fraunhofer diffraction) of a response to an circular aperture. The airy function would be the result. But IM does not do the physics, it just implements the mathematical expression of the airy function over some range of argument values.

The radial gradient is simply a representation of r. It is linearly increasing from 0 value in the middle to 1 at the sides. When you apply the airy function to it, you are evaluating airy(r)=[2*j1(pi*r)/(pi*r)]^2 for r ranging from 0 to 1. The internal scaling by pi, then means the horizontal range is from 0 to pi rather than 0 to 1. You can scale that along the r coordinate by supply a scaling value (a) so that you evaluate airy(a*r) which then goes from 0 to pi*a and produces the corresponding airy values. The scaling value simply controls the horizontal extent of the Airy function that one achieves in the image.

Hope that helps.

P.S. The negate is needed to invert the grayscale radial-gradient which naturally has white at the center and ramps down to black. We need black in the middle to represent r=0 and white at the sides to represent r=1. see http://www.imagemagick.org/Usage/canvas ... l-gradient
jlettvin

Re: -fx airy, j0, and j1 functions

Post by jlettvin »

Thank you.
I am beginning to grasp this.
Without your help, I would have not made the strides I have today.

I still notice that radial-gradient has a questionable character.
Let me explain.

I noticed that radial-gradient: has the value 1.0 at radius half the width of the square.
This means that the gradient goes flat towards the corners, staying at value 1.0.
This is because the distance to the corner is sqrt(2) the square's half-width.
To handle this problem I have begun to use this command to generate the desired gradient:

convert -size 364x364 radial-gradient: -negate -crop 255x255+54+54 jmask.gif

This makes a 255x255 image that has gradients all the way into the corners.

My goal is to make 128x128 images that displace the gradient center
to imitate the displacements of point sources by cropping the 255x255 image.
I accomplish this by using commands like these:

# Make a Red radial-gradient with the center in the lower left corner.
convert jmask.gif -channel G -evaluate set 0 +channel -channel B -evaluate set 0 +channel -crop 128x128+63+63 jR.gif

# Make a Green radial-gradient with the center in the upper right corner.
convert jmask.gif -channel R -evaluate set 0 +channel -channel B -evaluate set 0 +channel -crop 128x128+191+191 jG.gif

Are there simpler ways to accomplish this efficiently?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: -fx airy, j0, and j1 functions

Post by fmw42 »

try these

size=255
size2=`convert xc: -format "%[fx:$size*sqrt(2)]" info:`
convert -size ${size2}x${size2} radial-gradient: -negate \
-gravity center -crop ${size}x${size}+0+0 +repage grad255.png

size=128
size2=`convert xc: -format "%[fx:2*$size]" info:`
size3=`convert xc: -format "%[fx:2*sqrt(2)*$size)]" info:`
convert -size ${size3}x${size3} radial-gradient:white-cyan -negate \
-gravity center -crop ${size2}x${size2}+0+0 +repage \
-gravity northeast -crop ${size}x${size}+0+0 +repage \
-channel r -auto-level grad128_ne.png

The gradient is colored white-cyan so that when negated it will be black to red

the -channel r -autolevel is there because of a slight inaccuracy in that the bottom left corner has a value of 1,0,0 and not 0,0,0. So I stretched the red channel to span the full range.

This method requires no computation of the offsets, if you want the origin value of 0 to be in one of the corners.


see radial-gradient coloring at http://www.imagemagick.org/Usage/canvas ... l-gradient

P.S. I would love the see a new radial-gradient function that allows one to specify the x and y radii and the center point. But it could easily be done using -fx, although it would be somewhat slow. But if the images were small, then it would not matter.

Here is the fx version of your corner radial-gradient:

size=128
rad=`convert xc: -format "%[fx:sqrt(2)*$size)]" info:`
convert -size ${size}x${size} xc: -fx "red*sqrt(i*i+j*j)/$rad" -rotate -90 grad128_ne2.png
Post Reply