Viewing is open to everyone. Downloading and starring need a GitHub sign-in. Sign in with GitHub

CKeyWpf.cs

v0.1.0-build.85 Latest Commit ede38f5

Size
3.8 KB
Lines
78
Language
csharp
SHA-256
042370e09992…
View on GitHub

Sign in with GitHub to download. Each download is recorded with your GitHub username.

1using System;
2using System.Windows;
3using System.Windows.Media;
4using System.Windows.Media.Imaging;
5
6namespace OpenCKey.Wpf
7{
8 /// <summary>WPF interop for CKey pixels and scanning.</summary>
9 public static class CKeyWpf
10 {
11 /// <summary>
12 /// Copies an RGBA image into a new <see cref="WriteableBitmap"/>
13 /// (<see cref="PixelFormats.Bgra32"/>, straight alpha, like the source).
14 /// Use it as an <c>Image.Source</c>; transparent symbols composite over the host's background.
15 /// </summary>
16 public static WriteableBitmap ToWriteableBitmap(this CKeyImage image, double dpi = 96)
17 {
18 if (image == null) throw new ArgumentNullException(nameof(image));
19 var bitmap = new WriteableBitmap(image.Width, image.Height, dpi, dpi, PixelFormats.Bgra32, null);
20 CopyTo(image, bitmap);
21 return bitmap;
22 }
23
24 /// <summary>Renders a symbol straight into a new <see cref="WriteableBitmap"/>.</summary>
25 public static WriteableBitmap ToWriteableBitmap(this CKeySymbol symbol, int size = 512,
26 RasterPolicy policy = RasterPolicy.Coverage,
27 bool transparent = false, CKeyStyle? style = null, double dpi = 96)
28 {
29 if (symbol == null) throw new ArgumentNullException(nameof(symbol));
30 return symbol.RenderRgba(size, policy, transparent, style).ToWriteableBitmap(dpi);
31 }
32
33 /// <summary>
34 /// Writes an RGBA image into an existing Bgra32 bitmap of the same size
35 /// (reuse one bitmap when re-rendering). Call on the bitmap's dispatcher thread.
36 /// </summary>
37 public static void CopyTo(this CKeyImage image, WriteableBitmap target)
38 {
39 if (image == null) throw new ArgumentNullException(nameof(image));
40 if (target == null) throw new ArgumentNullException(nameof(target));
41 if (target.PixelWidth != image.Width || target.PixelHeight != image.Height || target.Format != PixelFormats.Bgra32)
42 throw new ArgumentException("The target must be a Bgra32 bitmap of the image's size.", nameof(target));
43 byte[] rgba = image.Rgba;
44 var bgra = new byte[rgba.Length];
45 for (int i = 0; i < rgba.Length; i += 4)
46 {
47 bgra[i] = rgba[i + 2];
48 bgra[i + 1] = rgba[i + 1];
49 bgra[i + 2] = rgba[i];
50 bgra[i + 3] = rgba[i + 3];
51 }
52 target.WritePixels(new Int32Rect(0, 0, image.Width, image.Height), bgra, image.Width * 4, 0);
53 }
54
55 /// <summary>
56 /// Converts any <see cref="BitmapSource"/> (camera frame, screenshot,
57 /// loaded image) to 8-bit gray and scans it with <see cref="CKeyDecoder"/>.
58 /// </summary>
59 public static CKeyResult? Decode(BitmapSource frame)
60 {
61 byte[] gray = ToGray8(frame, out int width, out int height, out int stride);
62 return CKeyDecoder.Decode(gray, width, height, stride);
63 }
64
65 /// <summary>Converts a bitmap to Gray8 pixels for <see cref="CKeyDecoder"/> or <see cref="CKeyScanSession"/>.</summary>
66 public static byte[] ToGray8(BitmapSource frame, out int width, out int height, out int stride)
67 {
68 if (frame == null) throw new ArgumentNullException(nameof(frame));
69 BitmapSource gray = frame.Format == PixelFormats.Gray8 ? frame : new FormatConvertedBitmap(frame, PixelFormats.Gray8, null, 0);
70 width = gray.PixelWidth;
71 height = gray.PixelHeight;
72 stride = (width + 3) & ~3;
73 var pixels = new byte[stride * height];
74 gray.CopyPixels(pixels, stride, 0);
75 return pixels;
76 }
77 }
78}