To create a vintage style, oval shaped image


It’s a long time ago that I saw a picture of my great-grandmother. This image was of coarse grey scale and it had an oval shape with faded out fringe like:


Vintage

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.


Vintage

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.


Vintage


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.


Vintage


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.


Vintage

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


Vintage

is


Vintage

And with the substitution:


Vintage

Vintage

And resolved for a:


Vintage

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:


Vintage

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



Vintage



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;
}



With this my image becomes:


Vintage


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 button to load a .jpg file. If an image is loaded like this, the application will produce a second image named “Output.jpg” located in the same directory as is the loaded file. If no file is loaded the castle image will be transformed and saved in the application directory. The semiaxis a and b can be entered and the band within which the pixels are faded out can be entered. There are some default values that fit to the castle. The ellipse is always in the centre of the image.

It consists of just this main window:


Vintage


C# Demo Project vintage image
  • Img_Vintage.zip