Welcome Guest! You need to login or register to make posts.

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: Member, Administration, Moderator
Joined: 7/28/2003(UTC)
Posts: 1,572

Thanks: 5 times
Was thanked: 64 time(s) in 63 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: Member
Joined: 6/19/2014(UTC)
Posts: 1

Thanks Fedor, just what I needed...

:o)
Jon Ivar
Users browsing this topic
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.