📄 effect.extend.cs
字号:
/// <summary>
/// 对图像进行波浪特效处理
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">波浪振幅[1, 32]</param>
/// <returns></returns>
public Bitmap Wave(Bitmap b, int degree)
{
if (degree < 1) degree = 1;
if (degree > 32) degree = 32;
int width = b.Width;
int height = b.Height;
Bitmap dstImage = new Bitmap(width, height);
BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
System.IntPtr srcScan0 = srcData.Scan0;
System.IntPtr dstScan0 = dstData.Scan0;
int offset = stride - width * BPP;
unsafe
{
byte* src = (byte*)srcScan0;
byte* dst = (byte*)dstScan0;
int X, Y;
// 圆周率 2*pi
double PI2 = Math.PI * 2.0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
X = (int)(degree * Math.Sin(PI2 * y / 128.0)) + x;
Y = (int)(degree * Math.Cos(PI2 * x / 128.0)) + y;
// 边界约束
if (X < 0) X = 0;
if (X >= width) X = width - 1;
if (Y < 0) Y = 0;
if (Y >= height) Y = height - 1;
src = (byte*)srcScan0 + Y * stride + X * BPP;
dst[3] = src[3]; // A
dst[2] = src[2]; // R
dst[1] = src[1]; // G
dst[0] = src[0]; // B
dst += BPP;
} // x
dst += offset;
} // y
}
b.UnlockBits(srcData);
dstImage.UnlockBits(dstData);
b.Dispose();
return dstImage;
} // end of Wave
/// <summary>
/// 对图像进行摩尔纹特效处理
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">强度[1, 16]</param>
/// <returns></returns>
public Bitmap MoireFringe(Bitmap b, int degree)
{
if (degree < 1) degree = 1;
if (degree > 16) degree = 16;
int width = b.Width;
int height = b.Height;
int midX = width / 2;
int midY = height / 2;
Bitmap dstImage = new Bitmap(width, height);
BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
System.IntPtr srcScan0 = srcData.Scan0;
System.IntPtr dstScan0 = dstData.Scan0;
int offset = stride - width * BPP;
unsafe
{
byte* src = (byte*)srcScan0;
byte* dst = (byte*)dstScan0;
int X, Y;
int offsetX, offsetY;
// 弧度、半径
double radian, radius;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 当前点与图像中心点的偏移量
offsetX = x - midX;
offsetY = y - midY;
// 弧度
radian = Math.Atan2(offsetX, offsetY);
// 半径
radius = Math.Sqrt(offsetX * offsetX + offsetY * offsetY);
// 映射实际像素点
X = (int)(radius * Math.Sin(radian + degree * radius));
Y = (int)(radius * Math.Sin(radian + degree * radius));
// 边界约束
if (X < 0) X = 0;
if (X >= width) X = width - 1;
if (Y < 0) Y = 0;
if (Y >= height) Y = height - 1;
src = (byte*)srcScan0 + Y * stride + X * BPP;
dst[3] = src[3]; // A
dst[2] = src[2]; // R
dst[1] = src[1]; // G
dst[0] = src[0]; // B
dst += BPP;
} // x
dst += offset;
} // y
}
b.UnlockBits(srcData);
dstImage.UnlockBits(dstData);
// 将处理后的纹理图与原图像进行色彩混合
return Inosculate(b, dstImage, 128);
} // end of MoireFringe
/************************************************************
*
* 扩散、查找边缘、照亮边缘、灯光、马赛克、油画、曝光
*
************************************************************/
/// <summary>
/// 扩散
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">扩散幅度[1, 32]</param>
/// <returns></returns>
public Bitmap Diffuse(Bitmap b, int degree)
{
if (degree < 1) degree = 1;
if (degree > 32) degree = 32;
int width = b.Width;
int height = b.Height;
// 目标图像
Bitmap dstImage = (Bitmap)b.Clone();
BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
int stride = srcData.Stride;
System.IntPtr srcScan0 = srcData.Scan0;
System.IntPtr dstScan0 = dstData.Scan0;
int offset = stride - width * BPP;
unsafe
{
byte* src = (byte*)srcScan0;
byte* dst = (byte*)dstScan0;
Random myRand = new Random();
int X, Y;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 获取当前像素点周围的一随机点
X = x + myRand.Next(-degree, degree);
Y = y + myRand.Next(-degree, degree);
// 如果越界,则用图像边界上的点代替
if (X < 0) X = 0;
if (X >= width) X = width - 1;
if (Y < 0) Y = 0;
if (Y >= height) Y = height - 1;
// 指向源图像的随机点
src = (byte*)srcScan0 + (Y * stride) + (X * BPP);
dst[3] = src[3];
dst[2] = src[2];
dst[1] = src[1];
dst[0] = src[0];
dst += BPP;
} // x
dst += offset;
} // y
}
b.UnlockBits(srcData);
dstImage.UnlockBits(dstData);
b.Dispose();
return dstImage;
} // end of Diffuse
/// <summary>
/// 对图像进行查找边缘处理
/// </summary>
/// <param name="b">位图流</param>
/// <param name="angle">角度[0, 360]</param>
/// <returns></returns>
public Bitmap FindEdge(Bitmap b, int angle)
{
// 角度转弧度
double radian = (double)angle * 2.0 * Math.PI / 360.0;
// 每一权的弧度间隔
double pi4 = Math.PI / 4.0;
// 对图像进行卷积变换
Matrix3x3 m = new Matrix3x3();
m.TopLeft = Convert.ToInt32(Math.Cos(radian + pi4) * 256);
m.TopMid = Convert.ToInt32(Math.Cos(radian + 2.0 * pi4) * 256);
m.TopRight = Convert.ToInt32(Math.Cos(radian + 3.0 * pi4) * 256);
m.MidLeft = Convert.ToInt32(Math.Cos(radian) * 256);
m.Center = 0;
m.MidRight = Convert.ToInt32(Math.Cos(radian + 4.0 * pi4) * 256);
m.BottomLeft = Convert.ToInt32(Math.Cos(radian - pi4) * 256);
m.BottomMid = Convert.ToInt32(Math.Cos(radian - 2.0 * pi4) * 256);
m.BottomRight = Convert.ToInt32(Math.Cos(radian - 3.0 * pi4) * 256);
m.Scale = 256;
b = m.Convolute(b);
// 对图像进行负像处理
Adjustment a = new Adjustment();
b = a.Invert(b);
return b;
} // end of FindEdge
/// <summary>
/// 照亮边缘
/// </summary>
/// <param name="b">位图流</param>
/// <returns></returns>
public Bitmap GlowingEdge(Bitmap b)
{
int width = b.Width;
int height = b.Height;
BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
// 图像实际处理区域
// 不考虑最右 1 列,和最下 1 行
int rectTop = 0;
int rectBottom = height - 1;
int rectLeft = 0;
int rectRight = width - 1;
unsafe
{
int stride = data.Stride;
int offset = stride - width * BPP;
byte* p = (byte*)data.Scan0;
byte* bottom = p + stride;
byte* right = p + BPP;
int pixel;
for (int y = rectTop; y < rectBottom; y++)
{
for (int x = rectLeft; x < rectRight; x++)
{
// 指向当前点下方像素点
bottom = p + stride;
// 指向当前点右边像素点
right = p + BPP;
for (int i = 0; i < 3; i++)
{
pixel =
(p[i] - bottom[i]) * (p[i] - bottom[i]) +
(p[i] - right[i]) * (p[i] - right[i]);
pixel = (int)(Math.Sqrt(pixel) * 2);
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[i] = (byte)pixel;
} // i
// 向后移一像素
p += BPP;
} // x
// 移向下一行
// 这里得注意要多移 1 列,因最右列不必处理
p += offset + BPP;
} // y
}
b.UnlockBits(data);
return b;
} // end of GlowingEdge
/// <summary>
/// 灯光
/// </summary>
/// <param name="b">位图流</param>
/// <param name="power">光照强度</param>
/// <returns></returns>
public Bitmap Lighting(Bitmap b, int power)
{
int width = b.Width;
int height = b.Height;
// 光源中心点 X, Y 坐标
int x0 = width / 2;
int y0 = height / 2;
// 光源辐射半径
int radius = (int)Math.Sqrt(x0 * x0 + y0 * y0);
BitmapData data = b.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
byte* p = (byte*)data.Scan0;
int offset = data.Stride - width * BPP;
int pixel, brightness;
int distance, squareDistance;
int squareRadius = radius * radius;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 求当前点与光源中心点的距离
squareDistance = (x - x0) * (x - x0) + (y - y0) * (y - y0);
if (squareDistance < squareRadius)
{
distance = (int)Math.Sqrt(squareDistance);
// 当前点的光照强度
brightness = power * (radius - distance) / radius;
for (int i = 0; i < 3; i++)
{
pixel = p[i] + brightness;
if (pixel > 255) pixel = 255;
p[i] = (byte)pixel;
} // i
}
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of Lighting
/// <summary>
/// 对图像进行马赛克特效处理
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">块大小[1, 32]</param>
/// <returns></returns>
public Bitmap Mosaic(Bitmap b, int degree)
{
if (degree < 1) degree = 1;
if (degree > 32) degree = 32;
// 块大小
int block = degree;
int width = b.Width;
int height = b.Height;
Bitmap dstImage = (Bitmap)b.Clone();
BitmapData srcData = b.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
BitmapData dstData = dstImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
int srcStride = srcData.Stride;
int dstStride = dstData.Stride;
System.IntPtr srcScan0 = srcData.Scan0;
System.IntPtr dstScan0 = dstData.Scan0;
unsafe
{
byte* src = (byte*)srcScan0;
byte* dst = (byte*)dstScan0;
// 方块累加和
int sum = 0;
// 方块积
int product = block * block;
byte brightness = 0;
for (int y = 0; y < height; y += block)
{
for (int x = 0; x < width; x += block)
{
// 处理 B, G, R 三分量,不考虑 A 分量
for (int i = 0; i < 3; i++)
{
// 求小块内的亮度平均值
sum = 0;
for (int yB = 0; yB < block && (y + yB) < height; yB++)
{
for (int xB = 0; xB < block && (x + xB) < width; xB++)
{
src = (byte*)srcScan0 + ((y + yB) * srcStride) + ((x + xB) * BPP);
sum += src[i];
} // xB
} // yB
brightness = (byte)(sum / product);
// 将亮度值赋予目标图像
for (int yB = 0; yB < block && (y + yB) < height; yB++)
{
for (int xB = 0; xB < block && (x + xB) < width; xB++)
{
dst = (byte*)dstScan0 + ((y + yB) * dstStride) + ((x + xB) * BPP);
dst[i] = brightness;
} // xB
} // yB
} // i
} // x
} // y
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -