图像处理(一)——球面(凹凸)化
原图
凸面化处理结果
凹面化处理结果
/// <summary>
/// 图像滤镜---球面(凹凸)化
/// </summary>
/// <param name="bitmap">待处理图片</param>
/// <param name="originPoint">球面化的处理原点</param>
/// <param name="radius">球面化半径</param>
/// <param name="raised">是否凸面化</param>
/// <returns></returns>
private Bitmap GetHandledImage(Bitmap bitmap, Point originPoint, int radius, bool raised)
{
var bmp = (Bitmap)bitmap.Clone();
if (radius <= 0) return bmp;
try
{
var originX = (int)Math.Ceiling(originPoint.X) - 1;
var originY = (int)Math.Ceiling(originPoint.Y) - 1;
var width = bmp.Width;
var height = bmp.Height;
const int pixelSize = 4;
var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var byColorInfo = new byte[height * bmpData.Stride];
Marshal.Copy(bmpData.Scan0, byColorInfo, 0, byColorInfo.Length);
#region Safe
//var clone = (byte[])byColorInfo.Clone();
//for (var x = 0; x < width; x++)
//{
// for (var y = 0; y < height; y++)
// {
// var dx = x - originX;
// var dy = y - originY;
// var distance = Math.Sqrt(dx * dx + dy * dy);
// if (distance <= radius)
// {
// var theta = Math.Atan2(dy, dx);
// var mapR = raised ? (2 * radius / Math.PI) * Math.Asin(distance / radius) : Math.Sin(Math.PI * distance / (2 * radius)) * radius;
// dx = originX + (int)(mapR * Math.Cos(theta));
// dy = originY + (int)(mapR * Math.Sin(theta));
// if (dx < 0 || dx >= width || dy < 0 || dy >= height)
// {
// byColorInfo[y * bmpData.Stride + x * pixelSize] =
// byColorInfo[y * bmpData.Stride + x * pixelSize + 1] =
// byColorInfo[y * bmpData.Stride + x * pixelSize + 2] =
// byColorInfo[y * bmpData.Stride + x * pixelSize + 3] = 0;
// }
// else
// {
// byColorInfo[y * bmpData.Stride + x * pixelSize] = clone[dy * bmpData.Stride + dx * 4];
// byColorInfo[y * bmpData.Stride + x * pixelSize + 1] = clone[dy * bmpData.Stride + dx * 4 + 1];
// byColorInfo[y * bmpData.Stride + x * pixelSize + 2] = clone[dy * bmpData.Stride + dx * 4 + 2];
// byColorInfo[y * bmpData.Stride + x * pixelSize + 3] = clone[dy * bmpData.Stride + dx * 4 + 3];
// }
// }
// }
//}
//Marshal.Copy(byColorInfo, 0, bmpData.Scan0, byColorInfo.Length);
#endregion
#region Unsafe
unsafe
{
fixed (byte* source = byColorInfo)
{
var ptr = (byte*)(bmpData.Scan0);
for (var y = 0; y < height; y++)
{
for (var x = 0; x < width; x++)
{
var dx = x - originX;
var dy = y - originY;
var distance = Math.Sqrt(dx * dx + dy * dy);
if (distance <= radius)
{
var theta = Math.Atan2(dy, dx);
var mapR = raised ? (2 * radius / Math.PI) * Math.Asin(distance / radius): Math.Sin(Math.PI * distance / (2 * radius)) * radius;
dx = originX + (int)(mapR * Math.Cos(theta));
dy = originY + (int)(mapR * Math.Sin(theta));
if (dx < 0 || dx >= width || dy < 0 || dy >= height)
{
ptr[0] = ptr[1] = ptr[2] = ptr[3] = 0;
}
else
{
ptr[0] = source[dy * bmpData.Stride + dx * pixelSize];
ptr[1] = source[dy * bmpData.Stride + dx * pixelSize + 1];
ptr[2] = source[dy * bmpData.Stride + dx * pixelSize + 2];
ptr[3] = source[dy * bmpData.Stride + dx * pixelSize + 3];
}
}
ptr += pixelSize;
}
}
}
}
#endregion
bmp.UnlockBits(bmpData);
return bmp;
}
catch (Exception e)
{
return (Bitmap)bitmap.Clone();
}
}