O.k. that’s not my great-grandmother. It’s me how I had looked on such a picture 100 years ago
That looks quite funny and I thought why not doing the same on a digital image. It’s a cool exercise to work with an ellipse and its formula.
The idea is to define an inner and an outer ellipse around the main object of a picture and fade out the colours between these 2 ellipses (the light green area in the picture below) and in the same time convert the colours to a grey scale image.
Now the task to be solved is to find a measurement how much to fade a certain image pixel within these ellipses.
One possibility to achieve this would be to search for the point on the inner ellipse that builds together with the pixel (the blue point) a perpendicular onto the ellipse and use the distance to this point as the measurement to fade. That ends in a hell of a calculation and I regard that as way to complicate.
A bit simpler would be to draw a line from the pixel to the centre of the ellipse and use the distance of the pixel to the point this line crosses the ellipse as measurement.
But this approach creates a distortion of the outer ellipse (as can be seen) which looks ugly and is therefore useless as well.
The best approach (at least in my opinion) is to define a virtual ellipse of the same shape as the shape of the inner ellipse that crosses the pixel and use the size of this ellipse as measurement for the fading.
This ellipse must have the same ratio between its semiaxis a and b as has the inner ellipse. And the size of its half axis a compared to the semiaxis a of the inner ellipse gives the measurement to fade.
To implement this I have to find the semiaxis a and b of the ellipse trough my pixel with the coordinates x and y.
The formulation for an ellipse in the centre point
is
And with the substitution:
And resolved for a:
Is the semiaxis a for the ellipse that crosses the random pixel p(x,y).
The only thing needed is f and this can be retrieved from the inner ellipse:
If this a value is bigger the a of the inner ellipse I know the pixel p(x,y) is outside of the inner ellipse and must be faded. With the difference between these two semiaxis I get the fading parameter fader which is limited by the width of the band within which the image should be faded out. At the end the fader is normalized to a value between 0 and 1.
Implemented in a short c# sequence:
for (x = 1; x < bmpSource.Width - 1; x++)
{
for (y = 1; y < bmpSource.Height - 1; y++)
{
Color pix1 = bmpSource.GetPixel(x, y);
if ((x - centerX) != 0)
tg = (y - centerY) / (x - centerX);
else
tg = ellipseB;
double f = ellipseB / ellipseA;
double tempA = Math.Sqrt(((x - centerX)* (x - centerX) *f *f +(y - centerY)* (y - centerY))/f /f);
// compute the fading and gray scale
if (tempA > ellipseA)
{
double fader = tempA - ellipseA;
if (fader > band)
fader = band;
if (fader < 0)
fader = 0;
fader = fader / band;
R = pix1.R * (1.0 - fader) + 255.0 * fader;
G = pix1.G * (1.0 - fader) + 255.0 * fader;
B = pix1.B * (1.0 - fader) + 255.0 * fader;
}
else
{
R = pix1.R;
G = pix1.G;
B = pix1.B;
}
// set the corresponding pixel in the destination bitmap
Color nPix = Color.FromArgb((int)(R), (int)(G), (int)(B));
bmpDest.SetPixel(x, y, nPix);
}
}
With ellipseA and ellipseB the semiaxis of the inner ellipse, band as the distance between the inner and outer ellipse, bmpSource the source bitmap and bmpDest the destination bitmap.
This implementation transforms my image to
That’s quite cool, but not really vintage style. To have a real vintage style image we have to convert this to a grey scale image now. That’s no big deal. To use Alex Honolds words (I’m a great fan of him )
We introduce a new variable:
double
grayscale = (pix1.R + pix1.G + pix1.B) / 3.0;
and use this in
if (tempA > ellipseA)
{
double fader = tempA - ellipseA;
if (fader > band)
fader = band;
if (fader < 0)
fader = 0;
fader = fader / band;
R = grayscale * (1.0 - fader) + 255.0 * fader;
G = grayscale * (1.0 - fader) + 255.0 * fader;
B = grayscale * (1.0 - fader) + 255.0 * fader;
}
else
{
R = grayscale;
G = grayscale;
B = grayscale;
}
{
double fader = tempA - ellipseA;
if (fader > band)
fader = band;
if (fader < 0)
fader = 0;
fader = fader / band;
R = grayscale * (1.0 - fader) + 255.0 * fader;
G = grayscale * (1.0 - fader) + 255.0 * fader;
B = grayscale * (1.0 - fader) + 255.0 * fader;
}
else
{
R = grayscale;
G = grayscale;
B = grayscale;
}
With this my image becomes:
The castle of my home village as it had looked 100 years ago
In my demo project this image is loaded by default. There is an
It consists of just this main window:
C# Demo Project vintage image