Optimized the ScaleX code, now working on the blur [skip ci]

This commit is contained in:
Robin 2019-05-21 13:00:43 +02:00
commit 803ddf3b24
No known key found for this signature in database
GPG key ID: CBBB6557491B1140
6 changed files with 345 additions and 354 deletions

View file

@ -18,7 +18,6 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Threading.Tasks;
using Greenshot.Gfx.Structs;
namespace Greenshot.Gfx
@ -89,61 +88,61 @@ namespace Greenshot.Gfx
{
var halfRange = range / 2;
Parallel.For(0, unmanagedBitmap.Height, y =>
for(var y = 0; y <unmanagedBitmap.Height; y++)
{
unsafe {
var rgb32 = unmanagedBitmap[y];
Span<Bgr32> averages = stackalloc Bgr32[range];
var r = 0;
var g = 0;
var b = 0;
var hits = halfRange;
for (var x = 0; x < halfRange; x++)
{
ref Bgr32 color = ref rgb32[x];
var rgb32 = unmanagedBitmap[y];
Span<Bgr32> averages = stackalloc Bgr32[range];
var r = 0;
var g = 0;
var b = 0;
var hits = halfRange;
for (var x = 0; x < halfRange; x++)
{
ref var color = ref rgb32[x];
r += color.R;
g += color.G;
b += color.B;
}
for (var x = 0; x < unmanagedBitmap.Width; x++)
{
var leftSide = x - halfRange - 1;
if (leftSide >= 0)
{
// Get value at the left side of range
ref var color = ref rgb32[leftSide];
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var rightSide = x + halfRange;
if (rightSide < unmanagedBitmap.Width)
{
ref var color = ref rgb32[rightSide];
r += color.R;
g += color.G;
b += color.B;
hits++;
}
for (var x = 0; x < unmanagedBitmap.Width; x++)
ref var average = ref averages[x % range];
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (leftSide < 0)
{
var leftSide = x - halfRange - 1;
if (leftSide >= 0)
{
// Get value at the left side of range
ref Bgr32 color = ref rgb32[leftSide];
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var rightSide = x + halfRange;
if (rightSide < unmanagedBitmap.Width)
{
ref Bgr32 color = ref rgb32[rightSide];
r += color.R;
g += color.G;
b += color.B;
hits++;
}
ref Bgr32 average = ref averages[x % range];
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (leftSide >= 0)
{
// Now we can write the value from the calculated avarages
var readLocation = (leftSide % range);
rgb32[leftSide] = averages[readLocation];
}
continue;
}
// Now we can write the value from the calculated averages
var readLocation = (leftSide % range);
rgb32[leftSide] = averages[readLocation];
}
});
}
}
/// <summary>
@ -154,61 +153,61 @@ namespace Greenshot.Gfx
private static void BoxBlurVertical(UnmanagedBitmap<Bgr32> unmanagedBitmap, int range)
{
var halfRange = range / 2;
Parallel.For(0, unmanagedBitmap.Width, x =>
for(var x = 0; x <unmanagedBitmap.Width; x++)
{
unsafe {
var rgb32 = unmanagedBitmap.Span;
Span<Bgr32> averages = stackalloc Bgr32[range];
var hits = 0;
var r = 0;
var g = 0;
var b = 0;
for (var y = 0; y < halfRange; y++)
var rgb32 = unmanagedBitmap.Span;
Span<Bgr32> averages = stackalloc Bgr32[range];
var hits = 0;
var r = 0;
var g = 0;
var b = 0;
for (var y = 0; y < halfRange; y++)
{
ref var color = ref rgb32[(y * unmanagedBitmap.Width) + x];
r += color.R;
g += color.G;
b += color.B;
hits++;
}
for (var y = 0; y < unmanagedBitmap.Height; y++)
{
var topSide = y - halfRange - 1;
if (topSide >= 0)
{
ref Bgr32 color = ref rgb32[(y * unmanagedBitmap.Width) + x];
// Get value at the top side of range
ref var color = ref rgb32[x + (topSide * unmanagedBitmap.Width)];
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var bottomSide = y + halfRange;
if (bottomSide < unmanagedBitmap.Height)
{
ref var color = ref rgb32[x + (bottomSide * unmanagedBitmap.Width)];
r += color.R;
g += color.G;
b += color.B;
hits++;
}
for (var y = 0; y < unmanagedBitmap.Height; y++)
ref var average = ref averages[y % range];
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (topSide < 0)
{
var topSide = y - halfRange - 1;
if (topSide >= 0)
{
// Get value at the top side of range
ref Bgr32 color = ref rgb32[x + (topSide * unmanagedBitmap.Width)];
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var bottomSide = y + halfRange;
if (bottomSide < unmanagedBitmap.Height)
{
ref Bgr32 color = ref rgb32[x + (bottomSide * unmanagedBitmap.Width)];
r += color.R;
g += color.G;
b += color.B;
hits++;
}
ref Bgr32 average = ref averages[y % range];
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (topSide >= 0)
{
// Write the value from the calculated avarages
var readLocation = topSide % range;
rgb32[x + (topSide * unmanagedBitmap.Width)] = averages[readLocation];
}
continue;
}
// Write the value from the calculated averages
var readLocation = topSide % range;
rgb32[x + (topSide * unmanagedBitmap.Width)] = averages[readLocation];
}
});
}
}
/// <summary>
@ -220,65 +219,65 @@ namespace Greenshot.Gfx
{
var halfRange = range / 2;
Parallel.For(0, unmanagedBitmap.Height, y =>
for(var y = 0; y <unmanagedBitmap.Height; y++)
{
unsafe {
var argb32 = unmanagedBitmap[y];
Span<Bgra32> averages = stackalloc Bgra32[range];
var a = 0;
var r = 0;
var g = 0;
var b = 0;
var hits = halfRange;
for (var x = 0; x < halfRange; x++)
var argb32 = unmanagedBitmap[y];
Span<Bgra32> averages = stackalloc Bgra32[range];
var a = 0;
var r = 0;
var g = 0;
var b = 0;
var hits = halfRange;
for (var x = 0; x < halfRange; x++)
{
ref var color = ref argb32[x];
a += color.A;
r += color.R;
g += color.G;
b += color.B;
}
for (var x = 0; x < unmanagedBitmap.Width; x++)
{
var leftSide = x - halfRange - 1;
if (leftSide >= 0)
{
ref Bgra32 color = ref argb32[x];
// Get value at the left side of range
ref var color = ref argb32[leftSide];
a -= color.A;
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var rightSide = x + halfRange;
if (rightSide < unmanagedBitmap.Width)
{
ref var color = ref argb32[rightSide];
a += color.A;
r += color.R;
g += color.G;
b += color.B;
hits++;
}
for (var x = 0; x < unmanagedBitmap.Width; x++)
ref var average = ref averages[x % range];
average.A = (byte)(a / hits);
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (leftSide < 0)
{
var leftSide = x - halfRange - 1;
if (leftSide >= 0)
{
// Get value at the left side of range
ref Bgra32 color = ref argb32[leftSide];
a -= color.A;
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var rightSide = x + halfRange;
if (rightSide < unmanagedBitmap.Width)
{
ref Bgra32 color = ref argb32[rightSide];
a += color.A;
r += color.R;
g += color.G;
b += color.B;
hits++;
}
ref Bgra32 average = ref averages[x % range];
average.A = (byte)(a / hits);
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (leftSide >= 0)
{
// Now we can write the value from the calculated avarages
var readLocation = leftSide % range;
argb32[leftSide] = averages[readLocation];
}
continue;
}
// Now we can write the value from the calculated averages
var readLocation = leftSide % range;
argb32[leftSide] = averages[readLocation];
}
});
}
}
/// <summary>
@ -289,67 +288,66 @@ namespace Greenshot.Gfx
private static void BoxBlurVertical(UnmanagedBitmap<Bgra32> unmanagedBitmap, int range)
{
var halfRange = range / 2;
Parallel.For(0, unmanagedBitmap.Width, x =>
for(var x = 0; x <unmanagedBitmap.Width; x++)
{
unsafe
var argb32 = unmanagedBitmap.Span;
Span<Bgra32> averages = stackalloc Bgra32[range];
var hits = 0;
var a = 0;
var r = 0;
var g = 0;
var b = 0;
for (var y = 0; y < halfRange; y++)
{
var argb32 = unmanagedBitmap.Span;
Span<Bgra32> averages = stackalloc Bgra32[range];
var hits = 0;
var a = 0;
var r = 0;
var g = 0;
var b = 0;
for (var y = 0; y < halfRange; y++)
ref var color = ref argb32[x + (y * unmanagedBitmap.Width)];
a += color.A;
r += color.R;
g += color.G;
b += color.B;
hits++;
}
for (var y = 0; y < unmanagedBitmap.Height; y++)
{
var topSide = y - halfRange - 1;
if (topSide >= 0)
{
ref Bgra32 color = ref argb32[x + (y * unmanagedBitmap.Width)];
// Get value at the top side of range
ref var color = ref argb32[x + (topSide * unmanagedBitmap.Width)];
a -= color.A;
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var bottomSide = y + halfRange;
if (bottomSide < unmanagedBitmap.Height)
{
ref var color = ref argb32[x + (bottomSide * unmanagedBitmap.Width)];
a += color.A;
r += color.R;
g += color.G;
b += color.B;
hits++;
}
for (var y = 0; y < unmanagedBitmap.Height; y++)
ref var average = ref averages[(y % range)];
average.A = (byte)(a / hits);
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (topSide < 0)
{
var topSide = y - halfRange - 1;
if (topSide >= 0)
{
// Get value at the top side of range
ref Bgra32 color = ref argb32[x + (topSide * unmanagedBitmap.Width)];
a -= color.A;
r -= color.R;
g -= color.G;
b -= color.B;
hits--;
}
var bottomSide = y + halfRange;
if (bottomSide < unmanagedBitmap.Height)
{
ref Bgra32 color = ref argb32[x + (bottomSide * unmanagedBitmap.Width)];
a += color.A;
r += color.R;
g += color.G;
b += color.B;
hits++;
}
ref Bgra32 average = ref averages[(y % range)];
average.A = (byte)(a / hits);
average.R = (byte)(r / hits);
average.G = (byte)(g / hits);
average.B = (byte)(b / hits);
if (topSide >= 0)
{
// Write the value from the calculated avarages
var readLocation = (topSide % range);
argb32[x + (topSide * unmanagedBitmap.Width)] = averages[readLocation];
}
continue;
}
// Write the value from the calculated averages
var readLocation = (topSide % range);
argb32[x + (topSide * unmanagedBitmap.Width)] = averages[readLocation];
}
});
}
}
}
}

View file

@ -18,6 +18,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Greenshot.Gfx
@ -44,45 +45,44 @@ namespace Greenshot.Gfx
var sourceWidth = sourceBitmap.Width;
var destinationWidth = destinationBitmap.Width;
ReadOnlySpan<uint> sourceSpan = MemoryMarshal.Cast<TPixelLayout, uint>(sourceBitmap.Span);
var destinationSpan = MemoryMarshal.Cast<TPixelLayout, uint>(destinationBitmap.Span);
ref var destinationPointer = ref Unsafe.As<TPixelLayout, uint>(ref destinationBitmap.Span.GetPinnableReference());
ref var sourcePointer = ref Unsafe.As<TPixelLayout, uint>(ref sourceBitmap.Span.GetPinnableReference());
for (var y = 0; y < sourceBitmap.Height; y++)
{
var sourceYOffset = y * sourceWidth;
var destinationYOffset = (y << 1) * destinationWidth;
for (var x = 0; x < sourceWidth; x++)
{
var sourceOffset = sourceYOffset + x;
ref readonly uint colorE = ref sourceSpan[sourceOffset];
ref var colorE = ref Unsafe.Add(ref sourcePointer, sourceYOffset + x);
ref readonly uint colorB = ref colorE;
ref readonly var colorB = ref colorE;
if (y != 0)
{
colorB = ref sourceSpan[sourceOffset - sourceWidth];
colorB = ref Unsafe.Subtract(ref colorE, sourceWidth);
}
ref readonly uint colorH = ref colorE;
ref readonly var colorH = ref colorE;
if (y != sourceBitmap.Height - 1)
{
colorH = ref sourceSpan[sourceOffset + sourceWidth];
colorH = ref Unsafe.Add(ref colorE, sourceWidth);
}
ref readonly uint colorD = ref colorE;
ref readonly var colorD = ref colorE;
if (x > 0)
{
colorD = ref sourceSpan[sourceOffset - 1];
colorD = ref Unsafe.Subtract(ref colorE, 1);
}
ref readonly uint colorF = ref colorE;
ref readonly var colorF = ref colorE;
if (x < sourceBitmap.Width - 1)
{
colorF = ref sourceSpan[sourceOffset + 1];
colorF = ref Unsafe.Add(ref colorE, 1);
}
ref readonly uint colorE0 = ref colorE;
ref readonly uint colorE1 = ref colorE;
ref readonly uint colorE2 = ref colorE;
ref readonly uint colorE3 = ref colorE;
ref readonly var colorE0 = ref colorE;
ref readonly var colorE1 = ref colorE;
ref readonly var colorE2 = ref colorE;
ref readonly var colorE3 = ref colorE;
if (colorB != colorH && colorD != colorF)
{
if (colorH == colorF)
@ -102,17 +102,19 @@ namespace Greenshot.Gfx
colorE0 = ref colorD;
}
}
var destinationOffset = (x << 1) + destinationYOffset;
destinationSpan[destinationOffset + 1 + destinationWidth] = colorE3;
destinationSpan[destinationOffset + destinationWidth] = colorE2;
destinationSpan[destinationOffset + 1] = colorE1;
destinationSpan[destinationOffset] = colorE0;
ref var destColorE0 = ref Unsafe.Add(ref destinationPointer, (x << 1) + destinationYOffset);
destColorE0 = colorE0;
Unsafe.Add(ref destColorE0, 1 + destinationWidth) = colorE3;
Unsafe.Add(ref destColorE0, destinationWidth) = colorE2;
Unsafe.Add(ref destColorE0, 1) = colorE1;
}
}
return destinationBitmap;
}
/// <summary>
/// Use "Scale3x" algorithm to produce bitmap from the original.
/// Every pixel from input texture produces 6 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
@ -128,133 +130,129 @@ namespace Greenshot.Gfx
// Create destination bitmap, where the scaled image is written to
var destinationBitmap = new UnmanagedBitmap<TPixelLayout>(sourceBitmap.Width * 3, sourceBitmap.Height * 3);
ReadOnlySpan<uint> sourceSpan = MemoryMarshal.Cast<TPixelLayout, uint>(sourceBitmap.Span);
var destinationSpan = MemoryMarshal.Cast<TPixelLayout, uint>(destinationBitmap.Span);
var sourceWidth = sourceBitmap.Width;
var destinationWidth = destinationBitmap.Width;
unchecked
ref var destinationPointer = ref Unsafe.As<TPixelLayout, uint>(ref destinationBitmap.Span.GetPinnableReference());
ref var sourcePointer = ref Unsafe.As<TPixelLayout, uint>(ref sourceBitmap.Span.GetPinnableReference());
for (var y = 0; y < sourceBitmap.Height; y++)
{
for (var y = 0; y < sourceBitmap.Height; y++)
var sourceYOffset = y * sourceWidth;
var destinationYOffset = y * 3 * destinationWidth;
for (var x = 0; x < sourceWidth; x++)
{
var sourceYOffset = y * sourceWidth;
var destinationYOffset = y * 3 * destinationWidth;
for (var x = 0; x < sourceWidth; x++)
ref var colorE = ref Unsafe.Add(ref sourcePointer, sourceYOffset + x);
ref readonly var colorA = ref colorE;
ref readonly var colorB = ref colorE;
ref readonly var colorC = ref colorE;
ref readonly var colorD = ref colorE;
ref readonly var colorF = ref colorE;
ref readonly var colorG = ref colorE;
ref readonly var colorH = ref colorE;
ref readonly var colorI = ref colorE;
if (y != 0 && x != 0)
{
var sourceOffset = sourceYOffset + x;
ref readonly uint colorE = ref sourceSpan[sourceOffset];
ref readonly uint colorA = ref colorE;
ref readonly uint colorB = ref colorE;
ref readonly uint colorC = ref colorE;
ref readonly uint colorD = ref colorE;
ref readonly uint colorF = ref colorE;
ref readonly uint colorG = ref colorE;
ref readonly uint colorH = ref colorE;
ref readonly uint colorI = ref colorE;
if (y != 0 && x != 0)
{
colorA = ref sourceSpan[sourceOffset - 1 - sourceWidth];
}
if (y != 0)
{
colorB = ref sourceSpan[sourceOffset - sourceWidth];
}
if (x < sourceWidth - 1 && y != 0)
{
colorC = ref sourceSpan[sourceOffset + 1 - sourceWidth];
}
if (x != 0)
{
colorD = ref sourceSpan[sourceOffset - 1];
}
if (x < sourceWidth - 1)
{
colorF = ref sourceSpan[sourceOffset + 1];
}
if (x != 0 && y < sourceBitmap.Height - 1)
{
colorG = ref sourceSpan[sourceOffset - 1 + sourceWidth];
}
if (y < sourceBitmap.Height - 1)
{
colorH = ref sourceSpan[sourceOffset + sourceWidth];
}
if (x < sourceWidth - 1 && y < sourceBitmap.Height - 1)
{
colorI = ref sourceSpan[sourceOffset + 1 + sourceWidth];
}
ref readonly uint colorE0 = ref colorE;
ref readonly uint colorE1 = ref colorE;
ref readonly uint colorE2 = ref colorE;
ref readonly uint colorE3 = ref colorE;
ref readonly uint colorE4 = ref colorE;
ref readonly uint colorE5 = ref colorE;
ref readonly uint colorE6 = ref colorE;
ref readonly uint colorE7 = ref colorE;
ref readonly uint colorE8 = ref colorE;
if (colorB != colorH && colorD != colorF)
{
if (colorH == colorF)
{
colorE8 = ref colorF;
}
if (colorD == colorH && colorE != colorI || colorH == colorF && colorE != colorG)
{
colorE7 = ref colorH;
}
if (colorD == colorH)
{
colorE6 = ref colorD;
}
if (colorB == colorF && colorE != colorI || colorH == colorF && colorE != colorC)
{
colorE5 = ref colorF;
}
if (colorD == colorB && colorE != colorG || colorD == colorH && colorE != colorA)
{
colorE3 = ref colorD;
}
if (colorB == colorF)
{
colorE2 = ref colorF;
}
if (colorD == colorB && colorE != colorC || colorB == colorF && colorE != colorA)
{
colorE1 = ref colorB;
}
if (colorD == colorB)
{
colorE0 = ref colorD;
}
}
var destinationOffset = x * 3 + destinationYOffset;
destinationSpan[destinationOffset] = colorE0;
destinationSpan[destinationOffset + 1] = colorE1;
destinationSpan[destinationOffset + 2] = colorE2;
destinationOffset += destinationWidth;
destinationSpan[destinationOffset] = colorE3;
destinationSpan[destinationOffset + 1] = colorE4;
destinationSpan[destinationOffset + 2] = colorE5;
destinationOffset += destinationWidth;
destinationSpan[destinationOffset] = colorE6;
destinationSpan[destinationOffset + 1] = colorE7;
destinationSpan[destinationOffset + 2] = colorE8;
colorA = ref Unsafe.Subtract(ref colorE, 1 + sourceWidth);
}
if (y != 0)
{
colorB = ref Unsafe.Subtract(ref colorE, sourceWidth);
}
if (x < sourceWidth - 1 && y != 0)
{
colorC = ref Unsafe.Subtract(ref colorE, sourceWidth - 1);
}
if (x != 0)
{
colorD = ref Unsafe.Subtract(ref colorE, 1);
}
if (x < sourceWidth - 1)
{
colorF = ref Unsafe.Add(ref colorE, 1);
}
if (x != 0 && y < sourceBitmap.Height - 1)
{
colorG = ref Unsafe.Add(ref colorE, sourceWidth - 1);
}
if (y < sourceBitmap.Height - 1)
{
colorH = ref Unsafe.Add(ref colorE, sourceWidth);
}
if (x < sourceWidth - 1 && y < sourceBitmap.Height - 1)
{
colorI = ref Unsafe.Add(ref colorE, sourceWidth + 1);
}
ref readonly var colorE0 = ref colorE;
ref readonly var colorE1 = ref colorE;
ref readonly var colorE2 = ref colorE;
ref readonly var colorE3 = ref colorE;
ref readonly var colorE4 = ref colorE;
ref readonly var colorE5 = ref colorE;
ref readonly var colorE6 = ref colorE;
ref readonly var colorE7 = ref colorE;
ref readonly var colorE8 = ref colorE;
if (colorB != colorH && colorD != colorF)
{
if (colorH == colorF)
{
colorE8 = ref colorF;
}
if (colorD == colorH && colorE != colorI || colorH == colorF && colorE != colorG)
{
colorE7 = ref colorH;
}
if (colorD == colorH)
{
colorE6 = ref colorD;
}
if (colorB == colorF && colorE != colorI || colorH == colorF && colorE != colorC)
{
colorE5 = ref colorF;
}
if (colorD == colorB && colorE != colorG || colorD == colorH && colorE != colorA)
{
colorE3 = ref colorD;
}
if (colorB == colorF)
{
colorE2 = ref colorF;
}
if (colorD == colorB && colorE != colorC || colorB == colorF && colorE != colorA)
{
colorE1 = ref colorB;
}
if (colorD == colorB)
{
colorE0 = ref colorD;
}
}
var destinationOffset = x * 3 + destinationYOffset;
Unsafe.Add(ref destinationPointer, destinationOffset) = colorE0;
Unsafe.Add(ref destinationPointer, destinationOffset + 1) = colorE1;
Unsafe.Add(ref destinationPointer, destinationOffset + 2) = colorE2;
destinationOffset += destinationWidth;
Unsafe.Add(ref destinationPointer, destinationOffset) = colorE3;
Unsafe.Add(ref destinationPointer, destinationOffset + 1) = colorE4;
Unsafe.Add(ref destinationPointer, destinationOffset + 2) = colorE5;
destinationOffset += destinationWidth;
Unsafe.Add(ref destinationPointer, destinationOffset) = colorE6;
Unsafe.Add(ref destinationPointer, destinationOffset + 1) = colorE7;
Unsafe.Add(ref destinationPointer, destinationOffset + 2) = colorE8;
}
}

View file

@ -21,8 +21,7 @@ namespace Greenshot.PerformanceTests
{
_unmanagedTestBitmap = new UnmanagedBitmap<Bgr32>(400, 400);
_unmanagedTestBitmap.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255, Unused = 0});
using (var bitmap = _unmanagedTestBitmap.NativeBitmap)
using (var graphics = Graphics.FromImage(bitmap))
using (var graphics = Graphics.FromImage(_unmanagedTestBitmap.NativeBitmap))
using (var pen = new SolidBrush(Color.Blue))
{
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
@ -57,7 +56,7 @@ namespace Greenshot.PerformanceTests
}
}
//[Benchmark]
[Benchmark]
public void Blur_FastBitmap()
{
using (var bitmap = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format32bppRgb, Color.White))
@ -71,14 +70,13 @@ namespace Greenshot.PerformanceTests
}
}
//[Benchmark]
[Benchmark]
public void Blur_UnmanagedBitmap()
{
using (var unmanagedBitmap = new UnmanagedBitmap<Bgr32>(400, 400))
{
unmanagedBitmap.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255 });
using (var bitmap = unmanagedBitmap.NativeBitmap)
using (var graphics = Graphics.FromImage(bitmap))
using (var graphics = Graphics.FromImage(unmanagedBitmap.NativeBitmap))
using (var pen = new SolidBrush(Color.Blue))
{
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
@ -89,7 +87,7 @@ namespace Greenshot.PerformanceTests
}
//[Benchmark]
[Benchmark]
public void Blur_Old()
{
using (var bitmap = BitmapFactory.CreateEmpty(400, 400, PixelFormat.Format32bppRgb, Color.White))
@ -121,19 +119,19 @@ namespace Greenshot.PerformanceTests
_unmanagedTestBitmap.Scale2XReference().Dispose();
}
[Benchmark]
//[Benchmark]
public void Scale3x_FastBitmap()
{
ScaleX.Scale3X(_unmanagedTestBitmap).Dispose();
}
[Benchmark]
//[Benchmark]
public void Scale3x_Unmanaged()
{
_unmanagedTestBitmap.Scale3X().Dispose();
}
[Benchmark]
//[Benchmark]
public void Scale3x_Unmanaged_Reference()
{
_unmanagedTestBitmap.Scale3XReference().Dispose();

View file

@ -30,8 +30,8 @@ namespace Greenshot.PerformanceTests
// ReSharper disable once UnusedParameter.Local
private static void Main(string[] args)
{
//BenchmarkRunner.Run<GfxPerformance>();
BenchmarkRunner.Run<CapturePerformance>();
BenchmarkRunner.Run<GfxPerformance>();
//BenchmarkRunner.Run<CapturePerformance>();
Console.ReadLine();
}
}

View file

@ -70,19 +70,18 @@ namespace Greenshot.Tests
using (var pen = new SolidBrush(Color.Blue))
{
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
BoxBlurOld.ApplyOldBoxBlur(bitmapOld, 10);
}
BoxBlurOld.ApplyOldBoxBlur(bitmapOld, 10);
bitmapOld.NativeBitmap.Save(@"old.png", ImageFormat.Png);
bitmapNew.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255 });
using (var bitmap = bitmapNew.NativeBitmap)
using (var graphics = Graphics.FromImage(bitmap))
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
using (var pen = new SolidBrush(Color.Blue))
{
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
bitmapNew.ApplyBoxBlur(10);
bitmap.Save(@"new.png", ImageFormat.Png);
}
bitmapNew.ApplyBoxBlur(10);
bitmapNew.NativeBitmap.Save(@"new.png", ImageFormat.Png);
Assert.True(bitmapOld.IsEqualTo(bitmapNew), "New blur doesn't compare to old.");
}

View file

@ -37,7 +37,7 @@ namespace Greenshot.Tests
{
LogSettings.RegisterDefaultLogger<XUnitLogger>(LogLevels.Verbose, testOutputHelper);
}
[Fact]
public void Test_Scale2X_UnmanagedBitmap()
{
@ -50,8 +50,7 @@ namespace Greenshot.Tests
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
}
bitmapNew.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255, Unused = 0 });
using (var bitmap = bitmapNew.NativeBitmap)
using (var graphics = Graphics.FromImage(bitmap))
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
using (var pen = new SolidBrush(Color.Blue))
{
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
@ -78,13 +77,12 @@ namespace Greenshot.Tests
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
}
bitmapNew.Span.Fill(new Bgr32 { B = 255, G = 255, R = 255, Unused = 0 });
using (var bitmap = bitmapNew.NativeBitmap)
using (var graphics = Graphics.FromImage(bitmap))
using (var graphics = Graphics.FromImage(bitmapNew.NativeBitmap))
using (var pen = new SolidBrush(Color.Blue))
{
graphics.FillRectangle(pen, new Rectangle(30, 30, 340, 340));
using (var scaledUnmanagedBitmap = bitmapNew.Scale3X())
using (var scaledBitmap = ScaleX.Scale2X(bitmapOld))
using (var scaledBitmap = ScaleX.Scale3X(bitmapOld))
{
scaledUnmanagedBitmap.NativeBitmap.Save(@"new3x.png", ImageFormat.Png);
scaledBitmap.NativeBitmap.Save(@"old3x.png", ImageFormat.Png);