Skip to content

Commit 2c239e2

Browse files
authored
First Blood
Initial commit
1 parent e9013f0 commit 2c239e2

9 files changed

Lines changed: 930 additions & 0 deletions

File tree

NuGet.Config

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<!-- Standard NuGet -->
5+
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
6+
</packageSources>
7+
</configuration>

RedKnack.HalftonePlugin.sln

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.0.31903.59
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RedKnack.HalftonePlugin", "RedKnack.HalftonePlugin\RedKnack.HalftonePlugin.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
EndGlobal
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
using PaintDotNet;
2+
using PaintDotNet.Effects;
3+
using System;
4+
using System.Runtime.CompilerServices;
5+
6+
namespace RedKnack.HalftonePlugin
7+
{
8+
internal static class ColorUtils
9+
{
10+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
11+
public static float Luminance(ColorBgra c)
12+
=> c.R / 255f * 0.2126f
13+
+ c.G / 255f * 0.7152f
14+
+ c.B / 255f * 0.0722f;
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
public static float Brightness(ColorBgra c)
18+
=> (c.R + c.G + c.B) / (3f * 255f);
19+
20+
public static void RgbToCmyk(ColorBgra c,
21+
out float cyan, out float magenta, out float yellow, out float black)
22+
{
23+
float r = c.R / 255f;
24+
float g = c.G / 255f;
25+
float b = c.B / 255f;
26+
27+
float k = 1f - MathF.Max(r, MathF.Max(g, b));
28+
29+
if (k >= 1f)
30+
{
31+
cyan = magenta = yellow = 0f;
32+
black = 1f;
33+
return;
34+
}
35+
36+
float inv = 1f / (1f - k);
37+
cyan = (1f - r - k) * inv;
38+
magenta = (1f - g - k) * inv;
39+
yellow = (1f - b - k) * inv;
40+
black = k;
41+
}
42+
43+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
44+
public static ColorBgra CmykToRgb(float c, float m, float y, float k)
45+
{
46+
float r = (1f - c) * (1f - k);
47+
float g = (1f - m) * (1f - k);
48+
float b = (1f - y) * (1f - k);
49+
return ColorBgra.FromBgraClamped(
50+
(int)(b * 255f),
51+
(int)(g * 255f),
52+
(int)(r * 255f),
53+
255);
54+
}
55+
56+
public static ColorBgra SampleBilinear(Surface src, double x, double y)
57+
{
58+
int w = src.Width;
59+
int h = src.Height;
60+
61+
int x0 = Math.Clamp((int)Math.Floor(x), 0, w - 1);
62+
int y0 = Math.Clamp((int)Math.Floor(y), 0, h - 1);
63+
int x1 = Math.Clamp(x0 + 1, 0, w - 1);
64+
int y1 = Math.Clamp(y0 + 1, 0, h - 1);
65+
66+
float tx = (float)(x - Math.Floor(x));
67+
float ty = (float)(y - Math.Floor(y));
68+
69+
ColorBgra c00 = src[x0, y0];
70+
ColorBgra c10 = src[x1, y0];
71+
ColorBgra c01 = src[x0, y1];
72+
ColorBgra c11 = src[x1, y1];
73+
74+
return ColorBgra.FromBgraClamped(
75+
(int)(Lerp(Lerp(c00.B, c10.B, tx), Lerp(c01.B, c11.B, tx), ty)),
76+
(int)(Lerp(Lerp(c00.G, c10.G, tx), Lerp(c01.G, c11.G, tx), ty)),
77+
(int)(Lerp(Lerp(c00.R, c10.R, tx), Lerp(c01.R, c11.R, tx), ty)),
78+
(int)(Lerp(Lerp(c00.A, c10.A, tx), Lerp(c01.A, c11.A, tx), ty)));
79+
}
80+
81+
public static ColorBgra SampleBox(Surface src, double cx, double cy, int size)
82+
{
83+
int half = size / 2;
84+
int w = src.Width;
85+
int h = src.Height;
86+
87+
float r = 0, g = 0, b = 0, a = 0;
88+
int count = 0;
89+
90+
int x0 = Math.Max(0, (int)(cx - half));
91+
int x1 = Math.Min(w - 1, (int)(cx + half));
92+
int y0 = Math.Max(0, (int)(cy - half));
93+
int y1 = Math.Min(h - 1, (int)(cy + half));
94+
95+
for (int y = y0; y <= y1; y++)
96+
for (int x = x0; x <= x1; x++)
97+
{
98+
var px = src[x, y];
99+
if (px.A == 0) continue;
100+
r += px.R; g += px.G; b += px.B; a += px.A;
101+
count++;
102+
}
103+
104+
if (count == 0) return ColorBgra.Transparent;
105+
float inv = 1f / count;
106+
107+
int totalPixels = (x1 - x0 + 1) * (y1 - y0 + 1);
108+
float aAll = 0;
109+
for (int y = y0; y <= y1; y++)
110+
for (int x = x0; x <= x1; x++)
111+
aAll += src[x, y].A;
112+
float avgAlpha = aAll / totalPixels;
113+
return ColorBgra.FromBgraClamped(
114+
(int)(b * inv), (int)(g * inv), (int)(r * inv), (int)avgAlpha);
115+
}
116+
117+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
118+
public static float Lerp(float a, float b, float t) => a + (b - a) * t;
119+
120+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
121+
public static double Lerp(double a, double b, double t) => a + (b - a) * t;
122+
123+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
124+
public static double SmoothStep(double edge0, double edge1, double x)
125+
{
126+
double t = Math.Clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
127+
return t * t * (3.0 - 2.0 * t);
128+
}
129+
130+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
131+
public static byte ToByte(float v)
132+
=> (byte)Math.Clamp((int)(v * 255f + 0.5f), 0, 255);
133+
134+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
135+
public static ColorBgra BlendColors(ColorBgra bg, ColorBgra fg, float t)
136+
{
137+
return ColorBgra.FromBgraClamped(
138+
(int)(bg.B + (fg.B - bg.B) * t),
139+
(int)(bg.G + (fg.G - bg.G) * t),
140+
(int)(bg.R + (fg.R - bg.R) * t),
141+
(int)(bg.A + (fg.A - bg.A) * t));
142+
}
143+
}
144+
}

RedKnack.HalftonePlugin/Enums.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
namespace RedKnack.HalftonePlugin
2+
{
3+
public enum DotShape
4+
{
5+
Circle,
6+
Diamond,
7+
Square,
8+
Line,
9+
Cross,
10+
Ellipse,
11+
Euclidean,
12+
Ring,
13+
}
14+
15+
public enum ColorMode
16+
{
17+
Grayscale,
18+
CMYK,
19+
SpotColor,
20+
RGB,
21+
}
22+
23+
public enum DotSizeCurve
24+
{
25+
AreaProportional,
26+
Linear,
27+
Gamma,
28+
Sine,
29+
}
30+
}

0 commit comments

Comments
 (0)