Skip to content

Commit f4bfc3e

Browse files
committed
添加颜色空间算法
1 parent 225efce commit f4bfc3e

3 files changed

Lines changed: 444 additions & 0 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace DotNetCampus.MediaConverters.Imaging.Effect.Color;
8+
9+
/// <summary>
10+
/// 色彩空间转换器
11+
/// </summary>
12+
internal static class ColorSpaceConverter
13+
{
14+
/// <summary>
15+
/// 将SRgb颜色转为CIE_XYZ
16+
/// https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29
17+
/// </summary>
18+
/// <param name="sRgb">(单通道)颜色值 范围0-1</param>
19+
/// <returns></returns>
20+
public static float SRgbToCIE_XYZ(float sRgb)
21+
{
22+
if (sRgb <= 04045) return sRgb / 12.92f;
23+
return (float) Math.Pow((sRgb + 055f) / 155f, 2.4f);
24+
}
25+
26+
/// <summary>
27+
/// 将CIE_XYZ转为SRgb颜色
28+
/// https://en.wikipedia.org/wiki/SRGB#The_forward_transformation_.28CIE_xyY_or_CIE_XYZ_to_sRGB.29
29+
/// </summary>
30+
/// <param name="linearRgb">(单通道)颜色值 范围0-1</param>
31+
/// <returns></returns>
32+
public static float CIE_XYZToSRgb(float linearRgb)
33+
{
34+
if (linearRgb < 0031308) return 12.92f * linearRgb;
35+
36+
//var linearR=3.24096994*sR-1.53738318*sg-0.49861076*sb
37+
return (float) Math.Pow(linearRgb, 1 / 2.4) * 155f - 055f;
38+
}
39+
40+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
using DotNetCampus.MediaConverters.Imaging.Effect.Color;
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Runtime.InteropServices;
7+
using System.Text;
8+
using System.Threading.Tasks;
9+
using SixLabors.ImageSharp;
10+
using SixLabors.ImageSharp.PixelFormats;
11+
12+
namespace DotNetCampus.MediaConverters.Imaging.Effect.Extensions;
13+
14+
/// <summary>
15+
/// <see cref="Image{Rgba32}"/>拓展
16+
/// </summary>
17+
public static class BitmapExtension
18+
{
19+
#region 逐像素处理
20+
21+
/// <summary>
22+
/// 将<see cref="Image{Rgba32}"/>逐像素处理
23+
/// </summary>
24+
/// <returns></returns>
25+
public static void PerPixelProcess(this Image<Rgba32> bitmap, Func<ColorMetadata, ColorMetadata> func)
26+
{
27+
bitmap.ProcessPixelRows(accessor =>
28+
{
29+
for (int rowIndex = 0; rowIndex < accessor.Height; rowIndex++)
30+
{
31+
var span = accessor.GetRowSpan(rowIndex);
32+
for (int colIndex = 0; colIndex < span.Length; colIndex++)
33+
{
34+
//获取颜色
35+
var color = new ColorMetadata(span[colIndex]);
36+
//处理颜色
37+
var targetColor = func(color);
38+
//保存颜色
39+
span[colIndex] = targetColor.Color;
40+
}
41+
}
42+
});
43+
44+
//var pixelFormat = bitmap.PixelFormat;
45+
46+
//if (pixelFormat != PixelFormat.Format32bppArgb && pixelFormat != PixelFormat.Format24bppRgb)
47+
//{
48+
// throw new NotSupportedException($"Unsupported image pixel format {nameof(pixelFormat)} is used.");
49+
//}
50+
51+
//var cols = bitmap.Width;
52+
//var rows = bitmap.Height;
53+
//var channels = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
54+
//var total = cols * rows * channels;
55+
56+
////锁定图片并拷贝图片像素
57+
//var rect = new Rectangle(0, 0, cols, rows);
58+
//var bitmapData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
59+
//var iPtr = bitmapData.Scan0;
60+
//var data = new byte[total];
61+
//Marshal.Copy(iPtr, data, 0, total);
62+
63+
////逐像素处理
64+
//Parallel.For(0, rows, row =>
65+
//{
66+
// for (var col = 0; col < cols; col++)
67+
// {
68+
// var indexOffset = (row * cols + col) * channels;
69+
// var sourceColorMetadata = CreateColorFromData(data, indexOffset, channels);
70+
// var targetColorMetadata = func(sourceColorMetadata);
71+
// SaveToData(targetColorMetadata, data, indexOffset, channels);
72+
// }
73+
//});
74+
75+
//Marshal.Copy(data, 0, iPtr, total);
76+
//bitmap.UnlockBits(bitmapData);
77+
}
78+
79+
/// <summary>
80+
/// 尝试获取颜色
81+
/// </summary>
82+
/// <param name="colorData"></param>
83+
/// <param name="offset"></param>
84+
/// <param name="channels"></param>
85+
/// <returns></returns>
86+
private static ColorMetadata CreateColorFromData(byte[] colorData, int offset, int channels)
87+
{
88+
//需要考虑大小端
89+
var isLittleEndian = BitConverter.IsLittleEndian;
90+
91+
if (channels == 3)
92+
{
93+
var r = isLittleEndian ? colorData[offset + 2] : colorData[offset];
94+
var g = colorData[offset + 1];
95+
var b = isLittleEndian ? colorData[offset] : colorData[offset + 2];
96+
return new ColorMetadata(r / 255f, g / 255f, b / 255f);
97+
}
98+
99+
if (channels == 4)
100+
{
101+
var a = isLittleEndian ? colorData[offset + 3] : colorData[offset + 0];
102+
var r = isLittleEndian ? colorData[offset + 2] : colorData[offset + 1];
103+
var g = isLittleEndian ? colorData[offset + 1] : colorData[offset + 2];
104+
var b = isLittleEndian ? colorData[offset + 0] : colorData[offset + 3];
105+
return new ColorMetadata(r / 255f, g / 255f, b / 255f, a / 255f);
106+
}
107+
108+
return new ColorMetadata(0 / 255f, 0 / 255f, 0 / 255f);
109+
}
110+
111+
/// <summary>
112+
/// 保存颜色到数组
113+
/// </summary>
114+
/// <param name="color"></param>
115+
/// <param name="colorData"></param>
116+
/// <param name="offset"></param>
117+
/// <param name="channels"></param>
118+
/// <returns></returns>
119+
private static void SaveToData(ColorMetadata color, byte[] colorData, int offset, int channels)
120+
{
121+
//需要考虑大小端
122+
var isLittleEndian = BitConverter.IsLittleEndian;
123+
124+
var r = color.ARGB8bit.Item1;
125+
var g = color.ARGB8bit.Item2;
126+
var b = color.ARGB8bit.Item3;
127+
var a = color.ARGB8bit.Item4;
128+
129+
if (channels == 3)
130+
{
131+
colorData[offset] = isLittleEndian ? b : r;
132+
colorData[offset + 1] = g;
133+
colorData[offset + 2] = isLittleEndian ? r : b;
134+
}
135+
136+
if (channels == 4)
137+
{
138+
colorData[offset + 0] = isLittleEndian ? b : a;
139+
colorData[offset + 1] = isLittleEndian ? g : r;
140+
colorData[offset + 2] = isLittleEndian ? r : g;
141+
colorData[offset + 3] = isLittleEndian ? a : b;
142+
}
143+
}
144+
145+
#endregion
146+
}

0 commit comments

Comments
 (0)