C#实现图片曲线调整效果

项目背景

最近好友分享了OpenCV实现Photoshop算法-曲线调整的文章,然后就有人在问是否可以通过C#实现。在此分享一下如何使用纯C#代码,不依赖第三方库如何实现。

基本效果如下

在这里插入图片描述

基本思路

使用曲线控制图像的效果的原理,可以参考用OpenCV实现Photoshop算法(三): 曲线调整,本文就不在过多赘述。本文主要提供如何通过C#实现。
本项目主要分成两个部分:1、曲线绘制和X-Y对应值求法;2、X-Y对应关系如何作用于原图片。

主要模块——Curve

本模块主要的作用是绘制曲线和存储X-Y的对应关系。为了能够快速使用这个关系,可以生成一个数组保存这个关系,这样加快整个图像的生成。
代码如下:其中Bitmap用于返回绘制好的曲线,Result用于存储曲线上X-Y的对应关系。绘制曲线使用了Graphics,这种方法为C#自带的,不需要引入第三方依赖。

using System.Collections.Generic;
using System.Drawing;
using System.Linq;

namespace Curves
{
	public class Curve
	{
		private List<Point> points = new List<Point>();
		private int[] result = new int[256];

		private Bitmap bitmap = new Bitmap(256, 256);

		public int[] Result
		{
			get
			{
				return result;
			}
		}

		public Bitmap Bitmap
		{
			get
			{
				return bitmap;
			}
		}

		public Curve()
		{
			points.Add(new Point(0, 0));
			points.Add(new Point(255, 255));

			DrawCurve();
			GetResult();

		}

		public void AddPoint(Point point)
		{
			points.Add(point);
			points = points.OrderBy(p => p.X).ToList();

			DrawCurve();
			GetResult();
		}

		private int GetYValue(Bitmap bitmap, int x)
		{
			for (int i = 0; i < bitmap.Height; i++)
			{
				Color color = bitmap.GetPixel(x, i);
				if (color.B == 255)
				{
					return i;
				}
			}
			return 0;
		}

		private void GetResult()
		{
			for (int i = 0; i < 256; i++)
			{
				result[i] = GetYValue(bitmap, i);
			}
			result[255] = 255;
		}

		public void DrawCurve()
		{
			bitmap = new Bitmap(256, 256);
			using (Graphics g = Graphics.FromImage(bitmap))
			{
				g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
				Pen pen = new Pen(Color.Blue, 2);
				g.DrawCurve(pen, points.ToArray());
				g.Save();
			}
		}

	}
}

曲线图片控制模块

图片控制部分的思路是将Bitmap图片转为数组,对数组中的元素进行操作,以此加快处理速度。数组存储颜色信息时排布为RGB形式。因此处理不同的颜色通道,只需要操作对应的部分即可。另外按业务逻辑,应该在每加入一个新的曲线上的点,就更新原始图片和曲线图片,所以可以使用图片容器的鼠标事件。核心代码如下:

private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
{
	curve.AddPoint(e.Location);
	pictureBox2.Image = curve.Bitmap;
	Bitmap bmp = pictureBox1.Image as Bitmap;
	BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
	byte[] data = new byte[bitmapData.Stride * bitmapData.Height];
	Marshal.Copy(bitmapData.Scan0, data, 0, data.Length);
	for (int i = 0; i < data.Length; i = i + 3)
	{
		data[i] = (byte)curve.Result[data[i]];
	}
	Marshal.Copy(data, 0, bitmapData.Scan0, data.Length);
	bmp.UnlockBits(bitmapData);
	pictureBox1.Image = bmp;
}

功能拓展

除了RGB通道可以这样用曲线操作,将图像转为HSV(HSL)图像后,也可以对图像的色相、明度、饱和度进行调整,实现更多类似Photoshop的功能。

功能不足

本文在求得曲线的X-Y关系时,采用了指定X查找该列上颜色点对应的Y的值的方法,这种方法依赖于先绘制好图像后才可以使用。如果不依赖这种方式还可以使用插值法等方式,因为X-Y关系是个曲线,因此插值不是简单的线性插值,计算会更加复杂。

项目下载链接

https://download.csdn.net/download/qq_30270773/89640539

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值