This forum contains outdated content and is available for reading only. Please contact technical support if you have any questions.

Notification

Icon
Error

Options
Go to last post Go to first unread
Fedor  
#1 Posted : Thursday, June 19, 2014 12:28:46 AM(UTC)
Fedor

Rank: Advanced Member

Groups: Guest
Joined: 7/28/2003(UTC)
Posts: 1,660

Thanks: 5 times
Was thanked: 76 time(s) in 74 post(s)
This simple algorithm is based on the work of Tanner Helland. Please note this implementation supports neither interpolation nor memory-efficient pipeline image processing.

Code:
/// <summary>
/// Corrects lens distortion
/// </summary>
/// <param name="source">source bitmap</param>
/// <param name="strength">>= 0.  0 = no change, high numbers equal stronger correction.</param>
/// <param name="zoom">>= 1.  (1 = no change in zoom)</param>
/// <returns></returns>
private Aurigma.GraphicsMill.Bitmap CorrectLensDistortion(Aurigma.GraphicsMill.Bitmap source
	, float strength, float zoom)
{
	if (source.PixelFormat.Size < 8)
	{
		throw new Aurigma.GraphicsMill.UnsupportedPixelFormatException();
	}

	if (strength < 0)
	{ 
		throw new ArgumentOutOfRangeException();
	}

	if (zoom < 1)
	{ 
		throw new ArgumentOutOfRangeException();
	}


	var target = new Aurigma.GraphicsMill.Bitmap(source.Width, source.Height, source.PixelFormat);

	var bytes = source.PixelFormat.Size / 8; 

	int halfWidth = source.Width / 2;
	int halfHeight = source.Height / 2;

	float correctionRadius = (float)(Math.Sqrt(source.Width ^ 2 + source.Height ^ 2)) / strength;

	unsafe
	{
		//A pointer to the beginning of the pixel data region
		byte* sourcePointer = (byte*)(source.Scan0.ToPointer());
		byte* targetPointer = (byte*)(target.Scan0.ToPointer());
				
		//Number of bytes in a row
		int stride = target.Stride;

		//Number of rows
		int height = target.Height;
		int width = target.Width;

		for (int i = 0; i < height; i++)
		{
			byte* position = targetPointer + stride * i;

			for (int j = 0; j < width; j++)
			{
				float newX = (float)(j - halfWidth);
				float newY = (float)(i - halfHeight);

				float distance = (float)(Math.Sqrt(newX * newX + newY * newY));
				float r = distance / correctionRadius;

				float theta;

				if (r == 0)
				{
					theta = 1;
				}
				else
				{
					theta = (float)(Math.Atan(r)) / r;
				}

				int sourceX = halfWidth + (int)(theta * newX * zoom);
				int sourceY = halfHeight + (int)(theta * newY * zoom);

				//set color of pixel (x, y) to color of source image pixel at (sourceX, sourceY)
				if (sourceX >= 0 && sourceX < source.Width && sourceY >= 0 && sourceY < source.Height)
				{

					//target.SetPixel(j, i, source.GetPixel(sourceX, sourceY));
					byte* s = sourcePointer + stride * sourceY + sourceX * bytes;

					for (int z = 0; z < bytes; z++)
					{
						*position = *s;
						position++;
						s++;
					}
				}
				else
				{
					for (int z = 0; z < bytes; z++)
					{
						*position = 0;
						position++;							
					}
				}
			}
		}
	}

	return target;
}

Using:

Code:
var source = new Aurigma.GraphicsMill.Bitmap(@"c:\temp\photo.jpg");

var target = CorrectLensDistortion(source, 0.02f, 1f);

target.Save(@"c:\temp\out.jpg");

Edited by user Thursday, June 19, 2014 12:33:36 AM(UTC)  | Reason: Not specified

Best regards,

Fedor Skvortsov

Jon Ivar  
#2 Posted : Thursday, June 19, 2014 2:39:17 AM(UTC)
Jon Ivar

Rank: Newbie

Groups: Guest
Joined: 6/19/2014(UTC)
Posts: 1

Thanks Fedor, just what I needed...

:o)

Jon Ivar

Users browsing this topic
Guest (3)
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.