From 08470798b2dbfe1becb8bc336073cb9c5cb4fec1 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Tue, 30 Aug 2016 18:47:41 +1000 Subject: [PATCH] Start work on optimising /imgprint, start by creating faster pixel getter class. --- Drawing/Image/PixelGetter.cs | 95 ++++++++++++++++++++++++++++++++++++ MCGalaxy_.csproj | 1 + 2 files changed, 96 insertions(+) create mode 100644 Drawing/Image/PixelGetter.cs diff --git a/Drawing/Image/PixelGetter.cs b/Drawing/Image/PixelGetter.cs new file mode 100644 index 000000000..1435997bf --- /dev/null +++ b/Drawing/Image/PixelGetter.cs @@ -0,0 +1,95 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Drawing; +using System.Drawing.Imaging; + +namespace MCGalaxy.Drawing { + + public sealed class PixelGetter : IDisposable { + + Bitmap bmp; + BitmapData data; + public PixelGetter(Bitmap bmp) { + this.bmp = bmp; + } + + public void Init() { + bool fastPath = bmp.PixelFormat == PixelFormat.Format32bppRgb + || bmp.PixelFormat == PixelFormat.Format32bppArgb; + if (!fastPath) return; + // We can only use the fast path for 32bpp bitmaps + + Rectangle r = new Rectangle(0, 0, bmp.Width, bmp.Height); + data = bmp.LockBits(r, ImageLockMode.ReadOnly, bmp.PixelFormat); + } + + public void Iterate(Action callback) { + if (data == null) IterateSlow(callback); + else IterateFast(callback); + } + + unsafe void IterateFast(Action callback) { + Pixel pixel; + int width = bmp.Width, height = bmp.Height; + byte* scan0 = (byte*)data.Scan0; + + for (int y = 0; y < height; y++) { + pixel.Y = (ushort)y; + int* row = (int*)(scan0 + y * data.Stride); + for (int x = 0; x < width; x++) { + pixel.X = (ushort)x; + int argb = row[x]; + + pixel.R = (byte)(argb >> 16); + pixel.G = (byte)(argb >> 8); + pixel.B = (byte)(argb >> 8); + callback(pixel); + } + } + } + + void IterateSlow(Action callback) { + Pixel pixel; + int width = bmp.Width, height = bmp.Height; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + { + pixel.X = (ushort)x; pixel.Y = (ushort)y; + Color col = bmp.GetPixel(x, y); + int argb = col.ToArgb(); // R/G/B properties incur overhead + + pixel.R = (byte)(argb >> 16); + pixel.G = (byte)(argb >> 8); + pixel.B = (byte)(argb >> 8); + callback(pixel); + } + } + + public void Dispose() { + if (data != null) bmp.UnlockBits(data); + data = null; + bmp = null; + } + } + + public struct Pixel { + public ushort X, Y; + public byte R, G, B; + } +} diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index d0e89d379..f1bf5dce0 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -453,6 +453,7 @@ +