|
1 | 1 | using System; |
2 | 2 | using System.Collections.Generic; |
3 | | -using System.Drawing; |
4 | | -using System.Drawing.Imaging; |
5 | 3 | using System.Runtime.InteropServices; |
6 | | -using System.Text; |
7 | 4 | using System.Threading.Tasks; |
| 5 | +using SkiaSharp; |
8 | 6 |
|
9 | 7 | namespace Spectrogram |
10 | 8 | { |
@@ -54,52 +52,48 @@ public ImageMaker() |
54 | 52 |
|
55 | 53 | } |
56 | 54 |
|
57 | | - public Bitmap GetBitmap(List<double[]> ffts) |
| 55 | + public SKBitmap GetBitmap(List<double[]> ffts) |
58 | 56 | { |
59 | 57 | if (ffts.Count == 0) |
60 | 58 | throw new ArgumentException("Not enough data in FFTs to generate an image yet."); |
61 | 59 |
|
62 | | - int Width = IsRotated ? ffts[0].Length : ffts.Count; |
63 | | - int Height = IsRotated ? ffts.Count : ffts[0].Length; |
| 60 | + int width = IsRotated ? ffts[0].Length : ffts.Count; |
| 61 | + int height = IsRotated ? ffts.Count : ffts[0].Length; |
64 | 62 |
|
65 | | - Bitmap bmp = new(Width, Height, PixelFormat.Format8bppIndexed); |
66 | | - Colormap.Apply(bmp); |
| 63 | + var imageInfo = new SKImageInfo(width, height, SKColorType.Gray8); |
| 64 | + var bitmap = new SKBitmap(imageInfo); |
67 | 65 |
|
68 | | - Rectangle lockRect = new(0, 0, Width, Height); |
69 | | - BitmapData bitmapData = bmp.LockBits(lockRect, ImageLockMode.ReadOnly, bmp.PixelFormat); |
70 | | - int stride = bitmapData.Stride; |
71 | | - |
72 | | - byte[] bytes = new byte[bitmapData.Stride * bmp.Height]; |
73 | | - Parallel.For(0, Width, col => |
| 66 | + var pixelBuffer = bitmap.Bytes; |
| 67 | + Parallel.For(0, width, col => |
74 | 68 | { |
75 | 69 | int sourceCol = col; |
76 | 70 | if (IsRoll) |
77 | 71 | { |
78 | | - sourceCol += Width - RollOffset % Width; |
79 | | - if (sourceCol >= Width) |
80 | | - sourceCol -= Width; |
| 72 | + sourceCol += width - RollOffset % width; |
| 73 | + if (sourceCol >= width) |
| 74 | + sourceCol -= width; |
81 | 75 | } |
82 | 76 |
|
83 | | - for (int row = 0; row < Height; row++) |
| 77 | + for (int row = 0; row < height; row++) |
84 | 78 | { |
85 | 79 | double value = IsRotated |
86 | | - ? ffts[Height - row - 1][sourceCol] |
| 80 | + ? ffts[height - row - 1][sourceCol] |
87 | 81 | : ffts[sourceCol][row]; |
88 | 82 |
|
89 | 83 | if (IsDecibel) |
90 | 84 | value = 20 * Math.Log10(value * DecibelScaleFactor + 1); |
91 | 85 |
|
92 | 86 | value *= Intensity; |
93 | 87 | value = Math.Min(value, 255); |
94 | | - int bytePosition = (Height - 1 - row) * stride + col; |
95 | | - bytes[bytePosition] = (byte)value; |
| 88 | + int bytePosition = row * width + col; |
| 89 | + pixelBuffer[bytePosition] = (byte)value; |
96 | 90 | } |
97 | 91 | }); |
98 | 92 |
|
99 | | - Marshal.Copy(bytes, 0, bitmapData.Scan0, bytes.Length); |
100 | | - bmp.UnlockBits(bitmapData); |
101 | | - |
102 | | - return bmp; |
| 93 | + |
| 94 | + var gcHandle = GCHandle.Alloc(pixelBuffer, GCHandleType.Pinned); |
| 95 | + bitmap.InstallPixels(imageInfo, gcHandle.AddrOfPinnedObject(), imageInfo.RowBytes, delegate { gcHandle.Free(); }, null); |
| 96 | + return bitmap; |
103 | 97 | } |
104 | 98 | } |
105 | 99 | } |
0 commit comments