My apologies.
My earlier note used the wrong Bessel function, j0, in Airy
where it should have used j1.
Please allow me to document the correct calculation.
http://scienceworld.wolfram.com/physics/AiryDisk.htmlhttp://en.wikipedia.org/wiki/Airy_disk(See "Mathematical Details about halfway down)
The formula below is the correct mathematical description of
the PSF (Point Spread Function) of a monochromatic point source
on the optic axis of an in focus optical system with a circular aperture.
Airy: I( r ) = I0 * ( j1( r ) * j1( r ) ) / ( r * r )
where
r: ( 2 * pi * a * q ) / ( lambda * R )
a: radius of the aperture
q: radial distance from the optic axis
j1: Bessel function of the first kind of order 1
R: observation distance
lambda: wavelength
Note: The peak value of Airy is 0.25 since
the peak value of ( j1( r ) / r ) is 0.5
and this is correctly handled in the code you released.
It is probably appropriate to leave this intact
rather than conveniently normalizing Airy to 1.0.
I write C++ code to do this and write out .ppm files all the time.
It is actually fairly trivial though tricky code and the results are viewable here:
http://www.aneuran.com/aneuran/wikiThe images on that page illustrate the PSF of the human eye as the pupil changes diameter.
I have attempted to make the fix in your source, recompile, and test.
But the results seem to be incorrect.
In particular, this is the correction I attempted to make in magick/fx.c:
if (LocaleNCompare(expression,"airy",4) == 0)
{
alpha=FxEvaluateSubexpression(fx_info,channel,x,y,expression+4,beta, exception);
if (alpha == 0.0)
return(0.25);
double local = j1( (double) alpha ) / alpha;
return( (MagickRealType) ( local * local ) );
}
This is the test command that should produce a monochromatic Airy pattern:
convert WhitePointOnBlackBackground.gif -fx "airy( 0.1 * u )" MonochromaticPointSpreadFunction.gif
To be more consistent with how the human eye PSF converts a TV RGB pixel at one pupil size, use this command:
convert WhitePointOnBlackBackground.gif -channel red -fx "4*airy( 0.56 * u )" -channel green -fx "4*airy( 0.53 * u )" -channel blue -fx "4*airy( 0.43 * u )" HumanPSF.gif
This would account for the longitudinal chromatic aberration of the human optical apparatus.
Human vision also has transverse chromatic aberration where eccentricity from the optic center
displaces the centers of the Airy patterns so they are no longer concentric.
In fact, their relative displacements are in proportion to the difference in lambda
along a radial line from the optic center.
I do not yet seek to address this additional characteristic,
but hope one day to contribute workable fixes to the team.
Eventually, I hope to contribute code that completely emulates
characteristics of human optical transforms when presented with RGB data such as from a TV or computer.
Continuous spectrum characteristics may be beyond what is possible with ImageMagick.
Just to complete the information about this specialized Airy diffraction pattern:
the PSFs of multiple point sources are NOT ADDITIVE!
Airy ought not be used as an image filter.
The correct use of j1 in multiple source systems (pretty much all images) is
Intensity = square( w1 * j1( u1 ) + w2 * j1( u2 ) + ... wN * j1( uN ) );
where w1, w2, ... wN are wave heights for each of the contributing points.
In other words, the wave functions must be added (superposition) before squaring.
I would enjoy contributing to ImageMagick in ways like this
once I understand how to make j1 and Airy work at all.
As I said above, the sample fix I attempted failed to produce the desired results.
The image produced by "convert" does not resemble the images I produce from my own programs
and I know the results from those programs are correct from many years of testing.
Can you advise me on my error?