-
Notifications
You must be signed in to change notification settings - Fork 0
/
ScreenBleedHole.cs
77 lines (66 loc) · 3.35 KB
/
ScreenBleedHole.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using WindowsAPI;
using System.Drawing;
using System.Drawing.Imaging;
using System;
using System.Threading.Tasks;
namespace Gotchya
{
/// <summary>
/// Performs an effect that makes the desktop appear that it is bleeding from a hole.
/// </summary>
public static class ScreenBleedHole
{
public static void Run(int frames) {
Bitmap screenshot = Desktop.Screenshot();
Bitmap canvas = Desktop.Screenshot();
Mask mask = new Mask(screenshot);
unsafe {
BitmapData screenshotData = screenshot.LockBits(new Rectangle(0, 0, screenshot.Width, screenshot.Height), ImageLockMode.ReadWrite, screenshot.PixelFormat);
int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(screenshot.PixelFormat) / 8;
int heightInPixels = screenshotData.Height;
int widthInBytes = screenshotData.Width * bytesPerPixel;
byte* ptrFirstPixelScreenshot = (byte*)screenshotData.Scan0;
int lastBlue = 255;
int lastGreen = 255;
int lastRed = 255;
int h2 = heightInPixels / 2;
int w2 = widthInBytes / bytesPerPixel / 2;
for (int time = 1; time < frames; time++) {
float scale = time * 10000.0f;
BitmapData canvasData = canvas.LockBits(new Rectangle(0, 0, canvas.Width, canvas.Height), ImageLockMode.ReadWrite, canvas.PixelFormat);
byte* ptrFirstPixelCanvas = (byte*)canvasData.Scan0;
Parallel.For(0, heightInPixels, (y) => {
int yy = y - h2;
byte* currentLineScreenshot = ptrFirstPixelScreenshot + (y * screenshotData.Stride);
byte* currentLineCanvas = ptrFirstPixelCanvas + (y * canvasData.Stride);
for (int xBits = 0; xBits < widthInBytes; xBits = xBits + bytesPerPixel) {
int xx = xBits / bytesPerPixel - w2;
float factor = exp(-(xx * xx / scale) - (yy * yy / scale));
currentLineCanvas[xBits] = (byte)(currentLineScreenshot[xBits] - (int)(lastBlue * factor));
currentLineCanvas[xBits + 1] = (byte)(currentLineScreenshot[xBits + 1] - (int)(lastGreen * factor));
currentLineCanvas[xBits + 2] = (byte)(currentLineScreenshot[xBits + 2] - (int)(lastRed * factor));
lastBlue = currentLineScreenshot[xBits];
lastGreen = currentLineScreenshot[xBits + 1];
lastRed = currentLineScreenshot[xBits + 2];
}
});
canvas.UnlockBits(canvasData);
mask.Picture.Image = canvas;
mask.Picture.Update();
}
}
mask.Close();
Mouse.Move(15, Desktop.GetWidth() - 15);
}
//Math.Exp() approximate
private static float exp(float x) {
x = 1.0f + x / 256.0f;
x *= x; x *= x; x *= x; x *= x;
x *= x; x *= x; x *= x; x *= x;
return x;
}
private static int Flattern(int oldColor, int newColor, double factor) {
return newColor - (int)(oldColor * factor);
}
}
}