Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0abb99b
fix whitespacing in generated code
jongleur1983 Oct 6, 2018
9720fea
#718: add pixel types Gray8 and Gray16
jongleur1983 Oct 6, 2018
0354f32
#718: fix merge conflicts, adapt changes from PR #727 to t4 script
jongleur1983 Oct 6, 2018
904fcd5
#718: fix Gray8Tests
jongleur1983 Oct 6, 2018
58a5232
#718: extend IPixel interface and implement it everywhere, ...
jongleur1983 Oct 6, 2018
5d35bcd
#718: add missing inheritdoc comments
jongleur1983 Oct 6, 2018
c8efad0
#718: add missing documentation
jongleur1983 Oct 6, 2018
8de1769
Merge branch 'master' into 718-gray8-gray16
JimBobSquarePants Oct 8, 2018
1533c4c
Fix Gray8
JimBobSquarePants Oct 8, 2018
2950219
Update and normalise pixel format + disable out of date tests
JimBobSquarePants Oct 9, 2018
486ca25
Merge branch 'master' into 718-gray8-gray16
JimBobSquarePants Oct 9, 2018
d4327c5
Fix linear gradient brush test.
JimBobSquarePants Oct 10, 2018
891a1c5
Merge remote-tracking branch 'upstream/master' into 718-gray8-gray16
JimBobSquarePants Oct 10, 2018
c349c2b
Fix up Gray8 and Gary16 tests
JimBobSquarePants Oct 13, 2018
c85c739
Merge remote-tracking branch 'upstream/master' into 718-gray8-gray16
JimBobSquarePants Oct 13, 2018
1f7df77
Fix up pixel format tests
JimBobSquarePants Oct 13, 2018
1c2aee0
Generate bulk pixel operations for all standard packing operations an…
JimBobSquarePants Oct 15, 2018
d4bda60
Fix sandbox tests
JimBobSquarePants Oct 15, 2018
b14c35f
Fix JIT issue on 32bit framework
JimBobSquarePants Oct 15, 2018
c23dbcd
Merge branch 'master' into 718-gray8-gray16
JimBobSquarePants Oct 16, 2018
e97ced4
Merge remote-tracking branch 'upstream/master' into 718-gray8-gray16
JimBobSquarePants Oct 16, 2018
778895b
Use FormattableString
JimBobSquarePants Oct 16, 2018
1daa463
Use new IPixel API
JimBobSquarePants Oct 16, 2018
9b19631
common fixtures for PixelConversion* benchmarks
antonfirsov Oct 18, 2018
3051d71
PixelConversion_ConvertToRgba32_AsPartOfCompositeOperation
antonfirsov Oct 18, 2018
9ab574c
benchmarks for TPixel -> Vector4 conversion
antonfirsov Oct 18, 2018
21853e6
Merge branch 'master' into 718-gray8-gray16
antonfirsov Oct 18, 2018
170a00c
Merge branch 'af/simd-conversion' into 718-gray8-gray16
antonfirsov Oct 21, 2018
876f230
fix PixelOperationsTests
antonfirsov Oct 21, 2018
de2d037
Merge remote-tracking branch 'origin/master' into 718-gray8-gray16
antonfirsov Oct 21, 2018
5a070ea
wakeup message to the git status-checks
antonfirsov Oct 22, 2018
6ca596d
Something's wrong with the status checks
antonfirsov Oct 22, 2018
ed55a1f
CLA assistant, please wake up!
antonfirsov Oct 22, 2018
cd543b2
Bump build now Github should be returned to normal.
JimBobSquarePants Oct 22, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions src/ImageSharp/Common/Helpers/ImageMaths.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,73 @@ namespace SixLabors.ImageSharp
/// </summary>
internal static class ImageMaths
{
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="byte"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static byte Get8BitBT709Luminance(byte r, byte g, byte b) => (byte)((r * .2126F) + (g * .7152F) + (b * .0722F));

/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="ushort"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F));

/// <summary>
/// Scales a value from a 16 bit <see cref="ushort"/> to it's 8 bit <see cref="byte"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit compoonent value.</param>
/// <returns>The <see cref="byte"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static byte DownScaleFrom16BitTo8Bit(ushort component)
{
// To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
//
// (V * 255) / 65535
//
// This reduces to round(V / 257), or floor((V + 128.5)/257)
//
// Represent V as the two byte value vhi.vlo. Make a guess that the
// result is the top byte of V, vhi, then the correction to this value
// is:
//
// error = floor(((V-vhi.vhi) + 128.5) / 257)
// = floor(((vlo-vhi) + 128.5) / 257)
//
// This can be approximated using integer arithmetic (and a signed
// shift):
//
// error = (vlo-vhi+128) >> 8;
//
// The approximate differs from the exact answer only when (vlo-vhi) is
// 128; it then gives a correction of +1 when the exact correction is
// 0. This gives 128 errors. The exact answer (correct for all 16-bit
// input values) is:
//
// error = (vlo-vhi+128)*65535 >> 24;
//
// An alternative arithmetic calculation which also gives no errors is:
//
// (V * 255 + 32895) >> 16
return (byte)(((component * 255) + 32895) >> 16);
}

/// <summary>
/// Scales a value from an 8 bit <see cref="byte"/> to it's 16 bit <see cref="ushort"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit compoonent value.</param>
/// <returns>The <see cref="ushort"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257);

/// <summary>
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
/// </summary>
Expand Down
24 changes: 8 additions & 16 deletions src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,6 @@ private void ReadRle8<TPixel>(Buffer2D<TPixel> pixels, byte[] colors, int width,
where TPixel : struct, IPixel<TPixel>
{
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);

using (Buffer2D<byte> buffer = this.memoryAllocator.Allocate2D<byte>(width, height, AllocationOptions.Clean))
{
this.UncompressRle8(width, buffer.GetSpan());
Expand All @@ -233,8 +231,7 @@ private void ReadRle8<TPixel>(Buffer2D<TPixel> pixels, byte[] colors, int width,

for (int x = 0; x < width; x++)
{
rgba.Bgr = Unsafe.As<byte, Bgr24>(ref colors[bufferRow[x] * 4]);
color.PackFromRgba32(rgba);
color.PackFromBgr24(Unsafe.As<byte, Bgr24>(ref colors[bufferRow[x] * 4]));
pixelRow[x] = color;
}
}
Expand Down Expand Up @@ -352,8 +349,6 @@ private void ReadRgbPalette<TPixel>(Buffer2D<TPixel> pixels, byte[] colors, int
using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(arrayWidth + padding, AllocationOptions.Clean))
{
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);

Span<byte> rowSpan = row.GetSpan();

for (int y = 0; y < height; y++)
Expand All @@ -363,17 +358,14 @@ private void ReadRgbPalette<TPixel>(Buffer2D<TPixel> pixels, byte[] colors, int
int offset = 0;
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);

// TODO: Could use PixelOperations here!
for (int x = 0; x < arrayWidth; x++)
{
int colOffset = x * ppb;
for (int shift = 0, newX = colOffset; shift < ppb && newX < width; shift++, newX++)
{
int colorIndex = ((rowSpan[offset] >> (8 - bits - (shift * bits))) & mask) * 4;

// Stored in b-> g-> r order.
rgba.Bgr = Unsafe.As<byte, Bgr24>(ref colors[colorIndex]);
color.PackFromRgba32(rgba);
color.PackFromBgr24(Unsafe.As<byte, Bgr24>(ref colors[colorIndex]));
pixelRow[newX] = color;
}

Expand All @@ -397,7 +389,6 @@ private void ReadRgb16<TPixel>(Buffer2D<TPixel> pixels, int width, int height, b
int padding = CalculatePadding(width, 2);
int stride = (width * 2) + padding;
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);

using (IManagedByteBuffer buffer = this.memoryAllocator.AllocateManagedByteBuffer(stride))
{
Expand All @@ -412,11 +403,12 @@ private void ReadRgb16<TPixel>(Buffer2D<TPixel> pixels, int width, int height, b
{
short temp = BitConverter.ToInt16(buffer.Array, offset);

rgba.R = GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10);
rgba.G = GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5);
rgba.B = GetBytesFrom5BitValue(temp & Rgb16BMask);
var rgb = new Rgb24(
GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10),
GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5),
GetBytesFrom5BitValue(temp & Rgb16BMask));

color.PackFromRgba32(rgba);
color.PackFromRgb24(rgb);
pixelRow[x] = color;
offset += 2;
}
Expand Down Expand Up @@ -537,7 +529,7 @@ private void ReadInfoHeader()
this.metaData = meta;

short bitsPerPixel = this.infoHeader.BitsPerPixel;
var bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance);
BmpMetaData bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance);

// We can only encode at these bit rates so far.
if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24)
Expand Down
4 changes: 2 additions & 2 deletions src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream)

var fileHeader = new BmpFileHeader(
type: 19778, // BM
offset: 54,
fileSize: 54 + infoHeader.ImageSize,
reserved: 0,
fileSize: 54 + infoHeader.ImageSize);
offset: 54);

#if NETCOREAPP2_1
Span<byte> buffer = stackalloc byte[40];
Expand Down
34 changes: 24 additions & 10 deletions src/ImageSharp/Formats/Gif/GifDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -481,22 +481,36 @@ private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPi
}

ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.GetPixelRowSpan(writeY));
var rgba = new Rgba32(0, 0, 0, 255);
bool transFlag = this.graphicsControlExtension.TransparencyFlag;

// #403 The left + width value can be larger than the image width
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
if (!transFlag)
{
int index = Unsafe.Add(ref indicesRef, i);

if (!this.graphicsControlExtension.TransparencyFlag
|| this.graphicsControlExtension.TransparencyIndex != index)
// #403 The left + width value can be larger than the image width
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
{
int index = Unsafe.Add(ref indicesRef, i);
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
rgba.Rgb = colorTable[index];
pixel.PackFromRgba32(rgba);
Rgb24 rgb = colorTable[index];
pixel.PackFromRgb24(rgb);

i++;
}
}
else
{
byte transIndex = this.graphicsControlExtension.TransparencyIndex;
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
{
int index = Unsafe.Add(ref indicesRef, i);
if (transIndex != index)
{
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
Rgb24 rgb = colorTable[index];
pixel.PackFromRgb24(rgb);
}

i++;
i++;
}
}
}

Expand Down
34 changes: 14 additions & 20 deletions src/ImageSharp/Formats/Gif/GifEncoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.

using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -210,16 +211,20 @@ private int GetTransparentIndex<TPixel>(QuantizedFrame<TPixel> quantized)
{
// Transparent pixels are much more likely to be found at the end of a palette
int index = -1;
Rgba32 trans = default;
int length = quantized.Palette.Length;

ref TPixel paletteRef = ref MemoryMarshal.GetReference(quantized.Palette.AsSpan());
for (int i = quantized.Palette.Length - 1; i >= 0; i--)
using (IMemoryOwner<Rgba32> rgbaBuffer = this.memoryAllocator.Allocate<Rgba32>(length))
{
ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
entry.ToRgba32(ref trans);
if (trans.Equals(default))
Span<Rgba32> rgbaSpan = rgbaBuffer.GetSpan();
ref Rgba32 paletteRef = ref MemoryMarshal.GetReference(rgbaSpan);
PixelOperations<TPixel>.Instance.ToRgba32(quantized.Palette, rgbaSpan, length);

for (int i = quantized.Palette.Length - 1; i >= 0; i--)
{
index = i;
if (Unsafe.Add(ref paletteRef, i).Equals(default))
{
index = i;
}
}
}

Expand Down Expand Up @@ -406,24 +411,13 @@ private void WriteImageDescriptor<TPixel>(ImageFrame<TPixel> image, bool hasColo
private void WriteColorTable<TPixel>(QuantizedFrame<TPixel> image, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
int pixelCount = image.Palette.Length;

// The maximium number of colors for the bit depth
int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * 3;
Rgb24 rgb = default;
int pixelCount = image.Palette.Length;

using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength))
{
ref TPixel paletteRef = ref MemoryMarshal.GetReference(image.Palette.AsSpan());
ref Rgb24 rgb24Ref = ref Unsafe.As<byte, Rgb24>(ref MemoryMarshal.GetReference(colorTable.GetSpan()));
for (int i = 0; i < pixelCount; i++)
{
ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
entry.ToRgb24(ref rgb);
Unsafe.Add(ref rgb24Ref, i) = rgb;
}

// Write the palette to the stream
PixelOperations<TPixel>.Instance.ToRgb24Bytes(image.Palette.AsSpan(), colorTable.GetSpan(), pixelCount);
stream.Write(colorTable.Array, 0, colorTableLength);
}
}
Expand Down
Loading