📄 adjustment.cs
字号:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using PhotoSprite.ColorSpace;
namespace PhotoSprite.ImageProcessing
{
/// <summary>
/// 图像调整类
/// </summary>
public class Adjustment : ImageInfo
{
/************************************************************
*
* 色彩平衡、亮度、对比度、HSL 调整、Gamma 矫正
*
************************************************************/
/// <summary>
/// 图像色彩平衡
/// </summary>
/// <param name="b">位图流</param>
/// <param name="red">红色分量[-255, 255]</param>
/// <param name="green">绿色分量[-255, 255]</param>
/// <param name="blue">蓝色分量[-255, 255]</param>
/// <returns></returns>
public Bitmap ColorBalance(Bitmap b, int red, int green, int blue)
{
if (red < -255) red = -255;
if (red > 255) red = 255;
if (green < -255) green = -255;
if (green > 255) green = 255;
if (blue < -255) blue = -255;
if (blue > 255) blue = 255;
int width = b.Width;
int height = b.Height;
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;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
pixel = p[2] + red;
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[2] = (byte)pixel;
pixel = p[1] + green;
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[1] = (byte)pixel;
pixel = p[0] + blue;
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[0] = (byte)pixel;
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of ColorBalance
/// <summary>
/// 图像亮度调整
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">亮度值[-255, 255]</param>
/// <returns></returns>
public Bitmap Brightness(Bitmap b, int degree)
{
if (degree < -255) degree = -255;
if (degree > 255) degree = 255;
int width = b.Width;
int height = b.Height;
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 = 0;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 处理像素 B, G, R 亮度三分量
for (int i = 0; i < 3; i++)
{
pixel = p[i] + degree;
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[i] = (byte)pixel;
} // i
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of Brightness
/// <summary>
/// 图像对比度调整
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">对比度[-100, 100]</param>
/// <returns></returns>
public Bitmap Contrast(Bitmap b, int degree)
{
if (degree < -100) degree = -100;
if (degree > 100) degree = 100;
double pixel = 0;
double contrast = (100.0 + degree) / 100.0;
contrast *= contrast;
int width = b.Width;
int height = b.Height;
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;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 处理指定位置像素的对比度
for (int i = 0; i < 3; i++)
{
pixel = ((p[i] / 255.0 - 0.5) * contrast + 0.5) * 255;
if (pixel < 0) pixel = 0;
if (pixel > 255) pixel = 255;
p[i] = (byte)pixel;
} // i
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of Contrast
/// <summary>
/// 按指定的色调、饱和度、亮度对图像进行调整
/// </summary>
/// <param name="b">位图流</param>
/// <param name="hue">色调[-180, 180]</param>
/// <param name="saturation">饱和度[-1, 1]</param>
/// <param name="luminance">亮度[-1, 1]</param>
/// <returns></returns>
public Bitmap AdjustHsl(Bitmap b, float hue, float saturation, float luminance)
{
if (hue < -180.0f) hue = -180.0f;
if (hue > 180.0f) hue = 180f;
if (saturation < -1.0f) saturation = -1.0f;
if (saturation > 1.0f) saturation = 1.0f;
if (luminance < -1.0f) luminance = -1.0f;
if (luminance > 1.0f) luminance = 1.0f;
int width = b.Width;
int height = b.Height;
Bitmap dstImage = new Bitmap(width, height, b.PixelFormat);
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;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
HSL hsl = HSL.FromRgb(p[2], p[1], p[0]);
hsl.Hue += hue;
hsl.Saturation += saturation;
hsl.Luminance += luminance;
p[0] = hsl.GetBlue();
p[1] = hsl.GetGreen();
p[2] = hsl.GetRed();
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of AdjustHsl
/// <summary>
/// 图像 Gamma 矫正
/// </summary>
/// <param name="b">位图流</param>
/// <param name="degree">Gamma 矫正量[0.1, 5.0]</param>
/// <returns></returns>
public Bitmap GammaCorrect(Bitmap b, double degree)
{
if (degree < 0.1) degree = 0.1;
if (degree > 5.0) degree = 5.0;
byte[] Gamma = new byte[256];
double g = 1 / degree;
// 建立 Gamma 矫正映射表
for (int i = 0; i < 256; i++)
{
int pixel = (int)((255.0 * Math.Pow(i / 255.0, g)) + 0.5);
Gamma[i] = (byte)((pixel > 255) ? 255 : pixel);
} // i
// 根据 Gamma 矫正映射表对图像色彩进行映射处理
return Mapping(b, Gamma, ChannelMode.White);
} // end of GammaCorrect
/************************************************************
*
* 负像、交错负像、伪彩色
*
************************************************************/
/// <summary>
/// 反转,负像
/// </summary>
/// <param name="b">位图流</param>
/// <returns></returns>
public Bitmap Invert(Bitmap b)
{
int width = b.Width;
int height = b.Height;
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;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 与255进行异或运算,相当于按位非
p[2] ^= 0xFF;
p[1] ^= 0xFF;
p[0] ^= 0xFF;
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of Invert
/// <summary>
/// 交叉反转
/// </summary>
/// <param name="b">位图流</param>
/// <returns></returns>
public Bitmap Interleaving(Bitmap b)
{
int width = b.Width;
int height = b.Height;
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;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// 将指定位置的像素颜色反转
if ((x + y) % 2 == 0)
{
p[0] ^= 0xFF;
p[1] ^= 0xFF;
p[2] ^= 0xFF;
}
p += BPP;
} // x
p += offset;
} // y
}
b.UnlockBits(data);
return b;
} // end of Interleaving
/// <summary>
/// 按函数曲线形式映射伪彩色
/// </summary>
/// <param name="b">灰度位图流</param>
/// <returns></returns>
public Bitmap PseudoColor(Bitmap b)
{
int width = b.Width;
int height = b.Height;
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 R, G, B, gray;
R = G = B = gray = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -