Skip to content

Commit

Permalink
Merge pull request #1170 from b-editor/effects/shake
Browse files Browse the repository at this point in the history
Add PerlinNoise and ShakeEffect filter effects
  • Loading branch information
yuto-trd authored Nov 29, 2024
2 parents b34d9e2 + fb874e5 commit 7921389
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 0 deletions.
77 changes: 77 additions & 0 deletions src/Beutl.Engine/Graphics/FilterEffects/PerlinNoise.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
namespace Beutl.Graphics.Effects;

public class PerlinNoise
{
private readonly int[] _permutation;
private readonly int[] _p;

public PerlinNoise()
{
// Permutation array
_permutation =
[
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197,
62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20,
125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102,
143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200,
196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226,
250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47,
16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163,
70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79,
113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210,
144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31,
181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236,
205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
];

// Duplicate the permutation array
_p = new int[512];
for (int i = 0; i < 512; i++)
{
_p[i] = _permutation[i % 256];
}
}

public float Perlin(float x, float y)
{
int xi = (int)Math.Floor(x) & 255;
int yi = (int)Math.Floor(y) & 255;

float xf = x - (float)Math.Floor(x);
float yf = y - (float)Math.Floor(y);

float u = Fade(xf);
float v = Fade(yf);

int aa = _p[_p[xi] + yi];
int ab = _p[_p[xi] + yi + 1];
int ba = _p[_p[xi + 1] + yi];
int bb = _p[_p[xi + 1] + yi + 1];

float x1, x2;
x1 = Lerp(Grad(aa, xf, yf), Grad(ba, xf - 1, yf), u);
x2 = Lerp(Grad(ab, xf, yf - 1), Grad(bb, xf - 1, yf - 1), u);

return (Lerp(x1, x2, v) + 1) / 2; // Normalize to range 0 - 1
}

private static float Fade(float t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}

private static float Lerp(float a, float b, float t)
{
return a + t * (b - a);
}

private static float Grad(int hash, float x, float y)
{
int h = hash & 15;
float u = h < 8 ? x : y;
float v = h < 4 ? y : h == 12 || h == 14 ? x : 0;
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
}
112 changes: 112 additions & 0 deletions src/Beutl.Engine/Graphics/FilterEffects/ShakeEffect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using Beutl.Animation;
using Beutl.Language;
using Beutl.Media;

namespace Beutl.Graphics.Effects;

public class ShakeEffect : FilterEffect
{
public static readonly CoreProperty<float> StrengthXProperty;
public static readonly CoreProperty<float> StrengthYProperty;
public static readonly CoreProperty<float> SpeedProperty;

private readonly RenderInvalidatedEventArgs _invalidatedEventArgs;

private readonly PerlinNoise _random = new();
private float _time;
private float _strengthX = 50;
private float _strengthY = 50;
private float _speed = 100;
private float _offset;

static ShakeEffect()
{
StrengthXProperty = ConfigureProperty<float, ShakeEffect>(nameof(StrengthX))
.Accessor(o => o.StrengthX, (o, v) => o.StrengthX = v)
.DefaultValue(50)
.Register();

StrengthYProperty = ConfigureProperty<float, ShakeEffect>(nameof(StrengthY))
.Accessor(o => o.StrengthY, (o, v) => o.StrengthY = v)
.DefaultValue(50)
.Register();

SpeedProperty = ConfigureProperty<float, ShakeEffect>(nameof(Speed))
.Accessor(o => o.Speed, (o, v) => o.Speed = v)
.DefaultValue(100)
.Register();

AffectsRender<ShakeEffect>(StrengthXProperty, StrengthYProperty, SpeedProperty, IdProperty);
}

public ShakeEffect()
{
_invalidatedEventArgs = new RenderInvalidatedEventArgs(this);
}

[Display(Name = nameof(Strings.StrengthX), ResourceType = typeof(Strings))]
public float StrengthX
{
get => _strengthX;
set => SetAndRaise(StrengthXProperty, ref _strengthX, value);
}

[Display(Name = nameof(Strings.StrengthY), ResourceType = typeof(Strings))]
public float StrengthY
{
get => _strengthY;
set => SetAndRaise(StrengthYProperty, ref _strengthY, value);
}

[Display(Name = nameof(Strings.Speed), ResourceType = typeof(Strings))]
public float Speed
{
get => _speed;
set => SetAndRaise(SpeedProperty, ref _speed, value);
}

public override void ApplyAnimations(IClock clock)
{
base.ApplyAnimations(clock);
_time = (float)clock.CurrentTime.TotalSeconds;

RaiseInvalidated(_invalidatedEventArgs);
}

protected override void OnPropertyChanged(PropertyChangedEventArgs args)
{
base.OnPropertyChanged(args);
if (args is CorePropertyChangedEventArgs<Guid> targs)
{
if (targs.Property.Id == IdProperty.Id)
{
int hash = Id.GetHashCode();
_offset = new Random(hash).NextSingle() * 1000 - 500;
}
}
}

public override Rect TransformBounds(Rect bounds)
{
return Rect.Invalid;
}

public override void ApplyTo(FilterEffectContext context)
{
context.CustomEffect((_time, _speed, _strengthX, _strengthY, _random, _offset), (data, effectContext) =>
{
effectContext.ForEach((i, t) =>
{
float a = data._time * data._speed / 100 + data._offset;
float b = i + data._offset;
float randomX = data._random.Perlin(a, b);
float randomY = data._random.Perlin(b, a);
randomX = (randomX - 0.5F) * 2F * data._strengthX;
randomY = (randomY - 0.5F) * 2F * data._strengthY;
t.Bounds = t.Bounds.Translate(new Vector(randomX, randomY));
});
});
}
}
24 changes: 24 additions & 0 deletions src/Beutl.Language/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src/Beutl.Language/Strings.ja.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1330,4 +1330,16 @@ b-editorがダウンロードURLを管理します。</value>
<data name="Cut_Description" xml:space="preserve">
<value>選択したアイテムをカットします。</value>
</data>
<data name="ShakeEffect" xml:space="preserve">
<value>振動</value>
</data>
<data name="StrengthX" xml:space="preserve">
<value>強さX</value>
</data>
<data name="StrengthY" xml:space="preserve">
<value>強さY</value>
</data>
<data name="Speed" xml:space="preserve">
<value>スピード</value>
</data>
</root>
12 changes: 12 additions & 0 deletions src/Beutl.Language/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1330,4 +1330,16 @@ and b-editor maintains the download URL.</value>
<data name="Cut_Description" xml:space="preserve">
<value>Cut the selected item.</value>
</data>
<data name="ShakeEffect" xml:space="preserve">
<value>Shake</value>
</data>
<data name="StrengthX" xml:space="preserve">
<value>Strength X</value>
</data>
<data name="StrengthY" xml:space="preserve">
<value>Strength Y</value>
</data>
<data name="Speed" xml:space="preserve">
<value>Speed</value>
</data>
</root>
2 changes: 2 additions & 0 deletions src/Beutl.Operators/LibraryRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ public static void RegisterAll()

.AddFilterEffect<ColorShift>(Strings.ColorShift)

.AddFilterEffect<ShakeEffect>(Strings.ShakeEffect)

.AddGroup("OpenCV", gg => gg
.AddFilterEffect<Graphics.Effects.OpenCv.Blur>("CvBlur")
.AddFilterEffect<Graphics.Effects.OpenCv.GaussianBlur>("CvGaussianBlur")
Expand Down

0 comments on commit 7921389

Please sign in to comment.