mirror of
https://github.com/greenshot/greenshot
synced 2025-08-22 22:34:27 -07:00
Updated the Scale3x_Unmanaged and added Scale3x_Unmanaged_Reference
This commit is contained in:
parent
969d8f004d
commit
0561394194
2 changed files with 234 additions and 92 deletions
|
@ -32,16 +32,6 @@ namespace Greenshot.Gfx
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class ScaleXUnmanaged
|
public static class ScaleXUnmanaged
|
||||||
{
|
{
|
||||||
private const byte ColorB = 0;
|
|
||||||
private const byte ColorD = 1;
|
|
||||||
private const byte ColorE = 4;
|
|
||||||
private const byte ColorF = 2;
|
|
||||||
private const byte ColorH = 3;
|
|
||||||
private const byte ColorA = 5;
|
|
||||||
private const byte ColorC = 6;
|
|
||||||
private const byte ColorG = 7;
|
|
||||||
private const byte ColorI = 8;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use "Scale2x" algorithm to produce bitmap from the original.
|
/// Use "Scale2x" algorithm to produce bitmap from the original.
|
||||||
/// Every pixel from input texture produces 4 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
|
/// Every pixel from input texture produces 4 output pixels, for more details check out http://scale2x.sourceforge.net/algorithm.html
|
||||||
|
@ -139,6 +129,7 @@ namespace Greenshot.Gfx
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("Only 4 byte unmanaged structs are supported.");
|
throw new NotSupportedException("Only 4 byte unmanaged structs are supported.");
|
||||||
}
|
}
|
||||||
|
// Create destination bitmap, where the scaled image is written to
|
||||||
var destinationBitmap = new UnmanagedBitmap<TPixelLayout>(sourceBitmap.Width * 3, sourceBitmap.Height * 3);
|
var destinationBitmap = new UnmanagedBitmap<TPixelLayout>(sourceBitmap.Width * 3, sourceBitmap.Height * 3);
|
||||||
|
|
||||||
ReadOnlySpan<uint> sourceSpan = MemoryMarshal.Cast<TPixelLayout, uint>(sourceBitmap.Span);
|
ReadOnlySpan<uint> sourceSpan = MemoryMarshal.Cast<TPixelLayout, uint>(sourceBitmap.Span);
|
||||||
|
@ -147,11 +138,8 @@ namespace Greenshot.Gfx
|
||||||
var sourceWidth = sourceBitmap.Width;
|
var sourceWidth = sourceBitmap.Width;
|
||||||
var destinationWidth = destinationBitmap.Width;
|
var destinationWidth = destinationBitmap.Width;
|
||||||
|
|
||||||
unsafe
|
unchecked
|
||||||
{
|
{
|
||||||
var colors = stackalloc uint[9];
|
|
||||||
var colorsE = stackalloc uint[9];
|
|
||||||
|
|
||||||
for (var y = 0; y < sourceBitmap.Height; y++)
|
for (var y = 0; y < sourceBitmap.Height; y++)
|
||||||
{
|
{
|
||||||
var sourceYOffset = y * sourceWidth;
|
var sourceYOffset = y * sourceWidth;
|
||||||
|
@ -159,125 +147,121 @@ namespace Greenshot.Gfx
|
||||||
for (var x = 0; x < sourceWidth; x++)
|
for (var x = 0; x < sourceWidth; x++)
|
||||||
{
|
{
|
||||||
var sourceOffset = sourceYOffset + x;
|
var sourceOffset = sourceYOffset + x;
|
||||||
|
ref readonly uint colorE = ref sourceSpan[sourceOffset];
|
||||||
colors[ColorE] = 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)
|
if (y != 0 && x != 0)
|
||||||
{
|
{
|
||||||
colors[ColorA] = sourceSpan[(sourceOffset - 1) - sourceWidth];
|
colorA = ref sourceSpan[sourceOffset - 1 - sourceWidth];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorA] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y != 0)
|
if (y != 0)
|
||||||
{
|
{
|
||||||
colors[ColorB] = sourceSpan[sourceOffset - sourceWidth];
|
colorB = ref sourceSpan[sourceOffset - sourceWidth];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorB] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x < sourceWidth - 1 && y != 0)
|
if (x < sourceWidth - 1 && y != 0)
|
||||||
{
|
{
|
||||||
colors[ColorC] = sourceSpan[(sourceOffset + 1) - sourceWidth];
|
colorC = ref sourceSpan[sourceOffset + 1 - sourceWidth];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorC] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x != 0)
|
if (x != 0)
|
||||||
{
|
{
|
||||||
colors[ColorD] = sourceSpan[sourceOffset - 1];
|
colorD = ref sourceSpan[sourceOffset - 1];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorD] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x < sourceWidth - 1)
|
if (x < sourceWidth - 1)
|
||||||
{
|
{
|
||||||
colors[ColorF] = sourceSpan[sourceOffset + 1];
|
colorF = ref sourceSpan[sourceOffset + 1];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorF] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x != 0 && y < sourceBitmap.Height - 1)
|
if (x != 0 && y < sourceBitmap.Height - 1)
|
||||||
{
|
{
|
||||||
colors[ColorG] = sourceSpan[(sourceOffset - 1) + sourceWidth];
|
colorG = ref sourceSpan[sourceOffset - 1 + sourceWidth];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorG] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y < sourceBitmap.Height - 1)
|
if (y < sourceBitmap.Height - 1)
|
||||||
{
|
{
|
||||||
colors[ColorH] = sourceSpan[sourceOffset + sourceWidth];
|
colorH = ref sourceSpan[sourceOffset + sourceWidth];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorH] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x < sourceWidth - 1 && y < sourceBitmap.Height - 1)
|
if (x < sourceWidth - 1 && y < sourceBitmap.Height - 1)
|
||||||
{
|
{
|
||||||
colors[ColorI] = sourceSpan[sourceOffset + 1 + sourceWidth];
|
colorI = ref sourceSpan[sourceOffset + 1 + sourceWidth];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colors[ColorI] = colors[ColorE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colors[ColorB] != colors[ColorH] && colors[ColorD] != colors[ColorF])
|
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)
|
||||||
{
|
{
|
||||||
colorsE[8] = colors[ColorH] == colors[ColorF] ? colors[ColorF] : colors[ColorE];
|
if (colorH == colorF)
|
||||||
colorsE[7] = colors[ColorD] == colors[ColorH] && colors[ColorE] != colors[ColorI] || colors[ColorH] == colors[ColorF] && colors[ColorE] != colors[ColorG] ? colors[ColorH] : colors[ColorE];
|
{
|
||||||
colorsE[6] = colors[ColorD] == colors[ColorH] ? colors[ColorD] : colors[ColorE];
|
colorE8 = ref colorF;
|
||||||
colorsE[5] = colors[ColorB] == colors[ColorF] && colors[ColorE] != colors[ColorI] || colors[ColorH] == colors[ColorF] && colors[ColorE] != colors[ColorC] ? colors[ColorF] : colors[ColorE];
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
colorsE[4] = colors[ColorE];
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
colorsE[3] = colors[ColorD] == colors[ColorB] && colors[ColorE] != colors[ColorG] || colors[ColorD] == colors[ColorH] && colors[ColorE] != colors[ColorA] ? colors[ColorD] : colors[ColorE];
|
|
||||||
colorsE[2] = colors[ColorB] == colors[ColorF] ? colors[ColorF] : colors[ColorE];
|
|
||||||
colorsE[1] = colors[ColorD] == colors[ColorB] && colors[ColorE] != colors[ColorC] || colors[ColorB] == colors[ColorF] && colors[ColorE] != colors[ColorA] ? colors[ColorB] : colors[ColorE];
|
|
||||||
colorsE[0] = colors[ColorD] == colors[ColorB] ? colors[ColorD] : colors[ColorE];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
colorsE[8] = colors[ColorE];
|
|
||||||
colorsE[7] = colors[ColorE];
|
|
||||||
colorsE[6] = colors[ColorE];
|
|
||||||
colorsE[5] = colors[ColorE];
|
|
||||||
colorsE[4] = colors[ColorE];
|
|
||||||
colorsE[3] = colors[ColorE];
|
|
||||||
colorsE[2] = colors[ColorE];
|
|
||||||
colorsE[1] = colors[ColorE];
|
|
||||||
colorsE[0] = colors[ColorE];
|
|
||||||
}
|
|
||||||
var destinationOffset = x * 3 + destinationYOffset;
|
var destinationOffset = x * 3 + destinationYOffset;
|
||||||
|
|
||||||
destinationSpan[destinationOffset] = colorsE[0];
|
destinationSpan[destinationOffset] = colorE0;
|
||||||
destinationSpan[destinationOffset + 1] = colorsE[1];
|
destinationSpan[destinationOffset + 1] = colorE1;
|
||||||
destinationSpan[destinationOffset + 2] = colorsE[2];
|
destinationSpan[destinationOffset + 2] = colorE2;
|
||||||
|
|
||||||
destinationOffset += destinationWidth;
|
destinationOffset += destinationWidth;
|
||||||
destinationSpan[destinationOffset] = colorsE[3];
|
destinationSpan[destinationOffset] = colorE3;
|
||||||
destinationSpan[destinationOffset + 1] = colorsE[4];
|
destinationSpan[destinationOffset + 1] = colorE4;
|
||||||
destinationSpan[destinationOffset + 2] = colorsE[5];
|
destinationSpan[destinationOffset + 2] = colorE5;
|
||||||
|
|
||||||
destinationOffset += destinationWidth;
|
destinationOffset += destinationWidth;
|
||||||
destinationSpan[destinationOffset] = colorsE[6];
|
destinationSpan[destinationOffset] = colorE6;
|
||||||
destinationSpan[destinationOffset + 1] = colorsE[7];
|
destinationSpan[destinationOffset + 1] = colorE7;
|
||||||
destinationSpan[destinationOffset + 2] = colorsE[8];
|
destinationSpan[destinationOffset + 2] = colorE8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return destinationBitmap;
|
return destinationBitmap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,10 +33,13 @@ namespace Greenshot.Gfx
|
||||||
{
|
{
|
||||||
private const byte ColorB = 0;
|
private const byte ColorB = 0;
|
||||||
private const byte ColorD = 1;
|
private const byte ColorD = 1;
|
||||||
private const byte ColorE = 2;
|
private const byte ColorE = 4;
|
||||||
private const byte ColorF = 3;
|
private const byte ColorF = 2;
|
||||||
private const byte ColorH = 4;
|
private const byte ColorH = 3;
|
||||||
|
private const byte ColorA = 5;
|
||||||
|
private const byte ColorC = 6;
|
||||||
|
private const byte ColorG = 7;
|
||||||
|
private const byte ColorI = 8;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use "Scale2x" algorithm to produce bitmap from the original.
|
/// Use "Scale2x" algorithm to produce bitmap from the original.
|
||||||
|
@ -128,5 +131,160 @@ namespace Greenshot.Gfx
|
||||||
}
|
}
|
||||||
return destinationBitmap;
|
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
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sourceBitmap">UnmanagedBitmap to scale 3x</param>
|
||||||
|
/// <returns>UnmanagedBitmap</returns>
|
||||||
|
public static UnmanagedBitmap<TPixelLayout> Scale3XReference<TPixelLayout>(this UnmanagedBitmap<TPixelLayout> sourceBitmap) where TPixelLayout : unmanaged
|
||||||
|
{
|
||||||
|
if (Marshal.SizeOf<TPixelLayout>() != 4)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Only 4 byte unmanaged structs are supported.");
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var colors = stackalloc uint[9];
|
||||||
|
var colorsE = stackalloc uint[9];
|
||||||
|
|
||||||
|
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 sourceOffset = sourceYOffset + x;
|
||||||
|
|
||||||
|
colors[ColorE] = sourceSpan[sourceOffset];
|
||||||
|
|
||||||
|
if (y != 0 && x != 0)
|
||||||
|
{
|
||||||
|
colors[ColorA] = sourceSpan[(sourceOffset - 1) - sourceWidth];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorA] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y != 0)
|
||||||
|
{
|
||||||
|
colors[ColorB] = sourceSpan[sourceOffset - sourceWidth];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorB] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < sourceWidth - 1 && y != 0)
|
||||||
|
{
|
||||||
|
colors[ColorC] = sourceSpan[(sourceOffset + 1) - sourceWidth];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorC] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x != 0)
|
||||||
|
{
|
||||||
|
colors[ColorD] = sourceSpan[sourceOffset - 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorD] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < sourceWidth - 1)
|
||||||
|
{
|
||||||
|
colors[ColorF] = sourceSpan[sourceOffset + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorF] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x != 0 && y < sourceBitmap.Height - 1)
|
||||||
|
{
|
||||||
|
colors[ColorG] = sourceSpan[(sourceOffset - 1) + sourceWidth];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorG] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y < sourceBitmap.Height - 1)
|
||||||
|
{
|
||||||
|
colors[ColorH] = sourceSpan[sourceOffset + sourceWidth];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorH] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < sourceWidth - 1 && y < sourceBitmap.Height - 1)
|
||||||
|
{
|
||||||
|
colors[ColorI] = sourceSpan[sourceOffset + 1 + sourceWidth];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors[ColorI] = colors[ColorE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colors[ColorB] != colors[ColorH] && colors[ColorD] != colors[ColorF])
|
||||||
|
{
|
||||||
|
colorsE[8] = colors[ColorH] == colors[ColorF] ? colors[ColorF] : colors[ColorE];
|
||||||
|
colorsE[7] = colors[ColorD] == colors[ColorH] && colors[ColorE] != colors[ColorI] || colors[ColorH] == colors[ColorF] && colors[ColorE] != colors[ColorG] ? colors[ColorH] : colors[ColorE];
|
||||||
|
colorsE[6] = colors[ColorD] == colors[ColorH] ? colors[ColorD] : colors[ColorE];
|
||||||
|
colorsE[5] = colors[ColorB] == colors[ColorF] && colors[ColorE] != colors[ColorI] || colors[ColorH] == colors[ColorF] && colors[ColorE] != colors[ColorC] ? colors[ColorF] : colors[ColorE];
|
||||||
|
|
||||||
|
colorsE[4] = colors[ColorE];
|
||||||
|
|
||||||
|
colorsE[3] = colors[ColorD] == colors[ColorB] && colors[ColorE] != colors[ColorG] || colors[ColorD] == colors[ColorH] && colors[ColorE] != colors[ColorA] ? colors[ColorD] : colors[ColorE];
|
||||||
|
colorsE[2] = colors[ColorB] == colors[ColorF] ? colors[ColorF] : colors[ColorE];
|
||||||
|
colorsE[1] = colors[ColorD] == colors[ColorB] && colors[ColorE] != colors[ColorC] || colors[ColorB] == colors[ColorF] && colors[ColorE] != colors[ColorA] ? colors[ColorB] : colors[ColorE];
|
||||||
|
colorsE[0] = colors[ColorD] == colors[ColorB] ? colors[ColorD] : colors[ColorE];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorsE[8] = colors[ColorE];
|
||||||
|
colorsE[7] = colors[ColorE];
|
||||||
|
colorsE[6] = colors[ColorE];
|
||||||
|
colorsE[5] = colors[ColorE];
|
||||||
|
colorsE[4] = colors[ColorE];
|
||||||
|
colorsE[3] = colors[ColorE];
|
||||||
|
colorsE[2] = colors[ColorE];
|
||||||
|
colorsE[1] = colors[ColorE];
|
||||||
|
colorsE[0] = colors[ColorE];
|
||||||
|
}
|
||||||
|
var destinationOffset = x * 3 + destinationYOffset;
|
||||||
|
|
||||||
|
destinationSpan[destinationOffset] = colorsE[0];
|
||||||
|
destinationSpan[destinationOffset + 1] = colorsE[1];
|
||||||
|
destinationSpan[destinationOffset + 2] = colorsE[2];
|
||||||
|
|
||||||
|
destinationOffset += destinationWidth;
|
||||||
|
destinationSpan[destinationOffset] = colorsE[3];
|
||||||
|
destinationSpan[destinationOffset + 1] = colorsE[4];
|
||||||
|
destinationSpan[destinationOffset + 2] = colorsE[5];
|
||||||
|
|
||||||
|
destinationOffset += destinationWidth;
|
||||||
|
destinationSpan[destinationOffset] = colorsE[6];
|
||||||
|
destinationSpan[destinationOffset + 1] = colorsE[7];
|
||||||
|
destinationSpan[destinationOffset + 2] = colorsE[8];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destinationBitmap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue